@@ -1834,24 +1834,50 @@ Node *Node::find_child(const String &p_pattern, bool p_recursive, bool p_owned)
1834
1834
// Can be recursive or not, and limited to owned nodes.
1835
1835
TypedArray<Node> Node::find_children (const String &p_pattern, const String &p_type, bool p_recursive, bool p_owned) const {
1836
1836
ERR_THREAD_GUARD_V (TypedArray<Node>());
1837
- TypedArray<Node> ret;
1838
- ERR_FAIL_COND_V (p_pattern.is_empty () && p_type.is_empty (), ret);
1839
- _update_children_cache ();
1840
- Node *const *cptr = data.children_cache .ptr ();
1841
- int ccount = data.children_cache .size ();
1842
- for (int i = 0 ; i < ccount; i++) {
1843
- if (p_owned && !cptr[i]->data .owner ) {
1844
- continue ;
1837
+ TypedArray<Node> matches;
1838
+ ERR_FAIL_COND_V (p_pattern.is_empty () && p_type.is_empty (), matches);
1839
+
1840
+ // Save basic pattern and type info for faster lookup
1841
+ bool is_pattern_empty = p_pattern.is_empty ();
1842
+ bool is_type_empty = p_type.is_empty ();
1843
+ bool is_type_global_class = !is_type_empty && ScriptServer::is_global_class (p_type);
1844
+ String type_global_path = is_type_global_class ? ScriptServer::get_global_class_path (p_type) : " " ;
1845
+
1846
+ TypedArray<Node> to_search;
1847
+ to_search.append (this );
1848
+ bool is_adding_children = true ;
1849
+ while (!to_search.is_empty ()) {
1850
+ Node *entry = Object::cast_to<Node>(to_search.pop_front ());
1851
+
1852
+ // Add all the children to the list to search
1853
+ entry->_update_children_cache ();
1854
+ if (is_adding_children) {
1855
+ Node *const *cptr = entry->data .children_cache .ptr ();
1856
+ int ccount = entry->data .children_cache .size ();
1857
+ for (int i = 0 ; i < ccount; i++) {
1858
+ if (p_owned && !cptr[i]->data .owner ) {
1859
+ continue ;
1860
+ }
1861
+
1862
+ to_search.append (cptr[i]);
1863
+ }
1864
+
1865
+ // Stop further child adding if we don't want recursive
1866
+ if (!p_recursive) {
1867
+ is_adding_children = false ;
1868
+ }
1845
1869
}
1846
1870
1847
- if (p_pattern.is_empty () || cptr[i]->data .name .operator String ().match (p_pattern)) {
1848
- if (p_type.is_empty () || cptr[i]->is_class (p_type)) {
1849
- ret.append (cptr[i]);
1850
- } else if (cptr[i]->get_script_instance ()) {
1851
- Ref<Script> scr = cptr[i]->get_script_instance ()->get_script ();
1871
+ // Check if the entry matches
1872
+ bool is_pattern_match = is_pattern_empty || entry->data .name .operator String ().match (p_pattern);
1873
+ bool is_type_match = is_type_empty || entry->is_class (p_type);
1874
+ bool is_script_type_match = false ;
1875
+ if (!is_type_match) {
1876
+ if (ScriptInstance *script_inst = entry->get_script_instance ()) {
1877
+ Ref<Script> scr = script_inst->get_script ();
1852
1878
while (scr.is_valid ()) {
1853
- if ((ScriptServer::is_global_class (p_type) && ScriptServer::get_global_class_path (p_type) == scr->get_path ()) || p_type == scr->get_path ()) {
1854
- ret. append (cptr[i]) ;
1879
+ if ((is_type_global_class && type_global_path == scr->get_path ()) || p_type == scr->get_path ()) {
1880
+ is_script_type_match = true ;
1855
1881
break ;
1856
1882
}
1857
1883
@@ -1860,12 +1886,13 @@ TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_ty
1860
1886
}
1861
1887
}
1862
1888
1863
- if (p_recursive) {
1864
- ret.append_array (cptr[i]->find_children (p_pattern, p_type, true , p_owned));
1889
+ // Save it if it matches the pattern and at least one type
1890
+ if (is_pattern_match && (is_type_match || is_script_type_match)) {
1891
+ matches.append (entry);
1865
1892
}
1866
1893
}
1867
1894
1868
- return ret ;
1895
+ return matches ;
1869
1896
}
1870
1897
1871
1898
void Node::reparent (Node *p_parent, bool p_keep_global_transform) {
0 commit comments