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;