Skip to content

Commit 351ea12

Browse files
committed
Use iterative approach
1 parent c3d3188 commit 351ea12

File tree

1 file changed

+52
-23
lines changed

1 file changed

+52
-23
lines changed

scene/main/node.cpp

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,42 +2005,71 @@ Node *Node::find_child(const String &p_pattern, bool p_recursive, bool p_owned)
20052005
// Can be recursive or not, and limited to owned nodes.
20062006
TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_type, bool p_recursive, bool p_owned) const {
20072007
ERR_THREAD_GUARD_V(TypedArray<Node>());
2008+
20082009
TypedArray<Node> ret;
20092010
ERR_FAIL_COND_V(p_pattern.is_empty() && p_type.is_empty(), ret);
20102011

2011-
const auto find_children_add = [&](const auto &p_find_children_add, TypedArray<Node> &p_array, const Node *p_current_node) -> void {
2012-
p_current_node->_update_children_cache();
2012+
// Start at first child
2013+
_update_children_cache();
2014+
if (data.children_cache.is_empty()) {
2015+
return ret;
2016+
}
2017+
const Node *current_node = data.children_cache[0];
20132018

2014-
Node *const *cptr = p_current_node->data.children_cache.ptr();
2015-
int ccount = p_current_node->data.children_cache.size();
2016-
for (int i = 0; i < ccount; i++) {
2017-
if (p_owned && !cptr[i]->data.owner) {
2018-
continue;
2019+
// Check current node repeatedly
2020+
while (current_node != this) {
2021+
if (p_owned && !current_node->data.owner) {
2022+
continue;
2023+
}
2024+
2025+
if (p_pattern.is_empty() || current_node->data.name.operator String().match(p_pattern)) {
2026+
if (p_type.is_empty() || current_node->is_class(p_type)) {
2027+
ret.append(current_node);
2028+
} else if (current_node->get_script_instance()) {
2029+
Ref<Script> scr = current_node->get_script_instance()->get_script();
2030+
while (scr.is_valid()) {
2031+
if ((ScriptServer::is_global_class(p_type) && ScriptServer::get_global_class_path(p_type) == scr->get_path()) || p_type == scr->get_path()) {
2032+
ret.append(current_node);
2033+
break;
2034+
}
2035+
2036+
scr = scr->get_base_script();
2037+
}
20192038
}
2039+
}
20202040

2021-
if (p_pattern.is_empty() || cptr[i]->data.name.operator String().match(p_pattern)) {
2022-
if (p_type.is_empty() || cptr[i]->is_class(p_type)) {
2023-
p_array.append(cptr[i]);
2024-
} else if (cptr[i]->get_script_instance()) {
2025-
Ref<Script> scr = cptr[i]->get_script_instance()->get_script();
2026-
while (scr.is_valid()) {
2027-
if ((ScriptServer::is_global_class(p_type) && ScriptServer::get_global_class_path(p_type) == scr->get_path()) || p_type == scr->get_path()) {
2028-
p_array.append(cptr[i]);
2029-
break;
2030-
}
2041+
current_node->_update_children_cache();
20312042

2032-
scr = scr->get_base_script();
2043+
if (p_recursive) {
2044+
// Try go to first child
2045+
if (!current_node->data.children_cache.is_empty()) {
2046+
current_node = current_node->data.children_cache[0];
2047+
}
2048+
// Find next sibling
2049+
else {
2050+
while (current_node != this) {
2051+
const LocalVector<Node *> &siblings = current_node->data.parent->data.children_cache;
2052+
2053+
// Try go to next sibling
2054+
if (current_node->data.index + 1 < siblings.size()) {
2055+
current_node = siblings[current_node->data.index + 1];
2056+
break;
2057+
}
2058+
// Go back to parent
2059+
else {
2060+
current_node = current_node->data.parent;
20332061
}
20342062
}
20352063
}
2064+
}
2065+
else {
2066+
const LocalVector<Node *> &siblings = current_node->data.parent->data.children_cache;
20362067

2037-
if (p_recursive) {
2038-
p_find_children_add(p_find_children_add, p_array, cptr[i]);
2039-
}
2068+
// Go to next sibling
2069+
current_node = siblings[current_node->data.index + 1];
20402070
}
2041-
};
2071+
}
20422072

2043-
find_children_add(find_children_add, ret, this);
20442073
return ret;
20452074
}
20462075

0 commit comments

Comments
 (0)