From 78dc608aa891e5076f710bbdb530adbc851832ec Mon Sep 17 00:00:00 2001 From: diddykonga Date: Fri, 17 Dec 2021 12:04:35 -0600 Subject: [PATCH] Change 'find_node' to 'find_nodes' and Add 'type' parameter Changed 'find_node' to 'find_nodes' which now returns an 'TypedArray', as well as Added a 'type' parameter to match against specific node types, which supports inheritance. --- doc/classes/Node.xml | 17 ++++++----- editor/import/scene_import_settings.cpp | 5 ++-- scene/main/node.cpp | 38 ++++++++++++++++++------- scene/main/node.h | 2 +- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 5ae50f86d4c..aa3de1382f5 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -181,16 +181,19 @@ [b]Note:[/b] It will not work properly if the node contains a script with constructor arguments (i.e. needs to supply arguments to [method Object._init] method). In that case, the node will be duplicated without a script. - - + + - - + + + - Finds a descendant of this node whose name matches [code]mask[/code] as in [method String.match] (i.e. case-sensitive, but [code]"*"[/code] matches zero or more characters and [code]"?"[/code] matches any single character except [code]"."[/code]). Returns [code]null[/code] if no matching [Node] is found. - [b]Note:[/b] It does not match against the full path, just against individual node names. + Finds descendants of this node whose, name matches [code]mask[/code] as in [method String.match], and/or type matches [code]type[/code] as in [method Object.is_class]. + [code]mask[/code] does not match against the full path, just against individual node names. It is case-sensitive, with [code]"*"[/code] matching zero or more characters and [code]"?"[/code] matching any single character except [code]"."[/code]). + [code]type[/code] will check equality or inheritance. It is case-sensitive, [code]"Object"[/code] will match a node whose type is [code]"Node"[/code] but not the other way around. If [code]owned[/code] is [code]true[/code], this method only finds nodes whose owner is this node. This is especially important for scenes instantiated through a script, because those scenes don't have an owner. - [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get a reference to another node. Whenever possible, consider using [method get_node] instead. To avoid using [method find_node] too often, consider caching the node reference into a variable. + Returns an empty array, if no matching nodes are found. + [b]Note:[/b] As this method walks through all the descendants of the node, it is the slowest way to get references to other nodes. To avoid using [method find_nodes] too often, consider caching the node references into variables. diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp index 488bd02de4d..4e062530410 100644 --- a/editor/import/scene_import_settings.cpp +++ b/editor/import/scene_import_settings.cpp @@ -377,9 +377,10 @@ void SceneImportSettings::_update_view_gizmos() { continue; } - MeshInstance3D *collider_view = static_cast(mesh_node->find_node("collider_view")); - CRASH_COND_MSG(collider_view == nullptr, "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); + TypedArray descendants = mesh_node->find_nodes("collider_view", "MeshInstance3D"); + CRASH_COND_MSG(descendants.is_empty(), "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`."); + MeshInstance3D *collider_view = static_cast(descendants[0].operator Object *()); collider_view->set_visible(generate_collider); if (generate_collider) { // This collider_view doesn't have a mesh so we need to generate a new one. diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 42a2e41a085..560e1eccbb6 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1344,27 +1344,45 @@ bool Node::has_node(const NodePath &p_path) const { return get_node_or_null(p_path) != nullptr; } -Node *Node::find_node(const String &p_mask, bool p_recursive, bool p_owned) const { +TypedArray Node::find_nodes(const String &p_mask, const String &p_type, bool p_recursive, bool p_owned) const { + TypedArray ret; + ERR_FAIL_COND_V(p_mask.is_empty() && p_type.is_empty(), ret); + Node *const *cptr = data.children.ptr(); int ccount = data.children.size(); for (int i = 0; i < ccount; i++) { if (p_owned && !cptr[i]->data.owner) { continue; } - if (cptr[i]->data.name.operator String().match(p_mask)) { - return cptr[i]; + + if (!p_mask.is_empty()) { + if (!cptr[i]->data.name.operator String().match(p_mask)) { + continue; + } else if (p_type.is_empty()) { + ret.append(cptr[i]); + } } - if (!p_recursive) { - continue; + if (cptr[i]->is_class(p_type)) { + ret.append(cptr[i]); + } else if (cptr[i]->get_script_instance()) { + Ref