diff --git a/doc/classes/AnimationNodeOneShot.xml b/doc/classes/AnimationNodeOneShot.xml index 28bea47e2198..93fa205ce377 100644 --- a/doc/classes/AnimationNodeOneShot.xml +++ b/doc/classes/AnimationNodeOneShot.xml @@ -74,14 +74,14 @@ The fade-in duration. For example, setting this to [code]1.0[/code] for a 5 second length animation will produce a cross-fade that starts at 0 second and ends at 1 second during the animation. - [b]Note:[/b] [AnimationNodeOneShot] transitions the current state after the end of the fading. When [AnimationNodeOutput] is considered as the most upstream, so the [member fadein_time] is scaled depending on the downstream delta. For example, if this value is set to [code]1.0[/code] and a [AnimationNodeTimeScale] with a value of [code]2.0[/code] is chained downstream, the actual processing time will be 0.5 second. + [b]Note:[/b] [AnimationNodeOneShot] transitions the current state after the end of the fading. Determines how cross-fading between animations is eased. If empty, the transition will be linear. Should be a unit [Curve]. The fade-out duration. For example, setting this to [code]1.0[/code] for a 5 second length animation will produce a cross-fade that starts at 4 second and ends at 5 second during the animation. - [b]Note:[/b] [AnimationNodeOneShot] transitions the current state after the end of the fading. When [AnimationNodeOutput] is considered as the most upstream, so the [member fadeout_time] is scaled depending on the downstream delta. For example, if this value is set to [code]1.0[/code] and an [AnimationNodeTimeScale] with a value of [code]2.0[/code] is chained downstream, the actual processing time will be 0.5 second. + [b]Note:[/b] [AnimationNodeOneShot] transitions the current state after the end of the fading. The blend type. diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 019a14e556c6..5ab63ae0196e 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -670,11 +670,17 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer: NodeTimeInfo os_nti = blend_input(1, pi, FILTER_PASS, true, p_test_only); // Blend values must be more than CMP_EPSILON to process discrete keys in edge. - if (Animation::is_less_or_equal_approx(cur_fade_in_remaining, 0) && !do_start && !is_fading_out && Animation::is_less_or_equal_approx(os_nti.get_remain(break_loop_at_end), fade_out)) { - is_fading_out = true; - cur_fade_out_remaining = os_nti.get_remain(break_loop_at_end); - cur_fade_in_remaining = 0; - set_parameter(internal_active, false); + if (Animation::is_less_or_equal_approx(cur_fade_in_remaining, 0) && !do_start && !is_fading_out) { + // Predict time scale by difference of delta times to estimate input animation's remain time in self time scale. + double abs_os_delta = Math::abs(os_nti.delta); + double tscl = Math::is_zero_approx(abs_delta) || Math::is_zero_approx(abs_os_delta) || Math::is_equal_approx(abs_delta, abs_os_delta) ? 1.0 : (abs_delta / abs_os_delta); + double os_rem = os_nti.get_remain(break_loop_at_end) * tscl; + if (Animation::is_less_or_equal_approx(os_rem, fade_out)) { + is_fading_out = true; + cur_fade_out_remaining = os_rem; + cur_fade_in_remaining = 0; + set_parameter(internal_active, false); + } } if (!p_seek) { @@ -686,11 +692,10 @@ AnimationNode::NodeTimeInfo AnimationNodeOneShot::_process(const AnimationMixer: set_parameter(time_to_restart, restart_sec); } } - double d = Math::abs(os_nti.delta); if (!do_start) { - cur_fade_in_remaining = MAX(0, cur_fade_in_remaining - d); // Don't consider seeked delta by restart. + cur_fade_in_remaining = MAX(0, cur_fade_in_remaining - abs_delta); // Don't consider seeked delta by restart. } - cur_fade_out_remaining = MAX(0, cur_fade_out_remaining - d); + cur_fade_out_remaining = MAX(0, cur_fade_out_remaining - abs_delta); } set_parameter(fade_in_remaining, cur_fade_in_remaining);