Improve scrolling actions in the animation track editor
- Implement timeline scrobbling using Alt + Mouse wheel anywhere in the animation track editor. - Snap settings are followed, and precise snapping can be obtained by also holding down Shift. - This modifier wasn't used by anything in the animation editor. - Allow zooming by using Ctrl + Mouse wheel on the timeline itself. - Previously, this was only possible on the track area, not the timeline.
This commit is contained in:
parent
26d0c90370
commit
a623eb5083
2 changed files with 124 additions and 54 deletions
|
@ -1595,6 +1595,10 @@ void AnimationTimelineEdit::set_zoom(Range *p_zoom) {
|
||||||
zoom->connect("value_changed", this, "_zoom_changed");
|
zoom->connect("value_changed", this, "_zoom_changed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimationTimelineEdit::set_track_edit(AnimationTrackEdit *p_track_edit) {
|
||||||
|
track_edit = p_track_edit;
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationTimelineEdit::set_play_position(float p_pos) {
|
void AnimationTimelineEdit::set_play_position(float p_pos) {
|
||||||
play_position_pos = p_pos;
|
play_position_pos = p_pos;
|
||||||
play_position->update();
|
play_position->update();
|
||||||
|
@ -1650,7 +1654,33 @@ void AnimationTimelineEdit::_play_position_draw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
|
void AnimationTimelineEdit::_gui_input(const Ref<InputEvent> &p_event) {
|
||||||
Ref<InputEventMouseButton> mb = p_event;
|
ERR_FAIL_COND(p_event.is_null());
|
||||||
|
|
||||||
|
const Ref<InputEventMouseButton> mb = p_event;
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_UP) {
|
||||||
|
get_zoom()->set_value(get_zoom()->get_value() * 1.05);
|
||||||
|
accept_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->is_pressed() && mb->get_command() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
|
||||||
|
get_zoom()->set_value(get_zoom()->get_value() / 1.05);
|
||||||
|
accept_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->is_pressed() && mb->get_alt() && mb->get_button_index() == BUTTON_WHEEL_UP) {
|
||||||
|
if (track_edit) {
|
||||||
|
track_edit->get_editor()->goto_prev_step(true);
|
||||||
|
}
|
||||||
|
accept_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->is_pressed() && mb->get_alt() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
|
||||||
|
if (track_edit) {
|
||||||
|
track_edit->get_editor()->goto_next_step(true);
|
||||||
|
}
|
||||||
|
accept_event();
|
||||||
|
}
|
||||||
|
|
||||||
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) {
|
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && hsize_rect.has_point(mb->get_position())) {
|
||||||
dragging_hsize = true;
|
dragging_hsize = true;
|
||||||
|
@ -1753,6 +1783,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
|
||||||
editing = false;
|
editing = false;
|
||||||
name_limit = 150 * EDSCALE;
|
name_limit = 150 * EDSCALE;
|
||||||
zoom = nullptr;
|
zoom = nullptr;
|
||||||
|
track_edit = nullptr;
|
||||||
|
|
||||||
play_position_pos = 0;
|
play_position_pos = 0;
|
||||||
play_position = memnew(Control);
|
play_position = memnew(Control);
|
||||||
|
@ -2316,6 +2347,7 @@ void AnimationTrackEdit::set_undo_redo(UndoRedo *p_undo_redo) {
|
||||||
|
|
||||||
void AnimationTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
|
void AnimationTrackEdit::set_timeline(AnimationTimelineEdit *p_timeline) {
|
||||||
timeline = p_timeline;
|
timeline = p_timeline;
|
||||||
|
timeline->set_track_edit(this);
|
||||||
timeline->connect("zoom_changed", this, "_zoom_changed");
|
timeline->connect("zoom_changed", this, "_zoom_changed");
|
||||||
timeline->connect("name_limit_changed", this, "_zoom_changed");
|
timeline->connect("name_limit_changed", this, "_zoom_changed");
|
||||||
}
|
}
|
||||||
|
@ -4960,6 +4992,16 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
|
||||||
scroll->accept_event();
|
scroll->accept_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->is_pressed() && mb->get_alt() && mb->get_button_index() == BUTTON_WHEEL_UP) {
|
||||||
|
goto_prev_step(true);
|
||||||
|
scroll->accept_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->is_pressed() && mb->get_alt() && mb->get_button_index() == BUTTON_WHEEL_DOWN) {
|
||||||
|
goto_next_step(true);
|
||||||
|
scroll->accept_event();
|
||||||
|
}
|
||||||
|
|
||||||
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
|
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
|
||||||
if (mb->is_pressed()) {
|
if (mb->is_pressed()) {
|
||||||
box_selecting = true;
|
box_selecting = true;
|
||||||
|
@ -5139,6 +5181,56 @@ void AnimationTrackEditor::_edit_menu_about_to_show() {
|
||||||
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
|
edit->get_popup()->set_item_disabled(edit->get_popup()->get_item_index(EDIT_APPLY_RESET), !player->can_apply_reset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimationTrackEditor::goto_prev_step(bool p_from_mouse_event) {
|
||||||
|
if (animation.is_null()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float step = animation->get_step();
|
||||||
|
if (step == 0) {
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
|
if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
|
||||||
|
// Use more precise snapping when holding Shift.
|
||||||
|
// This is used when scrobbling the timeline using Alt + Mouse wheel.
|
||||||
|
step *= 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
float pos = timeline->get_play_position();
|
||||||
|
pos = Math::stepify(pos - step, step);
|
||||||
|
if (pos < 0) {
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
set_anim_pos(pos);
|
||||||
|
emit_signal("timeline_changed", pos, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimationTrackEditor::goto_next_step(bool p_from_mouse_event) {
|
||||||
|
if (animation.is_null()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float step = animation->get_step();
|
||||||
|
if (step == 0) {
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
|
if (p_from_mouse_event && Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
|
||||||
|
// Use more precise snapping when holding Shift.
|
||||||
|
// This is used when scrobbling the timeline using Alt + Mouse wheel.
|
||||||
|
// Do not use precise snapping when using the menu action or keyboard shortcut,
|
||||||
|
// as the default keyboard shortcut requires pressing Shift.
|
||||||
|
step *= 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
float pos = timeline->get_play_position();
|
||||||
|
|
||||||
|
pos = Math::stepify(pos + step, step);
|
||||||
|
if (pos > animation->get_length()) {
|
||||||
|
pos = animation->get_length();
|
||||||
|
}
|
||||||
|
set_anim_pos(pos);
|
||||||
|
|
||||||
|
emit_signal("timeline_changed", pos, true);
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
||||||
last_menu_track_opt = p_option;
|
last_menu_track_opt = p_option;
|
||||||
switch (p_option) {
|
switch (p_option) {
|
||||||
|
@ -5424,42 +5516,10 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case EDIT_GOTO_NEXT_STEP: {
|
case EDIT_GOTO_NEXT_STEP: {
|
||||||
if (animation.is_null()) {
|
goto_next_step(false);
|
||||||
break;
|
|
||||||
}
|
|
||||||
float step = animation->get_step();
|
|
||||||
if (step == 0) {
|
|
||||||
step = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
float pos = timeline->get_play_position();
|
|
||||||
|
|
||||||
pos = Math::stepify(pos + step, step);
|
|
||||||
if (pos > animation->get_length()) {
|
|
||||||
pos = animation->get_length();
|
|
||||||
}
|
|
||||||
set_anim_pos(pos);
|
|
||||||
|
|
||||||
emit_signal("timeline_changed", pos, true);
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case EDIT_GOTO_PREV_STEP: {
|
case EDIT_GOTO_PREV_STEP: {
|
||||||
if (animation.is_null()) {
|
goto_prev_step(false);
|
||||||
break;
|
|
||||||
}
|
|
||||||
float step = animation->get_step();
|
|
||||||
if (step == 0) {
|
|
||||||
step = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
float pos = timeline->get_play_position();
|
|
||||||
pos = Math::stepify(pos - step, step);
|
|
||||||
if (pos < 0) {
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
set_anim_pos(pos);
|
|
||||||
emit_signal("timeline_changed", pos, true);
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case EDIT_APPLY_RESET: {
|
case EDIT_APPLY_RESET: {
|
||||||
AnimationPlayerEditor::singleton->get_player()->apply_reset(true);
|
AnimationPlayerEditor::singleton->get_player()->apply_reset(true);
|
||||||
|
|
|
@ -48,10 +48,13 @@
|
||||||
#include "scene/resources/animation.h"
|
#include "scene/resources/animation.h"
|
||||||
#include "scene_tree_editor.h"
|
#include "scene_tree_editor.h"
|
||||||
|
|
||||||
|
class AnimationTrackEdit;
|
||||||
|
|
||||||
class AnimationTimelineEdit : public Range {
|
class AnimationTimelineEdit : public Range {
|
||||||
GDCLASS(AnimationTimelineEdit, Range);
|
GDCLASS(AnimationTimelineEdit, Range);
|
||||||
|
|
||||||
Ref<Animation> animation;
|
Ref<Animation> animation;
|
||||||
|
AnimationTrackEdit *track_edit;
|
||||||
int name_limit;
|
int name_limit;
|
||||||
Range *zoom;
|
Range *zoom;
|
||||||
Range *h_scroll;
|
Range *h_scroll;
|
||||||
|
@ -100,6 +103,7 @@ public:
|
||||||
|
|
||||||
virtual Size2 get_minimum_size() const;
|
virtual Size2 get_minimum_size() const;
|
||||||
void set_animation(const Ref<Animation> &p_animation);
|
void set_animation(const Ref<Animation> &p_animation);
|
||||||
|
void set_track_edit(AnimationTrackEdit *p_track_edit);
|
||||||
void set_zoom(Range *p_zoom);
|
void set_zoom(Range *p_zoom);
|
||||||
Range *get_zoom() const { return zoom; }
|
Range *get_zoom() const { return zoom; }
|
||||||
void set_undo_redo(UndoRedo *p_undo_redo);
|
void set_undo_redo(UndoRedo *p_undo_redo);
|
||||||
|
@ -274,25 +278,6 @@ public:
|
||||||
class AnimationTrackEditor : public VBoxContainer {
|
class AnimationTrackEditor : public VBoxContainer {
|
||||||
GDCLASS(AnimationTrackEditor, VBoxContainer);
|
GDCLASS(AnimationTrackEditor, VBoxContainer);
|
||||||
|
|
||||||
enum {
|
|
||||||
EDIT_COPY_TRACKS,
|
|
||||||
EDIT_COPY_TRACKS_CONFIRM,
|
|
||||||
EDIT_PASTE_TRACKS,
|
|
||||||
EDIT_SCALE_SELECTION,
|
|
||||||
EDIT_SCALE_FROM_CURSOR,
|
|
||||||
EDIT_SCALE_CONFIRM,
|
|
||||||
EDIT_DUPLICATE_SELECTION,
|
|
||||||
EDIT_DUPLICATE_TRANSPOSED,
|
|
||||||
EDIT_DELETE_SELECTION,
|
|
||||||
EDIT_GOTO_NEXT_STEP,
|
|
||||||
EDIT_GOTO_PREV_STEP,
|
|
||||||
EDIT_APPLY_RESET,
|
|
||||||
EDIT_OPTIMIZE_ANIMATION,
|
|
||||||
EDIT_OPTIMIZE_ANIMATION_CONFIRM,
|
|
||||||
EDIT_CLEAN_UP_ANIMATION,
|
|
||||||
EDIT_CLEAN_UP_ANIMATION_CONFIRM
|
|
||||||
};
|
|
||||||
|
|
||||||
Ref<Animation> animation;
|
Ref<Animation> animation;
|
||||||
Node *root;
|
Node *root;
|
||||||
|
|
||||||
|
@ -503,6 +488,25 @@ protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum {
|
||||||
|
EDIT_COPY_TRACKS,
|
||||||
|
EDIT_COPY_TRACKS_CONFIRM,
|
||||||
|
EDIT_PASTE_TRACKS,
|
||||||
|
EDIT_SCALE_SELECTION,
|
||||||
|
EDIT_SCALE_FROM_CURSOR,
|
||||||
|
EDIT_SCALE_CONFIRM,
|
||||||
|
EDIT_DUPLICATE_SELECTION,
|
||||||
|
EDIT_DUPLICATE_TRANSPOSED,
|
||||||
|
EDIT_DELETE_SELECTION,
|
||||||
|
EDIT_GOTO_NEXT_STEP,
|
||||||
|
EDIT_GOTO_PREV_STEP,
|
||||||
|
EDIT_APPLY_RESET,
|
||||||
|
EDIT_OPTIMIZE_ANIMATION,
|
||||||
|
EDIT_OPTIMIZE_ANIMATION_CONFIRM,
|
||||||
|
EDIT_CLEAN_UP_ANIMATION,
|
||||||
|
EDIT_CLEAN_UP_ANIMATION_CONFIRM
|
||||||
|
};
|
||||||
|
|
||||||
void add_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);
|
void add_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);
|
||||||
void remove_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);
|
void remove_track_edit_plugin(const Ref<AnimationTrackEditPlugin> &p_plugin);
|
||||||
|
|
||||||
|
@ -533,6 +537,12 @@ public:
|
||||||
float snap_time(float p_value, bool p_relative = false);
|
float snap_time(float p_value, bool p_relative = false);
|
||||||
bool is_grouping_tracks();
|
bool is_grouping_tracks();
|
||||||
|
|
||||||
|
/** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */
|
||||||
|
void goto_prev_step(bool p_from_mouse_event);
|
||||||
|
|
||||||
|
/** If `p_from_mouse_event` is `true`, handle Shift key presses for precise snapping. */
|
||||||
|
void goto_next_step(bool p_from_mouse_event);
|
||||||
|
|
||||||
MenuButton *get_edit_menu();
|
MenuButton *get_edit_menu();
|
||||||
AnimationTrackEditor();
|
AnimationTrackEditor();
|
||||||
~AnimationTrackEditor();
|
~AnimationTrackEditor();
|
||||||
|
|
Loading…
Reference in a new issue