mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-31 15:32:45 +00:00
Merge branch 'futureproof_layers' into 'master'
Add layer size, make layers API more flexible See merge request OpenMW/openmw!1724
This commit is contained in:
commit
fbc84465c5
@ -7,6 +7,7 @@
|
|||||||
#include <components/lua_ui/resources.hpp>
|
#include <components/lua_ui/resources.hpp>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
#include "actions.hpp"
|
#include "actions.hpp"
|
||||||
@ -83,36 +84,33 @@ namespace MWLua
|
|||||||
class InsertLayerAction final : public Action
|
class InsertLayerAction final : public Action
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InsertLayerAction(std::string_view name, std::string_view afterName,
|
InsertLayerAction(std::string_view name, size_t index,
|
||||||
LuaUi::Layers::Options options, LuaUtil::LuaState* state)
|
LuaUi::Layer::Options options, LuaUtil::LuaState* state)
|
||||||
: Action(state)
|
: Action(state)
|
||||||
, mName(name)
|
, mName(name)
|
||||||
, mAfterName(afterName)
|
, mIndex(index)
|
||||||
, mOptions(options)
|
, mOptions(options)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void apply(WorldView&) const override
|
void apply(WorldView&) const override
|
||||||
{
|
{
|
||||||
size_t index = LuaUi::Layers::indexOf(mAfterName);
|
LuaUi::Layer::insert(mIndex, mName, mOptions);
|
||||||
if (index == LuaUi::Layers::size())
|
|
||||||
throw std::logic_error(std::string("Layer not found"));
|
|
||||||
LuaUi::Layers::insert(index, mName, mOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString() const override
|
std::string toString() const override
|
||||||
{
|
{
|
||||||
std::string result("Insert UI layer \"");
|
std::string result("Insert UI layer \"");
|
||||||
result += mName;
|
result += mName;
|
||||||
result += "\" after \"";
|
result += "\" at \"";
|
||||||
result += mAfterName;
|
result += mIndex;
|
||||||
result += "\"";
|
result += "\"";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mName;
|
std::string mName;
|
||||||
std::string mAfterName;
|
size_t mIndex;
|
||||||
LuaUi::Layers::Options mOptions;
|
LuaUi::Layer::Options mOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Lua arrays index from 1
|
// Lua arrays index from 1
|
||||||
@ -227,37 +225,58 @@ namespace MWLua
|
|||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto uiLayer = context.mLua->sol().new_usertype<LuaUi::Layer>("UiLayer");
|
||||||
|
uiLayer["name"] = sol::property([](LuaUi::Layer& self) { return self.name(); });
|
||||||
|
uiLayer["size"] = sol::property([](LuaUi::Layer& self) { return self.size(); });
|
||||||
|
uiLayer[sol::meta_function::to_string] = [](LuaUi::Layer& self)
|
||||||
|
{
|
||||||
|
return Misc::StringUtils::format("UiLayer(%s)", self.name());
|
||||||
|
};
|
||||||
|
|
||||||
sol::table layers = context.mLua->newTable();
|
sol::table layers = context.mLua->newTable();
|
||||||
layers[sol::meta_function::length] = []()
|
layers[sol::meta_function::length] = []()
|
||||||
{
|
{
|
||||||
return LuaUi::Layers::size();
|
return LuaUi::Layer::count();
|
||||||
};
|
};
|
||||||
layers[sol::meta_function::index] = [](size_t index)
|
layers[sol::meta_function::index] = [](size_t index)
|
||||||
{
|
{
|
||||||
index = fromLuaIndex(index);
|
index = fromLuaIndex(index);
|
||||||
return LuaUi::Layers::at(index);
|
return LuaUi::Layer(index);
|
||||||
};
|
};
|
||||||
layers["indexOf"] = [](std::string_view name) -> sol::optional<size_t>
|
layers["indexOf"] = [](std::string_view name) -> sol::optional<size_t>
|
||||||
{
|
{
|
||||||
size_t index = LuaUi::Layers::indexOf(name);
|
size_t index = LuaUi::Layer::indexOf(name);
|
||||||
if (index == LuaUi::Layers::size())
|
if (index == LuaUi::Layer::count())
|
||||||
return sol::nullopt;
|
return sol::nullopt;
|
||||||
else
|
else
|
||||||
return toLuaIndex(index);
|
return toLuaIndex(index);
|
||||||
};
|
};
|
||||||
layers["insertAfter"] = [context](std::string_view afterName, std::string_view name, const sol::object& opt)
|
layers["insertAfter"] = [context](std::string_view afterName, std::string_view name, const sol::object& opt)
|
||||||
{
|
{
|
||||||
LuaUi::Layers::Options options;
|
LuaUi::Layer::Options options;
|
||||||
options.mInteractive = LuaUtil::getValueOrDefault(LuaUtil::getFieldOrNil(opt, "interactive"), true);
|
options.mInteractive = LuaUtil::getValueOrDefault(LuaUtil::getFieldOrNil(opt, "interactive"), true);
|
||||||
context.mLuaManager->addAction(std::make_unique<InsertLayerAction>(name, afterName, options, context.mLua));
|
size_t index = LuaUi::Layer::indexOf(afterName);
|
||||||
|
if (index == LuaUi::Layer::count())
|
||||||
|
throw std::logic_error(std::string("Layer not found"));
|
||||||
|
index++;
|
||||||
|
context.mLuaManager->addAction(std::make_unique<InsertLayerAction>(name, index, options, context.mLua));
|
||||||
|
};
|
||||||
|
layers["insertBefore"] = [context](std::string_view beforename, std::string_view name, const sol::object& opt)
|
||||||
|
{
|
||||||
|
LuaUi::Layer::Options options;
|
||||||
|
options.mInteractive = LuaUtil::getValueOrDefault(LuaUtil::getFieldOrNil(opt, "interactive"), true);
|
||||||
|
size_t index = LuaUi::Layer::indexOf(beforename);
|
||||||
|
if (index == LuaUi::Layer::count())
|
||||||
|
throw std::logic_error(std::string("Layer not found"));
|
||||||
|
context.mLuaManager->addAction(std::make_unique<InsertLayerAction>(name, index, options, context.mLua));
|
||||||
};
|
};
|
||||||
{
|
{
|
||||||
auto pairs = [layers](const sol::object&)
|
auto pairs = [layers](const sol::object&)
|
||||||
{
|
{
|
||||||
auto next = [](const sol::table& l, size_t i) -> sol::optional<std::tuple<size_t, std::string>>
|
auto next = [](const sol::table& l, size_t i) -> sol::optional<std::tuple<size_t, LuaUi::Layer>>
|
||||||
{
|
{
|
||||||
if (i < LuaUi::Layers::size())
|
if (i < LuaUi::Layer::count())
|
||||||
return std::make_tuple(i + 1, LuaUi::Layers::at(i));
|
return std::make_tuple(i + 1, LuaUi::Layer(i));
|
||||||
else
|
else
|
||||||
return sol::nullopt;
|
return sol::nullopt;
|
||||||
};
|
};
|
||||||
|
29
components/lua_ui/layers.cpp
Normal file
29
components/lua_ui/layers.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "layers.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
namespace LuaUi
|
||||||
|
{
|
||||||
|
size_t Layer::indexOf(std::string_view name)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < count(); i++)
|
||||||
|
if (at(i)->getName() == name)
|
||||||
|
return i;
|
||||||
|
return count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layer::insert(size_t index, std::string_view name, Options options)
|
||||||
|
{
|
||||||
|
if (index > count())
|
||||||
|
throw std::logic_error("Invalid layer index");
|
||||||
|
if (indexOf(name) < count())
|
||||||
|
Log(Debug::Error) << "Layer \"" << name << "\" already exists";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto layer = MyGUI::LayerManager::getInstance()
|
||||||
|
.createLayerAt(std::string(name), "OverlappedLayer", index);
|
||||||
|
auto overlappedLayer = dynamic_cast<MyGUI::OverlappedLayer*>(layer);
|
||||||
|
overlappedLayer->setPick(options.mInteractive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,50 +6,63 @@
|
|||||||
|
|
||||||
#include <MyGUI_LayerManager.h>
|
#include <MyGUI_LayerManager.h>
|
||||||
#include <MyGUI_OverlappedLayer.h>
|
#include <MyGUI_OverlappedLayer.h>
|
||||||
|
#include <osg/Vec2f>
|
||||||
|
|
||||||
namespace LuaUi
|
namespace LuaUi
|
||||||
{
|
{
|
||||||
namespace Layers
|
// this wrapper is necessary, because the MyGUI LayerManager
|
||||||
|
// stores layers in a vector and their indices could change
|
||||||
|
class Layer
|
||||||
{
|
{
|
||||||
struct Options {
|
public:
|
||||||
bool mInteractive;
|
Layer(size_t index)
|
||||||
};
|
: mName(at(index)->getName())
|
||||||
|
, mCachedIndex(index)
|
||||||
|
{}
|
||||||
|
|
||||||
size_t size()
|
const std::string& name() const noexcept { return mName; };
|
||||||
{
|
const osg::Vec2f size()
|
||||||
return MyGUI::LayerManager::getInstance().getLayerCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string at(size_t index)
|
|
||||||
{
|
|
||||||
if (index >= size())
|
|
||||||
throw std::logic_error("Invalid layer index");
|
|
||||||
return MyGUI::LayerManager::getInstance().getLayer(index)->getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t indexOf(std::string_view name)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < size(); i++)
|
|
||||||
if (at(i) == name)
|
|
||||||
return i;
|
|
||||||
return size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void insert(size_t index, std::string_view name, Options options)
|
|
||||||
{
|
|
||||||
if (index > size())
|
|
||||||
throw std::logic_error("Invalid layer index");
|
|
||||||
if (indexOf(name) < size())
|
|
||||||
Log(Debug::Error) << "Layer \"" << name << "\" already exists";
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
auto layer = MyGUI::LayerManager::getInstance()
|
MyGUI::ILayer* p = refresh();
|
||||||
.createLayerAt(std::string(name), "OverlappedLayer", index);
|
MyGUI::IntSize size = p->getSize();
|
||||||
auto overlappedLayer = dynamic_cast<MyGUI::OverlappedLayer*>(layer);
|
return osg::Vec2f(size.width, size.height);
|
||||||
overlappedLayer->setPick(options.mInteractive);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
struct Options
|
||||||
|
{
|
||||||
|
bool mInteractive;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t count()
|
||||||
|
{
|
||||||
|
return MyGUI::LayerManager::getInstance().getLayerCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t indexOf(std::string_view name);
|
||||||
|
|
||||||
|
static void insert(size_t index, std::string_view name, Options options);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static MyGUI::ILayer* at(size_t index)
|
||||||
|
{
|
||||||
|
if (index >= count())
|
||||||
|
throw std::logic_error("Invalid layer index");
|
||||||
|
return MyGUI::LayerManager::getInstance().getLayer(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::ILayer* refresh()
|
||||||
|
{
|
||||||
|
MyGUI::ILayer* p = at(mCachedIndex);
|
||||||
|
if (p->getName() != mName)
|
||||||
|
{
|
||||||
|
mCachedIndex = indexOf(mName);
|
||||||
|
p = at(mCachedIndex);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
std::string mName;
|
||||||
|
size_t mCachedIndex;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // OPENMW_LUAUI_LAYERS
|
#endif // OPENMW_LUAUI_LAYERS
|
||||||
|
@ -77,15 +77,20 @@
|
|||||||
-- @field #Content content Optional @{openmw.ui#Content} of children layouts
|
-- @field #Content content Optional @{openmw.ui#Content} of children layouts
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Layers. Implements [iterables#List](iterables.html#List) of #string.
|
-- @type Layer
|
||||||
|
-- @field #string name Name of the layer
|
||||||
|
-- @field openmw.util#vector2 size Size of the layer in pixels
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Layers. Implements [iterables#List](iterables.html#List) of #Layer.
|
||||||
-- @type Layers
|
-- @type Layers
|
||||||
-- @list <#string>
|
-- @list <#Layer>
|
||||||
-- @usage
|
-- @usage
|
||||||
-- ui.layers.insertAfter('HUD', 'NewLayer', { interactive = true })
|
-- ui.layers.insertAfter('HUD', 'NewLayer', { interactive = true })
|
||||||
-- local fourthLayerName = ui.layers[4]
|
-- local fourthLayer = ui.layers[4]
|
||||||
-- local windowsIndex = ui.layers.indexOf('Windows')
|
-- local windowsIndex = ui.layers.indexOf('Windows')
|
||||||
-- for i, name in ipairs(ui.layers) do
|
-- for i, layer in ipairs(ui.layers) do
|
||||||
-- print('layer', i, name)
|
-- print('layer', i, layer.name, layer.size)
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -101,6 +106,13 @@
|
|||||||
-- @param #string name Name of the new layer
|
-- @param #string name Name of the new layer
|
||||||
-- @param #table options Table with a boolean `interactive` field (default is true). Layers with interactive = false will ignore all mouse interactions.
|
-- @param #table options Table with a boolean `interactive` field (default is true). Layers with interactive = false will ignore all mouse interactions.
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Creates a layer and inserts it before another layer (shifts indexes of some other layers).
|
||||||
|
-- @function [parent=#Layers] insertBefore
|
||||||
|
-- @param #string beforeName Name of the layer before which the new layer will be inserted
|
||||||
|
-- @param #string name Name of the new layer
|
||||||
|
-- @param #table options Table with a boolean `interactive` field (default is true). Layers with interactive = false will ignore all mouse interactions.
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Content. An array-like container, which allows to reference elements by their name.
|
-- Content. An array-like container, which allows to reference elements by their name.
|
||||||
-- Implements [iterables#List](iterables.html#List) of #Layout and [iterables#Map](iterables.html#Map) of #string to #Layout.
|
-- Implements [iterables#List](iterables.html#List) of #Layout and [iterables#Map](iterables.html#Map) of #string to #Layout.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user