diff --git a/src/Avalonia.Animation/Animators/Animator`1.cs b/src/Avalonia.Animation/Animators/Animator`1.cs
index e143d01e95..e79aa128d6 100644
--- a/src/Avalonia.Animation/Animators/Animator`1.cs
+++ b/src/Avalonia.Animation/Animators/Animator`1.cs
@@ -78,21 +78,21 @@ namespace Avalonia.Animation.Animators
double t0 = firstKeyframe.Cue.CueValue;
double t1 = lastKeyframe.Cue.CueValue;
- double fraction = (animationTime - t0) / (t1 - t0);
+ double progress = (animationTime - t0) / (t1 - t0);
- T from, to;
+ T oldValue, newValue;
if (firstKeyframe.isNeutral)
- from = neutralValue;
+ oldValue = neutralValue;
else
- from = (T)firstKeyframe.Value;
+ oldValue = (T)firstKeyframe.Value;
if (lastKeyframe.isNeutral)
- to = neutralValue;
+ newValue = neutralValue;
else
- to = (T)lastKeyframe.Value;
+ newValue = (T)lastKeyframe.Value;
- return Interpolate(fraction, from, to);
+ return Interpolate(progress, oldValue, newValue);
}
private int FindClosestBeforeKeyFrame(double time)
diff --git a/src/Avalonia.Animation/Animators/DoubleAnimator.cs b/src/Avalonia.Animation/Animators/DoubleAnimator.cs
index 4d72c52ea3..68975be9d0 100644
--- a/src/Avalonia.Animation/Animators/DoubleAnimator.cs
+++ b/src/Avalonia.Animation/Animators/DoubleAnimator.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Animation.Animators
///
public override double Interpolate(double progress, double oldValue, double newValue)
{
- return oldValue + (progress) * (newValue - oldValue);
+ return ((newValue - oldValue) * progress) + oldValue;
}
}
}
diff --git a/src/Avalonia.Animation/Transitions/DoubleTransition.cs b/src/Avalonia.Animation/Transitions/DoubleTransition.cs
index 23445e1122..d7dd93c743 100644
--- a/src/Avalonia.Animation/Transitions/DoubleTransition.cs
+++ b/src/Avalonia.Animation/Transitions/DoubleTransition.cs
@@ -14,9 +14,12 @@ namespace Avalonia.Animation
///
public override IObservable DoTransition(IObservable progress, double oldValue, double newValue)
{
- var delta = newValue - oldValue;
return progress
- .Select(p => Easing.Ease(p) * delta + oldValue);
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+ return ((newValue - oldValue) * f) + oldValue;
+ });
}
}
}
diff --git a/src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs
new file mode 100644
index 0000000000..8129bd38de
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs
@@ -0,0 +1,27 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class CornerRadiusAnimator : Animator
+ {
+ public override CornerRadius Interpolate(double progress, CornerRadius oldValue, CornerRadius newValue)
+ {
+ var deltaTL = newValue.TopLeft - oldValue.TopLeft;
+ var deltaTR = newValue.TopRight - oldValue.TopRight;
+ var deltaBR = newValue.BottomRight - oldValue.BottomRight;
+ var deltaBL = newValue.BottomLeft - oldValue.BottomLeft;
+
+ var nTL = progress * deltaTL + oldValue.TopLeft;
+ var nTR = progress * deltaTR + oldValue.TopRight;
+ var nBR = progress * deltaBR + oldValue.BottomRight;
+ var nBL = progress * deltaBL + oldValue.BottomLeft;
+
+ return new CornerRadius(nTL, nTR, nBR, nBL);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs
index a11481c924..793691e5ac 100644
--- a/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs
+++ b/src/Avalonia.Visuals/Animation/Animators/PointAnimator.cs
@@ -10,13 +10,8 @@ namespace Avalonia.Animation.Animators
public class PointAnimator : Animator
{
public override Point Interpolate(double progress, Point oldValue, Point newValue)
- {
- var deltaX = newValue.X - oldValue.Y;
- var deltaY = newValue.X - oldValue.Y;
-
- var nX = progress * deltaX + oldValue.X;
- var nY = progress * deltaY + oldValue.Y;
- return new Point(nX, nY);
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
}
}
}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs
new file mode 100644
index 0000000000..bb4f343e4a
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class SizeAnimator : Animator
+ {
+ public override Size Interpolate(double progress, Size oldValue, Size newValue)
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs
index ccc200d64f..a6ae95ce3f 100644
--- a/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs
+++ b/src/Avalonia.Visuals/Animation/Animators/ThicknessAnimator.cs
@@ -11,17 +11,7 @@ namespace Avalonia.Animation.Animators
{
public override Thickness Interpolate(double progress, Thickness oldValue, Thickness newValue)
{
- var deltaL = newValue.Left - oldValue.Left;
- var deltaT = newValue.Top - oldValue.Top;
- var deltaR = newValue.Right - oldValue.Right;
- var deltaB = newValue.Bottom - oldValue.Bottom;
-
- var nL = progress * deltaL + oldValue.Left;
- var nT = progress * deltaT + oldValue.Right;
- var nR = progress * deltaR + oldValue.Top;
- var nB = progress * deltaB + oldValue.Bottom;
-
- return new Thickness(nL, nT, nR, nB);
+ return ((newValue - oldValue) * progress) + oldValue;
}
}
}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs b/src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs
new file mode 100644
index 0000000000..e1ffb60971
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs
@@ -0,0 +1,17 @@
+using System;
+using Avalonia.Logging;
+using Avalonia.Media;
+
+namespace Avalonia.Animation.Animators
+{
+ ///
+ /// Animator that handles properties.
+ ///
+ public class VectorAnimator : Animator
+ {
+ public override Vector Interpolate(double progress, Vector oldValue, Vector newValue)
+ {
+ return ((newValue - oldValue) * progress) + oldValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs
new file mode 100644
index 0000000000..4b6703133d
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs
@@ -0,0 +1,36 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Reactive.Linq;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Transition class that handles with type.
+ ///
+ public class CornerRadiusTransition : Transition
+ {
+ ///
+ public override IObservable DoTransition(IObservable progress, CornerRadius oldValue, CornerRadius newValue)
+ {
+ return progress
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+
+ var deltaTL = newValue.TopLeft - oldValue.TopLeft;
+ var deltaTR = newValue.TopRight - oldValue.TopRight;
+ var deltaBR = newValue.BottomRight - oldValue.BottomRight;
+ var deltaBL = newValue.BottomLeft - oldValue.BottomLeft;
+
+ var nTL = f * deltaTL + oldValue.TopLeft;
+ var nTR = f * deltaTR + oldValue.TopRight;
+ var nBR = f * deltaBR + oldValue.BottomRight;
+ var nBL = f * deltaBL + oldValue.BottomLeft;
+
+ return new CornerRadius(nTL, nTR, nBR, nBL);
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
index a883c517dd..ea0000f960 100644
--- a/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
+++ b/src/Avalonia.Visuals/Animation/Transitions/PointTransition.cs
@@ -14,16 +14,11 @@ namespace Avalonia.Animation
///
public override IObservable DoTransition(IObservable progress, Point oldValue, Point newValue)
{
- var deltaX = newValue.X - oldValue.Y;
- var deltaY = newValue.X - oldValue.Y;
-
return progress
.Select(p =>
{
var f = Easing.Ease(p);
- var nX = f * deltaX + oldValue.X;
- var nY = f * deltaY + oldValue.Y;
- return new Point(nX, nY);
+ return ((newValue - oldValue) * f) + oldValue;
});
}
}
diff --git a/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs
new file mode 100644
index 0000000000..5de59edc53
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs
@@ -0,0 +1,25 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Reactive.Linq;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Transition class that handles with type.
+ ///
+ public class SizeTransition : Transition
+ {
+ ///
+ public override IObservable DoTransition(IObservable progress, Size oldValue, Size newValue)
+ {
+ return progress
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+ return ((newValue - oldValue) * f) + oldValue;
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
index 6c2ca22b74..e6b5e8904b 100644
--- a/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
+++ b/src/Avalonia.Visuals/Animation/Transitions/ThicknessTransition.cs
@@ -14,20 +14,11 @@ namespace Avalonia.Animation
///
public override IObservable DoTransition(IObservable progress, Thickness oldValue, Thickness newValue)
{
- var deltaL = newValue.Left - oldValue.Left;
- var deltaT = newValue.Top - oldValue.Top;
- var deltaR = newValue.Right - oldValue.Right;
- var deltaB = newValue.Bottom - oldValue.Bottom;
-
return progress
- .Select(p =>
+ .Select(p =>
{
var f = Easing.Ease(p);
- var nL = f * deltaL + oldValue.Left;
- var nT = f * deltaT + oldValue.Right;
- var nR = f * deltaR + oldValue.Top;
- var nB = f * deltaB + oldValue.Bottom;
- return new Thickness(nL, nT, nR, nB);
+ return ((newValue - oldValue) * f) + oldValue;
});
}
}
diff --git a/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs b/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs
new file mode 100644
index 0000000000..5271c1378b
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs
@@ -0,0 +1,25 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using System.Reactive.Linq;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Transition class that handles with type.
+ ///
+ public class VectorTransition : Transition
+ {
+ ///
+ public override IObservable DoTransition(IObservable progress, Vector oldValue, Vector newValue)
+ {
+ return progress
+ .Select(p =>
+ {
+ var f = Easing.Ease(p);
+ return ((newValue - oldValue) * f) + oldValue;
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/CornerRadius.cs b/src/Avalonia.Visuals/CornerRadius.cs
index 2d41acb5bc..09163a2dac 100644
--- a/src/Avalonia.Visuals/CornerRadius.cs
+++ b/src/Avalonia.Visuals/CornerRadius.cs
@@ -3,12 +3,18 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
{
public struct CornerRadius
{
+ static CornerRadius()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(CornerRadius).IsAssignableFrom(prop.PropertyType));
+ }
+
public CornerRadius(double uniformRadius)
{
TopLeft = TopRight = BottomLeft = BottomRight = uniformRadius;
diff --git a/src/Avalonia.Visuals/Size.cs b/src/Avalonia.Visuals/Size.cs
index 8057571bf1..782c5ea67b 100644
--- a/src/Avalonia.Visuals/Size.cs
+++ b/src/Avalonia.Visuals/Size.cs
@@ -3,6 +3,7 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using Avalonia.Utilities;
namespace Avalonia
@@ -12,6 +13,11 @@ namespace Avalonia
///
public readonly struct Size
{
+ static Size()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Size).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// A size representing infinity.
///
diff --git a/src/Avalonia.Visuals/Thickness.cs b/src/Avalonia.Visuals/Thickness.cs
index 9d4ee2d704..830ee4666e 100644
--- a/src/Avalonia.Visuals/Thickness.cs
+++ b/src/Avalonia.Visuals/Thickness.cs
@@ -141,6 +141,36 @@ namespace Avalonia
a.Bottom + b.Bottom);
}
+ ///
+ /// Subtracts two Thicknesses.
+ ///
+ /// The first thickness.
+ /// The second thickness.
+ /// The equality.
+ public static Thickness operator -(Thickness a, Thickness b)
+ {
+ return new Thickness(
+ a.Left - b.Left,
+ a.Top - b.Top,
+ a.Right - b.Right,
+ a.Bottom - b.Bottom);
+ }
+
+ ///
+ /// Multiplies a Thickness to a scalar.
+ ///
+ /// The thickness.
+ /// The scalar.
+ /// The equality.
+ public static Thickness operator *(Thickness a, double b)
+ {
+ return new Thickness(
+ a.Left * b,
+ a.Top * b,
+ a.Right * b,
+ a.Bottom * b);
+ }
+
///
/// Adds a Thickness to a Size.
///
diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs
index c2db17cd86..2f1690184d 100644
--- a/src/Avalonia.Visuals/Vector.cs
+++ b/src/Avalonia.Visuals/Vector.cs
@@ -3,6 +3,7 @@
using System;
using System.Globalization;
+using Avalonia.Animation.Animators;
using JetBrains.Annotations;
namespace Avalonia
@@ -12,6 +13,11 @@ namespace Avalonia
///
public readonly struct Vector
{
+ static Vector()
+ {
+ Animation.Animation.RegisterAnimator(prop => typeof(Vector).IsAssignableFrom(prop.PropertyType));
+ }
+
///
/// The X vector.
///
@@ -60,7 +66,7 @@ namespace Avalonia
/// The dot product
public static double operator *(Vector a, Vector b)
{
- return a.X*b.X + a.Y*b.Y;
+ return a.X * b.X + a.Y * b.Y;
}
///
@@ -88,7 +94,7 @@ namespace Avalonia
///
/// Length of the vector
///
- public double Length => Math.Sqrt(X*X + Y*Y);
+ public double Length => Math.Sqrt(X * X + Y * Y);
///
/// Negates a vector.