Preserve current Animation progress if SpeedRatio or PlaybackDirection changes
#19830
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Apologies for not opening an Issue first... Let me know if there's a better way of doing this and I can change anything.
What does the pull request do?
This PR makes it possible to change
SpeedRatioandPlaybackDirectionwhile animation is running without affecting the current animation progress. PR keeps compatibility with old behavior when speed does not change.What is the current behavior?
When
Animation.SpeedRatioorAnimation.PlaybackDirectionchanges, the animation progress/timeline IS affected.What is the updated/expected behavior with this PR?
When
Animation.SpeedRatioorAnimation.PlaybackDirectionchanges, the animation progress/timeline IS NOT affected.How was the solution implemented (if it's not obvious)?
In short
When relevant properties change during a running animation, the animation's current progress is remembered and animation continues from that point on with respect to property changes.
This is all that's needed to handle a changing
SpeedRatio. ForPlaybackDirection, a lot more care has to be put into the logic as explained in the following subsections.Definition of proper animation direction
Proper animation direction is the value of
PlaybackDirectionat first frame of the animation. In code it is indicated by_timeMovesBackwardsfield.PlaybackDirection.NormalandPlaybackDirection.Alternateresult in positive proper animation direction, whilePlaybackDirection.ReverseandPlaybackDirection.AlternateReverseresult in negative proper animation direction. IfPlaybackDirectionchanges direction some time after the first frame of animation, the animation will start playing backwards. If left running, animation will eventually reach the starting position of animation the second time.Behavior at starting position
When animation begins playing there is nothing new to discuss, it plays as it always has. When animation reverses direction and reaches the starting position subsequently, animation will always hold value of initial keyframe (first or last keyframe depending on proper animation direction), no matter the value of
FillMode.Animations with INFINITE
IterationCountwill continue backwards past the starting position of the animation. This is to allow changing animation direction without affecting the infinitely repeating nature of the animation.Animations with finite
IterationCountwill be clamped to the starting position and will wait for direction to change back into proper animation direction. When that happens, animation will again start playing normally the same way as it has when animation started the first time (albeit with a potentially different speed). Test Reversing_Direction_Past_Initial_Point_Clamps_To_Initial_Point has been added to check the correctnes of this behavior.Behavior of delays
Between the starting position and ending position of animation, behavior of both
DelayandDelayBetweenIterationsis always the same, no matter how many times any given delay has been reached. This can be though of as delays being "baked-into" the animation. I believe this is what most people would expect and want.The only new delay behavior is with animations where

IterationCountis INFINITE. When animation plays backwards past the starting point, theDelayBetweenIterationswill be played in the opposite part of the iteration time. Here is a quick/crudely drawn illustration of animation timeline to make it clearer:If user wants to always have the same delay between all iterations, then both
DelayandDelayBetweenIterationsneed to be set to the same value.Unhandled case
Changing between
Alternateand non-AlternatePlaybackDirections are not handled. This means that switching between such two modes (fromNormalorReversetoAlternateorAlternateReverseor vice versa) can result in a "jump" of current animation progress depending on when you switch it.This could be handled in a way that kind of "does" make sense, but I don't see a reason why anyone would need to switch between these two modes.
Finally
Please review carefully in case I missed something, I wouldn't want to break animations which are probably considered a core feature.
I should also mention that I didn't do any testing of
FillMode(besides what I mentioned above), I just assumed that if all UnitTests pass, then it works as expected.Checklist
Animation Speedpage to RenderDemo sample for previewBreaking changes
IterationCount.Valuemay no longer be greater thanlong.MaxValue.Obsoletions / Deprecations
NONE
Fixed issues
Fixes #19979