소스 검색

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).
Hugo Locurcio 3 년 전
부모
커밋
f064258aee
2개의 변경된 파일63개의 추가작업 그리고 1개의 파일을 삭제
  1. 62 1
      editor/animation_track_editor.cpp
  2. 1 0
      editor/animation_track_editor.h

+ 62 - 1
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;

+ 1 - 0
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();