@ -19,7 +19,7 @@ namespace Avalonia.Animation
/// <summary>
/// List of type-converted keyframes.
/// </summary>
private readonly Sorted List< double , ( AnimatorKeyFrame , bool isNeutral ) > _ convertedKeyframes = new Sorted List< double , ( AnimatorKeyFrame , bool ) > ( ) ;
private readonly List < AnimatorKeyFrame > _ convertedKeyframes = new List < AnimatorKeyFrame > ( ) ;
private bool isVerfifiedAndConverted ;
@ -58,41 +58,49 @@ namespace Avalonia.Animation
/// <param name="t">The time parameter, relative to the total animation time</param>
protected ( double IntraKFTime , KeyFramePair < T > KFPair ) GetKFPairAndIntraKFTime ( double t )
{
KeyValuePair < double , ( AnimatorKeyFrame frame , bool isNeutral ) > f irstCue , lastCue ;
AnimatorKeyFrame firstCue , lastCue ;
int kvCount = _ convertedKeyframes . Count ;
if ( kvCount > 2 )
{
if ( DoubleUtils . AboutEqual ( t , 0.0 ) | | t < 0.0 )
{
firstCue = _ convertedKeyframes . First ( ) ;
lastCue = _ convertedKeyframes . Skip ( 1 ) . First ( ) ;
firstCue = _ convertedKeyframes [ 0 ] ;
lastCue = _ convertedKeyframes [ 1 ] ;
}
else if ( DoubleUtils . AboutEqual ( t , 1.0 ) | | t > 1.0 )
{
firstCue = _ convertedKeyframes . Skip ( kvCount - 2 ) . First ( ) ;
lastCue = _ convertedKeyframes . Last ( ) ;
firstCue = _ convertedKeyframes [ _ convertedKeyframes . Count - 2 ] ;
lastCue = _ convertedKeyframes [ _ convertedKeyframes . Count - 1 ] ;
}
else
{
firstCue = _ convertedKeyframes . Last ( j = > j . Key < = t ) ;
lastCue = _ convertedKeyframes . First ( j = > j . Key > = t ) ;
( double time , int index ) maxval = ( 0.0d , 0 ) ;
for ( int i = 0 ; i < _ convertedKeyframes . Count ; i + + )
{
var comp = _ convertedKeyframes [ i ] . Cue . CueValue ;
if ( t > = comp )
{
maxval = ( comp , i ) ;
}
}
firstCue = _ convertedKeyframes [ maxval . index ] ;
lastCue = _ convertedKeyframes [ maxval . index + 1 ] ;
}
}
else
{
firstCue = _ convertedKeyframes . First ( ) ;
lastCue = _ convertedKeyframes . Last ( ) ;
firstCue = _ convertedKeyframes [ 0 ] ;
lastCue = _ convertedKeyframes [ 1 ] ;
}
double t0 = firstCue . Key ;
double t1 = lastCue . Key ;
double t0 = firstCue . Cue . CueValue ;
double t1 = lastCue . Cue . CueValue ;
var intraframeTime = ( t - t0 ) / ( t1 - t0 ) ;
var firstFrameData = ( firstCue . Value . frame . GetTypedValue < T > ( ) , firstCue . Val ue . isNeutral ) ;
var lastFrameData = ( lastCue . Value . frame . GetTypedValue < T > ( ) , lastCue . Val ue . isNeutral ) ;
var firstFrameData = ( firstCue . GetTypedValue < T > ( ) , firstCue . isNeutral ) ;
var lastFrameData = ( lastCue . GetTypedValue < T > ( ) , lastCue . isNeutral ) ;
return ( intraframeTime , new KeyFramePair < T > ( firstFrameData , lastFrameData ) ) ;
}
/// <summary>
/// Runs the KeyFrames Animation.
/// </summary>
@ -113,16 +121,25 @@ namespace Avalonia.Animation
protected abstract T DoInterpolation ( double time , T neutralValue ) ;
/// <summary>
/// Verifies and conve rts keyframe values according to this class's target type.
/// Verifies, converts and so rts keyframe values according to this class's target type.
/// </summary>
private void VerifyConvertKeyFrames ( )
{
foreach ( AnimatorKeyFrame keyframe in this )
{
_ convertedKeyframes . Add ( keyframe . Cue . CueValue , ( keyframe , false ) ) ;
_ convertedKeyframes . Add ( keyframe ) ;
}
AddNeutralKeyFramesIfNeeded ( ) ;
var copy = _ convertedKeyframes . ToList ( ) . OrderBy ( p = > p . Cue . CueValue ) ;
_ convertedKeyframes . Clear ( ) ;
foreach ( AnimatorKeyFrame keyframe in copy )
{
_ convertedKeyframes . Add ( keyframe ) ;
}
isVerfifiedAndConverted = true ;
}
@ -133,13 +150,13 @@ namespace Avalonia.Animation
hasStartKey = hasEndKey = false ;
// Check if there's start and end keyframes.
foreach ( var converted in _ convertedKeyframes . Key s )
foreach ( var frame in _ convertedKeyframes )
{
if ( DoubleUtils . AboutEqual ( converted , 0.0 ) )
if ( DoubleUtils . AboutEqual ( frame . Cue . CueValue , 0.0 ) )
{
hasStartKey = true ;
}
else if ( DoubleUtils . AboutEqual ( converted , 1.0 ) )
else if ( DoubleUtils . AboutEqual ( frame . Cue . CueValue , 1.0 ) )
{
hasEndKey = true ;
}
@ -153,12 +170,12 @@ namespace Avalonia.Animation
{
if ( ! hasStartKey )
{
_ convertedKeyframes . Add ( 0.0d , ( new AnimatorKeyFrame { Value = default ( T ) } , true ) ) ;
_ convertedKeyframes . Add ( new AnimatorKeyFrame ( null , new Cue ( 0.0d ) ) { Value = default ( T ) , isNeutral = true } ) ;
}
if ( ! hasEndKey )
{
_ convertedKeyframes . Add ( 1.0d , ( new AnimatorKeyFrame { Value = default ( T ) } , true ) ) ;
_ convertedKeyframes . Add ( new AnimatorKeyFrame ( null , new Cue ( 1.0d ) ) { Value = default ( T ) , isNeutral = true } ) ;
}
}
}