diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index f50e164e0f35..4dff22327880 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -1177,6 +1177,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { moving_selection_attempt = true; moving_selection = false; + moving_selection_mouse_begin_x = mb->get_position().x; moving_selection_from_key = index; moving_selection_from_track = selected_track; moving_selection_offset = Vector2(); @@ -1258,7 +1259,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { if (moving_selection_attempt && mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (!read_only) { - if (moving_selection && (abs(moving_selection_offset.x) > 0 || abs(moving_selection_offset.y) > 0)) { + if (moving_selection && (abs(moving_selection_offset.x) > CMP_EPSILON || abs(moving_selection_offset.y) > CMP_EPSILON)) { //combit it EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); @@ -1272,7 +1273,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { } // 2- remove overlapped keys for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) { - real_t newtime = editor->snap_time(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; int idx = animation->track_find_key(E->get().first, newtime, Animation::FIND_MODE_APPROX); if (idx == -1) { @@ -1296,7 +1297,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { // 3-move the keys (re insert them) for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) { - real_t newpos = editor->snap_time(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); real_t h = key[0]; h += moving_selection_offset.y; @@ -1314,7 +1315,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { // 4-(undo) remove inserted keys for (SelectionSet::Element *E = selection.back(); E; E = E->prev()) { - real_t newpos = editor->snap_time(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); } @@ -1356,7 +1357,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { 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 newpos = editor->snap_time(oldpos + moving_selection_offset.x); + real_t newpos = oldpos + moving_selection_offset.x; undo_redo->add_do_method(this, "_select_at_anim", animation, E->get().first, newpos); undo_redo->add_undo_method(this, "_select_at_anim", animation, E->get().first, oldpos); @@ -1364,14 +1365,15 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { undo_redo->commit_action(); - moving_selection = false; } else if (select_single_attempt != IntPair(-1, -1)) { selection.clear(); selection.insert(select_single_attempt); set_animation_and_track(animation, select_single_attempt.first, read_only); } + moving_selection = false; moving_selection_attempt = false; + moving_selection_mouse_begin_x = 0.0; queue_redraw(); } } @@ -1383,11 +1385,22 @@ void AnimationBezierTrackEdit::gui_input(const Ref &p_event) { select_single_attempt = IntPair(-1, -1); } - float y = (get_size().height / 2.0 - mm->get_position().y) * timeline_v_zoom + timeline_v_scroll; - float x = editor->snap_time(((mm->get_position().x - limit) / timeline->get_zoom_scale()) + timeline->get_value()); - if (!read_only) { - moving_selection_offset = Vector2(x - animation->track_get_key_time(moving_selection_from_track, moving_selection_from_key), y - animation->bezier_track_get_key_value(moving_selection_from_track, moving_selection_from_key)); + float y = (get_size().height / 2.0 - mm->get_position().y) * timeline_v_zoom + timeline_v_scroll; + float moving_selection_begin_time = ((moving_selection_mouse_begin_x - limit) / timeline->get_zoom_scale()) + timeline->get_value(); + float new_time = ((mm->get_position().x - limit) / timeline->get_zoom_scale()) + timeline->get_value(); + float moving_selection_pivot = animation->track_get_key_time(moving_selection_from_track, moving_selection_from_key); + float time_delta = new_time - moving_selection_begin_time; + + float snapped_time = editor->snap_time(moving_selection_pivot + time_delta); + float time_offset = 0.0; + if (abs(moving_selection_offset.x) > CMP_EPSILON || (snapped_time > moving_selection_pivot && time_delta > CMP_EPSILON) || (snapped_time < moving_selection_pivot && time_delta < -CMP_EPSILON)) { + time_offset = snapped_time - moving_selection_pivot; + } + float moving_selection_begin_value = animation->bezier_track_get_key_value(moving_selection_from_track, moving_selection_from_key); + float y_offset = y - moving_selection_begin_value; + + moving_selection_offset = Vector2(time_offset, y_offset); } additional_moving_handle_lefts.clear(); @@ -1501,17 +1514,18 @@ bool AnimationBezierTrackEdit::_try_select_at_ui_pos(const Point2 &p_pos, bool p moving_selection_attempt = true; moving_selection_from_key = pair.second; moving_selection_from_track = pair.first; + moving_selection_mouse_begin_x = p_pos.x; moving_selection_offset = Vector2(); moving_handle_track = pair.first; moving_handle_left = animation->bezier_track_get_key_in_handle(pair.first, pair.second); moving_handle_right = animation->bezier_track_get_key_out_handle(pair.first, pair.second); if (selection.has(pair)) { - select_single_attempt = pair; moving_selection = false; } else { moving_selection = true; } + select_single_attempt = pair; } set_animation_and_track(animation, pair.first, read_only); diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h index ec2b52221eb6..44f36e801e2b 100644 --- a/editor/animation_bezier_editor.h +++ b/editor/animation_bezier_editor.h @@ -107,6 +107,7 @@ class AnimationBezierTrackEdit : public Control { typedef Pair IntPair; bool moving_selection_attempt = false; + float moving_selection_mouse_begin_x = 0.0; IntPair select_single_attempt; bool moving_selection = false; int moving_selection_from_key = 0; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index f893234acfc2..a498ed4a96f1 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2000,13 +2000,13 @@ void AnimationTrackEdit::_notification(int p_what) { for (int i = 0; i < animation->track_get_key_count(track); i++) { float offset = animation->track_get_key_time(track, i) - timeline->get_value(); if (editor->is_key_selected(track, i) && editor->is_moving_selection()) { - offset = editor->snap_time(offset + editor->get_moving_selection_offset(), true); + offset = offset + editor->get_moving_selection_offset(); } offset = offset * scale + limit; if (i < animation->track_get_key_count(track) - 1) { float offset_n = animation->track_get_key_time(track, i + 1) - timeline->get_value(); if (editor->is_key_selected(track, i + 1) && editor->is_moving_selection()) { - offset_n = editor->snap_time(offset_n + editor->get_moving_selection_offset()); + offset_n = offset_n + editor->get_moving_selection_offset(); } offset_n = offset_n * scale + limit; @@ -2907,8 +2907,10 @@ void AnimationTrackEdit::gui_input(const Ref &p_event) { if (mb.is_valid() && moving_selection_attempt) { if (!mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { moving_selection_attempt = false; - if (moving_selection) { - emit_signal(SNAME("move_selection_commit")); + if (moving_selection && moving_selection_effective) { + if (abs(editor->get_moving_selection_offset()) > CMP_EPSILON) { + emit_signal(SNAME("move_selection_commit")); + } } else if (select_single_attempt != -1) { emit_signal(SNAME("select_key"), select_single_attempt, true); } @@ -2981,8 +2983,18 @@ void AnimationTrackEdit::gui_input(const Ref &p_event) { emit_signal(SNAME("move_selection_begin")); } - float new_ofs = (mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale(); - emit_signal(SNAME("move_selection"), new_ofs - moving_selection_from_ofs); + float moving_begin_time = ((moving_selection_mouse_begin_x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value(); + float new_time = ((mm->get_position().x - timeline->get_name_limit()) / timeline->get_zoom_scale()) + timeline->get_value(); + float delta = new_time - moving_begin_time; + float snapped_time = editor->snap_time(moving_selection_pivot + delta); + + float offset = 0.0; + if (abs(editor->get_moving_selection_offset()) > CMP_EPSILON || (snapped_time > moving_selection_pivot && delta > CMP_EPSILON) || (snapped_time < moving_selection_pivot && delta < -CMP_EPSILON)) { + offset = snapped_time - moving_selection_pivot; + moving_selection_effective = true; + } + + emit_signal(SNAME("move_selection"), offset); } } @@ -3025,12 +3037,16 @@ bool AnimationTrackEdit::_try_select_at_ui_pos(const Point2 &p_pos, bool p_aggre if (editor->is_key_selected(track, key_idx)) { if (p_deselectable) { emit_signal(SNAME("deselect_key"), key_idx); + moving_selection_pivot = 0.0f; + moving_selection_mouse_begin_x = 0.0f; } } else { emit_signal(SNAME("select_key"), key_idx, false); moving_selection_attempt = true; + moving_selection_effective = false; select_single_attempt = -1; - moving_selection_from_ofs = (p_pos.x - limit) / timeline->get_zoom_scale(); + moving_selection_pivot = animation->track_get_key_time(track, key_idx); + moving_selection_mouse_begin_x = p_pos.x; } } else { if (!editor->is_key_selected(track, key_idx)) { @@ -3041,12 +3057,15 @@ bool AnimationTrackEdit::_try_select_at_ui_pos(const Point2 &p_pos, bool p_aggre } moving_selection_attempt = true; - moving_selection_from_ofs = (p_pos.x - limit) / timeline->get_zoom_scale(); + moving_selection_effective = false; + moving_selection_pivot = animation->track_get_key_time(track, key_idx); + moving_selection_mouse_begin_x = p_pos.x; } if (read_only) { moving_selection_attempt = false; - moving_selection_from_ofs = 0.0f; + moving_selection_pivot = 0.0f; + moving_selection_mouse_begin_x = 0.0f; } return true; } @@ -5423,7 +5442,7 @@ void AnimationTrackEditor::_move_selection_commit() { } // 2 - Remove overlapped keys. for (RBMap::Element *E = selection.back(); E; E = E->prev()) { - float newtime = snap_time(E->get().pos + motion); + float newtime = E->get().pos + motion; int idx = animation->track_find_key(E->key().track, newtime, Animation::FIND_MODE_APPROX); if (idx == -1) { continue; @@ -5448,13 +5467,13 @@ void AnimationTrackEditor::_move_selection_commit() { // 3 - Move the keys (Reinsert them). for (RBMap::Element *E = selection.back(); E; E = E->prev()) { - float newpos = snap_time(E->get().pos + motion); + float newpos = E->get().pos + motion; undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key)); } // 4 - (Undo) Remove inserted keys. for (RBMap::Element *E = selection.back(); E; E = E->prev()) { - float newpos = snap_time(E->get().pos + motion); + float newpos = E->get().pos + motion; undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos); } @@ -5474,7 +5493,7 @@ void AnimationTrackEditor::_move_selection_commit() { // 7 - Reselect. for (RBMap::Element *E = selection.back(); E; E = E->prev()) { float oldpos = E->get().pos; - float newpos = snap_time(oldpos + motion); + float newpos = oldpos + motion; undo_redo->add_do_method(this, "_select_at_anim", animation, E->key().track, newpos); undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 0d6f93fefc43..d7fddc95da4e 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -286,9 +286,11 @@ class AnimationTrackEdit : public Control { mutable int dropping_at = 0; float insert_at_pos = 0.0f; bool moving_selection_attempt = false; + bool moving_selection_effective = false; + float moving_selection_pivot = 0.0f; + float moving_selection_mouse_begin_x = 0.0f; int select_single_attempt = -1; bool moving_selection = false; - float moving_selection_from_ofs = 0.0f; bool in_group = false; AnimationTrackEditor *editor = nullptr;