@@ -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.
20062006TypedArray<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