@ -131,17 +131,23 @@ namespace Avalonia.Base.UnitTests.Animation
}
[Theory]
[InlineData(FillMode.Backward, 0, 0d, 0.7d)]
[InlineData(FillMode.Both, 0, 0d, 0.7d)]
[InlineData(FillMode.Forward, 100, 0d, 0.7d)]
[InlineData(FillMode.Backward, 0, 0.3d, 0.7d)]
[InlineData(FillMode.Both, 0, 0.3d, 0.7d)]
[InlineData(FillMode.Forward, 100, 0.3d, 0.7d)]
public void Check_FillMode_Start_Value ( FillMode fillMode , double target , double startCue , double endCue )
[InlineData(FillMode.Backward, 50.0, 0.0, 0.7, false)]
[InlineData(FillMode.Backward, 50.0, 0.0, 0.7, true )]
[InlineData(FillMode.Both, 50.0, 0.0, 0.7, false)]
[InlineData(FillMode.Both, 50.0, 0.0, 0.7, true )]
[InlineData(FillMode.Forward, 50.0, 0.0, 0.7, false)] // no delay but cue 0.0: the animation has started normally, explaining the 50.0 target without fill
[InlineData(FillMode.Forward, 100.0, 0.0, 0.7, true )]
[InlineData(FillMode.Backward, 50.0, 0.3, 0.7, false)]
[InlineData(FillMode.Backward, 50.0, 0.3, 0.7, true )]
[InlineData(FillMode.Both, 50.0, 0.3, 0.7, false)]
[InlineData(FillMode.Both, 50.0, 0.3, 0.7, true )]
[InlineData(FillMode.Forward, 100.0, 0.3, 0.7, false)]
[InlineData(FillMode.Forward, 100.0, 0.3, 0.7, true )]
public void Check_FillMode_Start_Value ( FillMode fillMode , double target , double startCue , double endCue , bool delay )
{
var keyframe1 = new KeyFrame ( )
{
Setters = { new Setter ( Layoutable . WidthProperty , 0d ) , } , Cue = new Cue ( startCue )
Setters = { new Setter ( Layoutable . WidthProperty , 5 0d ) , } , Cue = new Cue ( startCue )
} ;
var keyframe2 = new KeyFrame ( )
@ -152,7 +158,7 @@ namespace Avalonia.Base.UnitTests.Animation
var animation = new Animation ( )
{
Duration = TimeSpan . FromSeconds ( 1 0d ) ,
Delay = TimeSpan . FromSeconds ( 5d ) ,
Delay = delay ? TimeSpan . FromSeconds ( 5d ) : TimeSpan . Zero ,
FillMode = fillMode ,
Children = { keyframe1 , keyframe2 }
} ;
@ -169,28 +175,34 @@ namespace Avalonia.Base.UnitTests.Animation
}
[Theory]
[InlineData(FillMode.Backward, 100, 0.3d, 1d)]
[InlineData(FillMode.Both, 300, 0.3d, 1d)]
[InlineData(FillMode.Forward, 300, 0.3d, 1d)]
[InlineData(FillMode.Backward, 100, 0.3d, 0.7d)]
[InlineData(FillMode.Both, 300, 0.3d, 0.7d)]
[InlineData(FillMode.Forward, 300, 0.3d, 0.7d)]
public void Check_FillMode_End_Value ( FillMode fillMode , double target , double startCue , double endCue )
[InlineData(FillMode.Backward, 100.0, 0.3, 1.0, false)]
[InlineData(FillMode.Backward, 100.0, 0.3, 1.0, true )]
[InlineData(FillMode.Both, 300.0, 0.3, 1.0, false)]
[InlineData(FillMode.Both, 300.0, 0.3, 1.0, true )]
[InlineData(FillMode.Forward, 300.0, 0.3, 1.0, false)]
[InlineData(FillMode.Forward, 300.0, 0.3, 1.0, true )]
[InlineData(FillMode.Backward, 100.0, 0.3, 0.7, false)]
[InlineData(FillMode.Backward, 100.0, 0.3, 0.7, true )]
[InlineData(FillMode.Both, 300.0, 0.3, 0.7, false)]
[InlineData(FillMode.Both, 300.0, 0.3, 0.7, true )]
[InlineData(FillMode.Forward, 300.0, 0.3, 0.7, false)]
[InlineData(FillMode.Forward, 300.0, 0.3, 0.7, true )]
public void Check_FillMode_End_Value ( FillMode fillMode , double target , double startCue , double endCue , bool delay )
{
var keyframe1 = new KeyFrame ( )
{
Setters = { new Setter ( Layoutable . WidthProperty , 0d ) , } , Cue = new Cue ( 0.7d )
Setters = { new Setter ( Layoutable . WidthProperty , 0d ) , } , Cue = new Cue ( startCue )
} ;
var keyframe2 = new KeyFrame ( )
{
Setters = { new Setter ( Layoutable . WidthProperty , 3 0 0d ) , } , Cue = new Cue ( 1d )
Setters = { new Setter ( Layoutable . WidthProperty , 3 0 0d ) , } , Cue = new Cue ( endCue )
} ;
var animation = new Animation ( )
{
Duration = TimeSpan . FromSeconds ( 1 0d ) ,
Delay = TimeSpan . FromSeconds ( 5d ) ,
Delay = delay ? TimeSpan . FromSeconds ( 5d ) : TimeSpan . Zero ,
FillMode = fillMode ,
Children = { keyframe1 , keyframe2 }
} ;
@ -502,6 +514,96 @@ namespace Avalonia.Base.UnitTests.Animation
animationRun . Wait ( ) ;
}
[Theory]
[InlineData(0, 1, 2)]
[InlineData(0, 2, 1)]
[InlineData(1, 0, 2)]
[InlineData(1, 2, 0)]
[InlineData(2, 0, 1)]
[InlineData(2, 1, 0)]
public void KeyFrames_Order_Does_Not_Matter ( int index0 , int index1 , int index2 )
{
static KeyFrame CreateKeyFrame ( double width , double cue )
= > new ( )
{
Setters = { new Setter ( Layoutable . WidthProperty , width ) } ,
Cue = new Cue ( cue )
} ;
var keyFrames = new [ ]
{
CreateKeyFrame ( 1 0 0.0 , 0.0 ) ,
CreateKeyFrame ( 2 0 0.0 , 0.5 ) ,
CreateKeyFrame ( 3 0 0.0 , 1.0 )
} ;
var animation = new Animation
{
Duration = TimeSpan . FromSeconds ( 1.0 ) ,
IterationCount = new IterationCount ( 1 ) ,
Easing = new LinearEasing ( ) ,
FillMode = FillMode . Forward
} ;
animation . Children . Add ( keyFrames [ index0 ] ) ;
animation . Children . Add ( keyFrames [ index1 ] ) ;
animation . Children . Add ( keyFrames [ index2 ] ) ;
var border = new Border
{
Height = 1 0 0.0 ,
Width = 5 0.0
} ;
var clock = new TestClock ( ) ;
animation . RunAsync ( border , clock ) ;
clock . Step ( TimeSpan . Zero ) ;
Assert . Equal ( 1 0 0.0 , border . Width ) ;
clock . Step ( TimeSpan . FromSeconds ( 0.5 ) ) ;
Assert . Equal ( 2 0 0.0 , border . Width ) ;
clock . Step ( TimeSpan . FromSeconds ( 1.0 ) ) ;
Assert . Equal ( 3 0 0.0 , border . Width ) ;
}
[Theory]
[InlineData(0.0)]
[InlineData(0.5)]
[InlineData(1.0)]
public void Single_KeyFrame_Works ( double cue )
{
var animation = new Animation
{
Duration = TimeSpan . FromSeconds ( 1.0 ) ,
IterationCount = new IterationCount ( 1 ) ,
Easing = new LinearEasing ( ) ,
FillMode = FillMode . Forward ,
Children =
{
new KeyFrame
{
Setters = { new Setter ( Layoutable . WidthProperty , 1 0 0.0 ) } ,
Cue = new Cue ( cue )
}
}
} ;
var border = new Border
{
Height = 1 0 0.0 ,
Width = 5 0.0
} ;
var clock = new TestClock ( ) ;
animation . RunAsync ( border , clock ) ;
clock . Step ( TimeSpan . Zero ) ;
clock . Step ( TimeSpan . FromSeconds ( cue ) ) ;
Assert . Equal ( 1 0 0.0 , border . Width ) ;
}
private sealed class FakeAnimator : InterpolatingAnimator < double >
{
public double LastProgress { get ; set ; } = double . NaN ;