Skip to content

Commit e24d536

Browse files
committed
Merge pull request godotengine#95564 from Arnklit/default-bezier-keys
Add option to auto tangent new bezier points in animation editor
2 parents 9fee8ed + 5934804 commit e24d536

File tree

6 files changed

+211
-86
lines changed

6 files changed

+211
-86
lines changed

editor/animation_bezier_editor.cpp

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "editor/gui/editor_spin_slider.h"
3838
#include "editor/plugins/animation_player_editor_plugin.h"
3939
#include "editor/themes/editor_scale.h"
40+
#include "scene/gui/option_button.h"
4041
#include "scene/gui/view_panner.h"
4142
#include "scene/resources/text_line.h"
4243

@@ -97,8 +98,6 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
9798
}
9899
}
99100

100-
out_handle += Vector2(offset, height);
101-
102101
float offset_n = animation->track_get_key_time(p_track, i_n);
103102
float height_n = animation->bezier_track_get_key_value(p_track, i_n);
104103
Vector2 in_handle = animation->bezier_track_get_key_in_handle(p_track, i_n);
@@ -116,6 +115,37 @@ void AnimationBezierTrackEdit::_draw_track(int p_track, const Color &p_color) {
116115
}
117116
}
118117

118+
if (moving_inserted_key && moving_selection_from_track == p_track) {
119+
if (moving_selection_from_key == i) {
120+
Animation::HandleMode handle_mode = animation->bezier_track_get_key_handle_mode(p_track, i);
121+
if (handle_mode != Animation::HANDLE_MODE_FREE) {
122+
float offset_p = offset;
123+
float height_p = height;
124+
if (E->prev()) {
125+
int i_p = E->prev()->get();
126+
offset_p = animation->track_get_key_time(p_track, i_p);
127+
height_p = animation->bezier_track_get_key_value(p_track, i_p);
128+
}
129+
130+
animation->bezier_track_calculate_handles(offset, offset_p, height_p, offset_n, height_n, handle_mode, Animation::HANDLE_SET_MODE_AUTO, nullptr, &out_handle);
131+
}
132+
} else if (moving_selection_from_key == i_n) {
133+
Animation::HandleMode handle_mode = animation->bezier_track_get_key_handle_mode(p_track, i_n);
134+
if (handle_mode != Animation::HANDLE_MODE_FREE) {
135+
float offset_nn = offset_n;
136+
float height_nn = height_n;
137+
if (E->next()->next()) {
138+
int i_nn = E->next()->next()->get();
139+
offset_nn = animation->track_get_key_time(p_track, i_nn);
140+
height_nn = animation->bezier_track_get_key_value(p_track, i_nn);
141+
}
142+
143+
animation->bezier_track_calculate_handles(offset_n, offset, height, offset_nn, height_nn, handle_mode, Animation::HANDLE_SET_MODE_AUTO, &in_handle, nullptr);
144+
}
145+
}
146+
}
147+
148+
out_handle += Vector2(offset, height);
119149
in_handle += Vector2(offset_n, height_n);
120150

121151
Vector2 start(offset, height);
@@ -570,18 +600,53 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
570600
}
571601

572602
Vector2 in_vec = animation->bezier_track_get_key_in_handle(i, j);
603+
Vector2 out_vec = animation->bezier_track_get_key_out_handle(i, j);
573604

574605
if ((moving_handle == 1 || moving_handle == -1) && moving_handle_track == i && moving_handle_key == j) {
575606
in_vec = moving_handle_left;
576607
}
577-
Vector2 pos_in(((offset + in_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + in_vec.y));
578-
579-
Vector2 out_vec = animation->bezier_track_get_key_out_handle(i, j);
580608

581609
if ((moving_handle == 1 || moving_handle == -1) && moving_handle_track == i && moving_handle_key == j) {
582610
out_vec = moving_handle_right;
583611
}
584612

613+
if (moving_inserted_key && moving_selection_from_key == j) {
614+
Animation::HandleMode handle_mode = animation->bezier_track_get_key_handle_mode(i, j);
615+
if (handle_mode != Animation::HANDLE_MODE_FREE) {
616+
int key_prev = 0;
617+
int key_next = moving_selection_from_key;
618+
for (int k = 0; k < key_count; k++) {
619+
if (k == moving_selection_from_key) {
620+
continue;
621+
}
622+
623+
if (animation->track_get_key_time(i, k) < offset) {
624+
key_prev = k;
625+
} else {
626+
key_next = k;
627+
break;
628+
}
629+
}
630+
631+
float prev_time = offset;
632+
float prev_value = value;
633+
if (key_prev != moving_selection_from_key) {
634+
prev_time = animation->track_get_key_time(i, key_prev);
635+
prev_value = animation->bezier_track_get_key_value(i, key_prev);
636+
}
637+
638+
float next_time = offset;
639+
float next_value = value;
640+
if (key_next != moving_selection_from_key) {
641+
next_time = animation->track_get_key_time(i, key_next);
642+
next_value = animation->bezier_track_get_key_value(i, key_next);
643+
}
644+
645+
animation->bezier_track_calculate_handles(offset, prev_time, prev_value, next_time, next_value, handle_mode, Animation::HANDLE_SET_MODE_AUTO, &in_vec, &out_vec);
646+
}
647+
}
648+
649+
Vector2 pos_in(((offset + in_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + in_vec.y));
585650
Vector2 pos_out(((offset + out_vec.x) - timeline->get_value()) * scale + limit, _bezier_h_to_pixel(value + out_vec.y));
586651

587652
if (i == selected_track || is_selected) {
@@ -1402,6 +1467,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
14021467
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
14031468
undo_redo->create_action(TTR("Add Bezier Point"));
14041469
undo_redo->add_do_method(animation.ptr(), "bezier_track_insert_key", selected_track, time, new_point[0], Vector2(new_point[1], new_point[2]), Vector2(new_point[3], new_point[4]));
1470+
undo_redo->add_do_method(editor, "_bezier_track_set_key_handle_mode_at_time", animation.ptr(), selected_track, time, (Animation::HandleMode)editor->bezier_key_mode->get_selected_id(), Animation::HANDLE_SET_MODE_AUTO);
14051471
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", selected_track, time);
14061472
undo_redo->commit_action();
14071473

@@ -1412,6 +1478,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
14121478
_select_at_anim(animation, selected_track, animation->track_get_key_time(selected_track, index), true);
14131479

14141480
moving_selection_attempt = true;
1481+
moving_inserted_key = true;
14151482
moving_selection = false;
14161483
moving_selection_mouse_begin = mb->get_position();
14171484
moving_selection_from_key = index;
@@ -1539,6 +1606,14 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
15391606
real_t h = key[0];
15401607
h += moving_selection_offset.y;
15411608
key[0] = h;
1609+
1610+
Animation::HandleMode handle_mode = animation->bezier_track_get_key_handle_mode(E->get().first, E->get().second);
1611+
Animation::HandleSetMode handle_set_mode = Animation::HANDLE_SET_MODE_NONE;
1612+
if (moving_inserted_key) {
1613+
handle_mode = (Animation::HandleMode)editor->bezier_key_mode->get_selected_id();
1614+
handle_set_mode = Animation::HANDLE_SET_MODE_AUTO;
1615+
}
1616+
15421617
undo_redo->add_do_method(
15431618
this,
15441619
"_bezier_track_insert_key_at_anim",
@@ -1548,7 +1623,8 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
15481623
key[0],
15491624
Vector2(key[1], key[2]),
15501625
Vector2(key[3], key[4]),
1551-
animation->bezier_track_get_key_handle_mode(E->get().first, E->get().second));
1626+
handle_mode,
1627+
handle_set_mode);
15521628
}
15531629

15541630
// 4 - (undo) Remove inserted keys.
@@ -1621,6 +1697,7 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
16211697

16221698
moving_selection = false;
16231699
moving_selection_attempt = false;
1700+
moving_inserted_key = false;
16241701
moving_selection_mouse_begin = Point2();
16251702
queue_redraw();
16261703
}
@@ -2058,9 +2135,11 @@ void AnimationBezierTrackEdit::_menu_selected(int p_index) {
20582135
}
20592136
float h = (get_size().height / 2.0 - menu_insert_key.y) * timeline_v_zoom + timeline_v_scroll;
20602137
Array new_point = animation->make_default_bezier_key(h);
2138+
Animation::HandleMode handle_mode = (Animation::HandleMode)editor->bezier_key_mode->get_selected_id();
20612139
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
20622140
undo_redo->create_action(TTR("Add Bezier Point"));
20632141
undo_redo->add_do_method(animation.ptr(), "track_insert_key", selected_track, time, new_point);
2142+
undo_redo->add_do_method(editor, "_bezier_track_set_key_handle_mode_at_time", animation.ptr(), selected_track, time, handle_mode, Animation::HANDLE_SET_MODE_AUTO);
20642143
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
20652144
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", selected_track, time);
20662145
AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton();
@@ -2343,9 +2422,9 @@ void AnimationBezierTrackEdit::delete_selection() {
23432422
}
23442423
}
23452424

2346-
void AnimationBezierTrackEdit::_bezier_track_insert_key_at_anim(const Ref<Animation> &p_anim, int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const Animation::HandleMode p_handle_mode) {
2425+
void AnimationBezierTrackEdit::_bezier_track_insert_key_at_anim(const Ref<Animation> &p_anim, int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const Animation::HandleMode p_handle_mode, Animation::HandleSetMode p_handle_set_mode) {
23472426
int idx = p_anim->bezier_track_insert_key(p_track, p_time, p_value, p_in_handle, p_out_handle);
2348-
p_anim->bezier_track_set_key_handle_mode(p_track, idx, p_handle_mode);
2427+
p_anim->bezier_track_set_key_handle_mode(p_track, idx, p_handle_mode, p_handle_set_mode);
23492428
}
23502429

23512430
void AnimationBezierTrackEdit::_bind_methods() {
@@ -2354,7 +2433,7 @@ void AnimationBezierTrackEdit::_bind_methods() {
23542433
ClassDB::bind_method(D_METHOD("_select_at_anim"), &AnimationBezierTrackEdit::_select_at_anim);
23552434
ClassDB::bind_method(D_METHOD("_update_hidden_tracks_after"), &AnimationBezierTrackEdit::_update_hidden_tracks_after);
23562435
ClassDB::bind_method(D_METHOD("_update_locked_tracks_after"), &AnimationBezierTrackEdit::_update_locked_tracks_after);
2357-
ClassDB::bind_method(D_METHOD("_bezier_track_insert_key_at_anim"), &AnimationBezierTrackEdit::_bezier_track_insert_key_at_anim);
2436+
ClassDB::bind_method(D_METHOD("_bezier_track_insert_key_at_anim"), &AnimationBezierTrackEdit::_bezier_track_insert_key_at_anim, DEFVAL(Animation::HANDLE_SET_MODE_NONE));
23582437

23592438
ADD_SIGNAL(MethodInfo("select_key", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "single"), PropertyInfo(Variant::INT, "track")));
23602439
ADD_SIGNAL(MethodInfo("deselect_key", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::INT, "track")));

editor/animation_bezier_editor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class AnimationBezierTrackEdit : public Control {
108108
typedef Pair<int, int> IntPair;
109109

110110
bool moving_selection_attempt = false;
111+
bool moving_inserted_key = false;
111112
Point2 moving_selection_mouse_begin;
112113
IntPair select_single_attempt;
113114
bool moving_selection = false;
@@ -230,7 +231,7 @@ class AnimationBezierTrackEdit : public Control {
230231
void paste_keys(real_t p_ofs, bool p_ofs_valid);
231232
void delete_selection();
232233

233-
void _bezier_track_insert_key_at_anim(const Ref<Animation> &p_anim, int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const Animation::HandleMode p_handle_mode);
234+
void _bezier_track_insert_key_at_anim(const Ref<Animation> &p_anim, int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle, const Animation::HandleMode p_handle_mode, Animation::HandleSetMode p_handle_set_mode = Animation::HANDLE_SET_MODE_NONE);
234235

235236
AnimationBezierTrackEdit();
236237
};

editor/animation_track_editor.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4882,6 +4882,9 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
48824882
}
48834883

48844884
undo_redo->add_do_method(animation.ptr(), "track_insert_key", p_id.track_idx, time, value);
4885+
if (!created && p_id.type == Animation::TYPE_BEZIER) {
4886+
undo_redo->add_do_method(this, "_bezier_track_set_key_handle_mode_at_time", animation.ptr(), p_id.track_idx, time, (Animation::HandleMode)bezier_key_mode->get_selected_id(), Animation::HANDLE_SET_MODE_AUTO);
4887+
}
48854888

48864889
if (created) {
48874890
// Just remove the track.
@@ -6318,12 +6321,17 @@ void AnimationTrackEditor::_bezier_edit(int p_for_track) {
63186321
}
63196322

63206323
void AnimationTrackEditor::_bezier_track_set_key_handle_mode(Animation *p_anim, int p_track, int p_index, Animation::HandleMode p_mode, Animation::HandleSetMode p_set_mode) {
6321-
if (!p_anim) {
6322-
return;
6323-
}
6324+
ERR_FAIL_NULL(p_anim);
63246325
p_anim->bezier_track_set_key_handle_mode(p_track, p_index, p_mode, p_set_mode);
63256326
}
63266327

6328+
void AnimationTrackEditor::_bezier_track_set_key_handle_mode_at_time(Animation *p_anim, int p_track, float p_time, Animation::HandleMode p_mode, Animation::HandleSetMode p_set_mode) {
6329+
ERR_FAIL_NULL(p_anim);
6330+
int index = p_anim->track_find_key(p_track, p_time, Animation::FIND_MODE_APPROX);
6331+
ERR_FAIL_COND(index < 0);
6332+
_bezier_track_set_key_handle_mode(p_anim, p_track, index, p_mode, p_set_mode);
6333+
}
6334+
63276335
void AnimationTrackEditor::_anim_duplicate_keys(float p_ofs, bool p_ofs_valid, int p_track) {
63286336
if (selection.size() && animation.is_valid()) {
63296337
int top_track = 0x7FFFFFFF;
@@ -7701,6 +7709,7 @@ void AnimationTrackEditor::_bind_methods() {
77017709
ClassDB::bind_method("_clear_selection", &AnimationTrackEditor::_clear_selection);
77027710

77037711
ClassDB::bind_method(D_METHOD("_bezier_track_set_key_handle_mode", "animation", "track_idx", "key_idx", "key_handle_mode", "key_handle_set_mode"), &AnimationTrackEditor::_bezier_track_set_key_handle_mode, DEFVAL(Animation::HANDLE_SET_MODE_NONE));
7712+
ClassDB::bind_method(D_METHOD("_bezier_track_set_key_handle_mode_at_time", "animation", "track_idx", "time", "key_handle_mode", "key_handle_set_mode"), &AnimationTrackEditor::_bezier_track_set_key_handle_mode_at_time, DEFVAL(Animation::HANDLE_SET_MODE_NONE));
77047713

77057714
ADD_SIGNAL(MethodInfo("timeline_changed", PropertyInfo(Variant::FLOAT, "position"), PropertyInfo(Variant::BOOL, "timeline_only"), PropertyInfo(Variant::BOOL, "update_position_only")));
77067715
ADD_SIGNAL(MethodInfo("keying_changed"));
@@ -7872,6 +7881,21 @@ AnimationTrackEditor::AnimationTrackEditor() {
78727881
spacer->set_h_size_flags(SIZE_EXPAND_FILL);
78737882
bottom_hf->add_child(spacer);
78747883

7884+
Label *bezier_key_default_label = memnew(Label);
7885+
bezier_key_default_label->set_text(TTR("Bezier Default Mode:"));
7886+
bottom_hf->add_child(bezier_key_default_label);
7887+
7888+
bezier_key_mode = memnew(OptionButton);
7889+
bezier_key_mode->add_item(TTR("Free"));
7890+
bezier_key_mode->add_item(TTR("Linear"));
7891+
bezier_key_mode->add_item(TTR("Balanced"));
7892+
bezier_key_mode->add_item(TTR("Mirrored"));
7893+
bezier_key_mode->set_tooltip_text(TTR("Set the default behavior of new bezier keys."));
7894+
bezier_key_mode->select(2);
7895+
7896+
bottom_hf->add_child(bezier_key_mode);
7897+
bottom_hf->add_child(memnew(VSeparator));
7898+
78757899
bezier_edit_icon = memnew(Button);
78767900
bezier_edit_icon->set_flat(true);
78777901
bezier_edit_icon->set_disabled(true);

editor/animation_track_editor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ class AnimationTrackEditor : public VBoxContainer {
618618
OptionButton *snap_mode = nullptr;
619619
Button *auto_fit = nullptr;
620620
Button *auto_fit_bezier = nullptr;
621+
OptionButton *bezier_key_mode = nullptr;
621622

622623
Button *imported_anim_warning = nullptr;
623624
void _show_imported_anim_warning();
@@ -767,6 +768,7 @@ class AnimationTrackEditor : public VBoxContainer {
767768
void _cancel_bezier_edit();
768769
void _bezier_edit(int p_for_track);
769770
void _bezier_track_set_key_handle_mode(Animation *p_anim, int p_track, int p_index, Animation::HandleMode p_mode, Animation::HandleSetMode p_set_mode = Animation::HANDLE_SET_MODE_NONE);
771+
void _bezier_track_set_key_handle_mode_at_time(Animation *p_anim, int p_track, float p_time, Animation::HandleMode p_mode, Animation::HandleSetMode p_set_mode = Animation::HANDLE_SET_MODE_NONE);
770772

771773
////////////// edit menu stuff
772774

0 commit comments

Comments
 (0)