From 626f220e509572fba57686137c8f8a0e815dccbf Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 8 Dec 2018 20:56:06 +0800 Subject: [PATCH] Added animators for Size,Point, Vector and CornerRadius --- .../Animators/Animator`1.cs | 14 ++++---- .../Animators/DoubleAnimator.cs | 2 +- .../Transitions/DoubleTransition.cs | 7 ++-- .../Animators/CornerRadiusAnimator.cs | 27 ++++++++++++++ .../Animation/Animators/PointAnimator.cs | 9 ++--- .../Animation/Animators/SizeAnimator.cs | 17 +++++++++ .../Animation/Animators/ThicknessAnimator.cs | 12 +------ .../Animation/Animators/VectorAnimator.cs | 17 +++++++++ .../Transitions/CornerRadiusTransition.cs | 36 +++++++++++++++++++ .../Animation/Transitions/PointTransition.cs | 7 +--- .../Animation/Transitions/SizeTransition.cs | 25 +++++++++++++ .../Transitions/ThicknessTransition.cs | 13 ++----- .../Animation/Transitions/VectorTransition.cs | 25 +++++++++++++ src/Avalonia.Visuals/CornerRadius.cs | 6 ++++ src/Avalonia.Visuals/Size.cs | 6 ++++ src/Avalonia.Visuals/Thickness.cs | 30 ++++++++++++++++ src/Avalonia.Visuals/Vector.cs | 10 ++++-- 17 files changed, 216 insertions(+), 47 deletions(-) create mode 100644 src/Avalonia.Visuals/Animation/Animators/CornerRadiusAnimator.cs create mode 100644 src/Avalonia.Visuals/Animation/Animators/SizeAnimator.cs create mode 100644 src/Avalonia.Visuals/Animation/Animators/VectorAnimator.cs create mode 100644 src/Avalonia.Visuals/Animation/Transitions/CornerRadiusTransition.cs create mode 100644 src/Avalonia.Visuals/Animation/Transitions/SizeTransition.cs create mode 100644 src/Avalonia.Visuals/Animation/Transitions/VectorTransition.cs 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.