Merge branch 'ui_pairs' into 'master'

Implement pairs and ipairs for ui.content and ui.layers. Document all iterable types in a uniform way.

See merge request OpenMW/openmw!1643
C++20
Petr Mikheev 2 years ago
commit ff7ac7192b

@ -166,6 +166,21 @@ namespace MWLua
else
return sol::nullopt;
};
{
auto pairs = [](LuaUi::Content& content)
{
auto next = [](LuaUi::Content& content, size_t i) -> sol::optional<std::tuple<size_t, sol::table>>
{
if (i < content.size())
return std::make_tuple(i + 1, content.at(i));
else
return sol::nullopt;
};
return std::make_tuple(next, content, 0);
};
uiContent[sol::meta_function::ipairs] = pairs;
uiContent[sol::meta_function::pairs] = pairs;
}
auto element = context.mLua->sol().new_usertype<LuaUi::Element>("Element");
element["layout"] = sol::property(
@ -233,6 +248,21 @@ namespace MWLua
options.mInteractive = LuaUtil::getValueOrDefault(LuaUtil::getFieldOrNil(opt, "interactive"), true);
context.mLuaManager->addAction(std::make_unique<LayerAction>(name, afterName, options, context.mLua));
};
{
auto pairs = [layers](const sol::object&)
{
auto next = [](const sol::table& l, size_t i) -> sol::optional<std::tuple<size_t, std::string>>
{
if (i < LuaUi::Layers::size())
return std::make_tuple(i + 1, LuaUi::Layers::at(i));
else
return sol::nullopt;
};
return std::make_tuple(next, layers, 0);
};
layers[sol::meta_function::pairs] = pairs;
layers[sol::meta_function::ipairs] = pairs;
}
api["layers"] = LuaUtil::makeReadOnly(layers);
sol::table typeTable = context.mLua->newTable();

@ -59,6 +59,23 @@ namespace LuaUtil
mLua["writeToLog"] = [](std::string_view s) { Log(Debug::Level::Info) << s; };
mLua["cmetatable"] = [](const sol::table& v) -> sol::object { return v[sol::metatable_key]; };
// Some fixes for compatibility between different Lua versions
if (mLua["unpack"] == sol::nil)
mLua["unpack"] = mLua["table"]["unpack"];
else if (mLua["table"]["unpack"] == sol::nil)
mLua["table"]["unpack"] = mLua["unpack"];
if (LUA_VERSION_NUM <= 501)
{
mLua.script(R"(
local _pairs = pairs
local _ipairs = ipairs
local _cmeta = cmetatable
pairs = function(v) return ((_cmeta(v) or v).__pairs or _pairs)(v) end
ipairs = function(v) return ((_cmeta(v) or v).__ipairs or _ipairs)(v) end
)");
}
mLua.script(R"(
local _pairs = pairs
local _ipairs = ipairs
@ -78,22 +95,6 @@ namespace LuaUtil
function ipairsForReadOnly(v) return _ipairs(_cmeta(v).__index) end
)");
// Some fixes for compatibility between different Lua versions
if (mLua["unpack"] == sol::nil)
mLua["unpack"] = mLua["table"]["unpack"];
else if (mLua["table"]["unpack"] == sol::nil)
mLua["table"]["unpack"] = mLua["unpack"];
if (LUA_VERSION_NUM <= 501)
{
mLua.script(R"(
local _pairs = pairs
local _ipairs = ipairs
local _cmeta = cmetatable
pairs = function(v) return ((_cmeta(v) or v).__pairs or _pairs)(v) end
ipairs = function(v) return ((_cmeta(v) or v).__ipairs or _ipairs)(v) end
)");
}
mSandboxEnv = sol::table(mLua, sol::create);
mSandboxEnv["_VERSION"] = mLua["_VERSION"];
for (const std::string& s : safeFunctions)

@ -67,4 +67,3 @@ cd $FILES_DIR/builtin_scripts
$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/camera.lua

@ -25,6 +25,7 @@ Lua API reference
openmw_aux_time
interface_ai
interface_camera
iterables
- :ref:`Engine handlers reference`

@ -0,0 +1,50 @@
Iterable types
==============
List Iterable
-------------
An iterable with defined size and order.
.. code-block:: Lua
-- can iterate over the list with pairs
for i, v in pairs(list) do
-- ...
end
.. code-block:: Lua
-- can iterate over the list with ipairs
for i, v in ipairs(list) do
-- ...
end
.. code-block:: Lua
-- can get total size with the size # operator
local length = #list
.. code-block:: Lua
-- can index the list with numbers
for i = 1, length do
list[i]
end
Map Iterable
------------
An iterable with undefined order.
.. code-block:: Lua
-- can iterate over the map with pairs
for k, v in pairs(map) do
-- ...
end
.. code-block:: Lua
-- can index the map by key
map[key]

@ -498,7 +498,7 @@ At some moment it will send the 'DamagedByDarkPower' event to all nearby actors:
local nearby = require('openmw.nearby')
local function onActivated()
for i, actor in nearby.actors:ipairs() do
for i, actor in ipairs(nearby.actors) do
local dist = (self.position - actor.position):length()
if dist < 500 then
local damage = (1 - dist / 500) * 200

@ -289,9 +289,9 @@
-------------------------------------------------------------------------------
-- List of GameObjects.
-- List of GameObjects. Implements [iterables#List](iterables.html#List) of #GameObject
-- @type ObjectList
-- @extends #list<#GameObject>
-- @list <#GameObject>
-------------------------------------------------------------------------------
-- Filter list with a Query.

@ -64,12 +64,16 @@
-- @field #Content content Optional @{openmw.ui#Content} of children layouts
---
-- Layers
-- Layers. Implements [iterables#List](iterables.html#List) of #string.
-- @type Layers
-- @list <#string>
-- @usage
-- ui.layers.insertAfter('HUD', 'NewLayer', { interactive = true })
-- local fourthLayerName = ui.layers[4]
-- local windowsIndex = ui.layers.indexOf('Windows')
-- for i, name in ipairs(ui.layers) do
-- print('layer', i, name)
-- end
---
-- Index of the layer with the givent name. Returns nil if the layer doesn't exist
@ -85,7 +89,8 @@
-- @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.
-- @type Content
-- @list <#Layout>
-- @usage

Loading…
Cancel
Save