Browse Source

Merge pull request #65352 from Mickeon/try-scene-tree-filter-multi-word

Rémi Verschelde 3 năm trước cách đây
mục cha
commit
211631801d

+ 80 - 9
editor/scene_tree_editor.cpp

@@ -603,7 +603,7 @@ void SceneTreeEditor::_update_tree(bool p_scroll_to_selected) {
 	updating_tree = false;
 	updating_tree = false;
 	tree_dirty = false;
 	tree_dirty = false;
 
 
-	if (!filter.is_empty()) {
+	if (!filter.strip_edges().is_empty()) {
 		_update_filter(nullptr, p_scroll_to_selected);
 		_update_filter(nullptr, p_scroll_to_selected);
 	}
 	}
 }
 }
@@ -618,18 +618,28 @@ bool SceneTreeEditor::_update_filter(TreeItem *p_parent, bool p_scroll_to_select
 		return false;
 		return false;
 	}
 	}
 
 
-	bool keep = false;
+	bool keep_for_children = false;
 	for (TreeItem *child = p_parent->get_first_child(); child; child = child->get_next()) {
 	for (TreeItem *child = p_parent->get_first_child(); child; child = child->get_next()) {
-		keep = _update_filter(child, p_scroll_to_selected) || keep;
+		// Always keep if at least one of the children are kept.
+		keep_for_children = _update_filter(child, p_scroll_to_selected) || keep_for_children;
 	}
 	}
 
 
-	if (!keep) {
-		StringName node_type = get_node(p_parent->get_metadata(0))->get_class();
-		bool is_kept_by_type = (filter.begins_with("type:") && filter.trim_prefix("type:").is_subsequence_ofn(node_type)) || (filter.begins_with("t:") && filter.trim_prefix("t:").is_subsequence_ofn(node_type));
-		keep = (filter.is_subsequence_ofn(p_parent->get_text(0)) || is_kept_by_type);
+	// Now find other reasons to keep this Node, too.
+	PackedStringArray terms = filter.to_lower().split_spaces();
+	bool keep = _item_matches_all_terms(p_parent, terms);
+
+	p_parent->set_visible(keep_for_children || keep);
+	if (keep_for_children) {
+		if (keep) {
+			p_parent->clear_custom_color(0);
+			p_parent->set_selectable(0, true);
+		} else {
+			p_parent->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), SNAME("Editor")));
+			p_parent->set_selectable(0, false);
+			p_parent->deselect(0);
+		}
 	}
 	}
 
 
-	p_parent->set_visible(keep);
 	if (editor_selection) {
 	if (editor_selection) {
 		Node *n = get_node(p_parent->get_metadata(0));
 		Node *n = get_node(p_parent->get_metadata(0));
 		if (keep) {
 		if (keep) {
@@ -644,7 +654,68 @@ bool SceneTreeEditor::_update_filter(TreeItem *p_parent, bool p_scroll_to_select
 		}
 		}
 	}
 	}
 
 
-	return keep;
+	return keep || keep_for_children;
+}
+
+bool SceneTreeEditor::_item_matches_all_terms(TreeItem *p_item, PackedStringArray p_terms) {
+	if (p_terms.is_empty()) {
+		return true;
+	}
+
+	for (int i = 0; i < p_terms.size(); i++) {
+		String term = p_terms[i];
+
+		// Recognise special filter.
+		if (term.contains(":") && !term.get_slicec(':', 0).is_empty()) {
+			String parameter = term.get_slicec(':', 0);
+			String argument = term.get_slicec(':', 1);
+
+			if (parameter == "type" || parameter == "t") {
+				// Filter by Type.
+				String node_type = get_node(p_item->get_metadata(0))->get_class().to_lower();
+
+				if (!node_type.contains(argument)) {
+					return false;
+				}
+			} else if (parameter == "group" || parameter == "g") {
+				// Filter by Group.
+				Node *node = get_node(p_item->get_metadata(0));
+
+				List<Node::GroupInfo> group_info_list;
+				node->get_groups(&group_info_list);
+				if (group_info_list.is_empty()) {
+					return false;
+				}
+				// When argument is empty, match all Nodes belonging to any group.
+				if (!argument.is_empty()) {
+					bool term_in_groups = false;
+					for (int j = 0; j < group_info_list.size(); j++) {
+						// Ignore private groups.
+						if (String(group_info_list[j].name).begins_with("__")) {
+							continue;
+						}
+						if (String(group_info_list[j].name).to_lower().contains(argument)) {
+							term_in_groups = true;
+							break;
+						}
+					}
+					if (!term_in_groups) {
+						return false;
+					}
+				}
+			} else {
+				WARN_PRINT(vformat(TTR("Special Node filter \"%s\" is not recognised. Available filters include \"type\" and \"group\"."), parameter));
+				continue;
+			}
+		} else {
+			// Default.
+			if (!p_item->get_text(0).to_lower().contains(term)) {
+				return false;
+			}
+		}
+	}
+
+	return true;
 }
 }
 
 
 void SceneTreeEditor::_compute_hash(Node *p_node, uint64_t &hash) {
 void SceneTreeEditor::_compute_hash(Node *p_node, uint64_t &hash) {

+ 1 - 0
editor/scene_tree_editor.h

@@ -78,6 +78,7 @@ class SceneTreeEditor : public Control {
 	void _test_update_tree();
 	void _test_update_tree();
 	void _update_tree(bool p_scroll_to_selected = false);
 	void _update_tree(bool p_scroll_to_selected = false);
 	bool _update_filter(TreeItem *p_parent = nullptr, bool p_scroll_to_selected = false);
 	bool _update_filter(TreeItem *p_parent = nullptr, bool p_scroll_to_selected = false);
+	bool _item_matches_all_terms(TreeItem *p_item, PackedStringArray p_terms);
 	void _tree_changed();
 	void _tree_changed();
 	void _tree_process_mode_changed();
 	void _tree_process_mode_changed();
 	void _node_removed(Node *p_node);
 	void _node_removed(Node *p_node);