mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 21:35:24 +00:00
Merge branch 'mw_templates' into 'master'
MWUI interface (resolve https://gitlab.com/OpenMW/openmw/-/issues/6594) Closes #6594 See merge request OpenMW/openmw!1702
This commit is contained in:
commit
c649d94fee
@ -82,38 +82,6 @@ namespace MWLua
|
|||||||
std::shared_ptr<LuaUi::Element> mElement;
|
std::shared_ptr<LuaUi::Element> mElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InsertLayerAction final : public LuaManager::Action
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
InsertLayerAction(std::string_view name, size_t index,
|
|
||||||
LuaUi::Layer::Options options, LuaUtil::LuaState* state)
|
|
||||||
: Action(state)
|
|
||||||
, mName(name)
|
|
||||||
, mIndex(index)
|
|
||||||
, mOptions(options)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void apply(WorldView&) const override
|
|
||||||
{
|
|
||||||
LuaUi::Layer::insert(mIndex, mName, mOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const override
|
|
||||||
{
|
|
||||||
std::string result("Insert UI layer \"");
|
|
||||||
result += mName;
|
|
||||||
result += "\" at \"";
|
|
||||||
result += mIndex;
|
|
||||||
result += "\"";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string mName;
|
|
||||||
size_t mIndex;
|
|
||||||
LuaUi::Layer::Options mOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lua arrays index from 1
|
// Lua arrays index from 1
|
||||||
inline size_t fromLuaIndex(size_t i) { return i - 1; }
|
inline size_t fromLuaIndex(size_t i) { return i - 1; }
|
||||||
inline size_t toLuaIndex(size_t i) { return i + 1; }
|
inline size_t toLuaIndex(size_t i) { return i + 1; }
|
||||||
@ -252,6 +220,18 @@ namespace MWLua
|
|||||||
context.mLuaManager->addAction(std::make_unique<UiAction>(UiAction::CREATE, element, context.mLua));
|
context.mLuaManager->addAction(std::make_unique<UiAction>(UiAction::CREATE, element, context.mLua));
|
||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
|
api["updateAll"] = [context]()
|
||||||
|
{
|
||||||
|
LuaUi::Element::forEach([](LuaUi::Element* e) { e->mUpdate = true; });
|
||||||
|
context.mLuaManager->addAction([]()
|
||||||
|
{
|
||||||
|
LuaUi::Element::forEach([](LuaUi::Element* e) { e->update(); });
|
||||||
|
}, "Update all UI elements");
|
||||||
|
};
|
||||||
|
api["_getMenuTransparency"] = []()
|
||||||
|
{
|
||||||
|
return Settings::Manager::getFloat("menu transparency", "GUI");
|
||||||
|
};
|
||||||
|
|
||||||
auto uiLayer = context.mLua->sol().new_usertype<LuaUi::Layer>("UiLayer");
|
auto uiLayer = context.mLua->sol().new_usertype<LuaUi::Layer>("UiLayer");
|
||||||
uiLayer["name"] = sol::property([](LuaUi::Layer& self) { return self.name(); });
|
uiLayer["name"] = sol::property([](LuaUi::Layer& self) { return self.name(); });
|
||||||
@ -287,7 +267,7 @@ namespace MWLua
|
|||||||
if (index == LuaUi::Layer::count())
|
if (index == LuaUi::Layer::count())
|
||||||
throw std::logic_error(std::string("Layer not found"));
|
throw std::logic_error(std::string("Layer not found"));
|
||||||
index++;
|
index++;
|
||||||
context.mLuaManager->addAction(std::make_unique<InsertLayerAction>(name, index, options, context.mLua));
|
context.mLuaManager->addAction([=]() { LuaUi::Layer::insert(index, name, options); }, "Insert UI layer");
|
||||||
};
|
};
|
||||||
layers["insertBefore"] = [context](std::string_view beforename, std::string_view name, const sol::object& opt)
|
layers["insertBefore"] = [context](std::string_view beforename, std::string_view name, const sol::object& opt)
|
||||||
{
|
{
|
||||||
@ -296,7 +276,7 @@ namespace MWLua
|
|||||||
size_t index = LuaUi::Layer::indexOf(beforename);
|
size_t index = LuaUi::Layer::indexOf(beforename);
|
||||||
if (index == LuaUi::Layer::count())
|
if (index == LuaUi::Layer::count())
|
||||||
throw std::logic_error(std::string("Layer not found"));
|
throw std::logic_error(std::string("Layer not found"));
|
||||||
context.mLuaManager->addAction(std::make_unique<InsertLayerAction>(name, index, options, context.mLua));
|
context.mLuaManager->addAction([=]() { LuaUi::Layer::insert(index, name, options); }, "Insert UI layer");
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
auto pairs = [layers](const sol::object&)
|
auto pairs = [layers](const sol::object&)
|
||||||
|
@ -20,9 +20,11 @@ namespace LuaUi
|
|||||||
constexpr std::string_view external = "external";
|
constexpr std::string_view external = "external";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string defaultWidgetType = "LuaWidget";
|
||||||
|
|
||||||
std::string widgetType(const sol::table& layout)
|
std::string widgetType(const sol::table& layout)
|
||||||
{
|
{
|
||||||
return layout.get_or(LayoutKeys::type, std::string("LuaWidget"));
|
return layout.get_or(LayoutKeys::type, defaultWidgetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyWidget(LuaUi::WidgetExtension* ext)
|
void destroyWidget(LuaUi::WidgetExtension* ext)
|
||||||
@ -74,11 +76,6 @@ namespace LuaUi
|
|||||||
|
|
||||||
void setTemplate(WidgetExtension* ext, const sol::object& templateLayout)
|
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);
|
sol::object props = LuaUtil::getFieldOrNil(templateLayout, LayoutKeys::props);
|
||||||
ext->setTemplateProperties(props);
|
ext->setTemplateProperties(props);
|
||||||
sol::object content = LuaUtil::getFieldOrNil(templateLayout, LayoutKeys::content);
|
sol::object content = LuaUtil::getFieldOrNil(templateLayout, LayoutKeys::content);
|
||||||
@ -107,13 +104,22 @@ namespace LuaUi
|
|||||||
|
|
||||||
WidgetExtension* createWidget(const sol::table& layout)
|
WidgetExtension* createWidget(const sol::table& layout)
|
||||||
{
|
{
|
||||||
std::string type = widgetType(layout);
|
sol::object typeField = LuaUtil::getFieldOrNil(layout, LayoutKeys::type);
|
||||||
std::string name = layout.get_or(LayoutKeys::name, std::string());
|
std::string type = LuaUtil::getValueOrDefault(typeField, defaultWidgetType);
|
||||||
|
sol::object templateTypeField = LuaUtil::getFieldOrNil(layout, LayoutKeys::templateLayout, LayoutKeys::type);
|
||||||
|
if (templateTypeField != sol::nil)
|
||||||
|
{
|
||||||
|
std::string templateType = LuaUtil::getValueOrDefault(templateTypeField, defaultWidgetType);
|
||||||
|
if (typeField != sol::nil && templateType != type)
|
||||||
|
throw std::logic_error(std::string("Template layout type ") + type
|
||||||
|
+ std::string(" doesn't match template type ") + templateType);
|
||||||
|
type = templateType;
|
||||||
|
}
|
||||||
static auto widgetTypeMap = widgetTypeToName();
|
static auto widgetTypeMap = widgetTypeToName();
|
||||||
if (widgetTypeMap.find(type) == widgetTypeMap.end())
|
if (widgetTypeMap.find(type) == widgetTypeMap.end())
|
||||||
throw std::logic_error(std::string("Invalid widget type ") += type);
|
throw std::logic_error(std::string("Invalid widget type ") += type);
|
||||||
|
|
||||||
|
std::string name = layout.get_or(LayoutKeys::name, std::string());
|
||||||
MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT(
|
MyGUI::Widget* widget = MyGUI::Gui::getInstancePtr()->createWidgetT(
|
||||||
type, "",
|
type, "",
|
||||||
MyGUI::IntCoord(), MyGUI::Align::Default,
|
MyGUI::IntCoord(), MyGUI::Align::Default,
|
||||||
|
@ -9,6 +9,13 @@ namespace LuaUi
|
|||||||
{
|
{
|
||||||
static std::shared_ptr<Element> make(sol::table layout);
|
static std::shared_ptr<Element> make(sol::table layout);
|
||||||
|
|
||||||
|
template<class Callback>
|
||||||
|
static void forEach(Callback callback)
|
||||||
|
{
|
||||||
|
for(auto& [e, _] : sAllElements)
|
||||||
|
callback(e);
|
||||||
|
}
|
||||||
|
|
||||||
WidgetExtension* mRoot;
|
WidgetExtension* mRoot;
|
||||||
WidgetExtension* mAttachedTo;
|
WidgetExtension* mAttachedTo;
|
||||||
sol::table mLayout;
|
sol::table mLayout;
|
||||||
|
@ -56,24 +56,25 @@ namespace LuaUi
|
|||||||
MyGUI::IntSize flexSize = calculateSize();
|
MyGUI::IntSize flexSize = calculateSize();
|
||||||
int growSize = 0;
|
int growSize = 0;
|
||||||
float growFactor = 0;
|
float growFactor = 0;
|
||||||
if (totalGrow > 0)
|
if (totalGrow > 0 && !mAutoSized)
|
||||||
{
|
{
|
||||||
growSize = primary(flexSize) - primary(childrenSize);
|
growSize = primary(flexSize) - primary(childrenSize);
|
||||||
growFactor = growSize / totalGrow;
|
growFactor = growSize / totalGrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntPoint childPosition;
|
MyGUI::IntPoint childPosition;
|
||||||
primary(childPosition) = alignSize(primary(flexSize) - growSize, primary(childrenSize), mAlign);
|
primary(childPosition) = alignSize(primary(flexSize) - growSize, primary(childrenSize), mAlign);
|
||||||
secondary(childPosition) = alignSize(secondary(flexSize), secondary(childrenSize), mArrange);
|
|
||||||
for (auto* w : children())
|
for (auto* w : children())
|
||||||
{
|
{
|
||||||
|
MyGUI::IntSize size = w->calculateSize();
|
||||||
|
secondary(childPosition) = alignSize(secondary(flexSize), secondary(size), mArrange);
|
||||||
w->forcePosition(childPosition);
|
w->forcePosition(childPosition);
|
||||||
MyGUI::IntSize size = w->widget()->getSize();
|
|
||||||
primary(size) += static_cast<int>(growFactor * getGrow(w));
|
primary(size) += static_cast<int>(growFactor * getGrow(w));
|
||||||
w->forceSize(size);
|
w->forceSize(size);
|
||||||
primary(childPosition) += primary(size);
|
primary(childPosition) += primary(size);
|
||||||
|
w->updateCoord();
|
||||||
}
|
}
|
||||||
WidgetExtension::updateProperties();
|
WidgetExtension::updateChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntSize LuaFlex::calculateSize()
|
MyGUI::IntSize LuaFlex::calculateSize()
|
||||||
@ -85,4 +86,10 @@ namespace LuaUi
|
|||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaFlex::updateCoord()
|
||||||
|
{
|
||||||
|
updateChildren();
|
||||||
|
WidgetExtension::updateCoord();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace LuaUi
|
|||||||
{
|
{
|
||||||
return MyGUI::IntSize();
|
return MyGUI::IntSize();
|
||||||
}
|
}
|
||||||
|
void updateCoord() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mHorizontal;
|
bool mHorizontal;
|
||||||
|
@ -197,10 +197,13 @@ namespace LuaUi
|
|||||||
MyGUI::IntSize slotSize = mSlot->widget()->getSize();
|
MyGUI::IntSize slotSize = mSlot->widget()->getSize();
|
||||||
MyGUI::IntPoint slotPosition = mSlot->widget()->getAbsolutePosition() - widget()->getAbsolutePosition();
|
MyGUI::IntPoint slotPosition = mSlot->widget()->getAbsolutePosition() - widget()->getAbsolutePosition();
|
||||||
MyGUI::IntCoord slotCoord(slotPosition, slotSize);
|
MyGUI::IntCoord slotCoord(slotPosition, slotSize);
|
||||||
if (mWidget->getSubWidgetMain())
|
MyGUI::Widget* clientWidget = mWidget->getClientWidget();
|
||||||
mWidget->getSubWidgetMain()->setCoord(slotCoord);
|
if (!clientWidget)
|
||||||
if (mWidget->getSubWidgetText())
|
clientWidget = mWidget;
|
||||||
mWidget->getSubWidgetText()->setCoord(slotCoord);
|
if (clientWidget->getSubWidgetMain())
|
||||||
|
clientWidget->getSubWidgetMain()->setCoord(slotCoord);
|
||||||
|
if (clientWidget->getSubWidgetText())
|
||||||
|
clientWidget->getSubWidgetText()->setCoord(slotCoord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,8 +253,7 @@ namespace LuaUi
|
|||||||
|
|
||||||
if (oldCoord != newCoord)
|
if (oldCoord != newCoord)
|
||||||
mWidget->setCoord(newCoord);
|
mWidget->setCoord(newCoord);
|
||||||
if (oldCoord.size() != newCoord.size())
|
updateChildrenCoord();
|
||||||
updateChildrenCoord();
|
|
||||||
if (oldCoord != newCoord && mOnCoordChange.has_value())
|
if (oldCoord != newCoord && mOnCoordChange.has_value())
|
||||||
mOnCoordChange.value()(this, newCoord);
|
mOnCoordChange.value()(this, newCoord);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ namespace LuaUi
|
|||||||
void forcePosition(const MyGUI::IntPoint& pos);
|
void forcePosition(const MyGUI::IntPoint& pos);
|
||||||
void clearForced();
|
void clearForced();
|
||||||
|
|
||||||
void updateCoord();
|
virtual void updateCoord();
|
||||||
|
|
||||||
const sol::table& getLayout() { return mLayout; }
|
const sol::table& getLayout() { return mLayout; }
|
||||||
void setLayout(const sol::table& layout) { mLayout = layout; }
|
void setLayout(const sol::table& layout) { mLayout = layout; }
|
||||||
|
@ -67,3 +67,4 @@ cd $FILES_DIR/builtin_scripts
|
|||||||
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR openmw_aux/*lua
|
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR openmw_aux/*lua
|
||||||
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR scripts/omw/ai.lua
|
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR scripts/omw/ai.lua
|
||||||
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR scripts/omw/camera.lua
|
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR scripts/omw/camera.lua
|
||||||
|
$DOCUMENTOR_PATH -f doc -d $OUTPUT_DIR scripts/omw/mwui/init.lua
|
||||||
|
@ -23,8 +23,10 @@ Lua API reference
|
|||||||
openmw_aux_calendar
|
openmw_aux_calendar
|
||||||
openmw_aux_util
|
openmw_aux_util
|
||||||
openmw_aux_time
|
openmw_aux_time
|
||||||
|
openmw_aux_ui
|
||||||
interface_ai
|
interface_ai
|
||||||
interface_camera
|
interface_camera
|
||||||
|
interface_mwui
|
||||||
iterables
|
iterables
|
||||||
|
|
||||||
|
|
||||||
@ -87,6 +89,8 @@ Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can overrid
|
|||||||
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|
||||||
|:ref:`openmw_aux.time <Package openmw_aux.time>` | everywhere | | Timers and game time utils |
|
|:ref:`openmw_aux.time <Package openmw_aux.time>` | everywhere | | Timers and game time utils |
|
||||||
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|
||||||
|
|:ref:`openmw_aux.ui <Package openmw_aux.ui>` | by player scripts | | User interface utils |
|
||||||
|
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|
||||||
|
|
||||||
**Interfaces of built-in scripts**
|
**Interfaces of built-in scripts**
|
||||||
|
|
||||||
|
6
docs/source/reference/lua-scripting/interface_mwui.rst
Normal file
6
docs/source/reference/lua-scripting/interface_mwui.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Interface MWUI
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
:file: generated_html/scripts_omw_mwui_init.html
|
||||||
|
|
5
docs/source/reference/lua-scripting/openmw_aux_ui.rst
Normal file
5
docs/source/reference/lua-scripting/openmw_aux_ui.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Package openmw_aux.ui
|
||||||
|
=======================
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
:file: generated_html/openmw_aux_ui.html
|
@ -8,6 +8,7 @@ set(LUA_BUILTIN_FILES
|
|||||||
openmw_aux/util.lua
|
openmw_aux/util.lua
|
||||||
openmw_aux/time.lua
|
openmw_aux/time.lua
|
||||||
openmw_aux/calendar.lua
|
openmw_aux/calendar.lua
|
||||||
|
openmw_aux/ui.lua
|
||||||
|
|
||||||
scripts/omw/ai.lua
|
scripts/omw/ai.lua
|
||||||
scripts/omw/camera.lua
|
scripts/omw/camera.lua
|
||||||
@ -18,9 +19,15 @@ set(LUA_BUILTIN_FILES
|
|||||||
scripts/omw/console/local.lua
|
scripts/omw/console/local.lua
|
||||||
|
|
||||||
l10n/Calendar/en.yaml
|
l10n/Calendar/en.yaml
|
||||||
|
|
||||||
|
scripts/omw/mwui/constants.lua
|
||||||
|
scripts/omw/mwui/borders.lua
|
||||||
|
scripts/omw/mwui/box.lua
|
||||||
|
scripts/omw/mwui/text.lua
|
||||||
|
scripts/omw/mwui/textEdit.lua
|
||||||
|
scripts/omw/mwui/init.lua
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach (f ${LUA_BUILTIN_FILES})
|
foreach (f ${LUA_BUILTIN_FILES})
|
||||||
copy_resource_file("${CMAKE_CURRENT_SOURCE_DIR}/${f}" "${OPENMW_RESOURCES_ROOT}" "resources/vfs/${f}")
|
copy_resource_file("${CMAKE_CURRENT_SOURCE_DIR}/${f}" "${OPENMW_RESOURCES_ROOT}" "resources/vfs/${f}")
|
||||||
endforeach (f)
|
endforeach (f)
|
||||||
|
|
||||||
|
@ -3,3 +3,4 @@ NPC,CREATURE: scripts/omw/ai.lua
|
|||||||
PLAYER: scripts/omw/console/player.lua
|
PLAYER: scripts/omw/console/player.lua
|
||||||
GLOBAL: scripts/omw/console/global.lua
|
GLOBAL: scripts/omw/console/global.lua
|
||||||
CUSTOM: scripts/omw/console/local.lua
|
CUSTOM: scripts/omw/console/local.lua
|
||||||
|
PLAYER: scripts/omw/mwui/init.lua
|
||||||
|
36
files/builtin_scripts/openmw_aux/ui.lua
Normal file
36
files/builtin_scripts/openmw_aux/ui.lua
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
local ui = require('openmw.ui')
|
||||||
|
|
||||||
|
---
|
||||||
|
-- `openmw_aux.ui` defines utility functions for UI.
|
||||||
|
-- Implementation can be found in `resources/vfs/openmw_aux/ui.lua`.
|
||||||
|
-- @module ui
|
||||||
|
-- @usage local auxUi = require('openmw_aux.ui')
|
||||||
|
local aux_ui = {}
|
||||||
|
|
||||||
|
local function deepContentCopy(content)
|
||||||
|
local result = ui.content{}
|
||||||
|
for _, v in ipairs(content) do
|
||||||
|
result:add(aux_ui.deepLayoutCopy(v))
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @function [parent=#ui] templates
|
||||||
|
-- @param #table layout
|
||||||
|
-- @return #table copied layout
|
||||||
|
function aux_ui.deepLayoutCopy(layout)
|
||||||
|
local result = {}
|
||||||
|
for k, v in pairs(layout) do
|
||||||
|
if k == 'content' then
|
||||||
|
result[k] = deepContentCopy(v)
|
||||||
|
elseif type(v) == 'table' then
|
||||||
|
result[k] = aux_ui.deepLayoutCopy(v)
|
||||||
|
else
|
||||||
|
result[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
return aux_ui
|
120
files/builtin_scripts/scripts/omw/mwui/borders.lua
Normal file
120
files/builtin_scripts/scripts/omw/mwui/borders.lua
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
local ui = require('openmw.ui')
|
||||||
|
local util = require('openmw.util')
|
||||||
|
|
||||||
|
local constants = require('scripts.omw.mwui.constants')
|
||||||
|
|
||||||
|
local v2 = util.vector2
|
||||||
|
|
||||||
|
local sideParts = {
|
||||||
|
left = util.vector2(0, 0.5),
|
||||||
|
right = util.vector2(1, 0.5),
|
||||||
|
top = util.vector2(0.5, 0),
|
||||||
|
bottom = util.vector2(0.5, 1),
|
||||||
|
}
|
||||||
|
local cornerParts = {
|
||||||
|
top_left_corner = util.vector2(0, 0),
|
||||||
|
top_right_corner = util.vector2(1, 0),
|
||||||
|
bottom_left_corner = util.vector2(0, 1),
|
||||||
|
bottom_right_corner = util.vector2(1, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
local resources = {}
|
||||||
|
do
|
||||||
|
local boxBorderPattern = 'textures/menu_thin_border_%s.dds'
|
||||||
|
for k, _ in pairs(sideParts) do
|
||||||
|
resources[k] = ui.texture{ path = boxBorderPattern:format(k) }
|
||||||
|
end
|
||||||
|
for k, _ in pairs(cornerParts) do
|
||||||
|
resources[k] = ui.texture{ path = boxBorderPattern:format(k) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local borderPieces = {}
|
||||||
|
for k, align in pairs(sideParts) do
|
||||||
|
local resource = resources[k]
|
||||||
|
local horizontal = align.x ~= 0.5
|
||||||
|
borderPieces[#borderPieces + 1] = {
|
||||||
|
type = ui.TYPE.Image,
|
||||||
|
props = {
|
||||||
|
resource = resource,
|
||||||
|
relativePosition = align,
|
||||||
|
anchor = align,
|
||||||
|
relativeSize = horizontal and v2(0, 1) or v2(1, 0),
|
||||||
|
size = (horizontal and v2(1, -2) or v2(-2, 1)) * constants.borderSize,
|
||||||
|
tileH = not horizontal,
|
||||||
|
tileV = horizontal,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, align in pairs(cornerParts) do
|
||||||
|
local resource = resources[k]
|
||||||
|
borderPieces[#borderPieces + 1] = {
|
||||||
|
type = ui.TYPE.Image,
|
||||||
|
props = {
|
||||||
|
resource = resource,
|
||||||
|
relativePosition = align,
|
||||||
|
anchor = align,
|
||||||
|
size = v2(1, 1) * constants.borderSize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
borderPieces[#borderPieces + 1] = {
|
||||||
|
external = {
|
||||||
|
slot = true,
|
||||||
|
},
|
||||||
|
props = {
|
||||||
|
position = v2(1, 1) * (constants.borderSize + constants.padding),
|
||||||
|
size = v2(-2, -2) * (constants.borderSize + constants.padding),
|
||||||
|
relativeSize = v2(1, 1),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local borders = {
|
||||||
|
content = ui.content(borderPieces)
|
||||||
|
}
|
||||||
|
borders.content:add({
|
||||||
|
external = {
|
||||||
|
slot = true,
|
||||||
|
},
|
||||||
|
props = {
|
||||||
|
size = v2(-2, -2) * constants.borderSize,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local horizontalLine = {
|
||||||
|
content = ui.content {
|
||||||
|
{
|
||||||
|
type = ui.TYPE.Image,
|
||||||
|
props = {
|
||||||
|
resource = resources.top,
|
||||||
|
tileH = true,
|
||||||
|
tileV = false,
|
||||||
|
size = v2(0, constants.borderSize),
|
||||||
|
relativeSize = v2(1, 0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local verticalLine = {
|
||||||
|
content = ui.content {
|
||||||
|
{
|
||||||
|
type = ui.TYPE.Image,
|
||||||
|
props = {
|
||||||
|
resource = resources.left,
|
||||||
|
tileH = false,
|
||||||
|
tileV = true,
|
||||||
|
size = v2(constants.borderSize, 0),
|
||||||
|
relativeSize = v2(0, 1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(templates)
|
||||||
|
templates.borders = borders
|
||||||
|
templates.horizontalLine = horizontalLine
|
||||||
|
templates.verticalLine = verticalLine
|
||||||
|
end
|
45
files/builtin_scripts/scripts/omw/mwui/box.lua
Normal file
45
files/builtin_scripts/scripts/omw/mwui/box.lua
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
local ui = require('openmw.ui')
|
||||||
|
local util = require('openmw.util')
|
||||||
|
|
||||||
|
local whiteTexture = ui.texture{ path = 'white' }
|
||||||
|
|
||||||
|
local menuTransparency = ui._getMenuTransparency()
|
||||||
|
|
||||||
|
return function(templates)
|
||||||
|
templates.backgroundTransparent = {
|
||||||
|
props = {
|
||||||
|
resource = whiteTexture,
|
||||||
|
color = util.color.rgb(0, 0, 0),
|
||||||
|
alpha = menuTransparency,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
templates.backgroundSolid = {
|
||||||
|
props = {
|
||||||
|
resource = whiteTexture,
|
||||||
|
color = util.color.rgb(0, 0, 0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
templates.box = {
|
||||||
|
props = {
|
||||||
|
inheritAlpha = false,
|
||||||
|
},
|
||||||
|
content = ui.content {
|
||||||
|
{
|
||||||
|
type = ui.TYPE.Image,
|
||||||
|
template = templates.backgroundTransparent,
|
||||||
|
props = {
|
||||||
|
relativeSize = util.vector2(1, 1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
template = templates.borders,
|
||||||
|
props = {
|
||||||
|
relativeSize = util.vector2(1, 1),
|
||||||
|
},
|
||||||
|
external = {
|
||||||
|
slot = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
8
files/builtin_scripts/scripts/omw/mwui/constants.lua
Normal file
8
files/builtin_scripts/scripts/omw/mwui/constants.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
local util = require('openmw.util')
|
||||||
|
|
||||||
|
return {
|
||||||
|
textNormalSize = 16,
|
||||||
|
sandColor = util.color.rgb(202 / 255, 165 / 255, 96 / 255),
|
||||||
|
borderSize = 4,
|
||||||
|
padding = 2,
|
||||||
|
}
|
101
files/builtin_scripts/scripts/omw/mwui/init.lua
Normal file
101
files/builtin_scripts/scripts/omw/mwui/init.lua
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
local util = require('openmw.util')
|
||||||
|
|
||||||
|
local function shallowLayoutCopy(source, target)
|
||||||
|
for k in pairs(target) do
|
||||||
|
target[k] = nil
|
||||||
|
end
|
||||||
|
for k, v in pairs(source) do
|
||||||
|
target[k] = v
|
||||||
|
end
|
||||||
|
return target
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @type Templates
|
||||||
|
-- @usage
|
||||||
|
-- local I = require('openmw.interfaces')
|
||||||
|
-- local ui = require('openmw.ui')
|
||||||
|
-- local auxUi = require('openmw_aux.ui')
|
||||||
|
-- ui.create {
|
||||||
|
-- template = I.MWUI.templates.textNormal,
|
||||||
|
-- layer = 'Windows',
|
||||||
|
-- type = ui.TYPE.Text,
|
||||||
|
-- props = {
|
||||||
|
-- text = 'Hello, world!',
|
||||||
|
-- },
|
||||||
|
-- }
|
||||||
|
-- -- important to copy here
|
||||||
|
-- local myText = auxUi.deepLayoutCopy(I.MWUI.templates.textNormal)
|
||||||
|
-- myText.props.textSize = 20
|
||||||
|
-- I.MWUI.templates.textNormal = myText
|
||||||
|
-- ui.updateAll()
|
||||||
|
|
||||||
|
local templatesMeta = {
|
||||||
|
__index = function(self, key)
|
||||||
|
return self.__templates[key]
|
||||||
|
end,
|
||||||
|
__newindex = function(self, key, template)
|
||||||
|
local target = self.__templates[key]
|
||||||
|
if target == template then
|
||||||
|
error("Overriding a template with itself")
|
||||||
|
else
|
||||||
|
shallowLayoutCopy(template, target)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @module MWUI
|
||||||
|
-- @usage require('openmw.interfaces').MWUI
|
||||||
|
local function TemplateOverrides(templates)
|
||||||
|
return setmetatable({
|
||||||
|
__templates = util.makeReadOnly(templates),
|
||||||
|
}, templatesMeta)
|
||||||
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @field [parent=#MWUI] #Templates templates
|
||||||
|
local templates = {}
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Standard rectangular border
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout border
|
||||||
|
require('scripts.omw.mwui.borders')(templates)
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Border combined with a transparent background
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout box
|
||||||
|
---
|
||||||
|
-- A transparent background
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout backgroundTransparent
|
||||||
|
---
|
||||||
|
-- A solid, non-transparent background
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout backgroundSolid
|
||||||
|
require('scripts.omw.mwui.box')(templates)
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Standard "sand" colored text
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout textNormal
|
||||||
|
require('scripts.omw.mwui.text')(templates)
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Single line text input
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout textEditLine
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Multiline text input
|
||||||
|
-- @field [parent=#Templates] openmw.ui#Layout textEditBox
|
||||||
|
require('scripts.omw.mwui.textEdit')(templates)
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Interface version
|
||||||
|
-- @field [parent=#MWUI] #number version
|
||||||
|
local interface = {
|
||||||
|
version = 0,
|
||||||
|
templates = TemplateOverrides(templates),
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
interfaceName = "MWUI",
|
||||||
|
interface = interface,
|
||||||
|
}
|
15
files/builtin_scripts/scripts/omw/mwui/text.lua
Normal file
15
files/builtin_scripts/scripts/omw/mwui/text.lua
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
local ui = require('openmw.ui')
|
||||||
|
|
||||||
|
local constants = require('scripts.omw.mwui.constants')
|
||||||
|
|
||||||
|
local textNormal = {
|
||||||
|
type = ui.TYPE.Text,
|
||||||
|
props = {
|
||||||
|
textSize = constants.textNormalSize,
|
||||||
|
textColor = constants.sandColor,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(templates)
|
||||||
|
templates.textNormal = textNormal
|
||||||
|
end
|
47
files/builtin_scripts/scripts/omw/mwui/textEdit.lua
Normal file
47
files/builtin_scripts/scripts/omw/mwui/textEdit.lua
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
local util = require('openmw.util')
|
||||||
|
local ui = require('openmw.ui')
|
||||||
|
|
||||||
|
local constants = require('scripts.omw.mwui.constants')
|
||||||
|
|
||||||
|
return function(templates)
|
||||||
|
local borderContent = ui.content {
|
||||||
|
{
|
||||||
|
template = templates.borders,
|
||||||
|
props = {
|
||||||
|
relativeSize = util.vector2(1, 1),
|
||||||
|
},
|
||||||
|
content = ui.content {
|
||||||
|
{
|
||||||
|
external = {
|
||||||
|
slot = true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.textEditLine = {
|
||||||
|
type = ui.TYPE.TextEdit,
|
||||||
|
props = {
|
||||||
|
textSize = constants.textNormalSize,
|
||||||
|
textColor = constants.sandColor,
|
||||||
|
textAlignH = ui.ALIGNMENT.Start,
|
||||||
|
textAlignV = ui.ALIGNMENT.Center,
|
||||||
|
multiline = false,
|
||||||
|
},
|
||||||
|
content = borderContent,
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.textEditBox = {
|
||||||
|
type = ui.TYPE.TextEdit,
|
||||||
|
props = {
|
||||||
|
textSize = constants.textNormalSize,
|
||||||
|
textColor = constants.sandColor,
|
||||||
|
textAlignH = ui.ALIGNMENT.Start,
|
||||||
|
textAlignV = ui.ALIGNMENT.Start,
|
||||||
|
multiline = true,
|
||||||
|
wordWrap = true,
|
||||||
|
},
|
||||||
|
content = borderContent,
|
||||||
|
}
|
||||||
|
end
|
@ -9,6 +9,13 @@
|
|||||||
-- Widget types
|
-- Widget types
|
||||||
-- @field [parent=#ui] #TYPE TYPE
|
-- @field [parent=#ui] #TYPE TYPE
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Alignment values (details depend on the specific property). For horizontal alignment the order is left to right, for vertical alignment the order is top to bottom.
|
||||||
|
-- @type ALIGNMENT
|
||||||
|
-- @field Start
|
||||||
|
-- @field Center
|
||||||
|
-- @field End
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Alignment values (left to right, top to bottom)
|
-- Alignment values (left to right, top to bottom)
|
||||||
-- @field [parent=#ui] #ALIGNMENT ALIGNMENT
|
-- @field [parent=#ui] #ALIGNMENT ALIGNMENT
|
||||||
@ -25,14 +32,6 @@
|
|||||||
-- @field TextEdit Accepts user text input
|
-- @field TextEdit Accepts user text input
|
||||||
-- @field Window Can be moved and resized by the user
|
-- @field Window Can be moved and resized by the user
|
||||||
|
|
||||||
---
|
|
||||||
-- Alignment values (details depend on the specific property).
|
|
||||||
-- For horizontal alignment the order is left to right, for vertical alignment the order is top to bottom.
|
|
||||||
-- @type ALIGNMENT
|
|
||||||
-- @field Start
|
|
||||||
-- @field Center
|
|
||||||
-- @field End
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Shows given message at the bottom of the screen.
|
-- Shows given message at the bottom of the screen.
|
||||||
-- @function [parent=#ui] showMessage
|
-- @function [parent=#ui] showMessage
|
||||||
@ -98,6 +97,9 @@
|
|||||||
-- @field #string searchHints Additional keywords used in search, not displayed anywhere
|
-- @field #string searchHints Additional keywords used in search, not displayed anywhere
|
||||||
-- @field #Element element The page's UI, which will be attached to the settings tab. The root widget has to have a fixed size. Set the `size` field in `props`, `relativeSize` is ignored.
|
-- @field #Element element The page's UI, which will be attached to the settings tab. The root widget has to have a fixed size. Set the `size` field in `props`, `relativeSize` is ignored.
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Update all existing UI elements. Potentially extremely slow, so only call this when necessary, e. g. after overriding a template.
|
||||||
|
-- @function [parent=#ui] updateAll
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Layout
|
-- Layout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user