8 changed files with 167 additions and 84 deletions
@ -0,0 +1,131 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Animation.Keyframes |
|||
{ |
|||
/// <summary>
|
|||
/// Provides statefulness for an iteration of a keyframe group animation.
|
|||
/// </summary>
|
|||
internal class KeyFramesStateMachine |
|||
{ |
|||
|
|||
ulong _delayTotalFrameCount, |
|||
_durationTotalFrameCount, |
|||
_delayFrameCount, |
|||
_durationFrameCount, |
|||
_repeatCount, |
|||
_currentIteration, |
|||
_totalIteration; |
|||
|
|||
bool _isLooping, _isRepeating, _isReversed; |
|||
private Direction _animationDirection; |
|||
KeyFramesStates _currentState; |
|||
|
|||
internal bool _unsubscribe = false; |
|||
private Animation _parentAnimation; |
|||
private Animatable _targetAnimatable; |
|||
|
|||
private enum KeyFramesStates |
|||
{ |
|||
INITIALIZE, |
|||
DO_DELAY, |
|||
DO_RUN, |
|||
RUN_FORWARDS, |
|||
RUN_BACKWARDS, |
|||
RUN_COMPLETE, |
|||
STOP |
|||
} |
|||
|
|||
public void Start(Animation animation, Animatable control) |
|||
{ |
|||
this._parentAnimation = animation; |
|||
this._targetAnimatable = control; |
|||
|
|||
// int _delayFrameCount,
|
|||
// _durationFrameCount,
|
|||
// _repeatCount,
|
|||
// _iterationDirection,
|
|||
// _currentIteration,
|
|||
// _totalIteration;
|
|||
|
|||
_delayTotalFrameCount = (ulong)(animation.Delay.Ticks / Timing.FrameTick.Ticks); |
|||
_durationTotalFrameCount = (ulong)(animation.Duration.Ticks / Timing.FrameTick.Ticks); |
|||
|
|||
if (_delayTotalFrameCount > 0) |
|||
{ |
|||
_currentState = KeyFramesStates.DO_DELAY; |
|||
} |
|||
|
|||
switch (animation.RepeatBehavior) |
|||
{ |
|||
case RepeatBehavior.Loop: |
|||
_isLooping = true; |
|||
break; |
|||
case RepeatBehavior.Repeat: |
|||
_isRepeating = true; |
|||
if (animation.RepeatCount != null) |
|||
{ |
|||
if (animation.RepeatCount == 0) |
|||
{ |
|||
throw new InvalidOperationException |
|||
($"RepeatCount should be greater than zero when RepeatBehavior is set to Repeat."); |
|||
} |
|||
_repeatCount = (ulong)animation.RepeatCount; |
|||
} |
|||
else |
|||
{ |
|||
throw new InvalidOperationException |
|||
($"RepeatCount should be defined when RepeatBehavior is set to Repeat."); |
|||
} |
|||
break; |
|||
} |
|||
this._animationDirection = animation.PlaybackDirection; |
|||
_currentState = KeyFramesStates.DO_RUN; |
|||
} |
|||
|
|||
private void SetInitialPlaybackDirection(bool isReversed) |
|||
{ |
|||
_isReversed = isReversed; |
|||
} |
|||
|
|||
private bool GetPlaybackDirection() |
|||
{ |
|||
_isReversed = !_isReversed; |
|||
return _isReversed; |
|||
} |
|||
|
|||
public double Step(PlayState _playState) |
|||
{ |
|||
if (_playState == PlayState.Stop) _currentState = KeyFramesStates.STOP; |
|||
|
|||
switch (_currentState) |
|||
{ |
|||
case KeyFramesStates.DO_DELAY: |
|||
if (_delayFrameCount >= _delayTotalFrameCount) |
|||
{ |
|||
_currentState = KeyFramesStates.DO_RUN; |
|||
} |
|||
_delayFrameCount++; |
|||
return 0d; |
|||
|
|||
case KeyFramesStates.DO_RUN: |
|||
|
|||
break; |
|||
|
|||
case KeyFramesStates.RUN_FORWARDS: |
|||
// break;
|
|||
|
|||
case KeyFramesStates.RUN_BACKWARDS: |
|||
// break;
|
|||
|
|||
case KeyFramesStates.RUN_COMPLETE: |
|||
// break;
|
|||
|
|||
case KeyFramesStates.STOP: |
|||
_unsubscribe = true; |
|||
break; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
} |
|||
} |
|||
Loading…
Reference in new issue