@ -11,7 +11,7 @@ namespace Avalonia.Animation
{
object _l astInterpValue ;
object _f irstKFValue ;
private ulong _d elayTotalFrameCount ,
_d urationTotalFrameCount ,
_d elayFrameCount ,
@ -33,18 +33,19 @@ namespace Avalonia.Animation
internal bool _ unsubscribe = false ;
private IObserver < object > _ targetObserver ;
[Flags]
private enum KeyFramesStates
{
INITIALIZE ,
DO_DELAY ,
DO_RUN ,
RUN_FORWARDS ,
RUN_BACKWARDS ,
RUN_APPLYVALUE ,
RUN_COMPLETE ,
PAUSE ,
STOP ,
DISPOSED
Initialize ,
DoDelay ,
DoRun ,
RunForwards ,
RunBackwards ,
RunApplyValue ,
RunComplete ,
Pause ,
Stop ,
Disposed
}
public void Initialize ( Animation animation , Animatable control , KeyFrames < T > keyframes )
@ -82,24 +83,14 @@ namespace Avalonia.Animation
break ;
}
switch ( animation . PlaybackDirection )
{
case PlaybackDirection . Reverse :
case PlaybackDirection . AlternateReverse :
_ isReversed = true ;
break ;
default :
_ isReversed = false ;
break ;
}
_ isReversed = ( animation . PlaybackDirection & PlaybackDirection . Reverse ) ! = 0 ;
_ animationDirection = _ targetAnimation . PlaybackDirection ;
_f illMode = _ targetAnimation . FillMode ;
if ( _d urationTotalFrameCount > 0 )
_ currentState = KeyFramesStates . DO_DELAY ;
_ currentState = KeyFramesStates . DoDelay ;
else
_ currentState = KeyFramesStates . DO_RUN ;
_ currentState = KeyFramesStates . DoRun ;
}
@ -124,21 +115,21 @@ namespace Avalonia.Animation
_ gotFirstKFValue = true ;
}
if ( _ currentState = = KeyFramesStates . DISPOSED )
if ( _ currentState = = KeyFramesStates . Disposed )
throw new InvalidProgramException ( "This KeyFrames Animation is already disposed." ) ;
if ( _ playState = = PlayState . Stop )
_ currentState = KeyFramesStates . STOP ;
_ currentState = KeyFramesStates . Stop ;
// Save state and pause the machine
if ( _ playState = = PlayState . Pause & & _ currentState ! = KeyFramesStates . PAUSE )
if ( _ playState = = PlayState . Pause & & _ currentState ! = KeyFramesStates . Pause )
{
_ savedState = _ currentState ;
_ currentState = KeyFramesStates . PAUSE ;
_ currentState = KeyFramesStates . Pause ;
}
// Resume the previous state
if ( _ playState ! = PlayState . Pause & & _ currentState = = KeyFramesStates . PAUSE )
if ( _ playState ! = PlayState . Pause & & _ currentState = = KeyFramesStates . Pause )
_ currentState = _ savedState ;
double _ tempDuration = 0d , _ easedTime ;
@ -146,7 +137,7 @@ namespace Avalonia.Animation
checkstate :
switch ( _ currentState )
{
case KeyFramesStates . DO_DELAY :
case KeyFramesStates . DoDelay :
if ( _f illMode = = FillMode . Backward
| | _f illMode = = FillMode . Both )
@ -163,60 +154,60 @@ namespace Avalonia.Animation
if ( _d elayFrameCount > _d elayTotalFrameCount )
{
_ currentState = KeyFramesStates . DO_RUN ;
_ currentState = KeyFramesStates . DoRun ;
goto checkstate ;
}
_d elayFrameCount + + ;
break ;
case KeyFramesStates . DO_RUN :
case KeyFramesStates . DoRun :
if ( _ isReversed )
_ currentState = KeyFramesStates . RUN_BACKWARDS ;
_ currentState = KeyFramesStates . RunBackwards ;
else
_ currentState = KeyFramesStates . RUN_FORWARDS ;
_ currentState = KeyFramesStates . RunForwards ;
goto checkstate ;
case KeyFramesStates . RUN_FORWARDS :
case KeyFramesStates . RunForwards :
if ( _d urationFrameCount > _d urationTotalFrameCount )
{
_ currentState = KeyFramesStates . RUN_COMPLETE ;
_ currentState = KeyFramesStates . RunComplete ;
goto checkstate ;
}
_ tempDuration = ( double ) _d urationFrameCount / _d urationTotalFrameCount ;
_ currentState = KeyFramesStates . RUN_APPLYVALUE ;
_ currentState = KeyFramesStates . RunApplyValue ;
goto checkstate ;
case KeyFramesStates . RUN_BACKWARDS :
case KeyFramesStates . RunBackwards :
if ( _d urationFrameCount > _d urationTotalFrameCount )
{
_ currentState = KeyFramesStates . RUN_COMPLETE ;
_ currentState = KeyFramesStates . RunComplete ;
goto checkstate ;
}
_ tempDuration = ( double ) ( _d urationTotalFrameCount - _d urationFrameCount ) / _d urationTotalFrameCount ;
_ currentState = KeyFramesStates . RUN_APPLYVALUE ;
_ currentState = KeyFramesStates . RunApplyValue ;
goto checkstate ;
case KeyFramesStates . RUN_APPLYVALUE :
case KeyFramesStates . RunApplyValue :
_ easedTime = _ targetAnimation . Easing . Ease ( _ tempDuration ) ;
_d urationFrameCount + + ;
_l astInterpValue = Interpolator ( _ easedTime ) ;
_ targetObserver . OnNext ( _l astInterpValue ) ;
_ currentState = KeyFramesStates . DO_RUN ;
_ currentState = KeyFramesStates . DoRun ;
break ;
case KeyFramesStates . RUN_COMPLETE :
case KeyFramesStates . RunComplete :
if ( _ checkLoopAndRepeat )
{
@ -225,17 +216,17 @@ namespace Avalonia.Animation
if ( _ isLooping )
{
_ currentState = KeyFramesStates . DO_RUN ;
_ currentState = KeyFramesStates . DoRun ;
}
else if ( _ isRepeating )
{
if ( _ currentIteration > = _ repeatCount )
{
_ currentState = KeyFramesStates . STOP ;
_ currentState = KeyFramesStates . Stop ;
}
else
{
_ currentState = KeyFramesStates . DO_RUN ;
_ currentState = KeyFramesStates . DoRun ;
}
_ currentIteration + + ;
}
@ -247,14 +238,15 @@ namespace Avalonia.Animation
break ;
}
_ currentState = KeyFramesStates . STOP ;
_ currentState = KeyFramesStates . Stop ;
goto checkstate ;
case KeyFramesStates . STOP :
case KeyFramesStates . Stop :
if ( _f illMode = = FillMode . Forward
| | _f illMode = = FillMode . Both )
{
_ targetControl . SetValue ( _ parent . Property , _l astInterpValue , BindingPriority . Animation ) ;
_ targetControl . SetValue ( _ parent . Property , _l astInterpValue , BindingPriority . LocalValue ) ;
}
_ targetObserver . OnCompleted ( ) ;
break ;
@ -267,10 +259,12 @@ namespace Avalonia.Animation
_ targetObserver = observer ;
return this ;
}
public void Dispose ( )
{
_ unsubscribe = true ;
_ currentState = KeyFramesStates . DISPOSED ;
_ currentState = KeyFramesStates . Disposed ;
}
}
}