diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 42418b3e8dd8..cb0a24a8ef8b 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -253,6 +253,18 @@ [b]Note:[/b] As this method walks upwards in the scene tree, it can be slow in large, deeply nested scene trees. Whenever possible, consider using [method get_node] with unique names instead (see [member unique_name_in_owner]), or caching the node references into variable. + + + + Returns the number of ancestor nodes. + + + + + + Returns an array of references to node's ancestors. + + @@ -280,6 +292,22 @@ If [param include_internal] is [code]false[/code], the returned array won't include internal children (see [code]internal[/code] parameter in [method add_child]). + + + + + Returns the number of descendant nodes. + If [param include_internal] is [code]false[/code], the returned array won't include internal descendants (see [code]internal[/code] parameter in [method add_child]). + + + + + + + Returns an array of references to node's descendants. + If [param include_internal] is [code]false[/code], the returned array won't include internal descendants (see [code]internal[/code] parameter in [method add_child]). + + diff --git a/scene/main/node.cpp b/scene/main/node.cpp index b947526e9685..14e495103f6f 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1289,6 +1289,51 @@ Node *Node::_get_child_by_name(const StringName &p_name) const { } } +int Node::get_descendant_count(bool p_include_internal) const { + int count = 0; + TypedArray children = get_children(p_include_internal); + count += children.size(); + for (int i = 0; i < children.size(); i++) { + Node *node = Object::cast_to(children[i]); + if (node->get_child_count(p_include_internal) > 0) { + count += node->get_descendant_count(p_include_internal); + } + } + return count; +} + +TypedArray Node::get_descendants(bool p_include_internal) const { + TypedArray res = get_children(p_include_internal); + TypedArray children = get_children(p_include_internal); + for (int i = 0; i < children.size(); i++) { + Node *node = Object::cast_to(children[i]); + if (node->get_child_count(p_include_internal) > 0) { + res.append_array(node->get_descendants(p_include_internal)); + } + } + return res; +} + +int Node::get_ancestor_count() const { + int count = 0; + const Node* current_node = this; + while (current_node->get_parent() != nullptr){ + count++; + current_node = current_node->get_parent(); + } + return count; +} + +TypedArray Node::get_ancestors() const { + TypedArray res; + const Node* current_node = this; + while (current_node->get_parent() != nullptr){ + res.append(current_node); + current_node = current_node->get_parent(); + } + return res; +} + Node *Node::get_node_or_null(const NodePath &p_path) const { if (p_path.is_empty()) { return nullptr; @@ -2857,6 +2902,10 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_child_count", "include_internal"), &Node::get_child_count, DEFVAL(false)); // Note that the default value bound for include_internal is false, while the method is declared with true. This is because internal nodes are irrelevant for GDSCript. ClassDB::bind_method(D_METHOD("get_children", "include_internal"), &Node::get_children, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_child", "idx", "include_internal"), &Node::get_child, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_descendants", "include_internal"), &Node::get_descendants, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_descendant_count", "include_internal"), &Node::get_descendant_count, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_ancestors"), &Node::get_ancestors); + ClassDB::bind_method(D_METHOD("get_ancestor_count"), &Node::get_ancestor_count); ClassDB::bind_method(D_METHOD("has_node", "path"), &Node::has_node); ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node); ClassDB::bind_method(D_METHOD("get_node_or_null", "path"), &Node::get_node_or_null); diff --git a/scene/main/node.h b/scene/main/node.h index b355c27b04a6..3577f5989715 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -331,6 +331,10 @@ class Node : public Object { int get_child_count(bool p_include_internal = true) const; Node *get_child(int p_index, bool p_include_internal = true) const; TypedArray get_children(bool p_include_internal = true) const; + TypedArray get_descendants(bool p_include_internal = true) const; + int get_descendant_count(bool p_include_internal = true) const; + TypedArray get_ancestors() const; + int get_ancestor_count() const; bool has_node(const NodePath &p_path) const; Node *get_node(const NodePath &p_path) const; Node *get_node_or_null(const NodePath &p_path) const;