Add linear/cubic angle interpolation to Animation interpolation type

This commit is contained in:
Silc Renew
2022-08-26 11:42:00 +09:00
parent 4808d01b2b
commit 931fb4dc11
12 changed files with 238 additions and 18 deletions

View File

@ -2122,10 +2122,12 @@ void AnimationTrackEdit::_notification(int p_what) {
get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons")),
get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")),
};
Ref<Texture2D> interp_icon[3] = {
Ref<Texture2D> interp_icon[5] = {
get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")),
get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")),
get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")),
get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")),
get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")),
};
Ref<Texture2D> cont_icon[4] = {
get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")),
@ -2848,6 +2850,23 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
menu->add_icon_item(get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), TTR("Nearest"), MENU_INTERPOLATION_NEAREST);
menu->add_icon_item(get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), TTR("Linear"), MENU_INTERPOLATION_LINEAR);
menu->add_icon_item(get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), TTR("Cubic"), MENU_INTERPOLATION_CUBIC);
// Check is angle property.
AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton();
if (ape) {
AnimationPlayer *ap = ape->get_player();
if (ap) {
NodePath path = animation->track_get_path(track);
Node *nd = ap->get_node(ap->get_root())->get_node(NodePath(path.get_concatenated_names()));
StringName prop = path.get_concatenated_subnames();
PropertyInfo prop_info;
ClassDB::get_property_info(nd->get_class(), prop, &prop_info);
bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians") != -1;
if (is_angle) {
menu->add_icon_item(get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")), TTR("Linear Angle"), MENU_INTERPOLATION_LINEAR_ANGLE);
menu->add_icon_item(get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")), TTR("Cubic Angle"), MENU_INTERPOLATION_CUBIC_ANGLE);
}
}
}
menu->reset_size();
Vector2 popup_pos = get_screen_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height);
@ -3188,7 +3207,9 @@ void AnimationTrackEdit::_menu_selected(int p_index) {
} break;
case MENU_INTERPOLATION_NEAREST:
case MENU_INTERPOLATION_LINEAR:
case MENU_INTERPOLATION_CUBIC: {
case MENU_INTERPOLATION_CUBIC:
case MENU_INTERPOLATION_LINEAR_ANGLE:
case MENU_INTERPOLATION_CUBIC_ANGLE: {
Animation::InterpolationType interp_mode = Animation::InterpolationType(p_index - MENU_INTERPOLATION_NEAREST);
undo_redo->create_action(TTR("Change Animation Interpolation Mode"));
undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track, interp_mode);
@ -6042,6 +6063,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
Vector<int> keys = E->value;
int len = keys.size() - 1;
// Special case for angle interpolation.
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.
Vector<Pair<double, Variant>> insert_queue;
for (int i = 0; i < len; i++) {
@ -6051,6 +6075,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
double to_t = animation->track_get_key_time(track, keys[i + 1]);
Variant from_v = animation->track_get_key_value(track, keys[i]);
Variant to_v = animation->track_get_key_value(track, keys[i + 1]);
if (is_using_angle) {
real_t a = from_v;
real_t b = to_v;
real_t to_diff = fmod(b - a, Math_TAU);
to_v = a + fmod(2.0 * to_diff, Math_TAU) - to_diff;
}
Variant delta_v;
Variant::sub(to_v, from_v, delta_v);
double duration = to_t - from_t;
@ -6192,10 +6222,14 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
do_bake |= b_bs && type == Animation::TYPE_BLEND_SHAPE;
do_bake |= b_v && type == Animation::TYPE_VALUE;
if (do_bake && !animation->track_is_compressed(i)) {
if (animation->track_get_interpolation_type(i) == Animation::INTERPOLATION_NEAREST) {
continue; // Nearest interpolation cannot be baked.
Animation::InterpolationType it = animation->track_get_interpolation_type(i);
if (it == Animation::INTERPOLATION_NEAREST) {
continue; // Nearest and Angle interpolation cannot be baked.
}
// Special case for angle interpolation.
bool is_using_angle = it == Animation::INTERPOLATION_LINEAR_ANGLE || it == Animation::INTERPOLATION_CUBIC_ANGLE;
// Make insert queue.
Vector<Pair<double, Variant>> insert_queue;
@ -6259,7 +6293,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
// Insert keys.
undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, 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--) {
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);