2
0
Эх сурвалжийг харах

Allow theming animation editor

passivestar 1 жил өмнө
parent
commit
6120786ddc

+ 72 - 71
editor/animation_bezier_editor.cpp

@@ -54,7 +54,7 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
 	int limit = timeline->get_name_limit();
 	int limit = timeline->get_name_limit();
 	int right_limit = get_size().width;
 	int right_limit = get_size().width;
 
 
-	//selection may have altered the order of keys
+	// Selection may have altered the order of keys.
 	RBMap<real_t, int> key_order;
 	RBMap<real_t, int> key_order;
 
 
 	for (int i = 0; i < animation->track_get_key_count(p_track); i++) {
 	for (int i = 0; i < animation->track_get_key_count(p_track); i++) {
@@ -111,11 +111,11 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
 		int to_x = (offset_n - timeline->get_value()) * scale + limit;
 		int to_x = (offset_n - timeline->get_value()) * scale + limit;
 		int point_end = to_x;
 		int point_end = to_x;
 
 
-		if (from_x > right_limit) { //not visible
+		if (from_x > right_limit) { // Not visible.
 			continue;
 			continue;
 		}
 		}
 
 
-		if (to_x < limit) { //not visible
+		if (to_x < limit) { // Not visible.
 			continue;
 			continue;
 		}
 		}
 
 
@@ -132,15 +132,15 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
 			float h;
 			float h;
 
 
 			if (j == point_end) {
 			if (j == point_end) {
-				h = end.y; //make sure it always connects
+				h = end.y; // Make sure it always connects.
 			} else if (j == point_start) {
 			} else if (j == point_start) {
-				h = start.y; //make sure it always connects
-			} else { //custom interpolation, used because it needs to show paths affected by moving the selection or handles
+				h = start.y; // Make sure it always connects.
+			} else { // Custom interpolation, used because it needs to show paths affected by moving the selection or handles.
 				int iterations = 10;
 				int iterations = 10;
 				float low = 0;
 				float low = 0;
 				float high = 1;
 				float high = 1;
 
 
-				//narrow high and low as much as possible
+				// Narrow high and low as much as possible.
 				for (int k = 0; k < iterations; k++) {
 				for (int k = 0; k < iterations; k++) {
 					float middle = (low + high) / 2.0;
 					float middle = (low + high) / 2.0;
 
 
@@ -153,7 +153,7 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
 					}
 					}
 				}
 				}
 
 
-				//interpolate the result:
+				// Interpolate the result.
 				Vector2 low_pos = start.bezier_interpolate(out_handle, in_handle, end, low);
 				Vector2 low_pos = start.bezier_interpolate(out_handle, in_handle, end, low);
 				Vector2 high_pos = start.bezier_interpolate(out_handle, in_handle, end, high);
 				Vector2 high_pos = start.bezier_interpolate(out_handle, in_handle, end, high);
 
 
@@ -236,27 +236,29 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 
 
 			int limit = timeline->get_name_limit();
 			int limit = timeline->get_name_limit();
 
 
+			const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+			const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+			const Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
+
+			const Color h_line_color = get_theme_color(SNAME("h_line_color"), SNAME("AnimationBezierTrackEdit"));
+			const Color v_line_color = get_theme_color(SNAME("v_line_color"), SNAME("AnimationBezierTrackEdit"));
+			const Color focus_color = get_theme_color(SNAME("focus_color"), SNAME("AnimationBezierTrackEdit"));
+			const Color track_focus_color = get_theme_color(SNAME("track_focus_color"), SNAME("AnimationBezierTrackEdit"));
+
+			const int h_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationBezierTrackEdit"));
+			const int v_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationBezierTrackEdit"));
+
 			if (has_focus()) {
 			if (has_focus()) {
-				Color accent = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
-				accent.a *= 0.7;
-				draw_rect(Rect2(Point2(), get_size()), accent, false, Math::round(EDSCALE));
+				draw_rect(Rect2(Point2(), get_size()), focus_color, false, Math::round(EDSCALE));
 			}
 			}
 
 
-			Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-			int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
-			Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
-			int hsep = get_theme_constant(SNAME("h_separation"), SNAME("ItemList"));
-			int vsep = get_theme_constant(SNAME("v_separation"), SNAME("ItemList"));
-			Color linecolor = color;
-			linecolor.a = 0.2;
-
-			draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor, Math::round(EDSCALE));
+			draw_line(Point2(limit, 0), Point2(limit, get_size().height), v_line_color, Math::round(EDSCALE));
 
 
 			int right_limit = get_size().width;
 			int right_limit = get_size().width;
 
 
-			track_v_scroll_max = vsep;
+			track_v_scroll_max = v_separation;
 
 
-			int vofs = vsep + track_v_scroll;
+			int vofs = v_separation + track_v_scroll;
 			int margin = 0;
 			int margin = 0;
 
 
 			RBMap<int, Color> subtrack_colors;
 			RBMap<int, Color> subtrack_colors;
@@ -286,7 +288,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 
 
 				Vector<int> tracks = E.value;
 				Vector<int> tracks = E.value;
 
 
-				// NAMES AND ICON
+				// Names and icon.
 				{
 				{
 					NodePath path = animation->track_get_path(tracks[0]);
 					NodePath path = animation->track_get_path(tracks[0]);
 
 
@@ -304,15 +306,15 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 						Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(node, "Node");
 						Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(node, "Node");
 
 
 						text = node->get_name();
 						text = node->get_name();
-						ofs += hsep;
+						ofs += h_separation;
 
 
 						TextLine text_buf = TextLine(text, font, font_size);
 						TextLine text_buf = TextLine(text, font, font_size);
-						text_buf.set_width(limit - ofs - icon->get_width() - hsep);
+						text_buf.set_width(limit - ofs - icon->get_width() - h_separation);
 
 
 						int h = MAX(text_buf.get_size().y, icon->get_height());
 						int h = MAX(text_buf.get_size().y, icon->get_height());
 
 
 						draw_texture(icon, Point2(ofs, vofs + int(h - icon->get_height()) / 2.0));
 						draw_texture(icon, Point2(ofs, vofs + int(h - icon->get_height()) / 2.0));
-						ofs += icon->get_width();
+						ofs += icon->get_width() + h_separation;
 
 
 						margin = icon->get_width();
 						margin = icon->get_width();
 
 
@@ -320,31 +322,31 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 						string_pos = string_pos.floor();
 						string_pos = string_pos.floor();
 						text_buf.draw(get_canvas_item(), string_pos, color);
 						text_buf.draw(get_canvas_item(), string_pos, color);
 
 
-						vofs += h + vsep;
-						track_v_scroll_max += h + vsep;
+						vofs += h + v_separation;
+						track_v_scroll_max += h + v_separation;
 					}
 					}
 				}
 				}
 
 
-				Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
+				const Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
 
 
 				Ref<Texture2D> remove = get_editor_theme_icon(SNAME("Remove"));
 				Ref<Texture2D> remove = get_editor_theme_icon(SNAME("Remove"));
-				float remove_hpos = limit - hsep - remove->get_width();
+				float remove_hpos = limit - h_separation - remove->get_width();
 
 
 				Ref<Texture2D> lock = get_editor_theme_icon(SNAME("Lock"));
 				Ref<Texture2D> lock = get_editor_theme_icon(SNAME("Lock"));
 				Ref<Texture2D> unlock = get_editor_theme_icon(SNAME("Unlock"));
 				Ref<Texture2D> unlock = get_editor_theme_icon(SNAME("Unlock"));
-				float lock_hpos = remove_hpos - hsep - lock->get_width();
+				float lock_hpos = remove_hpos - h_separation - lock->get_width();
 
 
 				Ref<Texture2D> visibility_visible = get_editor_theme_icon(SNAME("GuiVisibilityVisible"));
 				Ref<Texture2D> visibility_visible = get_editor_theme_icon(SNAME("GuiVisibilityVisible"));
 				Ref<Texture2D> visibility_hidden = get_editor_theme_icon(SNAME("GuiVisibilityHidden"));
 				Ref<Texture2D> visibility_hidden = get_editor_theme_icon(SNAME("GuiVisibilityHidden"));
-				float visibility_hpos = lock_hpos - hsep - visibility_visible->get_width();
+				float visibility_hpos = lock_hpos - h_separation - visibility_visible->get_width();
 
 
 				Ref<Texture2D> solo = get_editor_theme_icon(SNAME("AudioBusSolo"));
 				Ref<Texture2D> solo = get_editor_theme_icon(SNAME("AudioBusSolo"));
-				float solo_hpos = visibility_hpos - hsep - solo->get_width();
+				float solo_hpos = visibility_hpos - h_separation - solo->get_width();
 
 
-				float buttons_width = remove->get_width() + lock->get_width() + visibility_visible->get_width() + solo->get_width() + hsep * 3;
+				float buttons_width = remove->get_width() + lock->get_width() + visibility_visible->get_width() + solo->get_width() + h_separation * 3;
 
 
 				for (int i = 0; i < tracks.size(); ++i) {
 				for (int i = 0; i < tracks.size(); ++i) {
-					// RELATED TRACKS TITLES
+					// Related track titles.
 
 
 					int current_track = tracks[i];
 					int current_track = tracks[i];
 
 
@@ -353,9 +355,9 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 
 
 					Color cc = color;
 					Color cc = color;
 					TextLine text_buf = TextLine(path, font, font_size);
 					TextLine text_buf = TextLine(path, font, font_size);
-					text_buf.set_width(limit - margin - buttons_width);
+					text_buf.set_width(limit - margin - buttons_width - h_separation * 2);
 
 
-					Rect2 rect = Rect2(margin, vofs, solo_hpos - hsep - solo->get_width(), text_buf.get_size().y + vsep);
+					Rect2 rect = Rect2(margin, vofs, solo_hpos - h_separation - solo->get_width(), text_buf.get_size().y + v_separation);
 
 
 					cc.a *= 0.7;
 					cc.a *= 0.7;
 					float h;
 					float h;
@@ -381,14 +383,12 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 							track_color.set_hsv(h, 0.2, 0.8);
 							track_color.set_hsv(h, 0.2, 0.8);
 						}
 						}
 						track_color.a = 0.5;
 						track_color.a = 0.5;
-						draw_rect(Rect2(0, vofs, margin - hsep, text_buf.get_size().y * 0.8), track_color);
+						draw_rect(Rect2(0, vofs, margin - h_separation, text_buf.get_size().y * 0.8), track_color);
 						subtrack_colors[current_track] = track_color;
 						subtrack_colors[current_track] = track_color;
 
 
 						subtracks[current_track] = rect;
 						subtracks[current_track] = rect;
 					} else {
 					} else {
-						Color ac = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
-						ac.a = 0.5;
-						draw_rect(rect, ac);
+						draw_rect(rect, track_focus_color);
 						if (locked_tracks.has(selected_track)) {
 						if (locked_tracks.has(selected_track)) {
 							selected_track_color.set_hsv(h, 0.0, 0.4);
 							selected_track_color.set_hsv(h, 0.0, 0.4);
 						} else {
 						} else {
@@ -396,7 +396,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 						}
 						}
 					}
 					}
 
 
-					Vector2 string_pos = Point2(margin, vofs);
+					Vector2 string_pos = Point2(margin + h_separation, vofs);
 					text_buf.draw(get_canvas_item(), string_pos, cc);
 					text_buf.draw(get_canvas_item(), string_pos, cc);
 
 
 					float icon_start_height = vofs + rect.size.y / 2.0;
 					float icon_start_height = vofs + rect.size.y / 2.0;
@@ -432,15 +432,16 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 
 
 					subtrack_icons[current_track] = track_icons;
 					subtrack_icons[current_track] = track_icons;
 
 
-					vofs += text_buf.get_size().y + vsep;
-					track_v_scroll_max += text_buf.get_size().y + vsep;
+					vofs += text_buf.get_size().y + v_separation;
+					track_v_scroll_max += text_buf.get_size().y + v_separation;
 				}
 				}
 			}
 			}
 
 
-			Color accent = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
+			const Color accent = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
 
 
-			{ //guides
-				float min_left_scale = font->get_height(font_size) + vsep;
+			// Guides.
+			{
+				float min_left_scale = font->get_height(font_size) + v_separation;
 
 
 				float scale = (min_left_scale * 2) * timeline_v_zoom;
 				float scale = (min_left_scale * 2) * timeline_v_zoom;
 				float step = Math::pow(10.0, Math::round(Math::log(scale / 5.0) / Math::log(10.0))) * 5.0;
 				float step = Math::pow(10.0, Math::round(Math::log(scale / 5.0) / Math::log(10.0))) * 5.0;
@@ -462,7 +463,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 						iv -= 1;
 						iv -= 1;
 					}
 					}
 					if (!first && iv != prev_iv) {
 					if (!first && iv != prev_iv) {
-						Color lc = linecolor;
+						Color lc = h_line_color;
 						lc.a *= 0.5;
 						lc.a *= 0.5;
 						draw_line(Point2(limit, i), Point2(right_limit, i), lc, Math::round(EDSCALE));
 						draw_line(Point2(limit, i), Point2(right_limit, i), lc, Math::round(EDSCALE));
 						Color c = color;
 						Color c = color;
@@ -475,8 +476,8 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 				}
 				}
 			}
 			}
 
 
-			{ //draw OTHER curves
-
+			// Draw other curves.
+			{
 				float scale = timeline->get_zoom_scale();
 				float scale = timeline->get_zoom_scale();
 				Ref<Texture2D> point = get_editor_theme_icon(SNAME("KeyValue"));
 				Ref<Texture2D> point = get_editor_theme_icon(SNAME("KeyValue"));
 				for (const KeyValue<int, Color> &E : subtrack_colors) {
 				for (const KeyValue<int, Color> &E : subtrack_colors) {
@@ -498,12 +499,12 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
 				}
 				}
 
 
 				if (track_count > 0 && !hidden_tracks.has(selected_track)) {
 				if (track_count > 0 && !hidden_tracks.has(selected_track)) {
-					//draw edited curve
+					// Draw edited curve.
 					_draw_track(selected_track, selected_track_color);
 					_draw_track(selected_track, selected_track_color);
 				}
 				}
 			}
 			}
 
 
-			//draw editor handles
+			// Draw editor handles.
 			{
 			{
 				edit_points.clear();
 				edit_points.clear();
 				float scale = timeline->get_zoom_scale();
 				float scale = timeline->get_zoom_scale();
@@ -644,12 +645,12 @@ bool AnimationBezierTrackEdit::_is_track_displayed(int p_track_index) {
 
 
 // Check if the curves for a track are displayed in the editor (not hidden). Includes the check on the track visibility.
 // Check if the curves for a track are displayed in the editor (not hidden). Includes the check on the track visibility.
 bool AnimationBezierTrackEdit::_is_track_curves_displayed(int p_track_index) {
 bool AnimationBezierTrackEdit::_is_track_curves_displayed(int p_track_index) {
-	//Is the track is visible in the editor?
+	// Is the track is visible in the editor?
 	if (!_is_track_displayed(p_track_index)) {
 	if (!_is_track_displayed(p_track_index)) {
 		return false;
 		return false;
 	}
 	}
 
 
-	//And curves visible?
+	// And curves visible?
 	if (hidden_tracks.has(p_track_index)) {
 	if (hidden_tracks.has(p_track_index)) {
 		return false;
 		return false;
 	}
 	}
@@ -698,7 +699,7 @@ void AnimationBezierTrackEdit::_play_position_draw() {
 	int px = (-timeline->get_value() + play_position_pos) * scale + limit;
 	int px = (-timeline->get_value() + play_position_pos) * scale + limit;
 
 
 	if (px >= limit && px < (get_size().width)) {
 	if (px >= limit && px < (get_size().width)) {
-		Color color = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
+		const Color color = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
 		play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE));
 		play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE));
 	}
 	}
 }
 }
@@ -1218,7 +1219,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 			}
 			}
 		}
 		}
 
 
-		//insert new point
+		// Insert new point.
 		if (mb->get_position().x >= limit && mb->get_position().x < get_size().width && mb->is_command_or_control_pressed()) {
 		if (mb->get_position().x >= limit && mb->get_position().x < get_size().width && mb->is_command_or_control_pressed()) {
 			float h = (get_size().height / 2.0 - mb->get_position().y) * timeline_v_zoom + timeline_v_scroll;
 			float h = (get_size().height / 2.0 - mb->get_position().y) * timeline_v_zoom + timeline_v_scroll;
 			Array new_point = animation->make_default_bezier_key(h);
 			Array new_point = animation->make_default_bezier_key(h);
@@ -1234,7 +1235,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 			undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", selected_track, time);
 			undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", selected_track, time);
 			undo_redo->commit_action();
 			undo_redo->commit_action();
 
 
-			//then attempt to move
+			// Then attempt to move.
 			int index = animation->track_find_key(selected_track, time, Animation::FIND_MODE_APPROX);
 			int index = animation->track_find_key(selected_track, time, Animation::FIND_MODE_APPROX);
 			ERR_FAIL_COND(index == -1);
 			ERR_FAIL_COND(index == -1);
 			_clear_selection();
 			_clear_selection();
@@ -1252,7 +1253,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 			return;
 			return;
 		}
 		}
 
 
-		//box select
+		// Box select.
 		if (mb->get_position().x >= limit && mb->get_position().x < get_size().width) {
 		if (mb->get_position().x >= limit && mb->get_position().x < get_size().width) {
 			box_selecting_attempt = true;
 			box_selecting_attempt = true;
 			box_selecting = false;
 			box_selecting = false;
@@ -1264,7 +1265,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 
 
 	if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
 	if (box_selecting_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
 		if (box_selecting) {
 		if (box_selecting) {
-			//do actual select
+			// Do actual select.
 			if (!box_selecting_add) {
 			if (!box_selecting_add) {
 				_clear_selection();
 				_clear_selection();
 			}
 			}
@@ -1292,13 +1293,13 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 				}
 				}
 			}
 			}
 		} else {
 		} else {
-			_clear_selection(); //clicked and nothing happened, so clear the selection
+			_clear_selection(); // Clicked and nothing happened, so clear the selection.
 
 
-			//select by clicking on curve
+			// Select by clicking on curve.
 			int track_count = animation->get_track_count();
 			int track_count = animation->get_track_count();
 
 
 			real_t animation_length = animation->get_length();
 			real_t animation_length = animation->get_length();
-			animation->set_length(real_t(INT_MAX)); //bezier_track_interpolate doesn't find keys if they exist beyond anim length
+			animation->set_length(real_t(INT_MAX)); // bezier_track_interpolate doesn't find keys if they exist beyond anim length.
 
 
 			real_t time = ((mb->get_position().x - limit) / timeline->get_zoom_scale()) + timeline->get_value();
 			real_t time = ((mb->get_position().x - limit) / timeline->get_zoom_scale()) + timeline->get_value();
 
 
@@ -1334,11 +1335,11 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 
 
 				List<AnimMoveRestore> to_restore;
 				List<AnimMoveRestore> to_restore;
 				List<Animation::HandleMode> to_restore_handle_modes;
 				List<Animation::HandleMode> to_restore_handle_modes;
-				// 1-remove the keys
+				// 1 - Remove the keys.
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 					undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->get().first, E->get().second);
 					undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->get().first, E->get().second);
 				}
 				}
-				// 2- remove overlapped keys
+				// 2 - Remove overlapped keys.
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 					real_t newtime = animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x;
 					real_t newtime = animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x;
 
 
@@ -1348,7 +1349,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 					}
 					}
 
 
 					if (selection.has(IntPair(E->get().first, idx))) {
 					if (selection.has(IntPair(E->get().first, idx))) {
-						continue; //already in selection, don't save
+						continue; // Already in selection, don't save.
 					}
 					}
 
 
 					undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->get().first, newtime);
 					undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->get().first, newtime);
@@ -1362,7 +1363,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 					to_restore_handle_modes.push_back(animation->bezier_track_get_key_handle_mode(E->get().first, idx));
 					to_restore_handle_modes.push_back(animation->bezier_track_get_key_handle_mode(E->get().first, idx));
 				}
 				}
 
 
-				// 3-move the keys (re insert them)
+				// 3 - Move the keys (re-insert them).
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 					real_t newpos = animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x;
 					real_t newpos = animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x;
 					Array key = animation->track_get_key_value(E->get().first, E->get().second);
 					Array key = animation->track_get_key_value(E->get().first, E->get().second);
@@ -1381,13 +1382,13 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 							animation->bezier_track_get_key_handle_mode(E->get().first, E->get().second));
 							animation->bezier_track_get_key_handle_mode(E->get().first, E->get().second));
 				}
 				}
 
 
-				// 4-(undo) remove inserted keys
+				// 4 - (undo) Remove inserted keys.
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 					real_t newpos = animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x;
 					real_t newpos = animation->track_get_key_time(E->get().first, E->get().second) + moving_selection_offset.x;
 					undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->get().first, newpos);
 					undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->get().first, newpos);
 				}
 				}
 
 
-				// 5-(undo) reinsert keys
+				// 5 - (undo) Reinsert keys.
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 					real_t oldpos = animation->track_get_key_time(E->get().first, E->get().second);
 					real_t oldpos = animation->track_get_key_time(E->get().first, E->get().second);
 					Array key = animation->track_get_key_value(E->get().first, E->get().second);
 					Array key = animation->track_get_key_value(E->get().first, E->get().second);
@@ -1403,7 +1404,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 							animation->bezier_track_get_key_handle_mode(E->get().first, E->get().second));
 							animation->bezier_track_get_key_handle_mode(E->get().first, E->get().second));
 				}
 				}
 
 
-				// 6-(undo) reinsert overlapped keys
+				// 6 - (undo) Reinsert overlapped keys.
 				List<AnimMoveRestore>::ConstIterator restore_itr = to_restore.begin();
 				List<AnimMoveRestore>::ConstIterator restore_itr = to_restore.begin();
 				List<Animation::HandleMode>::ConstIterator handle_itr = to_restore_handle_modes.begin();
 				List<Animation::HandleMode>::ConstIterator handle_itr = to_restore_handle_modes.begin();
 				for (; restore_itr != to_restore.end() && handle_itr != to_restore_handle_modes.end(); ++restore_itr, ++handle_itr) {
 				for (; restore_itr != to_restore.end() && handle_itr != to_restore_handle_modes.end(); ++restore_itr, ++handle_itr) {
@@ -1425,7 +1426,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 				undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
 				undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
 				undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
 				undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
 
 
-				// 7-reselect
+				// 7 - Reselect.
 				int i = 0;
 				int i = 0;
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 				for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) {
 					real_t oldpos = animation->track_get_key_time(E->get().first, E->get().second);
 					real_t oldpos = animation->track_get_key_time(E->get().first, E->get().second);
@@ -1491,7 +1492,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 		box_selection_to = mm->get_position();
 		box_selection_to = mm->get_position();
 
 
 		if (get_local_mouse_position().y < 0) {
 		if (get_local_mouse_position().y < 0) {
-			//avoid cursor from going too above, so it does not lose focus with viewport
+			// Avoid cursor from going too above, so it does not lose focus with viewport.
 			warp_mouse(Vector2(get_local_mouse_position().x, 0));
 			warp_mouse(Vector2(get_local_mouse_position().x, 0));
 		}
 		}
 		queue_redraw();
 		queue_redraw();

+ 153 - 118
editor/animation_track_editor.cpp

@@ -1376,14 +1376,16 @@ void AnimationTimelineEdit::_anim_loop_pressed() {
 }
 }
 
 
 int AnimationTimelineEdit::get_buttons_width() const {
 int AnimationTimelineEdit::get_buttons_width() const {
-	Ref<Texture2D> interp_mode = get_editor_theme_icon(SNAME("TrackContinuous"));
-	Ref<Texture2D> interp_type = get_editor_theme_icon(SNAME("InterpRaw"));
-	Ref<Texture2D> loop_type = get_editor_theme_icon(SNAME("InterpWrapClamp"));
-	Ref<Texture2D> remove_icon = get_editor_theme_icon(SNAME("Remove"));
-	Ref<Texture2D> down_icon = get_theme_icon(SNAME("select_arrow"), SNAME("Tree"));
+	const Ref<Texture2D> interp_mode = get_editor_theme_icon(SNAME("TrackContinuous"));
+	const Ref<Texture2D> interp_type = get_editor_theme_icon(SNAME("InterpRaw"));
+	const Ref<Texture2D> loop_type = get_editor_theme_icon(SNAME("InterpWrapClamp"));
+	const Ref<Texture2D> remove_icon = get_editor_theme_icon(SNAME("Remove"));
+	const Ref<Texture2D> down_icon = get_theme_icon(SNAME("select_arrow"), SNAME("Tree"));
+
+	const int h_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationTrackEdit"));
 
 
 	int total_w = interp_mode->get_width() + interp_type->get_width() + loop_type->get_width() + remove_icon->get_width();
 	int total_w = interp_mode->get_width() + interp_type->get_width() + loop_type->get_width() + remove_icon->get_width();
-	total_w += (down_icon->get_width() + 4 * EDSCALE) * 4;
+	total_w += (down_icon->get_width() + h_separation) * 4;
 
 
 	return total_w;
 	return total_w;
 }
 }
@@ -1391,7 +1393,7 @@ int AnimationTimelineEdit::get_buttons_width() const {
 int AnimationTimelineEdit::get_name_limit() const {
 int AnimationTimelineEdit::get_name_limit() const {
 	Ref<Texture2D> hsize_icon = get_editor_theme_icon(SNAME("Hsize"));
 	Ref<Texture2D> hsize_icon = get_editor_theme_icon(SNAME("Hsize"));
 
 
-	int limit = MAX(name_limit, add_track->get_minimum_size().width + hsize_icon->get_width());
+	int limit = MAX(name_limit, add_track->get_minimum_size().width + hsize_icon->get_width() + 8 * EDSCALE);
 
 
 	limit = MIN(limit, get_size().width - get_buttons_width() - 1);
 	limit = MIN(limit, get_size().width - get_buttons_width() - 1);
 
 
@@ -1436,9 +1438,24 @@ void AnimationTimelineEdit::_notification(int p_what) {
 				return;
 				return;
 			}
 			}
 
 
-			Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-			int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
-			Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
+			const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+			const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+
+			const Ref<StyleBox> &stylebox_time_unavailable = get_theme_stylebox(SNAME("time_unavailable"), SNAME("AnimationTimelineEdit"));
+			const Ref<StyleBox> &stylebox_time_available = get_theme_stylebox(SNAME("time_available"), SNAME("AnimationTimelineEdit"));
+
+			const Color v_line_primary_color = get_theme_color(SNAME("v_line_primary_color"), SNAME("AnimationTimelineEdit"));
+			const Color v_line_secondary_color = get_theme_color(SNAME("v_line_secondary_color"), SNAME("AnimationTimelineEdit"));
+			const Color h_line_color = get_theme_color(SNAME("h_line_color"), SNAME("AnimationTimelineEdit"));
+			const Color font_primary_color = get_theme_color(SNAME("font_primary_color"), SNAME("AnimationTimelineEdit"));
+			const Color font_secondary_color = get_theme_color(SNAME("font_secondary_color"), SNAME("AnimationTimelineEdit"));
+
+			const int v_line_primary_margin = get_theme_constant(SNAME("v_line_primary_margin"), SNAME("AnimationTimelineEdit"));
+			const int v_line_secondary_margin = get_theme_constant(SNAME("v_line_secondary_margin"), SNAME("AnimationTimelineEdit"));
+			const int v_line_primary_width = get_theme_constant(SNAME("v_line_primary_width"), SNAME("AnimationTimelineEdit"));
+			const int v_line_secondary_width = get_theme_constant(SNAME("v_line_secondary_width"), SNAME("AnimationTimelineEdit"));
+			const int text_primary_margin = get_theme_constant(SNAME("text_primary_margin"), SNAME("AnimationTimelineEdit"));
+			const int text_secondary_margin = get_theme_constant(SNAME("text_secondary_margin"), SNAME("AnimationTimelineEdit"));
 
 
 			int zoomw = key_range;
 			int zoomw = key_range;
 			float scale = get_zoom_scale();
 			float scale = get_zoom_scale();
@@ -1450,7 +1467,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
 			}
 			}
 
 
 			Ref<Texture2D> hsize_icon = get_editor_theme_icon(SNAME("Hsize"));
 			Ref<Texture2D> hsize_icon = get_editor_theme_icon(SNAME("Hsize"));
-			hsize_rect = Rect2(get_name_limit() - hsize_icon->get_width() - 2 * EDSCALE, (get_size().height - hsize_icon->get_height()) / 2, hsize_icon->get_width(), hsize_icon->get_height());
+			hsize_rect = Rect2(get_name_limit() - hsize_icon->get_width() - 8 * EDSCALE, (get_size().height - hsize_icon->get_height()) / 2, hsize_icon->get_width(), hsize_icon->get_height());
 			draw_texture(hsize_icon, hsize_rect.position);
 			draw_texture(hsize_icon, hsize_rect.position);
 
 
 			{
 			{
@@ -1495,14 +1512,9 @@ void AnimationTimelineEdit::_notification(int p_what) {
 
 
 			int end_px = (l - get_value()) * scale;
 			int end_px = (l - get_value()) * scale;
 			int begin_px = -get_value() * scale;
 			int begin_px = -get_value() * scale;
-			Color notimecol = get_theme_color(SNAME("dark_color_2"), EditorStringName(Editor));
-			Color timecolor = color;
-			timecolor.a = 0.2;
-			Color linecolor = color;
-			linecolor.a = 0.2;
 
 
 			{
 			{
-				draw_rect(Rect2(Point2(get_name_limit(), 0), Point2(zoomw - 1, h)), notimecol);
+				draw_style_box(stylebox_time_unavailable, Rect2(Point2(get_name_limit(), 0), Point2(zoomw - 1, h)));
 
 
 				if (begin_px < zoomw && end_px > 0) {
 				if (begin_px < zoomw && end_px > 0) {
 					if (begin_px < 0) {
 					if (begin_px < 0) {
@@ -1512,13 +1524,9 @@ void AnimationTimelineEdit::_notification(int p_what) {
 						end_px = zoomw;
 						end_px = zoomw;
 					}
 					}
 
 
-					draw_rect(Rect2(Point2(get_name_limit() + begin_px, 0), Point2(end_px - begin_px, h)), timecolor);
+					draw_style_box(stylebox_time_available, Rect2(Point2(get_name_limit() + begin_px, 0), Point2(end_px - begin_px, h)));
 				}
 				}
 			}
 			}
-
-			Color color_time_sec = color;
-			Color color_time_dec = color;
-			color_time_dec.a *= 0.5;
 #define SC_ADJ 100
 #define SC_ADJ 100
 			int dec = 1;
 			int dec = 1;
 			int step = 1;
 			int step = 1;
@@ -1573,10 +1581,17 @@ void AnimationTimelineEdit::_notification(int p_what) {
 						bool sub = Math::floor(prev) == Math::floor(pos);
 						bool sub = Math::floor(prev) == Math::floor(pos);
 
 
 						if (frame != prev_frame && i >= prev_frame_ofs) {
 						if (frame != prev_frame && i >= prev_frame_ofs) {
-							draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
+							int line_margin = sub ? v_line_secondary_margin : v_line_primary_margin;
+							int line_width = sub ? v_line_secondary_width : v_line_primary_width;
+							Color line_color = sub ? v_line_secondary_color : v_line_primary_color;
 
 
-							draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), itos(frame), HORIZONTAL_ALIGNMENT_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
-							prev_frame_ofs = i + font->get_string_size(itos(frame), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + 5 * EDSCALE;
+							draw_line(Point2(get_name_limit() + i, 0 + line_margin), Point2(get_name_limit() + i, h - line_margin), line_color, line_width);
+
+							int text_margin = sub ? text_secondary_margin : text_primary_margin;
+
+							draw_string(font, Point2(get_name_limit() + i + text_margin, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), itos(frame), HORIZONTAL_ALIGNMENT_LEFT, zoomw - i, font_size, sub ? font_secondary_color : font_primary_color);
+
+							prev_frame_ofs = i + font->get_string_size(itos(frame), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + text_margin;
 						}
 						}
 					}
 					}
 				}
 				}
@@ -1592,13 +1607,20 @@ void AnimationTimelineEdit::_notification(int p_what) {
 
 
 					if ((sc / step) != (prev_sc / step) || (prev_sc < 0 && sc >= 0)) {
 					if ((sc / step) != (prev_sc / step) || (prev_sc < 0 && sc >= 0)) {
 						int scd = sc < 0 ? prev_sc : sc;
 						int scd = sc < 0 ? prev_sc : sc;
-						draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
-						draw_string(font, Point2(get_name_limit() + i + 3, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), String::num((scd - (scd % step)) / double(SC_ADJ), decimals), HORIZONTAL_ALIGNMENT_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
+						int line_margin = sub ? v_line_secondary_margin : v_line_primary_margin;
+						int line_width = sub ? v_line_secondary_width : v_line_primary_width;
+						Color line_color = sub ? v_line_secondary_color : v_line_primary_color;
+
+						draw_line(Point2(get_name_limit() + i, 0 + line_margin), Point2(get_name_limit() + i, h - line_margin), line_color, line_width);
+
+						int text_margin = sub ? text_secondary_margin : text_primary_margin;
+
+						draw_string(font, Point2(get_name_limit() + i + text_margin, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), String::num((scd - (scd % step)) / double(SC_ADJ), decimals), HORIZONTAL_ALIGNMENT_LEFT, zoomw - i, font_size, sub ? font_secondary_color : font_primary_color);
 					}
 					}
 				}
 				}
 			}
 			}
 
 
-			draw_line(Vector2(0, get_size().height), get_size(), linecolor, Math::round(EDSCALE));
+			draw_line(Vector2(0, get_size().height), get_size(), h_line_color, Math::round(EDSCALE));
 			update_values();
 			update_values();
 		} break;
 		} break;
 	}
 	}
@@ -1628,10 +1650,10 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation, boo
 
 
 Size2 AnimationTimelineEdit::get_minimum_size() const {
 Size2 AnimationTimelineEdit::get_minimum_size() const {
 	Size2 ms = add_track->get_minimum_size();
 	Size2 ms = add_track->get_minimum_size();
-	Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-	int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+	const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+	const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
 	ms.height = MAX(ms.height, font->get_height(font_size));
 	ms.height = MAX(ms.height, font->get_height(font_size));
-	ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_editor_theme_icon(SNAME("Hsize"))->get_width() + 2;
+	ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_editor_theme_icon(SNAME("Hsize"))->get_width() + 2 + 8 * EDSCALE;
 	return ms;
 	return ms;
 }
 }
 
 
@@ -1967,46 +1989,49 @@ void AnimationTrackEdit::_notification(int p_what) {
 
 
 			int limit = timeline->get_name_limit();
 			int limit = timeline->get_name_limit();
 
 
+			const Ref<StyleBox> &stylebox_odd = get_theme_stylebox(SNAME("odd"), SNAME("AnimationTrackEdit"));
+			const Ref<StyleBox> &stylebox_focus = get_theme_stylebox(SNAME("focus"), SNAME("AnimationTrackEdit"));
+			const Ref<StyleBox> &stylebox_hover = get_theme_stylebox(SNAME("hover"), SNAME("AnimationTrackEdit"));
+
+			const Color h_line_color = get_theme_color(SNAME("h_line_color"), SNAME("AnimationTrackEdit"));
+			const int h_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationTrackEdit"));
+			const int outer_margin = get_theme_constant(SNAME("outer_margin"), SNAME("AnimationTrackEdit"));
+
 			if (track % 2 == 1) {
 			if (track % 2 == 1) {
 				// Draw a background over odd lines to make long lists of tracks easier to read.
 				// Draw a background over odd lines to make long lists of tracks easier to read.
-				draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), Color(0.5, 0.5, 0.5, 0.05));
+				draw_style_box(stylebox_odd, Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)));
 			}
 			}
 
 
 			if (hovered) {
 			if (hovered) {
 				// Draw hover feedback.
 				// Draw hover feedback.
-				draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), Color(0.5, 0.5, 0.5, 0.1));
+				draw_style_box(stylebox_hover, Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)));
 			}
 			}
 
 
 			if (has_focus()) {
 			if (has_focus()) {
-				Color accent = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
-				accent.a *= 0.7;
 				// Offside so the horizontal sides aren't cutoff.
 				// Offside so the horizontal sides aren't cutoff.
-				draw_style_box(get_theme_stylebox(SNAME("Focus"), EditorStringName(EditorStyles)), Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)));
+				draw_style_box(stylebox_focus, Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)));
 			}
 			}
 
 
-			Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-			int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
-			Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
-			int hsep = get_theme_constant(SNAME("h_separation"), SNAME("ItemList"));
-			Color linecolor = color;
-			linecolor.a = 0.2;
+			const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+			const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+			const Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
 
 
-			Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
+			const Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
 
 
-			// NAMES AND ICONS //
+			// Names and icons.
 
 
 			{
 			{
 				Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon(SNAME("checked"), SNAME("CheckBox")) : get_theme_icon(SNAME("unchecked"), SNAME("CheckBox"));
 				Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon(SNAME("checked"), SNAME("CheckBox")) : get_theme_icon(SNAME("unchecked"), SNAME("CheckBox"));
 
 
-				int ofs = in_group ? check->get_width() : 0; // Not the best reference for margin but..
+				int ofs = in_group ? outer_margin : 0;
 
 
-				check_rect = Rect2(Point2(ofs, int(get_size().height - check->get_height()) / 2), check->get_size());
+				check_rect = Rect2(Point2(ofs, (get_size().height - check->get_height()) / 2).round(), check->get_size());
 				draw_texture(check, check_rect.position);
 				draw_texture(check, check_rect.position);
-				ofs += check->get_width() + hsep;
+				ofs += check->get_width() + h_separation;
 
 
 				Ref<Texture2D> key_type_icon = _get_key_type_icon();
 				Ref<Texture2D> key_type_icon = _get_key_type_icon();
-				draw_texture(key_type_icon, Point2(ofs, int(get_size().height - key_type_icon->get_height()) / 2));
-				ofs += key_type_icon->get_width() + hsep;
+				draw_texture(key_type_icon, Point2(ofs, (get_size().height - key_type_icon->get_height()) / 2).round());
+				ofs += key_type_icon->get_width() + h_separation;
 
 
 				NodePath anim_path = animation->track_get_path(track);
 				NodePath anim_path = animation->track_get_path(track);
 				Node *node = nullptr;
 				Node *node = nullptr;
@@ -2035,11 +2060,11 @@ void AnimationTrackEdit::_notification(int p_what) {
 					Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(node, "Node");
 					Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(node, "Node");
 					const Vector2 icon_size = Vector2(1, 1) * get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
 					const Vector2 icon_size = Vector2(1, 1) * get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
 
 
-					draw_texture_rect(icon, Rect2(Point2(ofs, int(get_size().height - icon_size.y) / 2), icon_size));
+					draw_texture_rect(icon, Rect2(Point2(ofs, (get_size().height - icon_size.y) / 2).round(), icon_size));
 					icon_cache = icon;
 					icon_cache = icon;
 
 
 					text = String() + node->get_name() + ":" + anim_path.get_concatenated_subnames();
 					text = String() + node->get_name() + ":" + anim_path.get_concatenated_subnames();
-					ofs += hsep;
+					ofs += h_separation;
 					ofs += icon_size.x;
 					ofs += icon_size.x;
 
 
 				} else {
 				} else {
@@ -2050,22 +2075,22 @@ void AnimationTrackEdit::_notification(int p_what) {
 
 
 				path_cache = text;
 				path_cache = text;
 
 
-				path_rect = Rect2(ofs, 0, limit - ofs - hsep, get_size().height);
+				path_rect = Rect2(ofs, 0, limit - ofs - h_separation, get_size().height);
 
 
 				Vector2 string_pos = Point2(ofs, (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size));
 				Vector2 string_pos = Point2(ofs, (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size));
 				string_pos = string_pos.floor();
 				string_pos = string_pos.floor();
-				draw_string(font, string_pos, text, HORIZONTAL_ALIGNMENT_LEFT, limit - ofs - hsep, font_size, text_color);
+				draw_string(font, string_pos, text, HORIZONTAL_ALIGNMENT_LEFT, limit - ofs - h_separation, font_size, text_color);
 
 
-				draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor, Math::round(EDSCALE));
+				draw_line(Point2(limit, 0), Point2(limit, get_size().height), h_line_color, Math::round(EDSCALE));
 			}
 			}
 
 
-			// KEYFRAMES //
+			// Keyframes.
 
 
-			draw_bg(limit, get_size().width - timeline->get_buttons_width());
+			draw_bg(limit, get_size().width - timeline->get_buttons_width() - outer_margin);
 
 
 			{
 			{
 				float scale = timeline->get_zoom_scale();
 				float scale = timeline->get_zoom_scale();
-				int limit_end = get_size().width - timeline->get_buttons_width();
+				int limit_end = get_size().width - timeline->get_buttons_width() - outer_margin;
 
 
 				for (int i = 0; i < animation->track_get_key_count(track); i++) {
 				for (int i = 0; i < animation->track_get_key_count(track); i++) {
 					float offset = animation->track_get_key_time(track, i) - timeline->get_value();
 					float offset = animation->track_get_key_time(track, i) - timeline->get_value();
@@ -2087,9 +2112,9 @@ void AnimationTrackEdit::_notification(int p_what) {
 				}
 				}
 			}
 			}
 
 
-			draw_fg(limit, get_size().width - timeline->get_buttons_width());
+			draw_fg(limit, get_size().width - timeline->get_buttons_width() - outer_margin);
 
 
-			// BUTTONS //
+			// Buttons.
 
 
 			{
 			{
 				Ref<Texture2D> wrap_icon[2] = {
 				Ref<Texture2D> wrap_icon[2] = {
@@ -2113,13 +2138,13 @@ void AnimationTrackEdit::_notification(int p_what) {
 					get_editor_theme_icon(SNAME("UseBlendDisable")),
 					get_editor_theme_icon(SNAME("UseBlendDisable")),
 				};
 				};
 
 
-				int ofs = get_size().width - timeline->get_buttons_width();
+				int ofs = get_size().width - timeline->get_buttons_width() - outer_margin;
 
 
-				Ref<Texture2D> down_icon = get_theme_icon(SNAME("select_arrow"), SNAME("Tree"));
+				const Ref<Texture2D> down_icon = get_theme_icon(SNAME("select_arrow"), SNAME("Tree"));
 
 
-				draw_line(Point2(ofs, 0), Point2(ofs, get_size().height), linecolor, Math::round(EDSCALE));
+				draw_line(Point2(ofs, 0), Point2(ofs, get_size().height), h_line_color, Math::round(EDSCALE));
 
 
-				ofs += hsep;
+				ofs += h_separation;
 				{
 				{
 					// Callmode.
 					// Callmode.
 
 
@@ -2134,7 +2159,7 @@ void AnimationTrackEdit::_notification(int p_what) {
 					Ref<Texture2D> update_icon = cont_icon[update_mode];
 					Ref<Texture2D> update_icon = cont_icon[update_mode];
 
 
 					update_mode_rect.position.x = ofs;
 					update_mode_rect.position.x = ofs;
-					update_mode_rect.position.y = int(get_size().height - update_icon->get_height()) / 2;
+					update_mode_rect.position.y = Math::round((get_size().height - update_icon->get_height()) / 2);
 					update_mode_rect.size = update_icon->get_size();
 					update_mode_rect.size = update_icon->get_size();
 
 
 					if (!animation->track_is_compressed(track) && animation->track_get_type(track) == Animation::TYPE_VALUE) {
 					if (!animation->track_is_compressed(track) && animation->track_get_type(track) == Animation::TYPE_VALUE) {
@@ -2149,12 +2174,12 @@ void AnimationTrackEdit::_notification(int p_what) {
 					update_mode_rect.position.y = 0;
 					update_mode_rect.position.y = 0;
 					update_mode_rect.size.y = get_size().height;
 					update_mode_rect.size.y = get_size().height;
 
 
-					ofs += update_icon->get_width() + hsep / 2;
-					update_mode_rect.size.x += hsep / 2;
+					ofs += update_icon->get_width() + h_separation / 2;
+					update_mode_rect.size.x += h_separation / 2;
 
 
 					if (!read_only) {
 					if (!read_only) {
 						if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_AUDIO) {
 						if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_AUDIO) {
-							draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
+							draw_texture(down_icon, Vector2(ofs, (get_size().height - down_icon->get_height()) / 2).round());
 							update_mode_rect.size.x += down_icon->get_width();
 							update_mode_rect.size.x += down_icon->get_width();
 						} else if (animation->track_get_type(track) == Animation::TYPE_BEZIER) {
 						} else if (animation->track_get_type(track) == Animation::TYPE_BEZIER) {
 							update_mode_rect.size.x += down_icon->get_width();
 							update_mode_rect.size.x += down_icon->get_width();
@@ -2167,8 +2192,8 @@ void AnimationTrackEdit::_notification(int p_what) {
 					}
 					}
 
 
 					ofs += down_icon->get_width();
 					ofs += down_icon->get_width();
-					draw_line(Point2(ofs + hsep * 0.5, 0), Point2(ofs + hsep * 0.5, get_size().height), linecolor, Math::round(EDSCALE));
-					ofs += hsep;
+					draw_line(Point2(ofs + h_separation * 0.5, 0), Point2(ofs + h_separation * 0.5, get_size().height), h_line_color, Math::round(EDSCALE));
+					ofs += h_separation;
 				}
 				}
 
 
 				{
 				{
@@ -2179,7 +2204,7 @@ void AnimationTrackEdit::_notification(int p_what) {
 					Ref<Texture2D> icon = interp_icon[interp_mode];
 					Ref<Texture2D> icon = interp_icon[interp_mode];
 
 
 					interp_mode_rect.position.x = ofs;
 					interp_mode_rect.position.x = ofs;
-					interp_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
+					interp_mode_rect.position.y = Math::round((get_size().height - icon->get_height()) / 2);
 					interp_mode_rect.size = icon->get_size();
 					interp_mode_rect.size = icon->get_size();
 
 
 					if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
 					if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
@@ -2189,19 +2214,19 @@ void AnimationTrackEdit::_notification(int p_what) {
 					interp_mode_rect.position.y = 0;
 					interp_mode_rect.position.y = 0;
 					interp_mode_rect.size.y = get_size().height;
 					interp_mode_rect.size.y = get_size().height;
 
 
-					ofs += icon->get_width() + hsep / 2;
-					interp_mode_rect.size.x += hsep / 2;
+					ofs += icon->get_width() + h_separation / 2;
+					interp_mode_rect.size.x += h_separation / 2;
 
 
 					if (!read_only && !animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
 					if (!read_only && !animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
-						draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
+						draw_texture(down_icon, Vector2(ofs, (get_size().height - down_icon->get_height()) / 2).round());
 						interp_mode_rect.size.x += down_icon->get_width();
 						interp_mode_rect.size.x += down_icon->get_width();
 					} else {
 					} else {
 						interp_mode_rect = Rect2();
 						interp_mode_rect = Rect2();
 					}
 					}
 
 
 					ofs += down_icon->get_width();
 					ofs += down_icon->get_width();
-					draw_line(Point2(ofs + hsep * 0.5, 0), Point2(ofs + hsep * 0.5, get_size().height), linecolor, Math::round(EDSCALE));
-					ofs += hsep;
+					draw_line(Point2(ofs + h_separation * 0.5, 0), Point2(ofs + h_separation * 0.5, get_size().height), h_line_color, Math::round(EDSCALE));
+					ofs += h_separation;
 				}
 				}
 
 
 				{
 				{
@@ -2212,7 +2237,7 @@ void AnimationTrackEdit::_notification(int p_what) {
 					Ref<Texture2D> icon = wrap_icon[loop_wrap ? 1 : 0];
 					Ref<Texture2D> icon = wrap_icon[loop_wrap ? 1 : 0];
 
 
 					loop_wrap_rect.position.x = ofs;
 					loop_wrap_rect.position.x = ofs;
-					loop_wrap_rect.position.y = int(get_size().height - icon->get_height()) / 2;
+					loop_wrap_rect.position.y = Math::round((get_size().height - icon->get_height()) / 2);
 					loop_wrap_rect.size = icon->get_size();
 					loop_wrap_rect.size = icon->get_size();
 
 
 					if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
 					if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
@@ -2222,19 +2247,19 @@ void AnimationTrackEdit::_notification(int p_what) {
 					loop_wrap_rect.position.y = 0;
 					loop_wrap_rect.position.y = 0;
 					loop_wrap_rect.size.y = get_size().height;
 					loop_wrap_rect.size.y = get_size().height;
 
 
-					ofs += icon->get_width() + hsep / 2;
-					loop_wrap_rect.size.x += hsep / 2;
+					ofs += icon->get_width() + h_separation / 2;
+					loop_wrap_rect.size.x += h_separation / 2;
 
 
 					if (!read_only && !animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
 					if (!read_only && !animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
-						draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
+						draw_texture(down_icon, Vector2(ofs, (get_size().height - down_icon->get_height()) / 2).round());
 						loop_wrap_rect.size.x += down_icon->get_width();
 						loop_wrap_rect.size.x += down_icon->get_width();
 					} else {
 					} else {
 						loop_wrap_rect = Rect2();
 						loop_wrap_rect = Rect2();
 					}
 					}
 
 
 					ofs += down_icon->get_width();
 					ofs += down_icon->get_width();
-					draw_line(Point2(ofs + hsep * 0.5, 0), Point2(ofs + hsep * 0.5, get_size().height), linecolor, Math::round(EDSCALE));
-					ofs += hsep;
+					draw_line(Point2(ofs + h_separation * 0.5, 0), Point2(ofs + h_separation * 0.5, get_size().height), h_line_color, Math::round(EDSCALE));
+					ofs += h_separation;
 				}
 				}
 
 
 				{
 				{
@@ -2242,8 +2267,8 @@ void AnimationTrackEdit::_notification(int p_what) {
 
 
 					Ref<Texture2D> icon = get_editor_theme_icon(animation->track_is_compressed(track) ? SNAME("Lock") : SNAME("Remove"));
 					Ref<Texture2D> icon = get_editor_theme_icon(animation->track_is_compressed(track) ? SNAME("Lock") : SNAME("Remove"));
 
 
-					remove_rect.position.x = ofs + ((get_size().width - ofs) - icon->get_width());
-					remove_rect.position.y = int(get_size().height - icon->get_height()) / 2;
+					remove_rect.position.x = ofs + ((get_size().width - ofs) - icon->get_width()) - outer_margin;
+					remove_rect.position.y = Math::round((get_size().height - icon->get_height()) / 2);
 					remove_rect.size = icon->get_size();
 					remove_rect.size = icon->get_size();
 
 
 					if (read_only) {
 					if (read_only) {
@@ -2255,9 +2280,9 @@ void AnimationTrackEdit::_notification(int p_what) {
 			}
 			}
 
 
 			if (in_group) {
 			if (in_group) {
-				draw_line(Vector2(timeline->get_name_limit(), get_size().height), get_size(), linecolor, Math::round(EDSCALE));
+				draw_line(Vector2(timeline->get_name_limit(), get_size().height), get_size(), h_line_color, Math::round(EDSCALE));
 			} else {
 			} else {
-				draw_line(Vector2(0, get_size().height), get_size(), linecolor, Math::round(EDSCALE));
+				draw_line(Vector2(0, get_size().height), get_size(), h_line_color, Math::round(EDSCALE));
 			}
 			}
 
 
 			if (dropping_at != 0) {
 			if (dropping_at != 0) {
@@ -2358,11 +2383,11 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
 		}
 		}
 	}
 	}
 
 
-	Vector2 ofs(p_x - icon_to_draw->get_width() / 2, int(get_size().height - icon_to_draw->get_height()) / 2);
+	Vector2 ofs(p_x - icon_to_draw->get_width() / 2, (get_size().height - icon_to_draw->get_height()) / 2);
 
 
 	if (animation->track_get_type(track) == Animation::TYPE_METHOD) {
 	if (animation->track_get_type(track) == Animation::TYPE_METHOD) {
-		Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-		int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+		const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+		const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
 		Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
 		Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
 		color.a = 0.5;
 		color.a = 0.5;
 
 
@@ -2486,9 +2511,9 @@ NodePath AnimationTrackEdit::get_path() const {
 
 
 Size2 AnimationTrackEdit::get_minimum_size() const {
 Size2 AnimationTrackEdit::get_minimum_size() const {
 	Ref<Texture2D> texture = get_editor_theme_icon(SNAME("Object"));
 	Ref<Texture2D> texture = get_editor_theme_icon(SNAME("Object"));
-	Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-	int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
-	int separation = get_theme_constant(SNAME("v_separation"), SNAME("ItemList"));
+	const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+	const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+	const int separation = get_theme_constant(SNAME("v_separation"), SNAME("ItemList"));
 
 
 	int max_h = MAX(texture->get_height(), font->get_height(font_size));
 	int max_h = MAX(texture->get_height(), font->get_height(font_size));
 	max_h = MAX(max_h, get_key_height());
 	max_h = MAX(max_h, get_key_height());
@@ -2977,7 +3002,7 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
 		}
 		}
 
 
 		path->set_text(animation->track_get_path(track));
 		path->set_text(animation->track_get_path(track));
-		Vector2 theme_ofs = path->get_theme_stylebox(CoreStringName(normal), SNAME("LineEdit"))->get_offset();
+		const Vector2 theme_ofs = path->get_theme_stylebox(CoreStringName(normal), SNAME("LineEdit"))->get_offset();
 
 
 		moving_selection_attempt = false;
 		moving_selection_attempt = false;
 		moving_selection = false;
 		moving_selection = false;
@@ -3419,11 +3444,19 @@ void AnimationTrackEditGroup::_notification(int p_what) {
 		} break;
 		} break;
 
 
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
-			Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-			int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
-			int separation = get_theme_constant(SNAME("h_separation"), SNAME("ItemList"));
+			const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+			const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
 			Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
 			Color color = get_theme_color(SceneStringName(font_color), SNAME("Label"));
 
 
+			const Ref<StyleBox> &stylebox_header = get_theme_stylebox(SNAME("header"), SNAME("AnimationTrackEditGroup"));
+			const int outer_margin = get_theme_constant(SNAME("outer_margin"), SNAME("AnimationTrackEdit"));
+
+			float v_margin_offset = stylebox_header->get_content_margin(SIDE_TOP) - stylebox_header->get_content_margin(SIDE_BOTTOM);
+
+			const Color h_line_color = get_theme_color(SNAME("h_line_color"), SNAME("AnimationTrackEditGroup"));
+			const Color v_line_color = get_theme_color(SNAME("v_line_color"), SNAME("AnimationTrackEditGroup"));
+			const int h_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationTrackEditGroup"));
+
 			if (root) {
 			if (root) {
 				Node *n = root->get_node_or_null(node);
 				Node *n = root->get_node_or_null(node);
 				if (n && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) {
 				if (n && EditorNode::get_singleton()->get_editor_selection()->is_selected(n)) {
@@ -3431,25 +3464,21 @@ void AnimationTrackEditGroup::_notification(int p_what) {
 				}
 				}
 			}
 			}
 
 
-			Color bgcol = get_theme_color(SNAME("dark_color_2"), EditorStringName(Editor));
-			bgcol.a *= 0.6;
-			draw_rect(Rect2(Point2(), get_size()), bgcol);
-			Color linecolor = color;
-			linecolor.a = 0.2;
+			draw_style_box(stylebox_header, Rect2(Point2(), get_size()));
 
 
-			draw_line(Point2(), Point2(get_size().width, 0), linecolor, Math::round(EDSCALE));
-			draw_line(Point2(timeline->get_name_limit(), 0), Point2(timeline->get_name_limit(), get_size().height), linecolor, Math::round(EDSCALE));
-			draw_line(Point2(get_size().width - timeline->get_buttons_width(), 0), Point2(get_size().width - timeline->get_buttons_width(), get_size().height), linecolor, Math::round(EDSCALE));
+			draw_line(Point2(), Point2(get_size().width, 0), h_line_color, Math::round(EDSCALE));
+			draw_line(Point2(timeline->get_name_limit(), 0), Point2(timeline->get_name_limit(), get_size().height), v_line_color, Math::round(EDSCALE));
+			draw_line(Point2(get_size().width - timeline->get_buttons_width() - outer_margin, 0), Point2(get_size().width - timeline->get_buttons_width() - outer_margin, get_size().height), v_line_color, Math::round(EDSCALE));
 
 
-			int ofs = 0;
-			draw_texture_rect(icon, Rect2(Point2(ofs, int(get_size().height - icon_size.y) / 2), icon_size));
-			ofs += separation + icon_size.x;
-			draw_string(font, Point2(ofs, int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), node_name, HORIZONTAL_ALIGNMENT_LEFT, timeline->get_name_limit() - ofs, font_size, color);
+			int ofs = stylebox_header->get_margin(SIDE_LEFT);
+			draw_texture_rect(icon, Rect2(Point2(ofs, (get_size().height - icon_size.y) / 2 + v_margin_offset).round(), icon_size));
+			ofs += h_separation + icon_size.x;
+			draw_string(font, Point2(ofs, (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size) + v_margin_offset).round(), node_name, HORIZONTAL_ALIGNMENT_LEFT, timeline->get_name_limit() - ofs, font_size, color);
 
 
 			int px = (-timeline->get_value() + timeline->get_play_position()) * timeline->get_zoom_scale() + timeline->get_name_limit();
 			int px = (-timeline->get_value() + timeline->get_play_position()) * timeline->get_zoom_scale() + timeline->get_name_limit();
 
 
 			if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) {
 			if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) {
-				Color accent = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
+				const Color accent = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
 				draw_line(Point2(px, 0), Point2(px, get_size().height), accent, Math::round(2 * EDSCALE));
 				draw_line(Point2(px, 0), Point2(px, get_size().height), accent, Math::round(2 * EDSCALE));
 			}
 			}
 		} break;
 		} break;
@@ -3484,11 +3513,14 @@ void AnimationTrackEditGroup::set_type_and_name(const Ref<Texture2D> &p_type, co
 }
 }
 
 
 Size2 AnimationTrackEditGroup::get_minimum_size() const {
 Size2 AnimationTrackEditGroup::get_minimum_size() const {
-	Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
-	int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
-	int separation = get_theme_constant(SNAME("v_separation"), SNAME("ItemList"));
+	const Ref<Font> font = get_theme_font(SceneStringName(font), SNAME("Label"));
+	const int font_size = get_theme_font_size(SceneStringName(font_size), SNAME("Label"));
+	const int separation = get_theme_constant(SNAME("v_separation"), SNAME("ItemList"));
+
+	const Ref<StyleBox> &header_style = get_theme_stylebox(SNAME("header"), SNAME("AnimationTrackEditGroup"));
+	const int content_margin = header_style->get_content_margin(SIDE_TOP) + header_style->get_content_margin(SIDE_BOTTOM);
 
 
-	return Vector2(0, MAX(font->get_height(font_size), icon_size.y) + separation);
+	return Vector2(0, MAX(font->get_height(font_size), icon_size.y) + separation + content_margin);
 }
 }
 
 
 void AnimationTrackEditGroup::set_timeline(AnimationTimelineEdit *p_timeline) {
 void AnimationTrackEditGroup::set_timeline(AnimationTimelineEdit *p_timeline) {
@@ -4891,6 +4923,12 @@ void AnimationTrackEditor::_notification(int p_what) {
 			edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_editor_theme_icon(SNAME("Reload")));
 			edit->get_popup()->set_item_icon(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), get_editor_theme_icon(SNAME("Reload")));
 			auto_fit->set_icon(get_editor_theme_icon(SNAME("AnimationAutoFit")));
 			auto_fit->set_icon(get_editor_theme_icon(SNAME("AnimationAutoFit")));
 			auto_fit_bezier->set_icon(get_editor_theme_icon(SNAME("AnimationAutoFitBezier")));
 			auto_fit_bezier->set_icon(get_editor_theme_icon(SNAME("AnimationAutoFitBezier")));
+
+			const int timeline_separation = get_theme_constant(SNAME("timeline_v_separation"), SNAME("AnimationTrackEditor"));
+			timeline_vbox->add_theme_constant_override("separation", timeline_separation);
+
+			const int track_separation = get_theme_constant(SNAME("track_v_separation"), SNAME("AnimationTrackEditor"));
+			track_vbox->add_theme_constant_override("separation", track_separation);
 		} break;
 		} break;
 
 
 		case NOTIFICATION_READY: {
 		case NOTIFICATION_READY: {
@@ -6389,7 +6427,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
 			undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
 			undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
 			undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
 			undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
 
 
-			// 7-reselect.
+			// 7 - Reselect.
 			for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 			for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
 				float oldpos = E->get().pos;
 				float oldpos = E->get().pos;
 				float newpos = NEW_POS(oldpos);
 				float newpos = NEW_POS(oldpos);
@@ -7182,11 +7220,10 @@ AnimationTrackEditor::AnimationTrackEditor() {
 	main_panel->add_child(timeline_scroll);
 	main_panel->add_child(timeline_scroll);
 	timeline_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
 	timeline_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
 
 
-	VBoxContainer *timeline_vbox = memnew(VBoxContainer);
+	timeline_vbox = memnew(VBoxContainer);
 	timeline_scroll->add_child(timeline_vbox);
 	timeline_scroll->add_child(timeline_vbox);
 	timeline_vbox->set_v_size_flags(SIZE_EXPAND_FILL);
 	timeline_vbox->set_v_size_flags(SIZE_EXPAND_FILL);
 	timeline_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
 	timeline_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
-	timeline_vbox->add_theme_constant_override("separation", 0);
 
 
 	info_message = memnew(Label);
 	info_message = memnew(Label);
 	info_message->set_text(TTR("Select an AnimationPlayer node to create and edit animations."));
 	info_message->set_text(TTR("Select an AnimationPlayer node to create and edit animations."));
@@ -7239,7 +7276,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
 	scroll->add_child(track_vbox);
 	scroll->add_child(track_vbox);
 	track_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
 	track_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
 	scroll->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
 	scroll->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
-	track_vbox->add_theme_constant_override("separation", 0);
 
 
 	HBoxContainer *bottom_hb = memnew(HBoxContainer);
 	HBoxContainer *bottom_hb = memnew(HBoxContainer);
 	add_child(bottom_hb);
 	add_child(bottom_hb);
@@ -7585,7 +7621,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
 	bake_grid->add_child(memnew(Label(TTR("FPS:"))));
 	bake_grid->add_child(memnew(Label(TTR("FPS:"))));
 	bake_grid->add_child(bake_fps);
 	bake_grid->add_child(bake_fps);
 
 
-	//
 	track_copy_dialog = memnew(ConfirmationDialog);
 	track_copy_dialog = memnew(ConfirmationDialog);
 	add_child(track_copy_dialog);
 	add_child(track_copy_dialog);
 	track_copy_dialog->set_title(TTR("Select Tracks to Copy"));
 	track_copy_dialog->set_title(TTR("Select Tracks to Copy"));
@@ -7617,7 +7652,7 @@ AnimationTrackEditor::~AnimationTrackEditor() {
 	}
 	}
 }
 }
 
 
-// AnimationTrackKeyEditEditorPlugin
+// AnimationTrackKeyEditEditorPlugin.
 
 
 void AnimationTrackKeyEditEditor::_time_edit_entered() {
 void AnimationTrackKeyEditEditor::_time_edit_entered() {
 	int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);
 	int key = animation->track_find_key(track, key_ofs, Animation::FIND_MODE_APPROX);

+ 1 - 0
editor/animation_track_editor.h

@@ -400,6 +400,7 @@ class AnimationTrackEditor : public VBoxContainer {
 	ScrollContainer *scroll = nullptr;
 	ScrollContainer *scroll = nullptr;
 	VBoxContainer *track_vbox = nullptr;
 	VBoxContainer *track_vbox = nullptr;
 	AnimationBezierTrackEdit *bezier_edit = nullptr;
 	AnimationBezierTrackEdit *bezier_edit = nullptr;
+	VBoxContainer *timeline_vbox = nullptr;
 
 
 	Label *info_message = nullptr;
 	Label *info_message = nullptr;
 
 

+ 65 - 0
editor/themes/editor_theme_manager.cpp

@@ -2233,6 +2233,71 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme
 		p_theme->set_stylebox("DictionaryAddItem0", EditorStringName(EditorStyles), style_dictionary_add_item);
 		p_theme->set_stylebox("DictionaryAddItem0", EditorStringName(EditorStyles), style_dictionary_add_item);
 	}
 	}
 
 
+	// Animation Editor.
+	{
+		// Timeline general.
+		p_theme->set_constant("timeline_v_separation", "AnimationTrackEditor", 0);
+		p_theme->set_constant("track_v_separation", "AnimationTrackEditor", 0);
+
+		// AnimationTimelineEdit.
+		// "primary" is used for integer timeline values, "secondary" for decimals.
+
+		Ref<StyleBoxFlat> style_time_unavailable = make_flat_stylebox(p_config.dark_color_2, 0, 0, 0, 0, 0);
+		Ref<StyleBoxFlat> style_time_available = make_flat_stylebox(p_config.font_color * Color(1, 1, 1, 0.2), 0, 0, 0, 0, 0);
+
+		p_theme->set_stylebox("time_unavailable", "AnimationTimelineEdit", style_time_unavailable);
+		p_theme->set_stylebox("time_available", "AnimationTimelineEdit", style_time_available);
+
+		p_theme->set_color("v_line_primary_color", "AnimationTimelineEdit", p_config.font_color * Color(1, 1, 1, 0.2));
+		p_theme->set_color("v_line_secondary_color", "AnimationTimelineEdit", p_config.font_color * Color(1, 1, 1, 0.2));
+		p_theme->set_color("h_line_color", "AnimationTimelineEdit", p_config.font_color * Color(1, 1, 1, 0.2));
+		p_theme->set_color("font_primary_color", "AnimationTimelineEdit", p_config.font_color);
+		p_theme->set_color("font_secondary_color", "AnimationTimelineEdit", p_config.font_color * Color(1, 1, 1, 0.5));
+
+		p_theme->set_constant("v_line_primary_margin", "AnimationTimelineEdit", 0);
+		p_theme->set_constant("v_line_secondary_margin", "AnimationTimelineEdit", 0);
+		p_theme->set_constant("v_line_primary_width", "AnimationTimelineEdit", 1 * EDSCALE);
+		p_theme->set_constant("v_line_secondary_width", "AnimationTimelineEdit", 1 * EDSCALE);
+		p_theme->set_constant("text_primary_margin", "AnimationTimelineEdit", 3 * EDSCALE);
+		p_theme->set_constant("text_secondary_margin", "AnimationTimelineEdit", 3 * EDSCALE);
+
+		// AnimationTrackEdit.
+
+		Ref<StyleBoxFlat> style_animation_track_odd = make_flat_stylebox(Color(0.5, 0.5, 0.5, 0.05), 0, 0, 0, 0, p_config.corner_radius);
+		Ref<StyleBoxFlat> style_animation_track_hover = make_flat_stylebox(Color(0.5, 0.5, 0.5, 0.1), 0, 0, 0, 0, p_config.corner_radius);
+
+		p_theme->set_stylebox("odd", "AnimationTrackEdit", style_animation_track_odd);
+		p_theme->set_stylebox("hover", "AnimationTrackEdit", style_animation_track_hover);
+		p_theme->set_stylebox("focus", "AnimationTrackEdit", p_config.button_style_focus);
+
+		p_theme->set_color("h_line_color", "AnimationTrackEdit", p_config.font_color * Color(1, 1, 1, 0.2));
+
+		p_theme->set_constant("h_separation", "AnimationTrackEdit", (p_config.increased_margin + 2) * EDSCALE);
+		p_theme->set_constant("outer_margin", "AnimationTrackEdit", p_config.increased_margin * 6 * EDSCALE);
+
+		// AnimationTrackEditGroup.
+
+		Ref<StyleBoxFlat> style_animation_track_header = make_flat_stylebox(p_config.dark_color_2 * Color(1, 1, 1, 0.6), p_config.increased_margin * 3, 0, 0, 0, p_config.corner_radius);
+
+		p_theme->set_stylebox("header", "AnimationTrackEditGroup", style_animation_track_header);
+
+		p_theme->set_color("h_line_color", "AnimationTrackEditGroup", p_config.font_color * Color(1, 1, 1, 0.2));
+		p_theme->set_color("v_line_color", "AnimationTrackEditGroup", p_config.font_color * Color(1, 1, 1, 0.2));
+
+		p_theme->set_constant("h_separation", "AnimationTrackEditGroup", (p_config.increased_margin + 2) * EDSCALE);
+		p_theme->set_constant("v_separation", "AnimationTrackEditGroup", 0);
+
+		// AnimationBezierTrackEdit.
+
+		p_theme->set_color("focus_color", "AnimationBezierTrackEdit", p_config.accent_color * Color(1, 1, 1, 0.7));
+		p_theme->set_color("track_focus_color", "AnimationBezierTrackEdit", p_config.accent_color * Color(1, 1, 1, 0.5));
+		p_theme->set_color("h_line_color", "AnimationBezierTrackEdit", p_config.font_color * Color(1, 1, 1, 0.2));
+		p_theme->set_color("v_line_color", "AnimationBezierTrackEdit", p_config.font_color * Color(1, 1, 1, 0.2));
+
+		p_theme->set_constant("h_separation", "AnimationBezierTrackEdit", (p_config.increased_margin + 2) * EDSCALE);
+		p_theme->set_constant("v_separation", "AnimationBezierTrackEdit", p_config.forced_even_separation * EDSCALE);
+	}
+
 	// Editor help.
 	// Editor help.
 	{
 	{
 		Ref<StyleBoxFlat> style_editor_help = p_config.base_style->duplicate();
 		Ref<StyleBoxFlat> style_editor_help = p_config.base_style->duplicate();