Repository: godotengine/godot (language: cpp)

Issue:
'Filter by Type' in the Scene Tree search bar does not handle user defined types via class_name
### Tested versions


- Linux, x64 
- Reproducible in 4.4.stable, Linux, x64, and 4.4.1.stable.

### System information

Godot v4.4.1.stable - Manjaro Linux #1 SMP PREEMPT_DYNAMIC Wed Dec 11 22:24:04 UTC 2024 on X11 - X11 display driver, Multi-window, 1 monitor - Vulkan (Forward+) - integrated Intel(R) HD Graphics 5500 (BDW GT2) - Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz (4 threads)

### Issue description

It seems this was handled by https://github.com/godotengine/godot/pull/58377, but does not address Types defined in nodes via `class_name MyType`. I think this breaks the expectation of filtering by type, since hovering on a node in the SceneTree, will reveal its most specific type, including the user defined.

The custom type nodes are matched when you specify a type that they inherit, but not the direct one.


### Steps to reproduce

Create a Scene with one node, with a script attached that defines its `class_name MyType`.
Go to the search bar in the Scene Tree in the same scene (or any other scene where the node is instantiated) and type `t:MyType`.

### Minimal reproduction project (MRP)

[bug_typesearch.zip](https://github.com/user-attachments/files/19614790/bug_typesearch.zip)


Discussion / hints:
Probably related to:
* https://github.com/godotengine/godot/issues/21789

Fix patch:
diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp
index ed104a341d6d..c100908a2e67 100644
--- a/editor/gui/scene_tree_editor.cpp
+++ b/editor/gui/scene_tree_editor.cpp
@@ -1107,6 +1107,33 @@ bool SceneTreeEditor::_update_filter(TreeItem *p_parent, bool p_scroll_to_select
 	return p_parent->is_visible();
 }
 
+bool SceneTreeEditor::_node_matches_class_term(const Node *p_item_node, const String &p_term) {
+	if (p_term.is_empty()) {
+		// Defend against https://github.com/godotengine/godot/issues/82473
+		return true;
+	}
+	Ref<Script> item_script = p_item_node->get_script();
+	while (item_script.is_valid()) {
+		String global_name = item_script->get_global_name();
+		if (global_name.to_lower().contains(p_term)) {
+			return true;
+		}
+		item_script = item_script->get_base_script();
+	}
+
+	String type = p_item_node->get_class();
+	// Every Node is a Node, duh!
+	while (type != "Node") {
+		if (type.to_lower().contains(p_term)) {
+			return true;
+		}
+
+		type = ClassDB::get_parent_class(type);
+	}
+
+	return false;
+}
+
 bool SceneTreeEditor::_item_matches_all_terms(TreeItem *p_item, const PackedStringArray &p_terms) {
 	if (p_terms.is_empty()) {
 		return true;
@@ -1122,18 +1149,8 @@ bool SceneTreeEditor::_item_matches_all_terms(TreeItem *p_item, const PackedStri
 
 			if (parameter == "type" || parameter == "t") {
 				// Filter by Type.
-				String type = get_node(p_item->get_metadata(0))->get_class();
-				bool term_in_inherited_class = false;
-				// Every Node is a Node, duh!
-				while (type != "Node") {
-					if (type.to_lower().contains(argument)) {
-						term_in_inherited_class = true;
-						break;
-					}
-
-					type = ClassDB::get_parent_class(type);
-				}
-				if (!term_in_inherited_class) {
+				Node *item_node = get_node(p_item->get_metadata(0));
+				if (!_node_matches_class_term(item_node, argument)) {
 					return false;
 				}
 			} else if (parameter == "group" || parameter == "g") {
diff --git a/editor/gui/scene_tree_editor.h b/editor/gui/scene_tree_editor.h
index d7eda45d3bf0..445f040453d8 100644
--- a/editor/gui/scene_tree_editor.h
+++ b/editor/gui/scene_tree_editor.h
@@ -146,6 +146,7 @@ class SceneTreeEditor : public Control {
 
 	void _test_update_tree();
 	bool _update_filter(TreeItem *p_parent = nullptr, bool p_scroll_to_selected = false);
+	bool _node_matches_class_term(const Node *p_item_node, const String &p_term);
 	bool _item_matches_all_terms(TreeItem *p_item, const PackedStringArray &p_terms);
 	void _tree_changed();
 	void _tree_process_mode_changed();


Test patch: