diff --git a/headers/enduro2d/high/node.hpp b/headers/enduro2d/high/node.hpp index aee801ac..6890ddc5 100644 --- a/headers/enduro2d/high/node.hpp +++ b/headers/enduro2d/high/node.hpp @@ -125,6 +125,9 @@ namespace e2d node_iptr next_sibling() noexcept; const_node_iptr next_sibling() const noexcept; + + node_iptr child_at(std::size_t index) noexcept; + const_node_iptr child_at(std::size_t index) const noexcept; protected: node() = default; node(gobject owner); diff --git a/samples/bin/library/scripts/emmy/high/node.lua b/samples/bin/library/scripts/emmy/high/node.lua index bb56fd29..00df09ed 100644 --- a/samples/bin/library/scripts/emmy/high/node.lua +++ b/samples/bin/library/scripts/emmy/high/node.lua @@ -140,5 +140,10 @@ function node.send_forward(self) end ---@return boolean function node.bring_to_front(self) end +---@param self node +---@param index integer +---@return node +function node.child_at(self, index) end + ---@type node _G.node = _G.node or node diff --git a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp index 1b204e37..a765eaf2 100644 --- a/sources/enduro2d/high/bindings/high_binds/node_binds.cpp +++ b/sources/enduro2d/high/bindings/high_binds/node_binds.cpp @@ -141,7 +141,13 @@ namespace e2d::bindings::high [](node& n) -> node_iptr { return n.prev_sibling(); }), "next_sibling", sol::property( - [](node& n) -> node_iptr { return n.next_sibling(); }) + [](node& n) -> node_iptr { return n.next_sibling(); }), + + "child_at", [](node& n, i32 index) -> node_iptr { + return index >= 0 + ? n.child_at(math::numeric_cast(index)) + : node_iptr(); + } ); } } diff --git a/sources/enduro2d/high/node.cpp b/sources/enduro2d/high/node.cpp index 162ef303..00199354 100644 --- a/sources/enduro2d/high/node.cpp +++ b/sources/enduro2d/high/node.cpp @@ -414,6 +414,22 @@ namespace e2d } return const_node_iptr(&*iter); } + + node_iptr node::child_at(std::size_t index) noexcept { + node_iptr child = first_child(); + for ( std::size_t i = 0; i < index && child; ++i ) { + child = child->next_sibling(); + } + return child; + } + + const_node_iptr node::child_at(std::size_t index) const noexcept { + const_node_iptr child = first_child(); + for ( std::size_t i = 0; i < index && child; ++i ) { + child = child->next_sibling(); + } + return child; + } } namespace e2d diff --git a/untests/sources/untests_high/node.cpp b/untests/sources/untests_high/node.cpp index 9b6249e7..9a6563fe 100644 --- a/untests/sources/untests_high/node.cpp +++ b/untests/sources/untests_high/node.cpp @@ -429,6 +429,27 @@ TEST_CASE("node") { REQUIRE_FALSE(cn4->next_sibling()); } } + SECTION("child_at") { + auto p = node::create(); + + auto n1 = node::create(p); + auto n2 = node::create(p); + auto n3 = node::create(p); + + REQUIRE(p->child_at(0) == n1); + REQUIRE(p->child_at(1) == n2); + REQUIRE(p->child_at(2) == n3); + REQUIRE_FALSE(p->child_at(3)); + + { + const_node_iptr cp = p; + + REQUIRE(cp->child_at(0) == n1); + REQUIRE(cp->child_at(1) == n2); + REQUIRE(cp->child_at(2) == n3); + REQUIRE_FALSE(cp->child_at(3)); + } + } SECTION("add_child_to_back/add_child_to_front") { auto p = node::create(); auto n1 = node::create();