godot icon indicating copy to clipboard operation
godot copied to clipboard

Add hover state to Tree items display

Open davthedev opened this issue 1 year ago • 15 comments

Implements https://github.com/godotengine/godot-proposals/issues/7160https://github.com/godotengine/godot-proposals/issues/7160

Since this is a bit less trivial than other hover additions, here are some explanations.

This change aims at improving the usability of the scene tree and all places where a Tree control is used. Moving the mouse above a tree item highlights it.

The highlight is also rendered on individual hovered icon buttons. In this case, the main row or cell it belongs to keeps its highlight in a "dimmed" version. This helps focusing on the icon while keeping the visual relationship with the piece of data the action is likely to impact.

Example with a slightly customized theme to illustrate a dense list:

itemshover

Detail on the "dimmed hover" effect:

itemshover1

To make it more obvious, here it is with customized colors:

itemshover2

Projects can take advantage of the new styling possibilities. All new visual elements are customizable using appropriate theme resources.

Editor and default themes are adjusted to provide the additional theme resources. Other existing stuff is left untouched in this regard, so that there are no regressions on existing projects.

The Tree control is a complex widget, handling many possibilities of display. The display and original click handling algorithm is based on recursive traversal.

I implemented a direct, lighter way to find out which item is hovered that exactly matches, or at best attempt, the algorithm used to determine the clicked item, because mouse movemens happen more often.

This PR is exclusively adding support for hover feedback. It does not fix a few inconsistencies I found in click coordinates resolution, especially for the buttons attached to a cell (think the script, show/hide, etc... you see in the scene tree) with some combination of spacings. Those may be addressed in separate PRs. The goal here is that the hovered zones match the currently clickable zones.

A good part of the complexity is that there is an algorithm to move those icons towards the left in comparison to their original position in the cell if there is horizontal scrolling. This is what keeps the icon buttons visible in the scene tree at all times even if there is a long node name that overflows. The logic to compute that offset is a little complex and I had to replicate it. The said algorithm is not implemented in right-to-left display and some of the public methods that return the position of the in-cell buttons do not apply it - matter for separate issue reports.

davthedev avatar Feb 19 '24 02:02 davthedev

This complex control has to be refactored in order to fix some positioning quirks. This waits for a more important upgrade where it is admissible to potentially break some themes.

For the changes covered in this PR, I reproduced in the hover code the way side buttons are positioned including the quirks. For example, you can see those giggling sideways if you scroll the inspector horizontally when names are longer. The original click detection is a recursive tree traversal; for the hover I found a simpler way without having to hook up to this recursivity. That is less execution complexity as well for an event that occurs more often than clicks. As some refactoring is planned for later, I opted of the simpler solution.

davthedev avatar Mar 12 '24 01:03 davthedev

CC @passivestar as I believe you had Opinions™ on this type of hover/select UX ;)

akien-mga avatar Mar 23 '24 23:03 akien-mga

CC @passivestar as I believe you had Opinions™ on this type of hover/select UX ;)

I like it, I think godot needs it. I actually wanted to work on this myself before I discovered this PR

I think I found a bug where it sometimes won't unhover when the mouse leaves the dock:

https://github.com/godotengine/godot/assets/60579014/f9e38469-ac2b-4cc4-8ee3-ce8fa449dee0

passivestar avatar Mar 24 '24 09:03 passivestar

I think I found a bug where it sometimes won't unhover when the mouse leaves the dock:

@davthedev Would you have time to see if you can reproduce and fix that issue?

akien-mga avatar Apr 04 '24 11:04 akien-mga

Sure! I will have more time to have a look in a couple days.

davthedev avatar Apr 04 '24 13:04 davthedev

Tree seems to be getting an InputEventMouseMotion after NOTIFICATION_MOUSE_EXIT, causing cache.hover_item to be set again before the queued redraw, which causes the bug that I found

You could either delay nullifying cache.hover_item to make sure it's null before the redraw happens, or properly check that the mouse cursor is in the tree when we're setting things in gui_input

None of that seems ideal though and I find it weird that we're getting a mouse motion event after the mouse exit notification, is it the intended behavior in godot?

passivestar avatar Apr 13 '24 21:04 passivestar

Also noted another couple bugs I should fix:

  • If the content is refreshed while hovering, the highlight is lost until the next mouse move. This happens on the "Distant" nodes tree while a scene is running.

  • Hover highlight is also visible during a drag-drop operation and can be misleading at that moment, as the one thing that should be highlighted during this operation is the drop target.

davthedev avatar Apr 16 '24 18:04 davthedev

Just fixed the two bugs above. Changed the mouse over (or not) tracking logic to tentatively fix @passivestar hover feedback bug, relying on MOUSE_ENTER / _EXIT notifications. As I was not able to reproduce on my side, can you have a look?

davthedev avatar Apr 22 '24 16:04 davthedev

As I was not able to reproduce on my side, can you have a look?

The bug is gone 🥳

I noticed two other things though:

  1. Hovering in the project manager is broken now? It uses a bright thin outline instead of whatever is was before

https://github.com/godotengine/godot/assets/60579014/0d0f5b35-f9ce-4727-8b56-21e6425061b1

  1. When hovering in a tree that has more than one main non-button column it highlights the right column, which doesn't always make sense semantically. In the shortcuts editor for example those buttons are related to the entire row, not just the rightmost column. When using trees in games it might not always make sense either

https://github.com/godotengine/godot/assets/60579014/e2578f49-6162-42ea-9ab5-5254a155049d

Perhaps when a tree has more than 2 main columns and you're hovering over a button it should highlight ALL of the columns or NONE of them, instead of the right one?

passivestar avatar Apr 22 '24 18:04 passivestar

I noticed two other things though:

1. Hovering in the project manager is broken now? It uses a bright thin outline instead of whatever is was before

Looks like a broken editor theme. The thin grey outline is the default StyleBox when nothing is specified in the system theme; I will have a look. I rebased my month-old work with lots of commits in between, probable collateral damage...

2. When hovering in a tree that has more than one main non-button column it highlights the right column, which doesn't always make sense semantically. In the shortcuts editor for example those buttons are related to the entire row, not just the rightmost column. When using trees in games it might not always make sense either

Because there are multiple possible select modes in the Tree control that can be set on each instance: entire row or single cell. The view you are referring to is in single-cell mode, unlike the node tree. It works like a spreadsheet editor. I think it is up to this specific screen to work its way around instead by configuring the Tree control instance correctly.

Here, the cell is the actual binding, which you can edit using the dedicated buttons. Makes sense IMHO.

If some actions need to relate to the whole row, while keeping the separate cell selection possible, there are multiple options:

  • Configure this screen in single-row selection mode - check UX as, for now, double-clicking the left cell unfolds the tree, and double-clicking the right cell opens the binding edit dialog.
  • Make a separate third column for the buttons
  • Add a setting to the Tree control mandating to highlight the whole row on specific cells / columns or buttons. Or a "select single cell but highlight whole row on buttons" selection mode

davthedev avatar Apr 22 '24 18:04 davthedev

I guess my main concern is not the shortcut window but the fact that the last column will always be highlighted in this mode whenever somebody makes a game with a spreadsheet in it. Kind of random? It seems like checking if there's more than one column and not highlighting any column (only highlighting the button) in this mode would be a more sensible default imo

passivestar avatar Apr 22 '24 19:04 passivestar