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).
This commit is contained in:
Hugo Locurcio 2022-03-21 22:59:34 +01:00
parent 748fde8df0
commit f064258aee
No known key found for this signature in database
GPG key ID: 39E8F8BE30B0A49C
2 changed files with 63 additions and 1 deletions

View file

@ -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;

View file

@ -173,6 +173,7 @@ class AnimationTrackEdit : public Control {
bool hovered = false;
bool clicking_on_name = false;
int hovering_key_idx = -1;
void _zoom_changed();