diff options
author | Hugo Locurcio <hugo.locurcio@hugo.pro> | 2022-03-21 22:59:34 +0100 |
---|---|---|
committer | Hugo Locurcio <hugo.locurcio@hugo.pro> | 2022-04-08 01:43:21 +0200 |
commit | f064258aee20ad5680d95fecb803cd02ab5bf1e6 (patch) | |
tree | ea64fcf87fc2d9a3650ec96a8bbf25d9a4dcbb5f | |
parent | 748fde8df0c85d63adb2d81fdab149d8f56cedc0 (diff) |
Highlight hovered keyframes in the animation track editor
Both unselected and selected keyframes feature hover feedback.
This currently only affects standard keyframes (i.e. not booleans,
colors or audio tracks which use custom icons).
-rw-r--r-- | editor/animation_track_editor.cpp | 63 | ||||
-rw-r--r-- | editor/animation_track_editor.h | 1 |
2 files changed, 63 insertions, 1 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 53631c1e3b..685dde4d98 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2252,6 +2252,8 @@ void AnimationTrackEdit::_notification(int p_what) { break; case NOTIFICATION_MOUSE_EXIT: hovered = false; + // When the mouse cursor exits the track, we're no longer hovering any keyframe. + hovering_key_idx = -1; update(); [[fallthrough]]; case NOTIFICATION_DRAG_END: { @@ -2365,7 +2367,13 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool } } - draw_texture(icon_to_draw, ofs); + // Use a different color for the currently hovered key. + // The color multiplier is chosen to work with both dark and light editor themes, + // and on both unselected and selected key icons. + draw_texture( + icon_to_draw, + ofs, + p_index == hovering_key_idx ? get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")) : Color(1, 1, 1)); } // Helper. @@ -2952,6 +2960,59 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { } Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + const int previous_hovering_key_idx = hovering_key_idx; + + // Hovering compressed keyframes for editing is not possible. + if (!animation->track_is_compressed(track)) { + const float scale = timeline->get_zoom_scale(); + const int limit = timeline->get_name_limit(); + const int limit_end = get_size().width - timeline->get_buttons_width(); + // Left Border including space occupied by keyframes on t=0. + const int limit_start_hitbox = limit - type_icon->get_width(); + const Point2 pos = mm->get_position(); + + if (pos.x >= limit_start_hitbox && pos.x <= limit_end) { + // Use the same logic as key selection to ensure that hovering accurately represents + // which key will be selected when clicking. + int key_idx = -1; + float key_distance = 1e20; + + hovering_key_idx = -1; + + // Hovering should happen in the opposite order of drawing for more accurate overlap hovering. + for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) { + Rect2 rect = get_key_rect(i, scale); + float offset = animation->track_get_key_time(track, i) - timeline->get_value(); + offset = offset * scale + limit; + rect.position.x += offset; + + if (rect.has_point(pos)) { + if (is_key_selectable_by_distance()) { + const float distance = ABS(offset - pos.x); + if (key_idx == -1 || distance < key_distance) { + key_idx = i; + key_distance = distance; + hovering_key_idx = i; + } + } else { + // First one does it. + hovering_key_idx = i; + break; + } + } + } + + print_line(hovering_key_idx); + + if (hovering_key_idx != previous_hovering_key_idx) { + // Required to draw keyframe hover feedback on the correct keyframe. + update(); + } + } + } + } + if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && moving_selection_attempt) { if (!moving_selection) { moving_selection = true; diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index a8a5d11c12..0f6d12b4d4 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -173,6 +173,7 @@ class AnimationTrackEdit : public Control { bool hovered = false; bool clicking_on_name = false; + int hovering_key_idx = -1; void _zoom_changed(); |