Browse Source

address review and add unit tests

pull/4180/head
Jumar Macato 6 years ago
parent
commit
ea12af0778
No known key found for this signature in database GPG Key ID: B19884DAC3A5BF3F
  1. 38
      src/Avalonia.Animation/Easing/Easing.cs
  2. 10
      src/Avalonia.Animation/Easing/SplineEasing.cs
  3. 14
      src/Avalonia.Animation/KeySpline.cs
  4. 85
      tests/Avalonia.Animation.UnitTests/KeySplineTests.cs

38
src/Avalonia.Animation/Easing/Easing.cs

@ -31,28 +31,34 @@ namespace Avalonia.Animation.Easings
var k = e.Split(',');
if (k.Count() != 4)
{
throw new FormatException($"SplineEasing only accepts exactly 4 arguments.");
}
var splineEase = new SplineEasing();
if (double.TryParse(k[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var x1))
splineEase.X1 = x1;
else
throw new FormatException($"Invalid SplineEasing control point X1 value: {k[0]}");
var setterArray = new Action<double>[4]
{
(x) => splineEase.X1 = x,
if (double.TryParse(k[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var y1))
splineEase.Y1 = y1;
else
throw new FormatException($"Invalid SplineEasing control point Y1 value: {k[1]}");
(x) => splineEase.Y1 = x,
if (double.TryParse(k[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var x2))
splineEase.X2 = x2;
else
throw new FormatException($"Invalid SplineEasing control point Y1 value: {k[2]}");
(x) => splineEase.X2 = x,
if (double.TryParse(k[3], NumberStyles.Any, CultureInfo.InvariantCulture, out var y2))
splineEase.Y2 = y2;
else
throw new FormatException($"Invalid SplineEasing control point Y1 value: {k[3]}");
(x) => splineEase.Y2 = x
};
for (int i = 0; i < 4; i++)
{
if (double.TryParse(k[i], NumberStyles.Any, CultureInfo.InvariantCulture, out var x))
{
setterArray[i](x);
}
else
{
throw new FormatException($"Parameter string \"{k[i]}\" is not a double.");
}
}
return splineEase;
}

10
src/Avalonia.Animation/Easing/SplineEasing.cs

@ -17,7 +17,8 @@ namespace Avalonia.Animation.Easings
get => _x1;
set
{
_x1 = value; _internalKeySpline.ControlPointX1 = _x1;
_x1 = value;
_internalKeySpline.ControlPointX1 = _x1;
}
}
@ -30,14 +31,15 @@ namespace Avalonia.Animation.Easings
get => _y1;
set
{
_y1 = value; _internalKeySpline.ControlPointY1 = _y1;
_y1 = value;
_internalKeySpline.ControlPointY1 = _y1;
}
}
/// <summary>
/// X coordinate of the second control point
/// </summary>
private double _x2 = 1.0d;
private double _x2;
public double X2
{
get => _x2;
@ -51,7 +53,7 @@ namespace Avalonia.Animation.Easings
/// <summary>
/// Y coordinate of the second control point
/// </summary>
private double _y2 = 1.0d;
private double _y2;
public double Y2
{
get => _y2;

14
src/Avalonia.Animation/KeySpline.cs

@ -98,6 +98,7 @@ namespace Avalonia.Animation
if (IsValidXValue(value))
{
_controlPointX1 = value;
_isDirty = true;
}
else
{
@ -112,7 +113,11 @@ namespace Avalonia.Animation
public double ControlPointY1
{
get => _controlPointY1;
set => _controlPointY1 = value;
set
{
_controlPointY1 = value;
_isDirty = true;
}
}
/// <summary>
@ -126,6 +131,7 @@ namespace Avalonia.Animation
if (IsValidXValue(value))
{
_controlPointX2 = value;
_isDirty = true;
}
else
{
@ -140,7 +146,11 @@ namespace Avalonia.Animation
public double ControlPointY2
{
get => _controlPointY2;
set => _controlPointY2 = value;
set
{
_controlPointY2 = value;
_isDirty = true;
}
}
/// <summary>

85
tests/Avalonia.Animation.UnitTests/KeySplineTests.cs

@ -1,4 +1,5 @@
using System;
using Avalonia.Animation.Easings;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using Avalonia.Styling;
@ -46,6 +47,22 @@ namespace Avalonia.Animation.UnitTests
Assert.Throws<ArgumentException>(() => keySpline.ControlPointX2 = input);
}
[Fact]
public void SplineEasing_Can_Be_Mutated()
{
var easing = new SplineEasing();
Assert.Equal(0, easing.Ease(0));
Assert.Equal(1, easing.Ease(1));
easing.X1 = 0.25;
easing.Y1 = 0.5;
easing.X2 = 0.75;
easing.Y2 = 1.0;
Assert.NotEqual(0.5, easing.Ease(0.5));
}
/*
To get the test values for the KeySpline test, you can:
1) Grab the WPF sample for KeySpline animations from https://github.com/microsoft/WPF-Samples/tree/master/Animation/KeySplineAnimations
@ -141,5 +158,73 @@ namespace Avalonia.Animation.UnitTests
expected = 1.8016358493761722;
Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
}
[Fact]
public void Check_KeySpline_Parsing_Is_Correct()
{
var keyframe1 = new KeyFrame()
{
Setters =
{
new Setter(RotateTransform.AngleProperty, -2.5d),
},
KeyTime = TimeSpan.FromSeconds(0)
};
var keyframe2 = new KeyFrame()
{
Setters =
{
new Setter(RotateTransform.AngleProperty, 2.5d),
},
KeyTime = TimeSpan.FromSeconds(5),
};
var animation = new Animation()
{
Duration = TimeSpan.FromSeconds(5),
Children =
{
keyframe1,
keyframe2
},
IterationCount = new IterationCount(5),
PlaybackDirection = PlaybackDirection.Alternate,
Easing = Easing.Parse("0.1123555056179775,0.657303370786517,0.8370786516853934,0.499999999999999999")
};
var rotateTransform = new RotateTransform(-2.5);
var rect = new Rectangle()
{
RenderTransform = rotateTransform
};
var clock = new TestClock();
var animationRun = animation.RunAsync(rect, clock);
// position is what you'd expect at end and beginning
clock.Step(TimeSpan.Zero);
Assert.Equal(rotateTransform.Angle, -2.5);
clock.Step(TimeSpan.FromSeconds(5));
Assert.Equal(rotateTransform.Angle, 2.5);
// test some points in between end and beginning
var tolerance = 0.01;
clock.Step(TimeSpan.Parse("00:00:10.0153932"));
var expected = -2.4122350198982545;
Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
clock.Step(TimeSpan.Parse("00:00:11.2655407"));
expected = -0.37153223002125113;
Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
clock.Step(TimeSpan.Parse("00:00:12.6158773"));
expected = 0.3967885416786294;
Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
clock.Step(TimeSpan.Parse("00:00:14.6495256"));
expected = 1.8016358493761722;
Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
}
}
}

Loading…
Cancel
Save