KeySplineTests.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using Avalonia.Animation;
  3. using Avalonia.Animation.Easings;
  4. using Avalonia.Controls.Shapes;
  5. using Avalonia.Media;
  6. using Avalonia.Styling;
  7. using Xunit;
  8. namespace Avalonia.Base.UnitTests.Animation
  9. {
  10. public class KeySplineTests
  11. {
  12. [Theory]
  13. [InlineData("1,2 3,4")]
  14. [InlineData("1 2 3 4")]
  15. [InlineData("1 2,3 4")]
  16. [InlineData("1,2,3,4")]
  17. public void Can_Parse_KeySpline_Via_TypeConverter(string input)
  18. {
  19. var conv = new KeySplineTypeConverter();
  20. var keySpline = (KeySpline)conv.ConvertFrom(input);
  21. Assert.Equal(1, keySpline.ControlPointX1);
  22. Assert.Equal(2, keySpline.ControlPointY1);
  23. Assert.Equal(3, keySpline.ControlPointX2);
  24. Assert.Equal(4, keySpline.ControlPointY2);
  25. }
  26. [Theory]
  27. [InlineData("1,2F,3,4")]
  28. [InlineData("Foo,Bar,Fee,Buzz")]
  29. public void Can_Handle_Invalid_String_KeySpline_Via_TypeConverter(string input)
  30. {
  31. var conv = new KeySplineTypeConverter();
  32. Assert.ThrowsAny<Exception>(() => (KeySpline)conv.ConvertFrom(input));
  33. }
  34. [Theory]
  35. [InlineData(0.00)]
  36. [InlineData(0.50)]
  37. [InlineData(1.00)]
  38. public void KeySpline_X_Values_In_Range_Do_Not_Throw(double input)
  39. {
  40. var keySpline = new KeySpline();
  41. keySpline.ControlPointX1 = input; // no exception will be thrown -- test will fail if exception thrown
  42. keySpline.ControlPointX2 = input; // no exception will be thrown -- test will fail if exception thrown
  43. }
  44. [Theory]
  45. [InlineData(-0.01)]
  46. [InlineData(1.01)]
  47. public void KeySpline_X_Values_Cannot_Be_Out_Of_Range(double input)
  48. {
  49. var keySpline = new KeySpline();
  50. Assert.Throws<ArgumentException>(() => keySpline.ControlPointX1 = input);
  51. Assert.Throws<ArgumentException>(() => keySpline.ControlPointX2 = input);
  52. }
  53. [Fact]
  54. public void SplineEasing_Can_Be_Mutated()
  55. {
  56. var easing = new SplineEasing();
  57. Assert.Equal(0, easing.Ease(0));
  58. Assert.Equal(1, easing.Ease(1));
  59. easing.X1 = 0.25;
  60. easing.Y1 = 0.5;
  61. easing.X2 = 0.75;
  62. easing.Y2 = 1.0;
  63. Assert.NotEqual(0.5, easing.Ease(0.5));
  64. }
  65. /*
  66. To get the test values for the KeySpline test, you can:
  67. 1) Grab the WPF sample for KeySpline animations from https://github.com/microsoft/WPF-Samples/tree/master/Animation/KeySplineAnimations
  68. 2) Add the following xaml somewhere:
  69. <Button Content="Capture"
  70. Click="Button_Click"/>
  71. <ScrollViewer VerticalScrollBarVisibility="Visible">
  72. <TextBlock Name="CaptureData"
  73. Text="---"
  74. TextWrapping="Wrap" />
  75. </ScrollViewer>
  76. 3) Add the following code to the code behind:
  77. private void Button_Click(object sender, RoutedEventArgs e)
  78. {
  79. CaptureData.Text += string.Format("\n{0} | {1}", myTranslateTransform3D.OffsetX, (TimeSpan)ExampleStoryboard.GetCurrentTime(this));
  80. CaptureData.Text +=
  81. "\nKeySpline=\"" + mySplineKeyFrame.KeySpline.ControlPoint1.X.ToString() + "," +
  82. mySplineKeyFrame.KeySpline.ControlPoint1.Y.ToString() + " " +
  83. mySplineKeyFrame.KeySpline.ControlPoint2.X.ToString() + "," +
  84. mySplineKeyFrame.KeySpline.ControlPoint2.Y.ToString() + "\"";
  85. CaptureData.Text += "\n-----";
  86. }
  87. 4) Run the app, mess with the slider values, then click the button to capture output values
  88. **/
  89. [Fact]
  90. public void Check_KeySpline_Handled_properly()
  91. {
  92. var keyframe1 = new KeyFrame()
  93. {
  94. Setters =
  95. {
  96. new Setter(RotateTransform.AngleProperty, -2.5d),
  97. },
  98. KeyTime = TimeSpan.FromSeconds(0)
  99. };
  100. var keyframe2 = new KeyFrame()
  101. {
  102. Setters =
  103. {
  104. new Setter(RotateTransform.AngleProperty, 2.5d),
  105. },
  106. KeyTime = TimeSpan.FromSeconds(5),
  107. KeySpline = new KeySpline(0.1123555056179775,
  108. 0.657303370786517,
  109. 0.8370786516853934,
  110. 0.499999999999999999)
  111. };
  112. var animation = new Avalonia.Animation.Animation()
  113. {
  114. Duration = TimeSpan.FromSeconds(5),
  115. Children =
  116. {
  117. keyframe1,
  118. keyframe2
  119. },
  120. IterationCount = new IterationCount(5),
  121. PlaybackDirection = PlaybackDirection.Alternate
  122. };
  123. var rotateTransform = new RotateTransform(-2.5);
  124. var rect = new Rectangle()
  125. {
  126. RenderTransform = rotateTransform
  127. };
  128. var clock = new TestClock();
  129. var animationRun = animation.RunAsync(rect, clock);
  130. // position is what you'd expect at end and beginning
  131. clock.Step(TimeSpan.Zero);
  132. Assert.Equal(rotateTransform.Angle, -2.5);
  133. clock.Step(TimeSpan.FromSeconds(5));
  134. Assert.Equal(rotateTransform.Angle, 2.5);
  135. // test some points in between end and beginning
  136. var tolerance = 0.01;
  137. clock.Step(TimeSpan.Parse("00:00:10.0153932"));
  138. var expected = -2.4122350198982545;
  139. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  140. clock.Step(TimeSpan.Parse("00:00:11.2655407"));
  141. expected = -0.37153223002125113;
  142. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  143. clock.Step(TimeSpan.Parse("00:00:12.6158773"));
  144. expected = 0.3967885416786294;
  145. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  146. clock.Step(TimeSpan.Parse("00:00:14.6495256"));
  147. expected = 1.8016358493761722;
  148. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  149. }
  150. [Fact]
  151. public void Check_KeySpline_Parsing_Is_Correct()
  152. {
  153. var keyframe1 = new KeyFrame()
  154. {
  155. Setters =
  156. {
  157. new Setter(RotateTransform.AngleProperty, -2.5d),
  158. },
  159. KeyTime = TimeSpan.FromSeconds(0)
  160. };
  161. var keyframe2 = new KeyFrame()
  162. {
  163. Setters =
  164. {
  165. new Setter(RotateTransform.AngleProperty, 2.5d),
  166. },
  167. KeyTime = TimeSpan.FromSeconds(5),
  168. };
  169. var animation = new Avalonia.Animation.Animation()
  170. {
  171. Duration = TimeSpan.FromSeconds(5),
  172. Children =
  173. {
  174. keyframe1,
  175. keyframe2
  176. },
  177. IterationCount = new IterationCount(5),
  178. PlaybackDirection = PlaybackDirection.Alternate,
  179. Easing = Easing.Parse("0.1123555056179775,0.657303370786517,0.8370786516853934,0.499999999999999999")
  180. };
  181. var rotateTransform = new RotateTransform(-2.5);
  182. var rect = new Rectangle()
  183. {
  184. RenderTransform = rotateTransform
  185. };
  186. var clock = new TestClock();
  187. var animationRun = animation.RunAsync(rect, clock);
  188. // position is what you'd expect at end and beginning
  189. clock.Step(TimeSpan.Zero);
  190. Assert.Equal(rotateTransform.Angle, -2.5);
  191. clock.Step(TimeSpan.FromSeconds(5));
  192. Assert.Equal(rotateTransform.Angle, 2.5);
  193. // test some points in between end and beginning
  194. var tolerance = 0.01;
  195. clock.Step(TimeSpan.Parse("00:00:10.0153932"));
  196. var expected = -2.4122350198982545;
  197. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  198. clock.Step(TimeSpan.Parse("00:00:11.2655407"));
  199. expected = -0.37153223002125113;
  200. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  201. clock.Step(TimeSpan.Parse("00:00:12.6158773"));
  202. expected = 0.3967885416786294;
  203. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  204. clock.Step(TimeSpan.Parse("00:00:14.6495256"));
  205. expected = 1.8016358493761722;
  206. Assert.True(Math.Abs(rotateTransform.Angle - expected) <= tolerance);
  207. }
  208. }
  209. }