From 88a866fb5a5864b84489e4e2a216f5be75b786de Mon Sep 17 00:00:00 2001 From: Kasper Arnklit Frandsen Date: Fri, 16 Aug 2024 14:11:32 +0100 Subject: [PATCH] Add separate timeline snapping control to Animation Editor --- editor/animation_bezier_editor.cpp | 6 +-- editor/animation_track_editor.cpp | 47 ++++++++++++------- editor/animation_track_editor.h | 6 ++- editor/icons/SnapKeys.svg | 1 + editor/icons/SnapTimeline.svg | 1 + .../animation_player_editor_plugin.cpp | 19 +++----- 6 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 editor/icons/SnapKeys.svg create mode 100644 editor/icons/SnapTimeline.svg diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 5196857240c..a2fba2c41eb 100644 --- a/editor/animation_bezier_editor.cpp +++ b/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); } } diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index e080a24c96c..95ba3012825 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3615,7 +3615,8 @@ void AnimationTrackEditor::set_animation(const Ref &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 &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); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 516ddb01541..8a263d7d209 100644 --- a/editor/animation_track_editor.h +++ b/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; diff --git a/editor/icons/SnapKeys.svg b/editor/icons/SnapKeys.svg new file mode 100644 index 00000000000..813781b8010 --- /dev/null +++ b/editor/icons/SnapKeys.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/icons/SnapTimeline.svg b/editor/icons/SnapTimeline.svg new file mode 100644 index 00000000000..b558545f5a4 --- /dev/null +++ b/editor/icons/SnapTimeline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 73c17aa7600..b8821129504 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/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 anim = player->get_animation(current); - ERR_FAIL_COND_V(!anim.is_valid(), 0.0); + const String current = player->get_assigned_animation(); + const Ref 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); }