diff --git a/editor/tree_search.cpp b/editor/tree_search.cpp index 0b3a8f5..f35d047 100644 --- a/editor/tree_search.cpp +++ b/editor/tree_search.cpp @@ -56,29 +56,41 @@ void TreeSearch::_clean_callable_cache() { } void TreeSearch::_filter_tree(const String &p_search_mask) { - if (matching_entries.size() == 0) { + if (matching_entries.is_empty()) { return; } + Vector item_visibilities; + item_visibilities.resize(ordered_tree_items.size()); + + // Make all entries visible that have any matching descendents. O(n) for (int i = 0; i < ordered_tree_items.size(); i++) { - TreeItem *cur_item = ordered_tree_items[i]; - - if (number_matches.has(cur_item)) { - continue; + TreeItem *entry = ordered_tree_items[i]; + if (number_matches.has(entry) && number_matches[entry] > 0) { + item_visibilities.set(i, true); } + } - TreeItem *first_counting_ancestor = cur_item; - bool parents_visible = true; - while (first_counting_ancestor && !number_matches.has(first_counting_ancestor)) { - // Performance: we only need to check the first visible ancestor. This is already optimal because of the ordering in ordered_tree_items. - if (!first_counting_ancestor->is_visible()){ - parents_visible = false; - break; + // Make all descendents of matching entries visible. O(n) * log(|matching_entries|) + for (int i = 0; i < ordered_tree_items.size(); i++) { + TreeItem *entry = ordered_tree_items[i]; + TreeItem *next_entry = entry->get_next(); + if (!next_entry && i < ordered_tree_items.size() - 1) { + next_entry = ordered_tree_items[i + 1]; + } + if (_vector_has_bsearch(matching_entries, entry)) { + int j = i; + for (; j < ordered_tree_items.size() && ordered_tree_items[j] != next_entry; j++) { + item_visibilities.set(j, true); } - first_counting_ancestor = first_counting_ancestor->get_parent(); + i = j - 1; // every entry is only processed once. } - if (!parents_visible || !first_counting_ancestor || !_vector_has_bsearch(matching_entries, first_counting_ancestor)) { - cur_item->set_visible(false); + } + + // apply visibility. O(n) + for (int i = 0; i < ordered_tree_items.size(); i++) { + if (!item_visibilities[i]) { + ordered_tree_items[i]->set_visible(false); } } }