mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-29 00:32:49 +00:00
Merge branch 'lua_ui_templates' into 'master'
Lua UI templates See merge request OpenMW/openmw!1475
This commit is contained in:
commit
53f2dfd1c0
@ -63,7 +63,6 @@ namespace MWLua
|
|||||||
|
|
||||||
// Implemented in uibindings.cpp
|
// Implemented in uibindings.cpp
|
||||||
sol::table initUserInterfacePackage(const Context&);
|
sol::table initUserInterfacePackage(const Context&);
|
||||||
void clearUserInterface();
|
|
||||||
|
|
||||||
// Implemented in inputbindings.cpp
|
// Implemented in inputbindings.cpp
|
||||||
sol::table initInputPackage(const Context&);
|
sol::table initInputPackage(const Context&);
|
||||||
|
@ -165,8 +165,8 @@ add_component_dir (queries
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (lua_ui
|
add_component_dir (lua_ui
|
||||||
widget element util layers content
|
properties widget element util layers content
|
||||||
text textedit window
|
text textedit window image
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,81 +7,21 @@
|
|||||||
|
|
||||||
namespace LuaUi
|
namespace LuaUi
|
||||||
{
|
{
|
||||||
|
namespace LayoutKeys
|
||||||
|
{
|
||||||
|
constexpr std::string_view type = "type";
|
||||||
|
constexpr std::string_view name = "name";
|
||||||
|
constexpr std::string_view layer = "layer";
|
||||||
|
constexpr std::string_view templateLayout = "template";
|
||||||
|
constexpr std::string_view props = "props";
|
||||||
|
constexpr std::string_view events = "events";
|
||||||
|
constexpr std::string_view content = "content";
|
||||||
|
constexpr std::string_view external = "external";
|
||||||
|
}
|
||||||
|
|
||||||
std::string widgetType(const sol::table& layout)
|
std::string widgetType(const sol::table& layout)
|
||||||
{
|
{
|
||||||
return layout.get_or("type", std::string("LuaWidget"));
|
return layout.get_or(LayoutKeys::type, std::string("LuaWidget"));
|
||||||
}
|
|
||||||
|
|
||||||
Content content(const sol::table& layout)
|
|
||||||
{
|
|
||||||
auto optional = layout.get<sol::optional<Content>>("content");
|
|
||||||
if (optional.has_value())
|
|
||||||
return optional.value();
|
|
||||||
else
|
|
||||||
return Content();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setProperties(LuaUi::WidgetExtension* ext, const sol::table& layout)
|
|
||||||
{
|
|
||||||
ext->setProperties(layout.get<sol::object>("props"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEventCallbacks(LuaUi::WidgetExtension* ext, const sol::table& layout)
|
|
||||||
{
|
|
||||||
ext->clearCallbacks();
|
|
||||||
auto events = layout.get<sol::optional<sol::table>>("events");
|
|
||||||
if (events.has_value())
|
|
||||||
{
|
|
||||||
events.value().for_each([ext](const sol::object& name, const sol::object& callback)
|
|
||||||
{
|
|
||||||
if (name.is<std::string>() && callback.is<LuaUtil::Callback>())
|
|
||||||
ext->setCallback(name.as<std::string>(), callback.as<LuaUtil::Callback>());
|
|
||||||
else if (!name.is<std::string>())
|
|
||||||
Log(Debug::Warning) << "UI event key must be a string";
|
|
||||||
else if (!callback.is<LuaUtil::Callback>())
|
|
||||||
Log(Debug::Warning) << "UI event handler for key \"" << name.as<std::string>()
|
|
||||||
<< "\" must be an openmw.async.callback";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLayout(LuaUi::WidgetExtension* ext, const sol::table& layout)
|
|
||||||
{
|
|
||||||
ext->setLayout(layout);
|
|
||||||
}
|
|
||||||
|
|
||||||
LuaUi::WidgetExtension* createWidget(const sol::table& layout, LuaUi::WidgetExtension* parent)
|
|
||||||
{
|
|
||||||
std::string type = widgetType(layout);
|
|
||||||
std::string skin = layout.get_or("skin", std::string());
|
|
||||||
std::string name = layout.get_or("name", std::string());
|
|
||||||
|
|
||||||
static auto widgetTypeMap = widgetTypeToName();
|
|
||||||
if (widgetTypeMap.find(type) == widgetTypeMap.end())
|
|
||||||
throw std::logic_error(std::string("Invalid widget type ") += type);
|
|
||||||
|
|
||||||
MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT(
|
|
||||||
type, skin,
|
|
||||||
MyGUI::IntCoord(), MyGUI::Align::Default,
|
|
||||||
std::string(), name);
|
|
||||||
|
|
||||||
LuaUi::WidgetExtension* ext = dynamic_cast<LuaUi::WidgetExtension*>(widget);
|
|
||||||
if (!ext)
|
|
||||||
throw std::runtime_error("Invalid widget!");
|
|
||||||
|
|
||||||
ext->initialize(layout.lua_state(), widget);
|
|
||||||
if (parent != nullptr)
|
|
||||||
widget->attachToWidget(parent->widget());
|
|
||||||
|
|
||||||
setEventCallbacks(ext, layout);
|
|
||||||
setProperties(ext, layout);
|
|
||||||
setLayout(ext, layout);
|
|
||||||
|
|
||||||
Content cont = content(layout);
|
|
||||||
for (size_t i = 0; i < cont.size(); i++)
|
|
||||||
ext->addChild(createWidget(cont.at(i), ext));
|
|
||||||
|
|
||||||
return ext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyWidget(LuaUi::WidgetExtension* ext)
|
void destroyWidget(LuaUi::WidgetExtension* ext)
|
||||||
@ -90,45 +30,121 @@ namespace LuaUi
|
|||||||
MyGUI::Gui::getInstancePtr()->destroyWidget(ext->widget());
|
MyGUI::Gui::getInstancePtr()->destroyWidget(ext->widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateWidget(const sol::table& layout, LuaUi::WidgetExtension* ext)
|
WidgetExtension* createWidget(const sol::table& layout);
|
||||||
|
void updateWidget(WidgetExtension* ext, const sol::table& layout);
|
||||||
|
|
||||||
|
std::vector<WidgetExtension*> updateContent(
|
||||||
|
const std::vector<WidgetExtension*>& children, const sol::object& contentObj)
|
||||||
{
|
{
|
||||||
setEventCallbacks(ext, layout);
|
std::vector<WidgetExtension*> result;
|
||||||
setProperties(ext, layout);
|
if (contentObj == sol::nil)
|
||||||
setLayout(ext, layout);
|
{
|
||||||
|
for (WidgetExtension* w : children)
|
||||||
Content newContent = content(layout);
|
destroyWidget(w);
|
||||||
|
return result;
|
||||||
size_t oldSize = ext->childCount();
|
}
|
||||||
size_t newSize = newContent.size();
|
if (!contentObj.is<Content>())
|
||||||
size_t minSize = std::min(oldSize, newSize);
|
throw std::logic_error("Layout content field must be a openmw.ui.content");
|
||||||
|
Content content = contentObj.as<Content>();
|
||||||
|
result.resize(content.size());
|
||||||
|
size_t minSize = std::min(children.size(), content.size());
|
||||||
for (size_t i = 0; i < minSize; i++)
|
for (size_t i = 0; i < minSize; i++)
|
||||||
{
|
{
|
||||||
LuaUi::WidgetExtension* oldWidget = ext->childAt(i);
|
WidgetExtension* ext = children[i];
|
||||||
sol::table newChild = newContent.at(i);
|
sol::table newLayout = content.at(i);
|
||||||
|
if (ext->widget()->getTypeName() == widgetType(newLayout)
|
||||||
if (oldWidget->widget()->getTypeName() != widgetType(newChild))
|
&& ext->getLayout() == newLayout)
|
||||||
{
|
{
|
||||||
destroyWidget(oldWidget);
|
updateWidget(ext, newLayout);
|
||||||
ext->assignChild(i, createWidget(newChild, ext));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
updateWidget(newChild, oldWidget);
|
{
|
||||||
|
destroyWidget(ext);
|
||||||
|
ext = createWidget(newLayout);
|
||||||
|
}
|
||||||
|
result[i] = ext;
|
||||||
}
|
}
|
||||||
|
for (size_t i = minSize; i < children.size(); i++)
|
||||||
for (size_t i = minSize; i < oldSize; i++)
|
destroyWidget(children[i]);
|
||||||
destroyWidget(ext->eraseChild(i));
|
for (size_t i = minSize; i < content.size(); i++)
|
||||||
|
result[i] = createWidget(content.at(i));
|
||||||
for (size_t i = minSize; i < newSize; i++)
|
return result;
|
||||||
ext->addChild(createWidget(newContent.at(i), ext));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLayer(const sol::table& layout, LuaUi::WidgetExtension* ext)
|
void setTemplate(WidgetExtension* ext, const sol::object& templateLayout)
|
||||||
|
{
|
||||||
|
// \todo remove when none of the widgets require this workaround
|
||||||
|
sol::object skin = LuaUtil::getFieldOrNil(templateLayout, "skin");
|
||||||
|
if (skin.is<std::string>())
|
||||||
|
ext->widget()->changeWidgetSkin(skin.as<std::string>());
|
||||||
|
|
||||||
|
sol::object props = LuaUtil::getFieldOrNil(templateLayout, LayoutKeys::props);
|
||||||
|
ext->setTemplateProperties(props);
|
||||||
|
sol::object content = LuaUtil::getFieldOrNil(templateLayout, LayoutKeys::content);
|
||||||
|
ext->setTemplateChildren(updateContent(ext->templateChildren(), content));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEventCallbacks(LuaUi::WidgetExtension* ext, const sol::object& eventsObj)
|
||||||
|
{
|
||||||
|
ext->clearCallbacks();
|
||||||
|
if (eventsObj == sol::nil)
|
||||||
|
return;
|
||||||
|
if (!eventsObj.is<sol::table>())
|
||||||
|
throw std::logic_error("The \"events\" layout field must be a table of callbacks");
|
||||||
|
auto events = eventsObj.as<sol::table>();
|
||||||
|
events.for_each([ext](const sol::object& name, const sol::object& callback)
|
||||||
|
{
|
||||||
|
if (name.is<std::string>() && callback.is<LuaUtil::Callback>())
|
||||||
|
ext->setCallback(name.as<std::string>(), callback.as<LuaUtil::Callback>());
|
||||||
|
else if (!name.is<std::string>())
|
||||||
|
Log(Debug::Warning) << "UI event key must be a string";
|
||||||
|
else if (!callback.is<LuaUtil::Callback>())
|
||||||
|
Log(Debug::Warning) << "UI event handler for key \"" << name.as<std::string>()
|
||||||
|
<< "\" must be an openmw.async.callback";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetExtension* createWidget(const sol::table& layout)
|
||||||
|
{
|
||||||
|
std::string type = widgetType(layout);
|
||||||
|
std::string name = layout.get_or(LayoutKeys::name, std::string());
|
||||||
|
|
||||||
|
static auto widgetTypeMap = widgetTypeToName();
|
||||||
|
if (widgetTypeMap.find(type) == widgetTypeMap.end())
|
||||||
|
throw std::logic_error(std::string("Invalid widget type ") += type);
|
||||||
|
|
||||||
|
MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT(
|
||||||
|
type, "",
|
||||||
|
MyGUI::IntCoord(), MyGUI::Align::Default,
|
||||||
|
std::string(), name);
|
||||||
|
|
||||||
|
WidgetExtension* ext = dynamic_cast<WidgetExtension*>(widget);
|
||||||
|
if (!ext)
|
||||||
|
throw std::runtime_error("Invalid widget!");
|
||||||
|
ext->initialize(layout.lua_state(), widget);
|
||||||
|
|
||||||
|
updateWidget(ext, layout);
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateWidget(WidgetExtension* ext, const sol::table& layout)
|
||||||
|
{
|
||||||
|
ext->setLayout(layout);
|
||||||
|
ext->setExternal(layout.get<sol::object>(LayoutKeys::external));
|
||||||
|
setTemplate(ext, layout.get<sol::object>(LayoutKeys::templateLayout));
|
||||||
|
ext->setProperties(layout.get<sol::object>(LayoutKeys::props));
|
||||||
|
setEventCallbacks(ext, layout.get<sol::object>(LayoutKeys::events));
|
||||||
|
|
||||||
|
ext->setChildren(updateContent(ext->children(), layout.get<sol::object>(LayoutKeys::content)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLayer(WidgetExtension* ext, const sol::table& layout)
|
||||||
{
|
{
|
||||||
MyGUI::ILayer* layerNode = ext->widget()->getLayer();
|
MyGUI::ILayer* layerNode = ext->widget()->getLayer();
|
||||||
std::string currentLayer = layerNode ? layerNode->getName() : std::string();
|
std::string currentLayer = layerNode ? layerNode->getName() : std::string();
|
||||||
std::string newLayer = layout.get_or("layer", std::string());
|
std::string newLayer = layout.get_or(LayoutKeys::layer, std::string());
|
||||||
if (!newLayer.empty() && !MyGUI::LayerManager::getInstance().isExist(newLayer))
|
if (!newLayer.empty() && !MyGUI::LayerManager::getInstance().isExist(newLayer))
|
||||||
throw std::logic_error(std::string("Layer ") += newLayer += " doesn't exist");
|
throw std::logic_error(std::string("Layer ") + newLayer + " doesn't exist");
|
||||||
else if (newLayer != currentLayer)
|
else if (newLayer != currentLayer)
|
||||||
{
|
{
|
||||||
MyGUI::LayerManager::getInstance().attachToLayerNode(newLayer, ext->widget());
|
MyGUI::LayerManager::getInstance().attachToLayerNode(newLayer, ext->widget());
|
||||||
@ -157,8 +173,8 @@ namespace LuaUi
|
|||||||
assert(!mRoot);
|
assert(!mRoot);
|
||||||
if (!mRoot)
|
if (!mRoot)
|
||||||
{
|
{
|
||||||
mRoot = createWidget(mLayout, nullptr);
|
mRoot = createWidget(mLayout);
|
||||||
setLayer(mLayout, mRoot);
|
setLayer(mRoot, mLayout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +182,8 @@ namespace LuaUi
|
|||||||
{
|
{
|
||||||
if (mRoot && mUpdate)
|
if (mRoot && mUpdate)
|
||||||
{
|
{
|
||||||
updateWidget(mLayout, mRoot);
|
updateWidget(mRoot, mLayout);
|
||||||
setLayer(mLayout, mRoot);
|
setLayer(mRoot, mLayout);
|
||||||
}
|
}
|
||||||
mUpdate = false;
|
mUpdate = false;
|
||||||
}
|
}
|
||||||
|
51
components/lua_ui/image.cpp
Normal file
51
components/lua_ui/image.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_RenderManager.h>
|
||||||
|
|
||||||
|
namespace LuaUi
|
||||||
|
{
|
||||||
|
void LuaTileRect::_setAlign(const MyGUI::IntSize& _oldsize)
|
||||||
|
{
|
||||||
|
mCurrentCoord.set(0, 0, mCroppedParent->getWidth(), mCroppedParent->getHeight());
|
||||||
|
mAlign = MyGUI::Align::Stretch;
|
||||||
|
MyGUI::TileRect::_setAlign(_oldsize);
|
||||||
|
mTileSize = mSetTileSize;
|
||||||
|
|
||||||
|
// zero tilesize stands for not tiling
|
||||||
|
if (mTileSize.width == 0)
|
||||||
|
mTileSize.width = mCoord.width;
|
||||||
|
if (mTileSize.height == 0)
|
||||||
|
mTileSize.height = mCoord.height;
|
||||||
|
|
||||||
|
// mCoord could be zero, prevent division by 0
|
||||||
|
// use arbitrary large numbers to prevent performance issues
|
||||||
|
if (mTileSize.width == 0)
|
||||||
|
mTileSize.width = 1e7;
|
||||||
|
if (mTileSize.height == 0)
|
||||||
|
mTileSize.height = 1e7;
|
||||||
|
}
|
||||||
|
|
||||||
|
LuaImage::LuaImage()
|
||||||
|
{
|
||||||
|
changeWidgetSkin("LuaImage");
|
||||||
|
mTileRect = dynamic_cast<LuaTileRect*>(getSubWidgetMain());
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaImage::updateProperties()
|
||||||
|
{
|
||||||
|
setImageTexture(propertyValue("path", std::string()));
|
||||||
|
|
||||||
|
bool tileH = propertyValue("tileH", false);
|
||||||
|
bool tileV = propertyValue("tileV", false);
|
||||||
|
MyGUI::ITexture* texture = MyGUI::RenderManager::getInstance().getTexture(_getTextureName());
|
||||||
|
MyGUI::IntSize textureSize;
|
||||||
|
if (texture != nullptr)
|
||||||
|
textureSize = MyGUI::IntSize(texture->getWidth(), texture->getHeight());
|
||||||
|
mTileRect->updateSize(MyGUI::IntSize(
|
||||||
|
tileH ? textureSize.width : 0,
|
||||||
|
tileV ? textureSize.height : 0
|
||||||
|
));
|
||||||
|
|
||||||
|
WidgetExtension::updateProperties();
|
||||||
|
}
|
||||||
|
}
|
37
components/lua_ui/image.hpp
Normal file
37
components/lua_ui/image.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef OPENMW_LUAUI_IMAGE
|
||||||
|
#define OPENMW_LUAUI_IMAGE
|
||||||
|
|
||||||
|
#include <MyGUI_TileRect.h>
|
||||||
|
#include <MyGUI_ImageBox.h>
|
||||||
|
|
||||||
|
#include "widget.hpp"
|
||||||
|
|
||||||
|
namespace LuaUi
|
||||||
|
{
|
||||||
|
class LuaTileRect : public MyGUI::TileRect
|
||||||
|
{
|
||||||
|
MYGUI_RTTI_DERIVED(LuaTileRect)
|
||||||
|
|
||||||
|
public:
|
||||||
|
void _setAlign(const MyGUI::IntSize& _oldsize) override;
|
||||||
|
|
||||||
|
void updateSize(MyGUI::IntSize tileSize) { mSetTileSize = tileSize; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MyGUI::IntSize mSetTileSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LuaImage : public MyGUI::ImageBox, public WidgetExtension
|
||||||
|
{
|
||||||
|
MYGUI_RTTI_DERIVED(LuaImage)
|
||||||
|
|
||||||
|
public:
|
||||||
|
LuaImage();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void updateProperties() override;
|
||||||
|
LuaTileRect* mTileRect;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENMW_LUAUI_IMAGE
|
@ -9,55 +9,81 @@
|
|||||||
|
|
||||||
namespace LuaUi
|
namespace LuaUi
|
||||||
{
|
{
|
||||||
template <typename T>
|
|
||||||
sol::optional<T> getProperty(sol::object from, std::string_view field) {
|
|
||||||
sol::object value = LuaUtil::getFieldOrNil(from, field);
|
|
||||||
if (value == sol::nil)
|
|
||||||
return sol::nullopt;
|
|
||||||
if (value.is<T>())
|
|
||||||
return value.as<T>();
|
|
||||||
std::string error("Property \"");
|
|
||||||
error += field;
|
|
||||||
error += "\" has an invalid value \"";
|
|
||||||
error += LuaUtil::toString(value);
|
|
||||||
error += "\"";
|
|
||||||
throw std::logic_error(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T parseProperty(sol::object from, std::string_view field, const T& defaultValue)
|
constexpr bool isMyGuiVector() {
|
||||||
|
return
|
||||||
|
std::is_same<T, MyGUI::IntPoint>() ||
|
||||||
|
std::is_same<T, MyGUI::IntSize>() ||
|
||||||
|
std::is_same<T, MyGUI::FloatPoint>() ||
|
||||||
|
std::is_same<T, MyGUI::FloatSize>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename LuaT>
|
||||||
|
sol::optional<T> parseValue(
|
||||||
|
sol::object table,
|
||||||
|
std::string_view field,
|
||||||
|
std::string_view errorPrefix)
|
||||||
{
|
{
|
||||||
sol::optional<T> opt = getProperty<T>(from, field);
|
sol::object opt = LuaUtil::getFieldOrNil(table, field);
|
||||||
if (opt.has_value())
|
if (opt != sol::nil && !opt.is<LuaT>())
|
||||||
return opt.value();
|
{
|
||||||
|
std::string error(errorPrefix);
|
||||||
|
error += " \"";
|
||||||
|
error += field;
|
||||||
|
error += "\" has an invalid value \"";
|
||||||
|
error += LuaUtil::toString(opt);
|
||||||
|
error += "\"";
|
||||||
|
throw std::logic_error(error);
|
||||||
|
}
|
||||||
|
if (!opt.is<LuaT>())
|
||||||
|
return sol::nullopt;
|
||||||
|
|
||||||
|
LuaT luaT = opt.as<LuaT>();
|
||||||
|
if constexpr (isMyGuiVector<T>())
|
||||||
|
return T(luaT.x(), luaT.y());
|
||||||
|
else
|
||||||
|
return luaT;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
sol::optional<T> parseValue(
|
||||||
|
sol::object table,
|
||||||
|
std::string_view field,
|
||||||
|
std::string_view errorPrefix)
|
||||||
|
{
|
||||||
|
if constexpr (isMyGuiVector<T>())
|
||||||
|
return parseValue<T, osg::Vec2f>(table, field, errorPrefix);
|
||||||
|
else
|
||||||
|
return parseValue<T, T>(table, field, errorPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T parseProperty(
|
||||||
|
sol::object props,
|
||||||
|
sol::object templateProps,
|
||||||
|
std::string_view field,
|
||||||
|
const T& defaultValue)
|
||||||
|
{
|
||||||
|
auto propOptional = parseValue<T>(props, field, "Property");
|
||||||
|
auto templateOptional = parseValue<T>(templateProps, field, "Template property");
|
||||||
|
|
||||||
|
if (propOptional.has_value())
|
||||||
|
return propOptional.value();
|
||||||
|
else if (templateOptional.has_value())
|
||||||
|
return templateOptional.value();
|
||||||
else
|
else
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MyGUI::types::TPoint<T> parseProperty(
|
T parseExternal(
|
||||||
sol::object from,
|
sol::object external,
|
||||||
std::string_view field,
|
std::string_view field,
|
||||||
const MyGUI::types::TPoint<T>& defaultValue)
|
const T& defaultValue)
|
||||||
{
|
{
|
||||||
auto v = getProperty<osg::Vec2f>(from, field);
|
auto optional = parseValue<T>(external, field, "External value");
|
||||||
if (v.has_value())
|
|
||||||
return MyGUI::types::TPoint<T>(v.value().x(), v.value().y());
|
|
||||||
else
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
return optional.value_or(defaultValue);
|
||||||
MyGUI::types::TSize<T> parseProperty(
|
|
||||||
sol::object from,
|
|
||||||
std::string_view field,
|
|
||||||
const MyGUI::types::TSize<T>& defaultValue)
|
|
||||||
{
|
|
||||||
auto v = getProperty<osg::Vec2f>(from, field);
|
|
||||||
if (v.has_value())
|
|
||||||
return MyGUI::types::TSize<T>(v.value().x(), v.value().y());
|
|
||||||
else
|
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,22 @@ namespace LuaUi
|
|||||||
{
|
{
|
||||||
LuaText::LuaText()
|
LuaText::LuaText()
|
||||||
: mAutoSized(true)
|
: mAutoSized(true)
|
||||||
{}
|
|
||||||
|
|
||||||
void LuaText::setProperties(sol::object props)
|
|
||||||
{
|
{
|
||||||
setCaption(parseProperty(props, "caption", std::string()));
|
changeWidgetSkin("NormalText");
|
||||||
mAutoSized = parseProperty(props, "autoSize", true);
|
}
|
||||||
WidgetExtension::setProperties(props);
|
|
||||||
|
void LuaText::updateProperties()
|
||||||
|
{
|
||||||
|
setCaption(propertyValue("caption", std::string()));
|
||||||
|
mAutoSized = propertyValue("autoSize", true);
|
||||||
|
WidgetExtension::updateProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaText::setCaption(const MyGUI::UString& caption)
|
||||||
|
{
|
||||||
|
MyGUI::TextBox::setCaption(caption);
|
||||||
|
if (mAutoSized)
|
||||||
|
updateCoord();
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntSize LuaText::calculateSize()
|
MyGUI::IntSize LuaText::calculateSize()
|
||||||
|
@ -13,7 +13,8 @@ namespace LuaUi
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
LuaText();
|
LuaText();
|
||||||
virtual void setProperties(sol::object) override;
|
virtual void updateProperties() override;
|
||||||
|
void setCaption(const MyGUI::UString& caption) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mAutoSized;
|
bool mAutoSized;
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
namespace LuaUi
|
namespace LuaUi
|
||||||
{
|
{
|
||||||
void LuaTextEdit::setProperties(sol::object props)
|
void LuaTextEdit::updateProperties()
|
||||||
{
|
{
|
||||||
setCaption(parseProperty(props, "caption", std::string()));
|
setCaption(propertyValue("caption", std::string()));
|
||||||
WidgetExtension::setProperties(props);
|
|
||||||
|
WidgetExtension::updateProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ namespace LuaUi
|
|||||||
{
|
{
|
||||||
MYGUI_RTTI_DERIVED(LuaTextEdit)
|
MYGUI_RTTI_DERIVED(LuaTextEdit)
|
||||||
|
|
||||||
virtual void setProperties(sol::object) override;
|
virtual void updateProperties() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "text.hpp"
|
#include "text.hpp"
|
||||||
#include "textedit.hpp"
|
#include "textedit.hpp"
|
||||||
#include "window.hpp"
|
#include "window.hpp"
|
||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
#include "element.hpp"
|
#include "element.hpp"
|
||||||
|
|
||||||
@ -18,6 +19,8 @@ namespace LuaUi
|
|||||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaText>("Widget");
|
MyGUI::FactoryManager::getInstance().registerFactory<LuaText>("Widget");
|
||||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaTextEdit>("Widget");
|
MyGUI::FactoryManager::getInstance().registerFactory<LuaTextEdit>("Widget");
|
||||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaWindow>("Widget");
|
MyGUI::FactoryManager::getInstance().registerFactory<LuaWindow>("Widget");
|
||||||
|
MyGUI::FactoryManager::getInstance().registerFactory<LuaImage>("Widget");
|
||||||
|
MyGUI::FactoryManager::getInstance().registerFactory<LuaTileRect>("BasisSkin");
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::unordered_map<std::string, std::string>& widgetTypeToName()
|
const std::unordered_map<std::string, std::string>& widgetTypeToName()
|
||||||
@ -27,6 +30,7 @@ namespace LuaUi
|
|||||||
{ "LuaText", "Text" },
|
{ "LuaText", "Text" },
|
||||||
{ "LuaTextEdit", "TextEdit" },
|
{ "LuaTextEdit", "TextEdit" },
|
||||||
{ "LuaWindow", "Window" },
|
{ "LuaWindow", "Window" },
|
||||||
|
{ "LuaImage", "Image" },
|
||||||
};
|
};
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
@ -16,22 +16,15 @@ namespace LuaUi
|
|||||||
, mAnchor()
|
, mAnchor()
|
||||||
, mLua{ nullptr }
|
, mLua{ nullptr }
|
||||||
, mWidget{ nullptr }
|
, mWidget{ nullptr }
|
||||||
|
, mSlot(this)
|
||||||
, mLayout{ sol::nil }
|
, mLayout{ sol::nil }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void WidgetExtension::triggerEvent(std::string_view name, const sol::object& argument = sol::nil) const
|
|
||||||
{
|
|
||||||
auto it = mCallbacks.find(name);
|
|
||||||
if (it != mCallbacks.end())
|
|
||||||
it->second(argument, mLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WidgetExtension::initialize(lua_State* lua, MyGUI::Widget* self)
|
void WidgetExtension::initialize(lua_State* lua, MyGUI::Widget* self)
|
||||||
{
|
{
|
||||||
mLua = lua;
|
mLua = lua;
|
||||||
mWidget = self;
|
mWidget = self;
|
||||||
|
updateTemplate();
|
||||||
mWidget->eventChangeCoord += MyGUI::newDelegate(this, &WidgetExtension::updateChildrenCoord);
|
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
@ -71,8 +64,56 @@ namespace LuaUi
|
|||||||
mWidget->eventKeySetFocus.clear();
|
mWidget->eventKeySetFocus.clear();
|
||||||
mWidget->eventKeyLostFocus.clear();
|
mWidget->eventKeyLostFocus.clear();
|
||||||
|
|
||||||
for (WidgetExtension* child : mContent)
|
for (WidgetExtension* w : mChildren)
|
||||||
child->deinitialize();
|
w->deinitialize();
|
||||||
|
for (WidgetExtension* w : mTemplateChildren)
|
||||||
|
w->deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetExtension::attach(WidgetExtension* ext)
|
||||||
|
{
|
||||||
|
ext->widget()->attachToWidget(mSlot->widget());
|
||||||
|
ext->updateCoord();
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetExtension* WidgetExtension::findFirst(std::string_view flagName)
|
||||||
|
{
|
||||||
|
if (externalValue(flagName, false))
|
||||||
|
return this;
|
||||||
|
for (WidgetExtension* w : mChildren)
|
||||||
|
{
|
||||||
|
WidgetExtension* result = w->findFirst(flagName);
|
||||||
|
if (result != nullptr)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetExtension::findAll(std::string_view flagName, std::vector<WidgetExtension*>& result)
|
||||||
|
{
|
||||||
|
if (externalValue(flagName, false))
|
||||||
|
result.push_back(this);
|
||||||
|
for (WidgetExtension* w : mChildren)
|
||||||
|
w->findAll(flagName, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetExtension* WidgetExtension::findFirstInTemplates(std::string_view flagName)
|
||||||
|
{
|
||||||
|
for (WidgetExtension* w : mTemplateChildren)
|
||||||
|
{
|
||||||
|
WidgetExtension* result = w->findFirst(flagName);
|
||||||
|
if (result != nullptr)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<WidgetExtension*> WidgetExtension::findAllInTemplates(std::string_view flagName)
|
||||||
|
{
|
||||||
|
std::vector<WidgetExtension*> result;
|
||||||
|
for (WidgetExtension* w : mTemplateChildren)
|
||||||
|
w->findAll(flagName, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
sol::table WidgetExtension::makeTable() const
|
sol::table WidgetExtension::makeTable() const
|
||||||
@ -91,9 +132,9 @@ namespace LuaUi
|
|||||||
|
|
||||||
sol::object WidgetExtension::mouseEvent(int left, int top, MyGUI::MouseButton button = MyGUI::MouseButton::None) const
|
sol::object WidgetExtension::mouseEvent(int left, int top, MyGUI::MouseButton button = MyGUI::MouseButton::None) const
|
||||||
{
|
{
|
||||||
auto position = osg::Vec2f(left, top);
|
osg::Vec2f position(left, top);
|
||||||
auto absolutePosition = mWidget->getAbsolutePosition();
|
MyGUI::IntPoint absolutePosition = mWidget->getAbsolutePosition();
|
||||||
auto offset = position - osg::Vec2f(absolutePosition.left, absolutePosition.top);
|
osg::Vec2f offset = position - osg::Vec2f(absolutePosition.left, absolutePosition.top);
|
||||||
sol::table table = makeTable();
|
sol::table table = makeTable();
|
||||||
table["position"] = position;
|
table["position"] = position;
|
||||||
table["offset"] = offset;
|
table["offset"] = offset;
|
||||||
@ -101,31 +142,36 @@ namespace LuaUi
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetExtension::addChild(WidgetExtension* ext)
|
void WidgetExtension::setChildren(const std::vector<WidgetExtension*>& children)
|
||||||
{
|
{
|
||||||
mContent.push_back(ext);
|
mChildren.resize(children.size());
|
||||||
|
for (size_t i = 0; i < children.size(); ++i)
|
||||||
|
{
|
||||||
|
mChildren[i] = children[i];
|
||||||
|
attach(mChildren[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetExtension* WidgetExtension::childAt(size_t index) const
|
void WidgetExtension::setTemplateChildren(const std::vector<WidgetExtension*>& children)
|
||||||
{
|
{
|
||||||
return mContent.at(index);
|
mTemplateChildren.resize(children.size());
|
||||||
|
for (size_t i = 0; i < children.size(); ++i)
|
||||||
|
{
|
||||||
|
mTemplateChildren[i] = children[i];
|
||||||
|
mTemplateChildren[i]->widget()->attachToWidget(mWidget);
|
||||||
|
}
|
||||||
|
updateTemplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetExtension::assignChild(size_t index, WidgetExtension* ext)
|
void WidgetExtension::updateTemplate()
|
||||||
{
|
{
|
||||||
if (mContent.size() <= index)
|
WidgetExtension* oldSlot = mSlot;
|
||||||
throw std::logic_error("Invalid widget child index");
|
mSlot = findFirstInTemplates("slot");
|
||||||
mContent[index] = ext;
|
if (mSlot == nullptr)
|
||||||
}
|
mSlot = this;
|
||||||
|
if (mSlot != oldSlot)
|
||||||
WidgetExtension* WidgetExtension::eraseChild(size_t index)
|
for (WidgetExtension* w : mChildren)
|
||||||
{
|
attach(w);
|
||||||
if (mContent.size() <= index)
|
|
||||||
throw std::logic_error("Invalid widget child index");
|
|
||||||
auto it = mContent.begin() + index;
|
|
||||||
WidgetExtension* ext = *it;
|
|
||||||
mContent.erase(it);
|
|
||||||
return ext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetExtension::setCallback(const std::string& name, const LuaUtil::Callback& callback)
|
void WidgetExtension::setCallback(const std::string& name, const LuaUtil::Callback& callback)
|
||||||
@ -150,25 +196,39 @@ namespace LuaUi
|
|||||||
|
|
||||||
void WidgetExtension::updateCoord()
|
void WidgetExtension::updateCoord()
|
||||||
{
|
{
|
||||||
mWidget->setCoord(calculateCoord());
|
MyGUI::IntCoord oldCoord = mWidget->getCoord();
|
||||||
|
MyGUI::IntCoord newCoord = calculateCoord();
|
||||||
|
|
||||||
|
if (oldCoord != newCoord)
|
||||||
|
mWidget->setCoord(newCoord);
|
||||||
|
if (oldCoord.size() != newCoord.size())
|
||||||
|
updateChildrenCoord();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetExtension::setProperties(sol::object props)
|
void WidgetExtension::setProperties(sol::object props)
|
||||||
{
|
{
|
||||||
mAbsoluteCoord = parseProperty(props, "position", MyGUI::IntPoint());
|
mProperties = props;
|
||||||
mAbsoluteCoord = parseProperty(props, "size", MyGUI::IntSize());
|
updateProperties();
|
||||||
mRelativeCoord = parseProperty(props, "relativePosition", MyGUI::FloatPoint());
|
|
||||||
mRelativeCoord = parseProperty(props, "relativeSize", MyGUI::FloatSize());
|
|
||||||
mAnchor = parseProperty(props, "anchor", MyGUI::FloatSize());
|
|
||||||
mWidget->setVisible(parseProperty(props, "visible", true));
|
|
||||||
|
|
||||||
updateCoord();
|
updateCoord();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WidgetExtension::updateChildrenCoord(MyGUI::Widget* _widget)
|
void WidgetExtension::updateProperties()
|
||||||
{
|
{
|
||||||
for (auto& child : mContent)
|
mAbsoluteCoord = propertyValue("position", MyGUI::IntPoint());
|
||||||
child->updateCoord();
|
mAbsoluteCoord = propertyValue("size", MyGUI::IntSize());
|
||||||
|
mRelativeCoord = propertyValue("relativePosition", MyGUI::FloatPoint());
|
||||||
|
mRelativeCoord = propertyValue("relativeSize", MyGUI::FloatSize());
|
||||||
|
mAnchor = propertyValue("anchor", MyGUI::FloatSize());
|
||||||
|
mWidget->setVisible(propertyValue("visible", true));
|
||||||
|
mWidget->setPointer(propertyValue("pointer", std::string("arrow")));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetExtension::updateChildrenCoord()
|
||||||
|
{
|
||||||
|
for (WidgetExtension* w : mTemplateChildren)
|
||||||
|
w->updateCoord();
|
||||||
|
for (WidgetExtension* w : mChildren)
|
||||||
|
w->updateCoord();
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntSize WidgetExtension::calculateSize()
|
MyGUI::IntSize WidgetExtension::calculateSize()
|
||||||
@ -199,6 +259,13 @@ namespace LuaUi
|
|||||||
return newCoord;
|
return newCoord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WidgetExtension::triggerEvent(std::string_view name, const sol::object& argument = sol::nil) const
|
||||||
|
{
|
||||||
|
auto it = mCallbacks.find(name);
|
||||||
|
if (it != mCallbacks.end())
|
||||||
|
it->second(argument, mLayout);
|
||||||
|
}
|
||||||
|
|
||||||
void WidgetExtension::keyPress(MyGUI::Widget*, MyGUI::KeyCode code, MyGUI::Char ch)
|
void WidgetExtension::keyPress(MyGUI::Widget*, MyGUI::KeyCode code, MyGUI::Char ch)
|
||||||
{
|
{
|
||||||
if (code == MyGUI::KeyCode::None)
|
if (code == MyGUI::KeyCode::None)
|
||||||
|
@ -26,35 +26,57 @@ namespace LuaUi
|
|||||||
// must be called after before destroying the underlying MyGUI::Widget
|
// must be called after before destroying the underlying MyGUI::Widget
|
||||||
virtual void deinitialize();
|
virtual void deinitialize();
|
||||||
|
|
||||||
void addChild(WidgetExtension* ext);
|
|
||||||
WidgetExtension* childAt(size_t index) const;
|
|
||||||
void assignChild(size_t index, WidgetExtension* ext);
|
|
||||||
WidgetExtension* eraseChild(size_t index);
|
|
||||||
size_t childCount() const { return mContent.size(); }
|
|
||||||
|
|
||||||
MyGUI::Widget* widget() const { return mWidget; }
|
MyGUI::Widget* widget() const { return mWidget; }
|
||||||
|
|
||||||
|
const std::vector<WidgetExtension*>& children() { return mChildren; }
|
||||||
|
void setChildren(const std::vector<WidgetExtension*>&);
|
||||||
|
|
||||||
|
const std::vector<WidgetExtension*>& templateChildren() { return mTemplateChildren; }
|
||||||
|
void setTemplateChildren(const std::vector<WidgetExtension*>&);
|
||||||
|
|
||||||
void setCallback(const std::string&, const LuaUtil::Callback&);
|
void setCallback(const std::string&, const LuaUtil::Callback&);
|
||||||
void clearCallbacks();
|
void clearCallbacks();
|
||||||
|
|
||||||
virtual void setProperties(sol::object);
|
void setProperties(sol::object);
|
||||||
|
void setTemplateProperties(sol::object props) { mTemplateProperties = props; }
|
||||||
|
|
||||||
|
void setExternal(sol::object external) { mExternal = external; }
|
||||||
|
|
||||||
MyGUI::IntCoord forcedCoord();
|
MyGUI::IntCoord forcedCoord();
|
||||||
void setForcedCoord(const MyGUI::IntCoord& offset);
|
void setForcedCoord(const MyGUI::IntCoord& offset);
|
||||||
void updateCoord();
|
void updateCoord();
|
||||||
|
|
||||||
|
const sol::table& getLayout() { return mLayout; }
|
||||||
void setLayout(const sol::table& layout) { mLayout = layout; }
|
void setLayout(const sol::table& layout) { mLayout = layout; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T externalValue(std::string_view name, const T& defaultValue)
|
||||||
|
{
|
||||||
|
return parseExternal(mExternal, name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
sol::table makeTable() const;
|
sol::table makeTable() const;
|
||||||
sol::object keyEvent(MyGUI::KeyCode) const;
|
sol::object keyEvent(MyGUI::KeyCode) const;
|
||||||
sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const;
|
sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const;
|
||||||
|
|
||||||
virtual MyGUI::IntSize calculateSize();
|
virtual MyGUI::IntSize calculateSize();
|
||||||
virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size);
|
virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size);
|
||||||
MyGUI::IntCoord calculateCoord();
|
MyGUI::IntCoord calculateCoord();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T propertyValue(std::string_view name, const T& defaultValue)
|
||||||
|
{
|
||||||
|
return parseProperty(mProperties, mTemplateProperties, name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetExtension* findFirstInTemplates(std::string_view flagName);
|
||||||
|
std::vector<WidgetExtension*> findAllInTemplates(std::string_view flagName);
|
||||||
|
|
||||||
|
virtual void updateTemplate();
|
||||||
|
virtual void updateProperties();
|
||||||
|
|
||||||
void triggerEvent(std::string_view name, const sol::object& argument) const;
|
void triggerEvent(std::string_view name, const sol::object& argument) const;
|
||||||
|
|
||||||
// offsets the position and size, used only in C++ widget code
|
// offsets the position and size, used only in C++ widget code
|
||||||
@ -71,12 +93,21 @@ namespace LuaUi
|
|||||||
// use lua_State* instead of sol::state_view because MyGUI requires a default constructor
|
// use lua_State* instead of sol::state_view because MyGUI requires a default constructor
|
||||||
lua_State* mLua;
|
lua_State* mLua;
|
||||||
MyGUI::Widget* mWidget;
|
MyGUI::Widget* mWidget;
|
||||||
|
std::vector<WidgetExtension*> mChildren;
|
||||||
std::vector<WidgetExtension*> mContent;
|
std::vector<WidgetExtension*> mTemplateChildren;
|
||||||
|
WidgetExtension* mSlot;
|
||||||
std::map<std::string, LuaUtil::Callback, std::less<>> mCallbacks;
|
std::map<std::string, LuaUtil::Callback, std::less<>> mCallbacks;
|
||||||
sol::table mLayout;
|
sol::table mLayout;
|
||||||
|
sol::object mProperties;
|
||||||
|
sol::object mTemplateProperties;
|
||||||
|
sol::object mExternal;
|
||||||
|
|
||||||
void updateChildrenCoord(MyGUI::Widget*);
|
void attach(WidgetExtension* ext);
|
||||||
|
|
||||||
|
WidgetExtension* findFirst(std::string_view name);
|
||||||
|
void findAll(std::string_view flagName, std::vector<WidgetExtension*>& result);
|
||||||
|
|
||||||
|
void updateChildrenCoord();
|
||||||
|
|
||||||
void keyPress(MyGUI::Widget*, MyGUI::KeyCode, MyGUI::Char);
|
void keyPress(MyGUI::Widget*, MyGUI::KeyCode, MyGUI::Char);
|
||||||
void keyRelease(MyGUI::Widget*, MyGUI::KeyCode);
|
void keyRelease(MyGUI::Widget*, MyGUI::KeyCode);
|
||||||
|
@ -11,46 +11,40 @@ namespace LuaUi
|
|||||||
, mMoveResize()
|
, mMoveResize()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void LuaWindow::initialize()
|
void LuaWindow::updateTemplate()
|
||||||
{
|
{
|
||||||
WidgetExtension::initialize();
|
for (auto& [w, _] : mActionWidgets)
|
||||||
|
|
||||||
assignWidget(mCaption, "Caption");
|
|
||||||
if (mCaption)
|
|
||||||
{
|
|
||||||
mCaption->eventMouseButtonPressed += MyGUI::newDelegate(this, &LuaWindow::notifyMousePress);
|
|
||||||
mCaption->eventMouseDrag += MyGUI::newDelegate(this, &LuaWindow::notifyMouseDrag);
|
|
||||||
}
|
|
||||||
for (auto w : getSkinWidgetsByName("Action"))
|
|
||||||
{
|
|
||||||
w->eventMouseButtonPressed += MyGUI::newDelegate(this, &LuaWindow::notifyMousePress);
|
|
||||||
w->eventMouseDrag += MyGUI::newDelegate(this, &LuaWindow::notifyMouseDrag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LuaWindow::deinitialize()
|
|
||||||
{
|
|
||||||
WidgetExtension::deinitialize();
|
|
||||||
|
|
||||||
if (mCaption)
|
|
||||||
{
|
|
||||||
mCaption->eventMouseButtonPressed.clear();
|
|
||||||
mCaption->eventMouseDrag.m_event.clear();
|
|
||||||
}
|
|
||||||
for (auto w : getSkinWidgetsByName("Action"))
|
|
||||||
{
|
{
|
||||||
w->eventMouseButtonPressed.clear();
|
w->eventMouseButtonPressed.clear();
|
||||||
w->eventMouseDrag.m_event.clear();
|
w->eventMouseDrag.m_event.clear();
|
||||||
}
|
}
|
||||||
|
mActionWidgets.clear();
|
||||||
|
|
||||||
|
WidgetExtension* captionWidget = findFirstInTemplates("caption");
|
||||||
|
mCaption = dynamic_cast<LuaText*>(captionWidget);
|
||||||
|
|
||||||
|
if (mCaption)
|
||||||
|
mActionWidgets.emplace(mCaption->widget(), mCaption);
|
||||||
|
for (WidgetExtension* ext : findAllInTemplates("action"))
|
||||||
|
mActionWidgets.emplace(ext->widget(), ext);
|
||||||
|
|
||||||
|
for (auto& [w, _] : mActionWidgets)
|
||||||
|
{
|
||||||
|
w->eventMouseButtonPressed += MyGUI::newDelegate(this, &LuaWindow::notifyMousePress);
|
||||||
|
w->eventMouseDrag += MyGUI::newDelegate(this, &LuaWindow::notifyMouseDrag);
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetExtension::updateTemplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaWindow::setProperties(sol::object props)
|
void LuaWindow::updateProperties()
|
||||||
{
|
{
|
||||||
if (mCaption)
|
if (mCaption)
|
||||||
mCaption->setCaption(parseProperty(props, "caption", std::string()));
|
mCaption->setCaption(propertyValue("caption", std::string()));
|
||||||
mMoveResize = MyGUI::IntCoord();
|
mMoveResize = MyGUI::IntCoord();
|
||||||
setForcedCoord(mMoveResize);
|
setForcedCoord(mMoveResize);
|
||||||
WidgetExtension::setProperties(props);
|
|
||||||
|
WidgetExtension::updateProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaWindow::notifyMousePress(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
|
void LuaWindow::notifyMousePress(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
|
||||||
@ -61,10 +55,11 @@ namespace LuaUi
|
|||||||
mPreviousMouse.left = left;
|
mPreviousMouse.left = left;
|
||||||
mPreviousMouse.top = top;
|
mPreviousMouse.top = top;
|
||||||
|
|
||||||
if (sender->isUserString("Scale"))
|
WidgetExtension* ext = mActionWidgets[sender];
|
||||||
mChangeScale = MyGUI::IntCoord::parse(sender->getUserString("Scale"));
|
|
||||||
else
|
mChangeScale = MyGUI::IntCoord(
|
||||||
mChangeScale = MyGUI::IntCoord(1, 1, 0, 0);
|
ext->externalValue("move", MyGUI::IntPoint(1, 1)),
|
||||||
|
ext->externalValue("resize", MyGUI::IntSize(0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaWindow::notifyMouseDrag(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
|
void LuaWindow::notifyMouseDrag(MyGUI::Widget* sender, int left, int top, MyGUI::MouseButton id)
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include <MyGUI_TextBox.h>
|
|
||||||
|
|
||||||
#include "widget.hpp"
|
#include "widget.hpp"
|
||||||
|
#include "text.hpp"
|
||||||
|
|
||||||
namespace LuaUi
|
namespace LuaUi
|
||||||
{
|
{
|
||||||
@ -15,20 +14,18 @@ namespace LuaUi
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
LuaWindow();
|
LuaWindow();
|
||||||
virtual void setProperties(sol::object) override;
|
virtual void updateTemplate() override;
|
||||||
|
virtual void updateProperties() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// \todo replace with LuaText when skins are properly implemented
|
LuaText* mCaption;
|
||||||
MyGUI::TextBox* mCaption;
|
std::map<MyGUI::Widget*, WidgetExtension*> mActionWidgets;
|
||||||
MyGUI::IntPoint mPreviousMouse;
|
MyGUI::IntPoint mPreviousMouse;
|
||||||
MyGUI::IntCoord mChangeScale;
|
MyGUI::IntCoord mChangeScale;
|
||||||
|
|
||||||
MyGUI::IntCoord mMoveResize;
|
MyGUI::IntCoord mMoveResize;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialize() override;
|
|
||||||
virtual void deinitialize() override;
|
|
||||||
|
|
||||||
void notifyMousePress(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
void notifyMousePress(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
||||||
void notifyMouseDrag(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
void notifyMouseDrag(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,9 @@ Every widget is defined by a layout, which is a Lua table with the following fie
|
|||||||
4. `content`: a Content (`openmw.ui.content`), which contains layouts for the children of this widget.
|
4. `content`: a Content (`openmw.ui.content`), which contains layouts for the children of this widget.
|
||||||
5. | `name`: an arbitrary string, the only limitatiion is it being unique within a `Content`.
|
5. | `name`: an arbitrary string, the only limitatiion is it being unique within a `Content`.
|
||||||
| Helpful for navigatilng through the layouts.
|
| Helpful for navigatilng through the layouts.
|
||||||
6. `layer`: only applies for the root widget.
|
6. `layer`: only applies for the root widget. (Windows, HUD, etc)
|
||||||
|
7. `template`: a Lua table which pre-defines a layout for this widget. See Templates below for more details.
|
||||||
|
8. `external`: similar to properties, but they affect how other widgets interact with this one. See the widget pages for details.
|
||||||
|
|
||||||
Layers
|
Layers
|
||||||
------
|
------
|
||||||
@ -57,7 +59,14 @@ A container holding all the widget's children. It has a few important difference
|
|||||||
| While there is nothing preventing you from changing the `name` of a table inside a content, it is not supported, and will lead to undefined behaviour.
|
| While there is nothing preventing you from changing the `name` of a table inside a content, it is not supported, and will lead to undefined behaviour.
|
||||||
| If you have to change the name, assign a new table to the index instead.
|
| If you have to change the name, assign a new table to the index instead.
|
||||||
|
|
||||||
.. TODO: Talk about skins/templates here when they are ready
|
Templates
|
||||||
|
---------
|
||||||
|
|
||||||
|
Templates are Lua tables with the following (optional) fields:
|
||||||
|
|
||||||
|
1. `props`: Same as in layouts, defines the behaviour of this widget. Can be overwritten by `props` values in the layout.
|
||||||
|
2. | `content`: Extra children to add to the widget. For example, the frame and caption for Window widgets.
|
||||||
|
| Contains normal layouts
|
||||||
|
|
||||||
Events
|
Events
|
||||||
------
|
------
|
||||||
@ -97,7 +106,7 @@ Example
|
|||||||
local layout = {
|
local layout = {
|
||||||
layers = 'Windows',
|
layers = 'Windows',
|
||||||
type = ui.TYPE.Window,
|
type = ui.TYPE.Window,
|
||||||
skin = 'MW_Window', -- TODO: replace all skins here when they are properly implemented
|
template = { skin = 'MW_Window' }, -- TODO: replace all skins here when they are re-implemented in Lua
|
||||||
props = {
|
props = {
|
||||||
size = v2(200, 250),
|
size = v2(200, 250),
|
||||||
-- put the window in the middle of the screen
|
-- put the window in the middle of the screen
|
||||||
@ -107,7 +116,7 @@ Example
|
|||||||
content = ui.content {
|
content = ui.content {
|
||||||
{
|
{
|
||||||
type = ui.TYPE.Text,
|
type = ui.TYPE.Text,
|
||||||
skin = 'SandText',
|
template = { skin = 'SandText' },
|
||||||
props = {
|
props = {
|
||||||
caption = 'Input password',
|
caption = 'Input password',
|
||||||
relativePosition = v2(0.5, 0),
|
relativePosition = v2(0.5, 0),
|
||||||
@ -117,7 +126,7 @@ Example
|
|||||||
{
|
{
|
||||||
name = 'input',
|
name = 'input',
|
||||||
type = ui.TYPE.TextEdit,
|
type = ui.TYPE.TextEdit,
|
||||||
skin = "MW_TextEdit",
|
template = { skin = "MW_TextEdit" },
|
||||||
props = {
|
props = {
|
||||||
caption = '',
|
caption = '',
|
||||||
relativePosition = v2(0.5, 0.5),
|
relativePosition = v2(0.5, 0.5),
|
||||||
@ -129,7 +138,7 @@ Example
|
|||||||
{
|
{
|
||||||
name = 'submit',
|
name = 'submit',
|
||||||
type = ui.TYPE.Text, -- TODO: replace with button when implemented
|
type = ui.TYPE.Text, -- TODO: replace with button when implemented
|
||||||
skin = "MW_Button",
|
template = { skin = "MW_Button" },
|
||||||
props = {
|
props = {
|
||||||
caption = 'Submit',
|
caption = 'Submit',
|
||||||
-- position at the bottom
|
-- position at the bottom
|
||||||
|
@ -33,6 +33,8 @@ Properties
|
|||||||
- boolean (true)
|
- boolean (true)
|
||||||
- Defines if the widget is visible
|
- Defines if the widget is visible
|
||||||
|
|
||||||
|
.. TODO: document the mouse pointer property, when API for reading / adding pointer types is available
|
||||||
|
|
||||||
Events
|
Events
|
||||||
------
|
------
|
||||||
|
|
||||||
@ -75,3 +77,18 @@ Events
|
|||||||
* - textInput
|
* - textInput
|
||||||
- string
|
- string
|
||||||
- Text input with this widget in focus
|
- Text input with this widget in focus
|
||||||
|
|
||||||
|
External
|
||||||
|
--------
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
:widths: 20 20 60
|
||||||
|
|
||||||
|
* - name
|
||||||
|
- type (default value)
|
||||||
|
- description
|
||||||
|
* - slot
|
||||||
|
- bool (false)
|
||||||
|
- | Only applies for template content (ignored in layout content).
|
||||||
|
| If true, all the widgets defined in layout content will be rendered as children of this widget.
|
||||||
|
| Only one widget per template can have slot = true (others will be ignored).
|
@ -15,4 +15,8 @@
|
|||||||
<Resource type="ResourceSkin" name="ImageBox" size="16 16">
|
<Resource type="ResourceSkin" name="ImageBox" size="16 16">
|
||||||
<BasisSkin type="MainSkin" offset="0 0 16 16"/>
|
<BasisSkin type="MainSkin" offset="0 0 16 16"/>
|
||||||
</Resource>
|
</Resource>
|
||||||
|
|
||||||
|
<Resource type="ResourceSkin" name="LuaImage">
|
||||||
|
<BasisSkin type="LuaTileRect"/>
|
||||||
|
</Resource>
|
||||||
</MyGUI>
|
</MyGUI>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user