diff --git a/doc/classes/AnimationMixer.xml b/doc/classes/AnimationMixer.xml index 26d28f9c500..9ccaa385db5 100644 --- a/doc/classes/AnimationMixer.xml +++ b/doc/classes/AnimationMixer.xml @@ -357,6 +357,7 @@ An [constant Animation.UPDATE_DISCRETE] track value takes precedence when blending [constant Animation.UPDATE_CONTINUOUS] or [constant Animation.UPDATE_CAPTURE] track values and [constant Animation.UPDATE_DISCRETE] track values. This is the default behavior for [AnimationPlayer]. + [b]Note:[/b] If a value track has non-numeric type key values, it is internally converted to use [constant ANIMATION_CALLBACK_MODE_DISCRETE_DOMINANT] with [constant Animation.UPDATE_DISCRETE]. An [constant Animation.UPDATE_CONTINUOUS] or [constant Animation.UPDATE_CAPTURE] track value takes precedence when blending the [constant Animation.UPDATE_CONTINUOUS] or [constant Animation.UPDATE_CAPTURE] track values and the [constant Animation.UPDATE_DISCRETE] track values. diff --git a/scene/animation/animation_mixer.cpp b/scene/animation/animation_mixer.cpp index 87ac0bf5c8a..0ee47ee0fef 100644 --- a/scene/animation/animation_mixer.cpp +++ b/scene/animation/animation_mixer.cpp @@ -693,6 +693,9 @@ bool AnimationMixer::_update_caches() { track_value->init_value = anim->track_get_key_value(i, 0); track_value->init_value.zero(); + // Can't interpolate them, need to convert. + track_value->is_variant_interpolatable = Animation::is_variant_interpolatable(track_value->init_value); + // If there is a Reset Animation, it takes precedence by overwriting. if (has_reset_anim) { int rt = reset_anim->find_track(path, track_src_type); @@ -1414,7 +1417,7 @@ void AnimationMixer::_blend_process(double p_delta, bool p_update_only) { bool is_value = ttype == Animation::TYPE_VALUE; bool is_discrete = is_value && a->value_track_get_update_mode(i) == Animation::UPDATE_DISCRETE; bool force_continuous = callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_FORCE_CONTINUOUS; - if (!is_discrete || force_continuous) { + if (t->is_variant_interpolatable && (!is_discrete || force_continuous)) { Variant value = is_value ? a->value_track_interpolate(i, time, is_discrete && force_continuous ? backward : false) : Variant(a->bezier_track_interpolate(i, time)); value = post_process_key_value(a, i, value, t->object_id); if (value == Variant()) { @@ -1727,7 +1730,7 @@ void AnimationMixer::_blend_apply() { case Animation::TYPE_VALUE: { TrackCacheValue *t = static_cast(track); - if (callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_DOMINANT && t->use_discrete) { + if (!t->is_variant_interpolatable || (callback_mode_discrete == ANIMATION_CALLBACK_MODE_DISCRETE_DOMINANT && t->use_discrete)) { break; // Don't overwrite the value set by UPDATE_DISCRETE. } diff --git a/scene/animation/animation_mixer.h b/scene/animation/animation_mixer.h index 7808ec788c5..5f7e6c54295 100644 --- a/scene/animation/animation_mixer.h +++ b/scene/animation/animation_mixer.h @@ -224,6 +224,7 @@ protected: Vector subpath; bool use_discrete = false; bool is_using_angle = false; + bool is_variant_interpolatable = true; Variant element_size; TrackCacheValue(const TrackCacheValue &p_other) : @@ -233,6 +234,7 @@ protected: subpath(p_other.subpath), use_discrete(p_other.use_discrete), is_using_angle(p_other.is_using_angle), + is_variant_interpolatable(p_other.is_variant_interpolatable), element_size(p_other.element_size) {} TrackCacheValue() { type = Animation::TYPE_VALUE; }