Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Tree Search Functionality with Highlighting and Filtering #229

Merged
merged 3 commits into from
Oct 13, 2024

Conversation

monxa
Copy link
Contributor

@monxa monxa commented Sep 25, 2024

Closes #192

Tested with GDExtension and Module.

Features:

  • Tree highlighting: Highlights items that match the search query.
  • Counting descendants: Shows the number of matching items within collapsed branches.
  • Jump to next match: on enter.
  • (Limbo-)Shortcut: Default CTRL-F.
  • Menu entry: Misc->Search Tree.

Known issues:

  • Unnecessarily redundant signals (af15dde)
  • TreeSearch::_draw_highlight_item: uses one magic number (same as engine code)
  • Performance
  • Editor scaling needs fixing (380f80c)
  • Searchbar spacing should be adjusted. (Already similar to Docs/Script search bar with 8c32395)
  • Word highlight drawing might be too obstructive. Especially in filter mode. (Will be solved after this is merged)
  • Jumping through entries currently inconsistent (8d29f16, 47706e9)
  • Filtering unstable. (74cf985, 465757e)
  • Decide if the current case matching behavior needs adjustment. Current: Match case when input includes capital letter.

Wishlist (non-blockers)

  1. Word highlight drawing might be too obstructive. Especially in filter mode.
    • Remember separate search-mask SearchInfo for each tab. (10c8f58)
    • Buttons for select next/previous entry (align with script/docs viewport). (ec6c4c3)
  2. Remember and restore tree collapse on jumping

This pr includes a significant amount of new code (~500 lines). I would greatly appreciate any feedback, especially regarding the known issues listed above.

demo_filter_tree.webm

@monxa monxa marked this pull request as draft September 26, 2024 05:55
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.h Outdated Show resolved Hide resolved
@limbonaut
Copy link
Owner

Thanks for submitting! Since it's a big chunk of code, I need some time to review it fully.

Got a crash during testing: with an active search, I switched to another tab and pressed enter. It's one of those cached TreeItem pointers, judging by the backtrace.

Thinking about it, search state should probably be remembered per tab. I only skimmed through your code a little bit, and it doesn't look like it's the case, but would require changes to achieve that. Maybe TreeSearch instances could be kept per tab? But those TreeItem pointers are a problem then - they must be invalidated as soon as the user switches to another tab (or Tree is rebuilt).

@monxa
Copy link
Contributor Author

monxa commented Sep 26, 2024

Thanks for submitting! Since it's a big chunk of code, I need some time to review it fully.

Got a crash during testing: with an active search, I switched to another tab and pressed enter. It's one of those cached TreeItem pointers, judging by the backtrace.

Thinking about it, search state should probably be remembered per tab. I only skimmed through your code a little bit, and it doesn't look like it's the case, but would require changes to achieve that. Maybe TreeSearch instances could be kept per tab? But those TreeItem pointers are a problem then - they must be invalidated as soon as the user switches to another tab (or Tree is rebuilt).

Great catch!

@monxa
Copy link
Contributor Author

monxa commented Sep 26, 2024

Yes this is a good chunk of code. And I expect much of it not to align with what you want. Please take your time for review(s).

Will later find some time to address invalidation and add some FAIL-conds.

You are thinking into an interesting direction with your proposal of caching multiple tabs.
I think that would need the TreeSearch to have access to TaskTree. I tried to avoid that in favor of molecularity and to avoid circular includes. If you need this to be changed into such an direction tho: I am very open to make the necessary changes.

Edit: Now that I think about it, it'd not be necessary to include the TaskTree. We could pass the necessary information down into the TreeSearch. E.G. the current tree reference.

For now tho, I will make this work without error before such major changes.

@monxa
Copy link
Contributor Author

monxa commented Sep 27, 2024

Got a crash during testing: with an active search, I switched to another tab and pressed enter. It's one of those cached TreeItem pointers, judging by the backtrace.

47706e9
Fixed a rather prevalent issue within TreeSearch::_select_item that led to the nullptr exception.

9a1641e
Moved the TreeSearch::update_tree call from TaskTree::_update_tree to TaskTree::_create_tree. This should catch all cases where the task tree gets updated, also those where it gets updated from the Editor Plugin directly. AFAIK, the caching approach is infeasible. We don't cache trees at all after all. If you want to transition towards such a solution in the future, I apologize for any additional implementation considerations this solution causes.

Copy link
Owner

@limbonaut limbonaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beware, nitpicks incoming 🤣

editor/limbo_ai_editor_plugin.cpp Outdated Show resolved Hide resolved
editor/limbo_ai_editor_plugin.cpp Outdated Show resolved Hide resolved
editor/task_tree.cpp Show resolved Hide resolved
editor/task_tree.cpp Outdated Show resolved Hide resolved
editor/task_tree.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
@limbonaut
Copy link
Owner

I've tested it, and it works really well - didn't find any other issues. If you are concerned about the selection box being confusing, we can try a custom StyleBox: a filled square built from the font color with the alpha set somewhere in [0.1,0.9] range - should work with any theme, I believe.

Some additional suggestions:

  • Show "Ctrl+F" shortcut in the Misc menu (already mentioned in a comment)
  • Remember search state per UI tab (borderline out-of-scope - we can make an issue to track it instead)
  • Also, case sensitivity can be unintuitive: I mistyped "playAnimation" and was surprised that it didn't find anything (not sure if it's an issue, though).

editor/tree_search.cpp Outdated Show resolved Hide resolved
monxa added a commit to monxa/limboai that referenced this pull request Sep 29, 2024
This commit vastly improves performance by not updating the tree
for search mask.

From this commit onward, we are in very unstable territory.

Relates to: limbonaut#229
monxa added a commit to monxa/limboai that referenced this pull request Sep 29, 2024
Experimental, hence this is on a different branch.

This commit vastly improves performance by not updating the tree
for search mask changes.

Relates to: limbonaut#229
monxa added a commit to monxa/limboai that referenced this pull request Sep 29, 2024
* Improve TreeSearch performance.

Experimental, hence this is on a different branch.

This commit vastly improves performance by not updating the tree
for search mask changes.

Relates to: limbonaut#229

* Fix SearchTree overdraw after performance optimization

* Manage Performance optimizations: TreeSearch no. 2
- Carefully manage callable_cache
- Only clear filter when previously filtered
- Reintroduce sorting for ordered_tree_items

This commit addresses performance issues in TreeSearch and fixes
a critical bug where ordered_tree_items was not being sorted.
The bug was introduced during a merge with the main feature branch.

* Use queue_redraw as much as possible for Tree updates.

* Fix TreeSearch after performance considerations
editor/tree_search.h Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
@monxa monxa force-pushed the tasktree-search branch 9 times, most recently from 55d47a3 to b7af98e Compare October 4, 2024 13:51
@monxa monxa changed the title WIP: Implement Tree Search Functionality with Highlighting and Filtering Implement Tree Search Functionality with Highlighting and Filtering Oct 4, 2024
@monxa monxa marked this pull request as ready for review October 4, 2024 14:35
@monxa
Copy link
Contributor Author

monxa commented Oct 4, 2024

As discussed. Squash incoming...

@monxa monxa force-pushed the tasktree-search branch 5 times, most recently from 14cfb14 to 93524dd Compare October 6, 2024 04:45
This commit introduces a comprehensive Tree Search feature, including:
- Tree highlighting: Highlights items that match the search query.
- Tree filtering: Filters items so only matches and descendants are
  shown.
- Counting descendants: Shows the number of matching items within collapsed branches.
- Jump to next match: on enter.
- (Limbo-)Shortcut: Default CTRL-F.
- Menu entry: Misc->Search Tree.
- Remember separate SearchInfo for each tab.

Key implementation details:
- Optimized performance for large trees
- Implemented recursive filtering for efficiency
- Added UI elements including next/previous match buttons

Development History:
- Initial implementation of highlighting and filtering
- Multiple rounds of performance optimization
- Bug fixes and refactoring for correctness
- UI enhancements and polish
- Code cleanup and style improvements
@ydeltastar
Copy link
Contributor

It works really well even with drag and drop. The only major issue I noticed is that when I have a task named AnimationTreeTravel, "animationtreetravel" gets a match but "animationTreetravel" or other case variations don't.

@monxa
Copy link
Contributor Author

monxa commented Oct 12, 2024

It works really well even with drag and drop. The only major issue I noticed is that when I have a task named AnimationTreeTravel, "animationtreetravel" gets a match but "animationTreetravel" or other case variations don't.

Yes. The current behavior: Match case when input contains capital letter. Might need adjustment: Not intuitive. @limbonaut also pointed this out.

IMO, we can easily change that after this is merged.
We can do either:

  • Always case-insensitive (Same as in docs)
  • "Match Case"-Checkbox (Same as in script editor)

@limbonaut
Copy link
Owner

It works really well even with drag and drop. The only major issue I noticed is that when I have a task named AnimationTreeTravel, "animationtreetravel" gets a match but "animationTreetravel" or other case variations don't.

From reading the code, I think the idea is that if you supply a lower-case string, the search assumes case-insensitive, and if you mix-in CAPS - it assumes case-sensitive. We are trying to establish if it's a bug or a feature.

@ydeltastar
Copy link
Contributor

Match case when input contains capital letter.

The search's placeholder text should probably include this as a hint.

Copy link
Owner

@limbonaut limbonaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! I've added just a few suggestions. In testing, it works like a charm.

We can consider if the case-sensitive issue needs changing, but no need to block this PR until that decision is made.

editor/limbo_ai_editor_plugin.cpp Outdated Show resolved Hide resolved
editor/limbo_ai_editor_plugin.h Show resolved Hide resolved
editor/limbo_ai_editor_plugin.cpp Outdated Show resolved Hide resolved
editor/tree_search.h Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
editor/tree_search.cpp Outdated Show resolved Hide resolved
Remove redundant comment

Prune tab_search_context

Fix restore tab on `_tab_closed`

Add break statement

Pass callable by reference in _draw_highlight_item

Refactor _initialize_controls into constructor

Remove redundant if (!line_edit_search)-check
@monxa
Copy link
Contributor Author

monxa commented Oct 13, 2024

MacOS task appears to be broken.

Fixed on master. See:
godotengine/godot#97981

@monxa
Copy link
Contributor Author

monxa commented Oct 13, 2024

The search's placeholder text should probably include this as a hint.

Does a tooltip for the search box suffice for now?

line_edit_search->set_tooltip_text("Match case if input contains capital letter.");

@limbonaut
Copy link
Owner

MacOS task appears to be broken.

Fixed on master. See: godotengine/godot#97981

Hmm, bummer.

@limbonaut
Copy link
Owner

Looks like it's good to merge 👍
I just need to fix the Vulkan SDK in CI.

@limbonaut
Copy link
Owner

Great stuff! ❤️ Thanks for the contribution.

@limbonaut limbonaut merged commit 19d771f into limbonaut:master Oct 13, 2024
14 of 16 checks passed
@monxa monxa deleted the tasktree-search branch October 14, 2024 23:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

A way to filter tasks in the tree view
3 participants