Skip to content

Commit 8a45f85

Browse files
authored
Merge pull request #59 from MisterPuma80/blazium_faster_find_children
Optimized Node.find_children:
2 parents d360605 + 3b7bb07 commit 8a45f85

File tree

1 file changed

+45
-18
lines changed

1 file changed

+45
-18
lines changed

scene/main/node.cpp

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,24 +1834,50 @@ Node *Node::find_child(const String &p_pattern, bool p_recursive, bool p_owned)
18341834
// Can be recursive or not, and limited to owned nodes.
18351835
TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_type, bool p_recursive, bool p_owned) const {
18361836
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+
}
18451869
}
18461870

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();
18521878
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;
18551881
break;
18561882
}
18571883

@@ -1860,12 +1886,13 @@ TypedArray<Node> Node::find_children(const String &p_pattern, const String &p_ty
18601886
}
18611887
}
18621888

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);
18651892
}
18661893
}
18671894

1868-
return ret;
1895+
return matches;
18691896
}
18701897

18711898
void Node::reparent(Node *p_parent, bool p_keep_global_transform) {

0 commit comments

Comments
 (0)