diff options
Diffstat (limited to 'scene/animation/animation_player.cpp')
-rw-r--r-- | scene/animation/animation_player.cpp | 141 |
1 files changed, 78 insertions, 63 deletions
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index fe67c0886f..f7baa7facc 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -109,7 +109,7 @@ bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) { Ref<AnimationLibrary> lib = d[lib_name]; add_animation_library(lib_name, lib); } - + emit_signal("animation_libraries_updated"); } else if (name.begins_with("next/")) { String which = name.get_slicec('/', 1); animation_set_next(which, p_value); @@ -468,7 +468,7 @@ Variant AnimationPlayer::_post_process_key_value(const Ref<Animation> &p_anim, i return p_value; } -void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) { +void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_prev_time, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, Animation::LoopedFlag p_looped_flag) { _ensure_node_caches(p_anim); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); @@ -664,7 +664,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double } } - if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE || (p_delta == 0 && update_mode == Animation::UPDATE_DISCRETE)) { //delta == 0 means seek + if (update_mode == Animation::UPDATE_CONTINUOUS || update_mode == Animation::UPDATE_CAPTURE) { Variant value = a->value_track_interpolate(i, p_time); if (value == Variant()) { @@ -681,9 +681,23 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double pa->value_accum = Animation::interpolate_variant(pa->value_accum, value, p_interp); } - } else if (p_is_current && p_delta != 0) { + } else { List<int> indices; - a->value_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged); + + if (p_seeked) { + int found_key = a->track_find_key(i, p_time); + if (found_key >= 0) { + indices.push_back(found_key); + } + } else { + if (p_started) { + int first_key = a->track_find_key(i, p_prev_time, true); + if (first_key >= 0) { + indices.push_back(first_key); + } + } + a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_looped_flag); + } for (int &F : indices) { Variant value = a->track_get_key_value(i, F); @@ -734,16 +748,26 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (!nc->node) { continue; } - if (p_delta == 0) { - continue; - } if (!p_is_current) { break; } List<int> indices; - a->method_track_get_key_indices(i, p_time, p_delta, &indices, p_pingponged); + if (p_seeked) { + int found_key = a->track_find_key(i, p_time); + if (found_key >= 0) { + indices.push_back(found_key); + } + } else { + if (p_started) { + int first_key = a->track_find_key(i, p_prev_time, true); + if (first_key >= 0) { + indices.push_back(first_key); + } + } + a->track_get_key_indices_in_range(i, p_time, p_delta, &indices, p_looped_flag); + } for (int &E : indices) { StringName method = a->method_track_get_name(i, E); @@ -787,9 +811,6 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double if (!nc->node) { continue; } - if (p_delta == 0) { - continue; - } if (p_seeked) { //find whatever should be playing @@ -833,7 +854,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double } else { //find stuff to play List<int> to_play; - a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged); + if (p_started) { + int first_key = a->track_find_key(i, p_prev_time, true); + if (first_key >= 0) { + to_play.push_back(first_key); + } + } + a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_looped_flag); if (to_play.size()) { int idx = to_play.back()->get(); @@ -893,7 +920,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double continue; } - if (p_delta == 0 || p_seeked) { + if (p_seeked) { //seek int idx = a->track_find_key(i, p_time); if (idx < 0) { @@ -928,7 +955,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double break; } - if (player->is_playing() || p_seeked) { + if (player->is_playing()) { player->play(anim_name); player->seek(at_anim_pos); nc->animation_playing = true; @@ -940,7 +967,13 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double } else { //find stuff to play List<int> to_play; - a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_pingponged); + if (p_started) { + int first_key = a->track_find_key(i, p_prev_time, true); + if (first_key >= 0) { + to_play.push_back(first_key); + } + } + a->track_get_key_indices_in_range(i, p_time, p_delta, &to_play, p_looped_flag); if (to_play.size()) { int idx = to_play.back()->get(); @@ -970,7 +1003,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, double next_pos = cd.pos + delta; real_t len = cd.from->animation->get_length(); - int pingponged = 0; + Animation::LoopedFlag looped_flag = Animation::LOOPED_FLAG_NONE; switch (cd.from->animation->get_loop_mode()) { case Animation::LOOP_NONE: { @@ -999,44 +1032,33 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, } break; case Animation::LOOP_LINEAR: { - double looped_next_pos = Math::fposmod(next_pos, (double)len); - if (looped_next_pos == 0 && next_pos != 0) { - // Loop multiples of the length to it, rather than 0 - // so state at time=length is previewable in the editor - next_pos = len; - } else { - next_pos = looped_next_pos; + if (next_pos < 0 && cd.pos >= 0) { + looped_flag = Animation::LOOPED_FLAG_START; + } + if (next_pos > len && cd.pos <= len) { + looped_flag = Animation::LOOPED_FLAG_END; } + next_pos = Math::fposmod(next_pos, (double)len); } break; case Animation::LOOP_PINGPONG: { - if ((int)Math::floor(abs(next_pos - cd.pos) / len) % 2 == 0) { - if (next_pos < 0 && cd.pos >= 0) { - cd.speed_scale *= -1.0; - pingponged = -1; - } - if (next_pos > len && cd.pos <= len) { - cd.speed_scale *= -1.0; - pingponged = 1; - } + if (next_pos < 0 && cd.pos >= 0) { + cd.speed_scale *= -1.0; + looped_flag = Animation::LOOPED_FLAG_START; } - double looped_next_pos = Math::pingpong(next_pos, (double)len); - if (looped_next_pos == 0 && next_pos != 0) { - // Loop multiples of the length to it, rather than 0 - // so state at time=length is previewable in the editor - next_pos = len; - } else { - next_pos = looped_next_pos; + if (next_pos > len && cd.pos <= len) { + cd.speed_scale *= -1.0; + looped_flag = Animation::LOOPED_FLAG_END; } + next_pos = Math::pingpong(next_pos, (double)len); } break; default: break; } + _animation_process_animation(cd.from, cd.pos, next_pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, looped_flag); cd.pos = next_pos; - - _animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started, pingponged); } void AnimationPlayer::_animation_process2(double p_delta, bool p_started) { @@ -1044,7 +1066,7 @@ void AnimationPlayer::_animation_process2(double p_delta, bool p_started) { accum_pass++; - _animation_process_data(c.current, p_delta, 1.0f, c.seeked && p_delta != 0, p_started); + _animation_process_data(c.current, p_delta, 1.0f, c.seeked, p_started); if (p_delta != 0) { c.seeked = false; } @@ -1283,6 +1305,7 @@ void AnimationPlayer::_animation_removed(const StringName &p_name, const StringN if (!animation_set.has(name)) { return; // No need to update because not the one from the library being used. } + _animation_set_cache_update(); // Erase blends if needed @@ -1376,8 +1399,9 @@ Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref animation_libraries.insert(insert_pos, ald); ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name)); - ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_name)); + ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed).bind(p_name)); ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_name)); + ald.library->connect(SNAME("animation_changed"), callable_mp(this, &AnimationPlayer::_animation_changed)); _animation_set_cache_update(); @@ -1399,29 +1423,18 @@ void AnimationPlayer::remove_animation_library(const StringName &p_name) { ERR_FAIL_COND(at_pos == -1); animation_libraries[at_pos].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added)); - animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added)); + animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed)); animation_libraries[at_pos].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed)); + animation_libraries[at_pos].library->disconnect(SNAME("animation_changed"), callable_mp(this, &AnimationPlayer::_animation_changed)); stop(); - for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[at_pos].library->animations) { - _unref_anim(K.value); - } - animation_libraries.remove_at(at_pos); _animation_set_cache_update(); notify_property_list_changed(); } -void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) { - Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), CONNECT_REFERENCE_COUNTED); -} - -void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) { - Ref<Animation>(p_anim)->disconnect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed)); -} - void AnimationPlayer::rename_animation_library(const StringName &p_name, const StringName &p_new_name) { if (p_name == p_new_name) { return; @@ -1438,11 +1451,11 @@ void AnimationPlayer::rename_animation_library(const StringName &p_name, const S animation_libraries[i].name = p_new_name; // rename connections animation_libraries[i].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added)); - animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added)); + animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed)); animation_libraries[i].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed)); animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name)); - animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added).bind(p_new_name)); + animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_removed).bind(p_new_name)); animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed).bind(p_new_name)); for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) { @@ -1772,9 +1785,8 @@ double AnimationPlayer::get_current_animation_length() const { return playback.current.from->animation->get_length(); } -void AnimationPlayer::_animation_changed() { +void AnimationPlayer::_animation_changed(const StringName &p_name) { clear_caches(); - emit_signal(SNAME("caches_cleared")); if (is_playing()) { playback.seeked = true; //need to restart stuff, like audio } @@ -1813,6 +1825,8 @@ void AnimationPlayer::clear_caches() { cache_update_size = 0; cache_update_prop_size = 0; cache_update_bezier_size = 0; + + emit_signal(SNAME("caches_cleared")); } void AnimationPlayer::set_active(bool p_active) { @@ -2039,7 +2053,7 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) { // Forcing the use of the original root because the scene where original player belongs may be not the active one Ref<AnimatedValuesBackup> old_values = aux_player->backup_animated_values(get_node(get_root())); aux_player->seek(0.0f, true); - aux_player->queue_delete(); + aux_player->queue_free(); if (p_user_initiated) { Ref<AnimatedValuesBackup> new_values = aux_player->backup_animated_values(); @@ -2131,7 +2145,7 @@ void AnimationPlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "root_node"), "set_root", "get_root"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ANIMATE_AS_TRIGGER), "set_current_animation", "get_current_animation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "current_animation", PROPERTY_HINT_ENUM, "", PROPERTY_USAGE_EDITOR), "set_current_animation", "get_current_animation"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "assigned_animation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_assigned_animation", "get_assigned_animation"); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "autoplay", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_autoplay", "get_autoplay"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reset_on_save", PROPERTY_HINT_NONE, ""), "set_reset_on_save_enabled", "is_reset_on_save_enabled"); @@ -2151,6 +2165,7 @@ void AnimationPlayer::_bind_methods() { ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "old_name"), PropertyInfo(Variant::STRING_NAME, "new_name"))); ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING_NAME, "anim_name"))); ADD_SIGNAL(MethodInfo("animation_list_changed")); + ADD_SIGNAL(MethodInfo("animation_libraries_updated")); ADD_SIGNAL(MethodInfo("caches_cleared")); BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS); |