Browse Source

Add separate timeline snapping control to Animation Editor

Kasper Arnklit Frandsen 1 năm trước cách đây
mục cha
commit
88a866fb5a

+ 3 - 3
editor/animation_bezier_editor.cpp

@@ -1660,7 +1660,7 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) {
 	switch (p_index) {
 		case MENU_KEY_INSERT: {
 			if (animation->get_track_count() > 0) {
-				if (editor->snap->is_pressed() && editor->step->get_value() != 0) {
+				if (editor->snap_keys->is_pressed() && editor->step->get_value() != 0) {
 					time = editor->snap_time(time);
 				}
 				while (animation->track_find_key(selected_track, time, Animation::FIND_MODE_APPROX) != -1) {
@@ -1736,7 +1736,7 @@ void AnimationBezierTrackEdit::duplicate_selected_keys(real_t p_ofs, bool p_ofs_
 		real_t insert_pos = p_ofs_valid ? p_ofs : timeline->get_play_position();
 
 		if (p_ofs_valid) {
-			if (editor->snap->is_pressed() && editor->step->get_value() != 0) {
+			if (editor->snap_keys->is_pressed() && editor->step->get_value() != 0) {
 				insert_pos = editor->snap_time(insert_pos);
 			}
 		}
@@ -1859,7 +1859,7 @@ void AnimationBezierTrackEdit::paste_keys(real_t p_ofs, bool p_ofs_valid) {
 
 			float insert_pos = p_ofs_valid ? p_ofs : timeline->get_play_position();
 			if (p_ofs_valid) {
-				if (editor->snap->is_pressed() && editor->step->get_value() != 0) {
+				if (editor->snap_keys->is_pressed() && editor->step->get_value() != 0) {
 					insert_pos = editor->snap_time(insert_pos);
 				}
 			}

+ 31 - 16
editor/animation_track_editor.cpp

@@ -3615,7 +3615,8 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re
 		_update_step_spinbox();
 		step->set_block_signals(false);
 		step->set_read_only(false);
-		snap->set_disabled(false);
+		snap_keys->set_disabled(false);
+		snap_timeline->set_disabled(false);
 		snap_mode->set_disabled(false);
 		auto_fit->set_disabled(false);
 		auto_fit_bezier->set_disabled(false);
@@ -3636,7 +3637,8 @@ void AnimationTrackEditor::set_animation(const Ref<Animation> &p_anim, bool p_re
 		step->set_value(0);
 		step->set_block_signals(false);
 		step->set_read_only(true);
-		snap->set_disabled(true);
+		snap_keys->set_disabled(true);
+		snap_timeline->set_disabled(true);
 		snap_mode->set_disabled(true);
 		bezier_edit_icon->set_disabled(true);
 		auto_fit->set_disabled(true);
@@ -4555,8 +4557,12 @@ bool AnimationTrackEditor::is_key_clipboard_active() const {
 	return key_clipboard.keys.size();
 }
 
-bool AnimationTrackEditor::is_snap_enabled() const {
-	return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL);
+bool AnimationTrackEditor::is_snap_timeline_enabled() const {
+	return snap_timeline->is_pressed() ^ Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL);
+}
+
+bool AnimationTrackEditor::is_snap_keys_enabled() const {
+	return snap_keys->is_pressed() ^ Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL);
 }
 
 bool AnimationTrackEditor::is_bezier_editor_active() const {
@@ -4896,7 +4902,8 @@ void AnimationTrackEditor::_notification(int p_what) {
 		case NOTIFICATION_THEME_CHANGED: {
 			zoom_icon->set_texture(get_editor_theme_icon(SNAME("Zoom")));
 			bezier_edit_icon->set_icon(get_editor_theme_icon(SNAME("EditBezier")));
-			snap->set_icon(get_editor_theme_icon(SNAME("Snap")));
+			snap_timeline->set_icon(get_editor_theme_icon(SNAME("SnapTimeline")));
+			snap_keys->set_icon(get_editor_theme_icon(SNAME("SnapKeys")));
 			view_group->set_icon(get_editor_theme_icon(view_group->is_pressed() ? SNAME("AnimationTrackList") : SNAME("AnimationTrackGroup")));
 			selected_filter->set_icon(get_editor_theme_icon(SNAME("AnimationFilter")));
 			imported_anim_warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning")));
@@ -5217,7 +5224,7 @@ int AnimationTrackEditor::_get_track_selected() {
 void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
 	ERR_FAIL_INDEX(p_track, animation->get_track_count());
 
-	if (snap->is_pressed() && step->get_value() != 0) {
+	if (snap_keys->is_pressed() && step->get_value() != 0) {
 		p_ofs = snap_time(p_ofs);
 	}
 	while (animation->track_find_key(p_track, p_ofs, Animation::FIND_MODE_APPROX) != -1) { // Make sure insertion point is valid.
@@ -5840,7 +5847,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(float p_ofs, bool p_ofs_valid, i
 			float insert_pos = p_ofs_valid ? p_ofs : timeline->get_play_position();
 
 			if (p_ofs_valid) {
-				if (snap->is_pressed() && step->get_value() != 0) {
+				if (snap_keys->is_pressed() && step->get_value() != 0) {
 					insert_pos = snap_time(insert_pos);
 				}
 			}
@@ -5988,7 +5995,7 @@ void AnimationTrackEditor::_anim_paste_keys(float p_ofs, bool p_ofs_valid, int p
 			float insert_pos = p_ofs_valid ? p_ofs : timeline->get_play_position();
 
 			if (p_ofs_valid) {
-				if (snap->is_pressed() && step->get_value() != 0) {
+				if (snap_keys->is_pressed() && step->get_value() != 0) {
 					insert_pos = snap_time(insert_pos);
 				}
 			}
@@ -7069,7 +7076,7 @@ void AnimationTrackEditor::_update_snap_unit() {
 }
 
 float AnimationTrackEditor::snap_time(float p_value, bool p_relative) {
-	if (is_snap_enabled()) {
+	if (is_snap_keys_enabled()) {
 		if (Input::get_singleton()->is_key_pressed(Key::SHIFT)) {
 			// Use more precise snapping when holding Shift.
 			snap_unit *= 0.25;
@@ -7323,13 +7330,21 @@ AnimationTrackEditor::AnimationTrackEditor() {
 	bottom_hb->add_child(view_group);
 	bottom_hb->add_child(memnew(VSeparator));
 
-	snap = memnew(Button);
-	snap->set_flat(true);
-	snap->set_text(TTR("Snap:") + " ");
-	bottom_hb->add_child(snap);
-	snap->set_disabled(true);
-	snap->set_toggle_mode(true);
-	snap->set_pressed(true);
+	snap_timeline = memnew(Button);
+	snap_timeline->set_flat(true);
+	bottom_hb->add_child(snap_timeline);
+	snap_timeline->set_disabled(true);
+	snap_timeline->set_toggle_mode(true);
+	snap_timeline->set_pressed(false);
+	snap_timeline->set_tooltip_text(TTR("Apply snapping to timeline cursor."));
+
+	snap_keys = memnew(Button);
+	snap_keys->set_flat(true);
+	bottom_hb->add_child(snap_keys);
+	snap_keys->set_disabled(true);
+	snap_keys->set_toggle_mode(true);
+	snap_keys->set_pressed(true);
+	snap_keys->set_tooltip_text(TTR("Apply snapping to selected key(s)."));
 
 	step = memnew(EditorSpinSlider);
 	step->set_min(0);

+ 4 - 2
editor/animation_track_editor.h

@@ -408,7 +408,8 @@ class AnimationTrackEditor : public VBoxContainer {
 	HSlider *zoom = nullptr;
 	EditorSpinSlider *step = nullptr;
 	TextureRect *zoom_icon = nullptr;
-	Button *snap = nullptr;
+	Button *snap_keys = nullptr;
+	Button *snap_timeline = nullptr;
 	Button *bezier_edit_icon = nullptr;
 	OptionButton *snap_mode = nullptr;
 	Button *auto_fit = nullptr;
@@ -728,7 +729,8 @@ public:
 	bool is_selection_active() const;
 	bool is_key_clipboard_active() const;
 	bool is_moving_selection() const;
-	bool is_snap_enabled() const;
+	bool is_snap_timeline_enabled() const;
+	bool is_snap_keys_enabled() const;
 	bool is_bezier_editor_active() const;
 	bool can_add_reset_key() const;
 	float get_moving_selection_offset() const;

+ 1 - 0
editor/icons/SnapKeys.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m 7,13 v 2 h 2 v -2 z m 6,0 v 2 h 2 v -2 z"/><path fill="#fff" fill-opacity=".686" d="m 7,13 h 2 v -2 a 2,2 0 0 1 4,0 v 2 h 2 v -2 a 4,4 0 0 0 -8,0 z"/><path fill="#fff" d="M 5,1 1,5 5,9 9,5 Z"/></svg>

+ 1 - 0
editor/icons/SnapTimeline.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="m 7,13 v 2 h 2 v -2 z m 6,0 v 2 h 2 v -2 z"/><path fill="#fff" fill-opacity=".686" d="m 7,13 h 2 v -2 a 2,2 0 0 1 4,0 v 2 h 2 v -2 a 4,4 0 0 0 -8,0 z"/><path fill="#fff" d="m 1,2 3,3 v 9 H 6 V 5 L 9,2 Z"/></svg>

+ 7 - 12
editor/plugins/animation_player_editor_plugin.cpp

@@ -537,17 +537,12 @@ void AnimationPlayerEditor::_select_anim_by_name(const String &p_anim) {
 }
 
 float AnimationPlayerEditor::_get_editor_step() const {
-	// Returns the effective snapping value depending on snapping modifiers, or 0 if snapping is disabled.
-	if (track_editor->is_snap_enabled()) {
-		const String current = player->get_assigned_animation();
-		const Ref<Animation> anim = player->get_animation(current);
-		ERR_FAIL_COND_V(!anim.is_valid(), 0.0);
+	const String current = player->get_assigned_animation();
+	const Ref<Animation> anim = player->get_animation(current);
+	ERR_FAIL_COND_V(anim.is_null(), 0.0);
 
-		// Use more precise snapping when holding Shift
-		return Input::get_singleton()->is_key_pressed(Key::SHIFT) ? anim->get_step() * 0.25 : anim->get_step();
-	}
-
-	return 0.0f;
+	// Use more precise snapping when holding Shift
+	return Input::get_singleton()->is_key_pressed(Key::SHIFT) ? anim->get_step() * 0.25 : anim->get_step();
 }
 
 void AnimationPlayerEditor::_animation_name_edited() {
@@ -1353,7 +1348,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_timeline_o
 	anim = player->get_animation(current);
 
 	double pos = CLAMP((double)anim->get_length() * (p_value / frame->get_max()), 0, (double)anim->get_length());
-	if (track_editor->is_snap_enabled()) {
+	if (track_editor->is_snap_timeline_enabled()) {
 		pos = Math::snapped(pos, _get_editor_step());
 	}
 	pos = CLAMP(pos, 0, (double)anim->get_length() - CMP_EPSILON2); // Hack: Avoid fposmod with LOOP_LINEAR.
@@ -1471,7 +1466,7 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_timel
 	}
 
 	updating = true;
-	frame->set_value(Math::snapped(p_pos, _get_editor_step()));
+	frame->set_value(track_editor->is_snap_timeline_enabled() ? Math::snapped(p_pos, _get_editor_step()) : p_pos);
 	updating = false;
 	_seek_value_changed(p_pos, p_timeline_only);
 }