Fixed AnimationTrackEditor redraw/deselect timing and find key compearation

This commit is contained in:
Silc Renew 2022-08-29 10:44:00 +09:00
parent 202f0f2f1b
commit 77cf519cf0
3 changed files with 161 additions and 171 deletions

View file

@ -3599,9 +3599,7 @@ void AnimationTrackEditor::cleanup() {
} }
void AnimationTrackEditor::_name_limit_changed() { void AnimationTrackEditor::_name_limit_changed() {
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update();
}
} }
void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only) { void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only) {
@ -3696,9 +3694,7 @@ void AnimationTrackEditor::set_anim_pos(float p_pos) {
for (int i = 0; i < track_edits.size(); i++) { for (int i = 0; i < track_edits.size(); i++) {
track_edits[i]->set_play_position(p_pos); track_edits[i]->set_play_position(p_pos);
} }
for (int i = 0; i < groups.size(); i++) { _redraw_groups();
groups[i]->update();
}
bezier_edit->set_play_position(p_pos); bezier_edit->set_play_position(p_pos);
} }
@ -4646,6 +4642,18 @@ void AnimationTrackEditor::_update_tracks() {
} }
} }
void AnimationTrackEditor::_redraw_tracks() {
for (int i = 0; i < track_edits.size(); i++) {
track_edits[i]->update();
}
}
void AnimationTrackEditor::_redraw_groups() {
for (int i = 0; i < groups.size(); i++) {
groups[i]->update();
}
}
void AnimationTrackEditor::_sync_animation_change() { void AnimationTrackEditor::_sync_animation_change() {
bezier_edit->update(); bezier_edit->update();
} }
@ -4727,12 +4735,8 @@ void AnimationTrackEditor::_animation_update() {
} }
if (same) { if (same) {
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update(); _redraw_groups();
}
for (int i = 0; i < groups.size(); i++) {
groups[i]->update();
}
} else { } else {
_update_tracks(); _update_tracks();
} }
@ -4782,12 +4786,8 @@ void AnimationTrackEditor::_notification(int p_what) {
} }
void AnimationTrackEditor::_update_scroll(double) { void AnimationTrackEditor::_update_scroll(double) {
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update(); _redraw_groups();
}
for (int i = 0; i < groups.size(); i++) {
groups[i]->update();
}
} }
void AnimationTrackEditor::_update_step(double p_new_step) { void AnimationTrackEditor::_update_step(double p_new_step) {
@ -4815,7 +4815,7 @@ void AnimationTrackEditor::_dropped_track(int p_from_track, int p_to_track) {
return; return;
} }
_clear_selection(); _clear_selection(true);
undo_redo->create_action(TTR("Rearrange Tracks")); undo_redo->create_action(TTR("Rearrange Tracks"));
undo_redo->add_do_method(animation.ptr(), "track_move_to", p_from_track, p_to_track); undo_redo->add_do_method(animation.ptr(), "track_move_to", p_from_track, p_to_track);
// Take into account that the position of the tracks that come after the one removed will change. // Take into account that the position of the tracks that come after the one removed will change.
@ -4993,14 +4993,11 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
void AnimationTrackEditor::_timeline_value_changed(double) { void AnimationTrackEditor::_timeline_value_changed(double) {
timeline->update_play_position(); timeline->update_play_position();
_redraw_tracks();
for (int i = 0; i < track_edits.size(); i++) { for (int i = 0; i < track_edits.size(); i++) {
track_edits[i]->update();
track_edits[i]->update_play_position(); track_edits[i]->update_play_position();
} }
_redraw_groups();
for (int i = 0; i < groups.size(); i++) {
groups[i]->update();
}
bezier_edit->update(); bezier_edit->update();
bezier_edit->update_play_position(); bezier_edit->update_play_position();
@ -5211,10 +5208,7 @@ void AnimationTrackEditor::_key_selected(int p_key, bool p_single, int p_track)
ki.pos = animation->track_get_key_time(p_track, p_key); ki.pos = animation->track_get_key_time(p_track, p_key);
selection[sk] = ki; selection[sk] = ki;
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update();
}
_update_key_edit(); _update_key_edit();
} }
@ -5228,10 +5222,7 @@ void AnimationTrackEditor::_key_deselected(int p_key, int p_track) {
selection.erase(sk); selection.erase(sk);
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update();
}
_update_key_edit(); _update_key_edit();
} }
@ -5242,10 +5233,7 @@ void AnimationTrackEditor::_move_selection_begin() {
void AnimationTrackEditor::_move_selection(float p_offset) { void AnimationTrackEditor::_move_selection(float p_offset) {
moving_selection_offset = p_offset; moving_selection_offset = p_offset;
_redraw_tracks();
for (int i = 0; i < track_edits.size(); i++) {
track_edits[i]->update();
}
} }
struct _AnimMoveRestore { struct _AnimMoveRestore {
@ -5282,9 +5270,7 @@ void AnimationTrackEditor::_clear_selection(bool p_update) {
selection.clear(); selection.clear();
if (p_update) { if (p_update) {
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update();
}
} }
_clear_key_edit(); _clear_key_edit();
@ -5442,21 +5428,16 @@ void AnimationTrackEditor::_move_selection_commit() {
undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos); undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos);
} }
undo_redo->commit_action();
moving_selection = false; moving_selection = false;
for (int i = 0; i < track_edits.size(); i++) { undo_redo->add_do_method(this, "_redraw_tracks");
track_edits[i]->update(); undo_redo->add_undo_method(this, "_redraw_tracks");
} undo_redo->commit_action();
_update_key_edit(); _update_key_edit();
} }
void AnimationTrackEditor::_move_selection_cancel() { void AnimationTrackEditor::_move_selection_cancel() {
moving_selection = false; moving_selection = false;
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update();
}
} }
bool AnimationTrackEditor::is_moving_selection() const { bool AnimationTrackEditor::is_moving_selection() const {
@ -5499,7 +5480,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
track_edits[track_edits.size() - 1]->grab_focus(); track_edits[track_edits.size() - 1]->grab_focus();
} }
} else { } else {
_clear_selection(); // Clear it. _clear_selection(true); // Clear it.
} }
box_selection->hide(); box_selection->hide();
@ -5519,7 +5500,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
if (!box_selection->is_visible_in_tree()) { if (!box_selection->is_visible_in_tree()) {
if (!mm->is_command_pressed() && !mm->is_shift_pressed()) { if (!mm->is_command_pressed() && !mm->is_shift_pressed()) {
_clear_selection(); _clear_selection(true);
} }
box_selection->show(); box_selection->show();
} }
@ -5666,32 +5647,21 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
} }
} }
undo_redo->commit_action(); undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
// Reselect duplicated. // Reselect duplicated.
RBMap<SelectedKey, KeyInfo> new_selection; RBMap<SelectedKey, KeyInfo> new_selection;
for (const Pair<int, float> &E : new_selection_values) { for (const Pair<int, float> &E : new_selection_values) {
int track = E.first; undo_redo->add_do_method(this, "_select_at_anim", animation, E.first, E.second);
float time = E.second; }
for (RBMap<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
int existing_idx = animation->track_find_key(track, time, true); undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, E->get().pos);
if (existing_idx == -1) {
continue;
}
SelectedKey sk2;
sk2.track = track;
sk2.key = existing_idx;
KeyInfo ki;
ki.pos = time;
new_selection[sk2] = ki;
} }
selection = new_selection; undo_redo->add_do_method(this, "_redraw_tracks");
_update_tracks(); undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action();
_update_key_edit(); _update_key_edit();
} }
} }
@ -6012,7 +5982,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos); undo_redo->add_undo_method(this, "_select_at_anim", animation, E->key().track, oldpos);
} }
#undef NEW_POS #undef NEW_POS
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action(); undo_redo->commit_action();
_update_key_edit();
} break; } break;
case EDIT_EASE_SELECTION: { case EDIT_EASE_SELECTION: {
@ -6066,7 +6041,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
bool is_using_angle = animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_LINEAR_ANGLE || animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_CUBIC_ANGLE; bool is_using_angle = animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_LINEAR_ANGLE || animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_CUBIC_ANGLE;
// Make insert queue. // Make insert queue.
Vector<Pair<double, Variant>> insert_queue; Vector<Pair<real_t, Variant>> insert_queue;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
// Check neighboring keys. // Check neighboring keys.
if (keys[i] + 1 == keys[i + 1]) { if (keys[i] + 1 == keys[i + 1]) {
@ -6085,7 +6060,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
double duration = to_t - from_t; double duration = to_t - from_t;
double fixed_duration = duration - 0.01; // Prevent to overwrap keys... double fixed_duration = duration - 0.01; // Prevent to overwrap keys...
for (double delta_t = dur_step; delta_t < fixed_duration; delta_t += dur_step) { for (double delta_t = dur_step; delta_t < fixed_duration; delta_t += dur_step) {
Pair<double, Variant> keydata; Pair<real_t, Variant> keydata;
keydata.first = from_t + delta_t; keydata.first = from_t + delta_t;
keydata.second = Tween::interpolate_variant(from_v, delta_v, delta_t, duration, transition_type, ease_type); keydata.second = Tween::interpolate_variant(from_v, delta_v, delta_t, duration, transition_type, ease_type);
insert_queue.append(keydata); insert_queue.append(keydata);
@ -6102,7 +6077,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
++E; ++E;
} }
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action(); undo_redo->commit_action();
_update_key_edit();
} break; } break;
@ -6122,6 +6102,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} break; } break;
case EDIT_ADD_RESET_KEY: { case EDIT_ADD_RESET_KEY: {
undo_redo->create_action(TTR("Anim Add RESET Keys")); undo_redo->create_action(TTR("Anim Add RESET Keys"));
Ref<Animation> reset = _create_and_get_reset_animation(); Ref<Animation> reset = _create_and_get_reset_animation();
int reset_tracks = reset->get_track_count(); int reset_tracks = reset->get_track_count();
HashSet<int> tracks_added; HashSet<int> tracks_added;
@ -6166,6 +6147,10 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} }
} }
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action(); undo_redo->commit_action();
} break; } break;
@ -6184,6 +6169,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} }
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation); undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation); undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action(); undo_redo->commit_action();
_update_key_edit(); _update_key_edit();
} }
@ -6196,11 +6183,15 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
goto_prev_step(false); goto_prev_step(false);
} break; } break;
case EDIT_BAKE_TRACK: { case EDIT_APPLY_RESET: {
AnimationPlayerEditor::get_singleton()->get_player()->apply_reset(true);
} break;
case EDIT_BAKE_ANIMATION: {
bake_dialog->popup_centered(Size2(200, 100) * EDSCALE); bake_dialog->popup_centered(Size2(200, 100) * EDSCALE);
} break; } break;
case EDIT_BAKE_TRACK_CONFIRM: { case EDIT_BAKE_ANIMATION_CONFIRM: {
undo_redo->create_action(TTR("Bake Track as Linear keys.")); undo_redo->create_action(TTR("Bake Animation as Linear keys."));
int track_len = animation->get_track_count(); int track_len = animation->get_track_count();
bool b_trs = bake_trs->is_pressed(); bool b_trs = bake_trs->is_pressed();
@ -6227,12 +6218,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
bool is_using_angle = it == Animation::INTERPOLATION_LINEAR_ANGLE || it == Animation::INTERPOLATION_CUBIC_ANGLE; bool is_using_angle = it == Animation::INTERPOLATION_LINEAR_ANGLE || it == Animation::INTERPOLATION_CUBIC_ANGLE;
// Make insert queue. // Make insert queue.
Vector<Pair<double, Variant>> insert_queue; Vector<Pair<real_t, Variant>> insert_queue;
switch (type) { switch (type) {
case Animation::TYPE_POSITION_3D: { case Animation::TYPE_POSITION_3D: {
for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) { for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) {
Pair<double, Variant> keydata; Pair<real_t, Variant> keydata;
keydata.first = delta_t; keydata.first = delta_t;
Vector3 v; Vector3 v;
animation->position_track_interpolate(i, delta_t, &v); animation->position_track_interpolate(i, delta_t, &v);
@ -6242,7 +6233,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} break; } break;
case Animation::TYPE_ROTATION_3D: { case Animation::TYPE_ROTATION_3D: {
for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) { for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) {
Pair<double, Variant> keydata; Pair<real_t, Variant> keydata;
keydata.first = delta_t; keydata.first = delta_t;
Quaternion v; Quaternion v;
animation->rotation_track_interpolate(i, delta_t, &v); animation->rotation_track_interpolate(i, delta_t, &v);
@ -6252,7 +6243,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} break; } break;
case Animation::TYPE_SCALE_3D: { case Animation::TYPE_SCALE_3D: {
for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) { for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) {
Pair<double, Variant> keydata; Pair<real_t, Variant> keydata;
keydata.first = delta_t; keydata.first = delta_t;
Vector3 v; Vector3 v;
animation->scale_track_interpolate(i, delta_t, &v); animation->scale_track_interpolate(i, delta_t, &v);
@ -6262,7 +6253,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} break; } break;
case Animation::TYPE_BLEND_SHAPE: { case Animation::TYPE_BLEND_SHAPE: {
for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) { for (double delta_t = 0.0; delta_t <= anim_len; delta_t += dur_step) {
Pair<double, Variant> keydata; Pair<real_t, Variant> keydata;
keydata.first = delta_t; keydata.first = delta_t;
float v; float v;
animation->blend_shape_track_interpolate(i, delta_t, &v); animation->blend_shape_track_interpolate(i, delta_t, &v);
@ -6272,7 +6263,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} break; } break;
case Animation::TYPE_VALUE: { case Animation::TYPE_VALUE: {
for (double delta_t = 0.0; delta_t < anim_len; delta_t += dur_step) { for (double delta_t = 0.0; delta_t < anim_len; delta_t += dur_step) {
Pair<double, Variant> keydata; Pair<real_t, Variant> keydata;
keydata.first = delta_t; keydata.first = delta_t;
keydata.second = animation->value_track_interpolate(i, delta_t); keydata.second = animation->value_track_interpolate(i, delta_t);
insert_queue.append(keydata); insert_queue.append(keydata);
@ -6292,7 +6283,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, is_using_angle ? Animation::INTERPOLATION_LINEAR_ANGLE : Animation::INTERPOLATION_LINEAR); undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, is_using_angle ? Animation::INTERPOLATION_LINEAR_ANGLE : Animation::INTERPOLATION_LINEAR);
for (int j = insert_queue.size() - 1; j >= 0; j--) { for (int j = insert_queue.size() - 1; j >= 0; j--) {
undo_redo->add_do_method(animation.ptr(), "track_insert_key", i, insert_queue[j].first, insert_queue[j].second); undo_redo->add_do_method(animation.ptr(), "track_insert_key", i, insert_queue[j].first, insert_queue[j].second);
undo_redo->add_undo_method(animation.ptr(), "track_remove_key", i, j); undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", i, insert_queue[j].first);
} }
// Undo methods. // Undo methods.
@ -6303,23 +6294,25 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
} }
} }
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
undo_redo->add_do_method(this, "_redraw_tracks");
undo_redo->add_undo_method(this, "_redraw_tracks");
undo_redo->commit_action(); undo_redo->commit_action();
_update_key_edit();
} break; } break;
case EDIT_APPLY_RESET: {
AnimationPlayerEditor::get_singleton()->get_player()->apply_reset(true);
} break;
case EDIT_OPTIMIZE_ANIMATION: { case EDIT_OPTIMIZE_ANIMATION: {
optimize_dialog->popup_centered(Size2(250, 180) * EDSCALE); optimize_dialog->popup_centered(Size2(250, 180) * EDSCALE);
} break; } break;
case EDIT_OPTIMIZE_ANIMATION_CONFIRM: { case EDIT_OPTIMIZE_ANIMATION_CONFIRM: {
animation->optimize(optimize_velocity_error->get_value(), optimize_angular_error->get_value(), optimize_precision_error->get_value()); animation->optimize(optimize_velocity_error->get_value(), optimize_angular_error->get_value(), optimize_precision_error->get_value());
_update_tracks(); _redraw_tracks();
undo_redo->clear_history(true, undo_redo->get_history_for_object(animation.ptr()).id); _update_key_edit();
undo_redo->clear_history(true, undo_redo->get_history_for_object(this).id); undo_redo->clear_history(true, undo_redo->get_history_id_for_object(animation.ptr()));
undo_redo->clear_history(true, undo_redo->get_history_id_for_object(this));
} break; } break;
case EDIT_CLEAN_UP_ANIMATION: { case EDIT_CLEAN_UP_ANIMATION: {
@ -6387,8 +6380,8 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) {
} }
} }
undo_redo->clear_history(true, undo_redo->get_history_for_object(animation.ptr()).id); undo_redo->clear_history(true, undo_redo->get_history_id_for_object(animation.ptr()));
undo_redo->clear_history(true, undo_redo->get_history_for_object(this).id); undo_redo->clear_history(true, undo_redo->get_history_id_for_object(this));
_update_tracks(); _update_tracks();
} }
@ -6410,13 +6403,8 @@ void AnimationTrackEditor::_selection_changed() {
if (selected_filter->is_pressed()) { if (selected_filter->is_pressed()) {
_update_tracks(); // Needs updatin. _update_tracks(); // Needs updatin.
} else { } else {
for (int i = 0; i < track_edits.size(); i++) { _redraw_tracks();
track_edits[i]->update(); _redraw_groups();
}
for (int i = 0; i < groups.size(); i++) {
groups[i]->update();
}
} }
} }
@ -6478,6 +6466,7 @@ void AnimationTrackEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_animation_update"), &AnimationTrackEditor::_animation_update); ClassDB::bind_method(D_METHOD("_animation_update"), &AnimationTrackEditor::_animation_update);
ClassDB::bind_method(D_METHOD("_track_grab_focus"), &AnimationTrackEditor::_track_grab_focus); ClassDB::bind_method(D_METHOD("_track_grab_focus"), &AnimationTrackEditor::_track_grab_focus);
ClassDB::bind_method(D_METHOD("_update_tracks"), &AnimationTrackEditor::_update_tracks); ClassDB::bind_method(D_METHOD("_update_tracks"), &AnimationTrackEditor::_update_tracks);
ClassDB::bind_method(D_METHOD("_redraw_tracks"), &AnimationTrackEditor::_redraw_tracks);
ClassDB::bind_method(D_METHOD("_clear_selection_for_anim"), &AnimationTrackEditor::_clear_selection_for_anim); ClassDB::bind_method(D_METHOD("_clear_selection_for_anim"), &AnimationTrackEditor::_clear_selection_for_anim);
ClassDB::bind_method(D_METHOD("_select_at_anim"), &AnimationTrackEditor::_select_at_anim); ClassDB::bind_method(D_METHOD("_select_at_anim"), &AnimationTrackEditor::_select_at_anim);
@ -6734,10 +6723,9 @@ AnimationTrackEditor::AnimationTrackEditor() {
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KeyModifierMask::CMD | Key::RIGHT), EDIT_GOTO_NEXT_STEP); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KeyModifierMask::CMD | Key::RIGHT), EDIT_GOTO_NEXT_STEP);
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KeyModifierMask::CMD | Key::LEFT), EDIT_GOTO_PREV_STEP); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KeyModifierMask::CMD | Key::LEFT), EDIT_GOTO_PREV_STEP);
edit->get_popup()->add_separator(); edit->get_popup()->add_separator();
edit->get_popup()->add_item(TTR("Bake Track"), EDIT_BAKE_TRACK);
edit->get_popup()->add_separator();
edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET);
edit->get_popup()->add_separator(); edit->get_popup()->add_separator();
edit->get_popup()->add_item(TTR("Bake Animation"), EDIT_BAKE_ANIMATION);
edit->get_popup()->add_item(TTR("Optimize Animation (no undo)"), EDIT_OPTIMIZE_ANIMATION); edit->get_popup()->add_item(TTR("Optimize Animation (no undo)"), EDIT_OPTIMIZE_ANIMATION);
edit->get_popup()->add_item(TTR("Clean-Up Animation (no undo)"), EDIT_CLEAN_UP_ANIMATION); edit->get_popup()->add_item(TTR("Clean-Up Animation (no undo)"), EDIT_CLEAN_UP_ANIMATION);
@ -6907,8 +6895,8 @@ AnimationTrackEditor::AnimationTrackEditor() {
// //
bake_dialog = memnew(ConfirmationDialog); bake_dialog = memnew(ConfirmationDialog);
bake_dialog->set_title(TTR("Track Baker")); bake_dialog->set_title(TTR("Anim. Baker"));
bake_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_BAKE_TRACK_CONFIRM)); bake_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_BAKE_ANIMATION_CONFIRM));
add_child(bake_dialog); add_child(bake_dialog);
GridContainer *bake_grid = memnew(GridContainer); GridContainer *bake_grid = memnew(GridContainer);
bake_grid->set_columns(2); bake_grid->set_columns(2);

View file

@ -330,6 +330,8 @@ class AnimationTrackEditor : public VBoxContainer {
void _sync_animation_change(); void _sync_animation_change();
void _animation_changed(); void _animation_changed();
void _update_tracks(); void _update_tracks();
void _redraw_tracks();
void _redraw_groups();
void _name_limit_changed(); void _name_limit_changed();
void _timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only); void _timeline_changed(float p_new_pos, bool p_drag, bool p_timeline_only);
@ -545,9 +547,9 @@ public:
EDIT_GOTO_NEXT_STEP, EDIT_GOTO_NEXT_STEP,
EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation. EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation.
EDIT_GOTO_PREV_STEP, EDIT_GOTO_PREV_STEP,
EDIT_BAKE_TRACK,
EDIT_BAKE_TRACK_CONFIRM,
EDIT_APPLY_RESET, EDIT_APPLY_RESET,
EDIT_BAKE_ANIMATION,
EDIT_BAKE_ANIMATION_CONFIRM,
EDIT_OPTIMIZE_ANIMATION, EDIT_OPTIMIZE_ANIMATION,
EDIT_OPTIMIZE_ANIMATION_CONFIRM, EDIT_OPTIMIZE_ANIMATION_CONFIRM,
EDIT_CLEAN_UP_ANIMATION, EDIT_CLEAN_UP_ANIMATION,

View file

@ -4201,25 +4201,25 @@ void Animation::_position_track_optimize(int p_idx, real_t p_allowed_velocity_er
void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_ROTATION_3D); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_ROTATION_3D);
RotationTrack *tt = static_cast<RotationTrack *>(tracks[p_idx]); RotationTrack *rt = static_cast<RotationTrack *>(tracks[p_idx]);
int i = 0; int i = 0;
while (i < tt->rotations.size() - 2) { while (i < rt->rotations.size() - 2) {
TKey<Quaternion> t0 = tt->rotations[i]; TKey<Quaternion> t0 = rt->rotations[i];
TKey<Quaternion> t1 = tt->rotations[i + 1]; TKey<Quaternion> t1 = rt->rotations[i + 1];
TKey<Quaternion> t2 = tt->rotations[i + 2]; TKey<Quaternion> t2 = rt->rotations[i + 2];
bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); bool erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
if (erase) { if (erase) {
tt->rotations.remove_at(i + 1); rt->rotations.remove_at(i + 1);
} else { } else {
i++; i++;
} }
} }
if (tt->rotations.size() == 2) { if (rt->rotations.size() == 2) {
if ((tt->rotations[0].value - tt->rotations[1].value).length() < p_allowed_precision_error) { if ((rt->rotations[0].value - rt->rotations[1].value).length() < p_allowed_precision_error) {
tt->rotations.remove_at(1); rt->rotations.remove_at(1);
} }
} }
} }
@ -4227,25 +4227,25 @@ void Animation::_rotation_track_optimize(int p_idx, real_t p_allowed_velocity_er
void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_SCALE_3D); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_SCALE_3D);
ScaleTrack *tt = static_cast<ScaleTrack *>(tracks[p_idx]); ScaleTrack *st = static_cast<ScaleTrack *>(tracks[p_idx]);
int i = 0; int i = 0;
while (i < tt->scales.size() - 2) { while (i < st->scales.size() - 2) {
TKey<Vector3> t0 = tt->scales[i]; TKey<Vector3> t0 = st->scales[i];
TKey<Vector3> t1 = tt->scales[i + 1]; TKey<Vector3> t1 = st->scales[i + 1];
TKey<Vector3> t2 = tt->scales[i + 2]; TKey<Vector3> t2 = st->scales[i + 2];
bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); bool erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
if (erase) { if (erase) {
tt->scales.remove_at(i + 1); st->scales.remove_at(i + 1);
} else { } else {
i++; i++;
} }
} }
if (tt->scales.size() == 2) { if (st->scales.size() == 2) {
if ((tt->scales[0].value - tt->scales[1].value).length() < p_allowed_precision_error) { if ((st->scales[0].value - st->scales[1].value).length() < p_allowed_precision_error) {
tt->scales.remove_at(1); st->scales.remove_at(1);
} }
} }
} }
@ -4253,25 +4253,25 @@ void Animation::_scale_track_optimize(int p_idx, real_t p_allowed_velocity_err,
void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) { void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) {
ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_BLEND_SHAPE); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_BLEND_SHAPE);
BlendShapeTrack *tt = static_cast<BlendShapeTrack *>(tracks[p_idx]); BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(tracks[p_idx]);
int i = 0; int i = 0;
while (i < tt->blend_shapes.size() - 2) { while (i < bst->blend_shapes.size() - 2) {
TKey<float> t0 = tt->blend_shapes[i]; TKey<float> t0 = bst->blend_shapes[i];
TKey<float> t1 = tt->blend_shapes[i + 1]; TKey<float> t1 = bst->blend_shapes[i + 1];
TKey<float> t2 = tt->blend_shapes[i + 2]; TKey<float> t2 = bst->blend_shapes[i + 2];
bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error); bool erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error);
if (erase) { if (erase) {
tt->blend_shapes.remove_at(i + 1); bst->blend_shapes.remove_at(i + 1);
} else { } else {
i++; i++;
} }
} }
if (tt->blend_shapes.size() == 2) { if (bst->blend_shapes.size() == 2) {
if (abs(tt->blend_shapes[0].value - tt->blend_shapes[1].value) < p_allowed_precision_error) { if (abs(bst->blend_shapes[0].value - bst->blend_shapes[1].value) < p_allowed_precision_error) {
tt->blend_shapes.remove_at(1); bst->blend_shapes.remove_at(1);
} }
} }
} }
@ -4279,28 +4279,28 @@ void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity
void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) {
ERR_FAIL_INDEX(p_idx, tracks.size()); ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_VALUE); ERR_FAIL_COND(tracks[p_idx]->type != TYPE_VALUE);
ValueTrack *tt = static_cast<ValueTrack *>(tracks[p_idx]); ValueTrack *vt = static_cast<ValueTrack *>(tracks[p_idx]);
if (tt->values.size() == 0) { if (vt->values.size() == 0) {
return; return;
} }
Variant::Type type = tt->values[0].value.get_type(); Variant::Type type = vt->values[0].value.get_type();
// Special case for angle interpolation. // Special case for angle interpolation.
bool is_using_angle = tt->interpolation == Animation::INTERPOLATION_LINEAR_ANGLE || tt->interpolation == Animation::INTERPOLATION_CUBIC_ANGLE; bool is_using_angle = vt->interpolation == Animation::INTERPOLATION_LINEAR_ANGLE || vt->interpolation == Animation::INTERPOLATION_CUBIC_ANGLE;
int i = 0; int i = 0;
while (i < tt->values.size() - 2) { while (i < vt->values.size() - 2) {
bool erase = false; bool erase = false;
switch (type) { switch (type) {
case Variant::FLOAT: { case Variant::FLOAT: {
TKey<float> t0; TKey<float> t0;
TKey<float> t1; TKey<float> t1;
TKey<float> t2; TKey<float> t2;
t0.time = tt->values[i].time; t0.time = vt->values[i].time;
t1.time = tt->values[i + 1].time; t1.time = vt->values[i + 1].time;
t2.time = tt->values[i + 2].time; t2.time = vt->values[i + 2].time;
t0.value = tt->values[i].value; t0.value = vt->values[i].value;
t1.value = tt->values[i + 1].value; t1.value = vt->values[i + 1].value;
t2.value = tt->values[i + 2].value; t2.value = vt->values[i + 2].value;
if (is_using_angle) { if (is_using_angle) {
float diff1 = fmod(t1.value - t0.value, Math_TAU); float diff1 = fmod(t1.value - t0.value, Math_TAU);
t1.value = t0.value + fmod(2.0 * diff1, Math_TAU) - diff1; t1.value = t0.value + fmod(2.0 * diff1, Math_TAU) - diff1;
@ -4316,36 +4316,36 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
TKey<Vector2> t0; TKey<Vector2> t0;
TKey<Vector2> t1; TKey<Vector2> t1;
TKey<Vector2> t2; TKey<Vector2> t2;
t0.time = tt->values[i].time; t0.time = vt->values[i].time;
t1.time = tt->values[i + 1].time; t1.time = vt->values[i + 1].time;
t2.time = tt->values[i + 2].time; t2.time = vt->values[i + 2].time;
t0.value = tt->values[i].value; t0.value = vt->values[i].value;
t1.value = tt->values[i + 1].value; t1.value = vt->values[i + 1].value;
t2.value = tt->values[i + 2].value; t2.value = vt->values[i + 2].value;
erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
} break; } break;
case Variant::VECTOR3: { case Variant::VECTOR3: {
TKey<Vector3> t0; TKey<Vector3> t0;
TKey<Vector3> t1; TKey<Vector3> t1;
TKey<Vector3> t2; TKey<Vector3> t2;
t0.time = tt->values[i].time; t0.time = vt->values[i].time;
t1.time = tt->values[i + 1].time; t1.time = vt->values[i + 1].time;
t2.time = tt->values[i + 2].time; t2.time = vt->values[i + 2].time;
t0.value = tt->values[i].value; t0.value = vt->values[i].value;
t1.value = tt->values[i + 1].value; t1.value = vt->values[i + 1].value;
t2.value = tt->values[i + 2].value; t2.value = vt->values[i + 2].value;
erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
} break; } break;
case Variant::QUATERNION: { case Variant::QUATERNION: {
TKey<Quaternion> t0; TKey<Quaternion> t0;
TKey<Quaternion> t1; TKey<Quaternion> t1;
TKey<Quaternion> t2; TKey<Quaternion> t2;
t0.time = tt->values[i].time; t0.time = vt->values[i].time;
t1.time = tt->values[i + 1].time; t1.time = vt->values[i + 1].time;
t2.time = tt->values[i + 2].time; t2.time = vt->values[i + 2].time;
t0.value = tt->values[i].value; t0.value = vt->values[i].value;
t1.value = tt->values[i + 1].value; t1.value = vt->values[i + 1].value;
t2.value = tt->values[i + 2].value; t2.value = vt->values[i + 2].value;
erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error);
} break; } break;
default: { default: {
@ -4353,18 +4353,18 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
} }
if (erase) { if (erase) {
tt->values.remove_at(i + 1); vt->values.remove_at(i + 1);
} else { } else {
i++; i++;
} }
} }
if (tt->values.size() == 2) { if (vt->values.size() == 2) {
bool single_key = false; bool single_key = false;
switch (type) { switch (type) {
case Variant::FLOAT: { case Variant::FLOAT: {
float val_0 = tt->values[0].value; float val_0 = vt->values[0].value;
float val_1 = tt->values[1].value; float val_1 = vt->values[1].value;
if (is_using_angle) { if (is_using_angle) {
float diff1 = fmod(val_1 - val_0, Math_TAU); float diff1 = fmod(val_1 - val_0, Math_TAU);
val_1 = val_0 + fmod(2.0 * diff1, Math_TAU) - diff1; val_1 = val_0 + fmod(2.0 * diff1, Math_TAU) - diff1;
@ -4372,25 +4372,25 @@ void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err,
single_key = abs(val_0 - val_1) < p_allowed_precision_error; single_key = abs(val_0 - val_1) < p_allowed_precision_error;
} break; } break;
case Variant::VECTOR2: { case Variant::VECTOR2: {
Vector2 val_0 = tt->values[0].value; Vector2 val_0 = vt->values[0].value;
Vector2 val_1 = tt->values[1].value; Vector2 val_1 = vt->values[1].value;
single_key = (val_0 - val_1).length() < p_allowed_precision_error; single_key = (val_0 - val_1).length() < p_allowed_precision_error;
} break; } break;
case Variant::VECTOR3: { case Variant::VECTOR3: {
Vector3 val_0 = tt->values[0].value; Vector3 val_0 = vt->values[0].value;
Vector3 val_1 = tt->values[1].value; Vector3 val_1 = vt->values[1].value;
single_key = (val_0 - val_1).length() < p_allowed_precision_error; single_key = (val_0 - val_1).length() < p_allowed_precision_error;
} break; } break;
case Variant::QUATERNION: { case Variant::QUATERNION: {
Quaternion val_0 = tt->values[0].value; Quaternion val_0 = vt->values[0].value;
Quaternion val_1 = tt->values[1].value; Quaternion val_1 = vt->values[1].value;
single_key = (val_0 - val_1).length() < p_allowed_precision_error; single_key = (val_0 - val_1).length() < p_allowed_precision_error;
} break; } break;
default: { default: {
} break; } break;
} }
if (single_key) { if (single_key) {
tt->values.remove_at(1); vt->values.remove_at(1);
} }
} }
} }