diff --git a/res/modules/internal/gui_util.lua b/res/modules/internal/gui_util.lua index c44e2fbe..15360521 100644 --- a/res/modules/internal/gui_util.lua +++ b/res/modules/internal/gui_util.lua @@ -60,6 +60,17 @@ function Element.new(docname, name) end, __newindex=function(self, k, v) gui.setattr(self.docname, self.name, k, v) + end, + __ipairs=function(self) + local i = 0 + return function() + i = i + 1 + local elem = gui.getattr(self.docname, self.name, i) + if elem == nil then + return + end + return i, elem + end end }) end diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index a70e7136..7c891c88 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -341,27 +341,41 @@ static int p_get_data(UINode* node, lua::State* L) { return 0; } +static const std::string& request_node_id(const DocumentNode& docnode) { + std::string id = docnode.node->getId(); + if (id.empty()) { + id = "#" + std::to_string( + reinterpret_cast(docnode.node.get())); + } + docnode.node->setId(std::move(id)); + UINode::getIndices( + docnode.node, docnode.document->getMapWriteable() + ); + return docnode.node->getId(); +} + +/// @brief Push UI-document node object to stack +/// using lua argument at 1 as document name +/// @param id UI-node id +static int push_document_node(lua::State* L, const std::string& id) { + lua::requireglobal(L, "__vc_get_document_node"); + lua::pushvalue(L, 1); + lua::pushstring(L, id); + return lua::call(L, 2, 1); +} + static int p_get_parent(UINode* node, lua::State* L) { auto parent = node->getParent(); if (!parent) { return 0; } - auto id = parent->getId(); - if (id.empty()) { - id = "#" + std::to_string(reinterpret_cast(parent)); - } - parent->setId(id); - auto docname = lua::require_string(L, 1); auto element = lua::require_string(L, 2); auto docnode = get_document_node_impl(L, docname, element); - UINode::getIndices( - parent->shared_from_this(), docnode.document->getMapWriteable() - ); - lua::requireglobal(L, "__vc_get_document_node"); - lua::pushvalue(L, 1); - lua::pushstring(L, id); - return lua::call(L, 2, 1); + + const auto& id = request_node_id(docnode); + + return push_document_node(L, id); } static int p_get_add(UINode* node, lua::State* L) { @@ -459,6 +473,21 @@ static int p_get_scroll(UINode* node, lua::State* L) { static int l_gui_getattr(lua::State* L) { auto docname = lua::require_string(L, 1); auto element = lua::require_string(L, 2); + if (lua::isnumber(L, 3)) { + auto docnode = get_document_node_impl(L, docname, element); + auto container = dynamic_cast(docnode.node.get()); + if (container == nullptr) { + return 0; + } + size_t index = lua::tointeger(L, 3) - 1; + const auto& nodes = container->getNodes(); + if (index >= nodes.size()) { + return 0; + } + const auto& node = nodes.at(index); + const auto& id = request_node_id(DocumentNode {docnode.document, node}); + return push_document_node(L, id); + } auto attr = lua::require_string(L, 3); static const std::unordered_map<