From ce4ef46df02b52554fc966c2c33420eeeafbea93 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 21 Mar 2018 20:27:25 +0800 Subject: [PATCH] *Added initial implementation of new Transitions *Added default easing classes *Added easing type converter --- src/Avalonia.Animation/Easing/BackEaseIn.cs | 21 +++++ .../Easing/BackEaseInOut.cs | 32 +++++++ src/Avalonia.Animation/Easing/BackEaseOut.cs | 21 +++++ src/Avalonia.Animation/Easing/BounceEaseIn.cs | 20 ++++ .../Easing/BounceEaseInOut.cs | 27 ++++++ .../Easing/BounceEaseOut.cs | 19 ++++ .../Easing/CircularEaseIn.cs | 23 +++++ .../Easing/CircularEaseInOut.cs | 29 ++++++ .../Easing/CircularEaseOut.cs | 22 +++++ src/Avalonia.Animation/Easing/CubicEaseIn.cs | 18 ++++ .../Easing/CubicEaseInOut.cs | 29 ++++++ src/Avalonia.Animation/Easing/CubicEaseOut.cs | 19 ++++ src/Avalonia.Animation/Easing/Easing.cs | 58 ++++++++++++ .../Easing/ElasticEaseIn.cs | 22 +++++ .../Easing/ElasticEaseInOut.cs | 30 ++++++ .../Easing/ElasticEaseOut.cs | 23 +++++ .../Easing/ExponentialEaseIn.cs | 21 +++++ .../Easing/ExponentialEaseInOut.cs | 30 ++++++ .../Easing/ExponentialEaseOut.cs | 21 +++++ src/Avalonia.Animation/Easing/LinearEasing.cs | 18 ++++ .../Easing/QuadraticEaseIn.cs | 18 ++++ .../Easing/QuadraticEaseInOut.cs | 28 ++++++ .../Easing/QuadraticEaseOut.cs | 19 ++++ .../Easing/QuarticEaseIn.cs | 20 ++++ .../Easing/QuarticEaseInOut.cs | 29 ++++++ .../Easing/QuarticEaseOut.cs | 20 ++++ .../Easing/QuinticEaseIn.cs | 18 ++++ .../Easing/QuinticEaseInOut.cs | 28 ++++++ .../Easing/QuinticEaseOut.cs | 19 ++++ src/Avalonia.Animation/Easing/SineEaseIn.cs | 20 ++++ .../Easing/SineEaseInOut.cs | 20 ++++ src/Avalonia.Animation/Easing/SineEaseOut.cs | 21 +++++ .../Helpers/BounceEaseHelper.cs | 39 ++++++++ .../Helpers/DoubleHelper.cs | 18 ++++ .../Helpers/EasingConstants.cs | 18 ++++ src/Avalonia.Animation/Timing.cs | 93 +++++++++++++++++++ .../Transitions/DoubleTransition.cs | 32 +++++++ .../Transitions/Transition.cs | 59 ++++++++++++ .../Transitions/Transitions.cs | 21 +++++ .../Converters/EasingTypeConverter.cs | 24 +++++ 40 files changed, 1067 insertions(+) create mode 100644 src/Avalonia.Animation/Easing/BackEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/BackEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/BackEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/BounceEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/BounceEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/BounceEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/CircularEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/CircularEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/CircularEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/CubicEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/CubicEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/CubicEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/Easing.cs create mode 100644 src/Avalonia.Animation/Easing/ElasticEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/ElasticEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/ElasticEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/ExponentialEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/ExponentialEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/ExponentialEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/LinearEasing.cs create mode 100644 src/Avalonia.Animation/Easing/QuadraticEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/QuadraticEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/QuadraticEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/QuarticEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/QuarticEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/QuarticEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/QuinticEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/QuinticEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/QuinticEaseOut.cs create mode 100644 src/Avalonia.Animation/Easing/SineEaseIn.cs create mode 100644 src/Avalonia.Animation/Easing/SineEaseInOut.cs create mode 100644 src/Avalonia.Animation/Easing/SineEaseOut.cs create mode 100644 src/Avalonia.Animation/Helpers/BounceEaseHelper.cs create mode 100644 src/Avalonia.Animation/Helpers/DoubleHelper.cs create mode 100644 src/Avalonia.Animation/Helpers/EasingConstants.cs create mode 100644 src/Avalonia.Animation/Timing.cs create mode 100644 src/Avalonia.Animation/Transitions/DoubleTransition.cs create mode 100644 src/Avalonia.Animation/Transitions/Transition.cs create mode 100644 src/Avalonia.Animation/Transitions/Transitions.cs create mode 100644 src/Markup/Avalonia.Markup.Xaml/Converters/EasingTypeConverter.cs diff --git a/src/Avalonia.Animation/Easing/BackEaseIn.cs b/src/Avalonia.Animation/Easing/BackEaseIn.cs new file mode 100644 index 0000000000..c846d6116d --- /dev/null +++ b/src/Avalonia.Animation/Easing/BackEaseIn.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a overshooting cubic function. + /// + public class BackEaseIn : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return p * p * p - p * Math.Sin(p * Math.PI); + } + } +} diff --git a/src/Avalonia.Animation/Easing/BackEaseInOut.cs b/src/Avalonia.Animation/Easing/BackEaseInOut.cs new file mode 100644 index 0000000000..4b190b4da9 --- /dev/null +++ b/src/Avalonia.Animation/Easing/BackEaseInOut.cs @@ -0,0 +1,32 @@ +// 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; + +namespace Avalonia.Animation.Easings +{ + /// + /// Eases a value + /// using a piecewise overshooting cubic function. + /// + public class BackEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (p < 0.5d) + { + double f = 2d * p; + return 0.5d * (f * f * f - f * Math.Sin(f * Math.PI)); + } + else + { + double f = (1d - (2d * p - 1d)); + return 0.5d * (1d - (f * f * f - f * Math.Sin(f * Math.PI))) + 0.5d; + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/BackEaseOut.cs b/src/Avalonia.Animation/Easing/BackEaseOut.cs new file mode 100644 index 0000000000..f671d61040 --- /dev/null +++ b/src/Avalonia.Animation/Easing/BackEaseOut.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a overshooting cubic function. + /// + public class BackEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double p = 1d - progress; + return 1 - (p * p * p - p * Math.Sin(p * Math.PI)); + } + } +} diff --git a/src/Avalonia.Animation/Easing/BounceEaseIn.cs b/src/Avalonia.Animation/Easing/BounceEaseIn.cs new file mode 100644 index 0000000000..5cf34e3f9a --- /dev/null +++ b/src/Avalonia.Animation/Easing/BounceEaseIn.cs @@ -0,0 +1,20 @@ +// 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. + + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a simulated bounce function. + /// + public class BounceEaseIn : Easing + { + /// + public override double Ease(double progress) + { + return 1 - BounceEaseHelper.Bounce(1 - progress); + } + + } +} diff --git a/src/Avalonia.Animation/Easing/BounceEaseInOut.cs b/src/Avalonia.Animation/Easing/BounceEaseInOut.cs new file mode 100644 index 0000000000..6db0424658 --- /dev/null +++ b/src/Avalonia.Animation/Easing/BounceEaseInOut.cs @@ -0,0 +1,27 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piecewise simulated bounce function. + /// + public class BounceEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + if (p < 0.5d) + { + return 0.5f * (1 - BounceEaseHelper.Bounce(1 - (p * 2))); + } + else + { + return 0.5f * BounceEaseHelper.Bounce(p * 2 - 1) + 0.5f; + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/BounceEaseOut.cs b/src/Avalonia.Animation/Easing/BounceEaseOut.cs new file mode 100644 index 0000000000..9cb4e9633d --- /dev/null +++ b/src/Avalonia.Animation/Easing/BounceEaseOut.cs @@ -0,0 +1,19 @@ +// 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. + + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a simulated bounce function. + /// + public class BounceEaseOut : Easing + { + /// + public override double Ease(double progress) + { + return BounceEaseHelper.Bounce(progress); + } + } +} diff --git a/src/Avalonia.Animation/Easing/CircularEaseIn.cs b/src/Avalonia.Animation/Easing/CircularEaseIn.cs new file mode 100644 index 0000000000..21b77db582 --- /dev/null +++ b/src/Avalonia.Animation/Easing/CircularEaseIn.cs @@ -0,0 +1,23 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using the shifted fourth quadrant of + /// the unit circle. + /// + public class CircularEaseIn : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return 1d - Math.Sqrt(1d - (p * p)); + } + + } +} diff --git a/src/Avalonia.Animation/Easing/CircularEaseInOut.cs b/src/Avalonia.Animation/Easing/CircularEaseInOut.cs new file mode 100644 index 0000000000..a5198a019f --- /dev/null +++ b/src/Avalonia.Animation/Easing/CircularEaseInOut.cs @@ -0,0 +1,29 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piecewise unit circle function. + /// + public class CircularEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + if (p < 0.5d) + { + return 0.5d * (1d - Math.Sqrt(1d - 4d * (p * p))); + } + else + { + return 0.5d * (Math.Sqrt(-((2d * p) - 3d) * ((2d * p) - 1d)) + 1d); + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/CircularEaseOut.cs b/src/Avalonia.Animation/Easing/CircularEaseOut.cs new file mode 100644 index 0000000000..33391ed816 --- /dev/null +++ b/src/Avalonia.Animation/Easing/CircularEaseOut.cs @@ -0,0 +1,22 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using the shifted second quadrant of + /// the unit circle. + /// + public class CircularEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return Math.Sqrt((2d - p) * p); + } + } +} diff --git a/src/Avalonia.Animation/Easing/CubicEaseIn.cs b/src/Avalonia.Animation/Easing/CubicEaseIn.cs new file mode 100644 index 0000000000..653164d7ab --- /dev/null +++ b/src/Avalonia.Animation/Easing/CubicEaseIn.cs @@ -0,0 +1,18 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a cubic equation. + /// + public class CubicEaseIn : Easing + { + /// + public override double Ease(double progress) + { + return progress * progress * progress; + } + } +} diff --git a/src/Avalonia.Animation/Easing/CubicEaseInOut.cs b/src/Avalonia.Animation/Easing/CubicEaseInOut.cs new file mode 100644 index 0000000000..ffdce75d45 --- /dev/null +++ b/src/Avalonia.Animation/Easing/CubicEaseInOut.cs @@ -0,0 +1,29 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piece-wise cubic equation. + /// + public class CubicEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (progress < 0.5d) + { + return 4d * p * p * p; + } + else + { + double f = ((2d * p) - 2d); + return 0.5d * f * f * f + 1d; + } + } + } + +} diff --git a/src/Avalonia.Animation/Easing/CubicEaseOut.cs b/src/Avalonia.Animation/Easing/CubicEaseOut.cs new file mode 100644 index 0000000000..6bbe756477 --- /dev/null +++ b/src/Avalonia.Animation/Easing/CubicEaseOut.cs @@ -0,0 +1,19 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a cubic equation. + /// + public class CubicEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double f = (progress - 1d); + return f * f * f + 1d; + } + } +} diff --git a/src/Avalonia.Animation/Easing/Easing.cs b/src/Avalonia.Animation/Easing/Easing.cs new file mode 100644 index 0000000000..75b98e8a3a --- /dev/null +++ b/src/Avalonia.Animation/Easing/Easing.cs @@ -0,0 +1,58 @@ +using Avalonia.Collections; +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Linq; +using System.ComponentModel; + +namespace Avalonia.Animation +{ + /// + /// Base class for all Easing classes. + /// + public abstract class Easing : IEasing + { + /// + public abstract double Ease(double progress); + + static Dictionary _easingTypes; + + static readonly Type s_thisType = typeof(Easing); + + /// + /// Parses a Easing type string. + /// + /// The Easing type string. + /// Returns the instance of the parsed type. + public static Easing Parse(string e) + { + // TODO: There should be a better way to + // find all the subclasses than this method... + if (_easingTypes == null) + { + _easingTypes = new Dictionary(); + + var derivedTypes = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(p => p.GetTypes()) + .Where(p => p.Namespace == s_thisType.Namespace) + .Where(p => p.IsSubclassOf(s_thisType)) + .Select(p=>p).ToList(); + + foreach (var easingType in derivedTypes) + _easingTypes.Add(easingType.Name, easingType); + } + + if (_easingTypes.ContainsKey(e)) + { + var type = _easingTypes[e]; + return (Easing)Activator.CreateInstance(type); + } + else + { + throw new FormatException($"Easing \"{e}\" was not found in {s_thisType.Namespace} namespace."); + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/ElasticEaseIn.cs b/src/Avalonia.Animation/Easing/ElasticEaseIn.cs new file mode 100644 index 0000000000..b0a95d8dc0 --- /dev/null +++ b/src/Avalonia.Animation/Easing/ElasticEaseIn.cs @@ -0,0 +1,22 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a damped sine function. + /// + public class ElasticEaseIn : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return Math.Sin(13d * EasingConstants.HALFPI * p) * Math.Pow(2d, 10d * (p - 1)); + } + } + +} diff --git a/src/Avalonia.Animation/Easing/ElasticEaseInOut.cs b/src/Avalonia.Animation/Easing/ElasticEaseInOut.cs new file mode 100644 index 0000000000..85dcfbd618 --- /dev/null +++ b/src/Avalonia.Animation/Easing/ElasticEaseInOut.cs @@ -0,0 +1,30 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piecewise damped sine function. + /// + public class ElasticEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (p < 0.5d) + { + return 0.5d * Math.Sin(13d * EasingConstants.HALFPI * (2d * p)) * Math.Pow(2d, 10d * ((2d * p) - 1d)); + } + else + { + return 0.5d * (Math.Sin(-13d * EasingConstants.HALFPI * ((2d * p - 1d) + 1d)) * Math.Pow(2d, -10d * (2d * p - 1d)) + 2d); + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/ElasticEaseOut.cs b/src/Avalonia.Animation/Easing/ElasticEaseOut.cs new file mode 100644 index 0000000000..830198468d --- /dev/null +++ b/src/Avalonia.Animation/Easing/ElasticEaseOut.cs @@ -0,0 +1,23 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a damped sine function. + /// + public class ElasticEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return Math.Sin(-13d * EasingConstants.HALFPI * (p + 1)) * Math.Pow(2d, -10d * p) + 1d; + + } + + } +} diff --git a/src/Avalonia.Animation/Easing/ExponentialEaseIn.cs b/src/Avalonia.Animation/Easing/ExponentialEaseIn.cs new file mode 100644 index 0000000000..5b9154d29c --- /dev/null +++ b/src/Avalonia.Animation/Easing/ExponentialEaseIn.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a exponential function. + /// + public class ExponentialEaseIn : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return (p == 0.0d) ? p : Math.Pow(2d, 10d * (p - 1d)); + } + } +} diff --git a/src/Avalonia.Animation/Easing/ExponentialEaseInOut.cs b/src/Avalonia.Animation/Easing/ExponentialEaseInOut.cs new file mode 100644 index 0000000000..0eaef18464 --- /dev/null +++ b/src/Avalonia.Animation/Easing/ExponentialEaseInOut.cs @@ -0,0 +1,30 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piecewise exponential function. + /// + public class ExponentialEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (p < 0.5d) + { + return 0.5d * Math.Pow(2d, (20d * p) - 10d); + } + else + { + return -0.5d * Math.Pow(2d, (-20d * p) + 10d) + 1d; + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/ExponentialEaseOut.cs b/src/Avalonia.Animation/Easing/ExponentialEaseOut.cs new file mode 100644 index 0000000000..c071d18d2e --- /dev/null +++ b/src/Avalonia.Animation/Easing/ExponentialEaseOut.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a exponential function. + /// + public class ExponentialEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + return (p == 1.0d) ? p : 1d - Math.Pow(2d, -10d * p); + } + } +} diff --git a/src/Avalonia.Animation/Easing/LinearEasing.cs b/src/Avalonia.Animation/Easing/LinearEasing.cs new file mode 100644 index 0000000000..fcbf6053f4 --- /dev/null +++ b/src/Avalonia.Animation/Easing/LinearEasing.cs @@ -0,0 +1,18 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Linearly eases a value. + /// + public class LinearEasing : Easing + { + /// + public override double Ease(double progress) + { + return progress; + } + } + +} diff --git a/src/Avalonia.Animation/Easing/QuadraticEaseIn.cs b/src/Avalonia.Animation/Easing/QuadraticEaseIn.cs new file mode 100644 index 0000000000..641fba4892 --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuadraticEaseIn.cs @@ -0,0 +1,18 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a quadratic function. + /// + public class QuadraticEaseIn : Easing + { + /// + public override double Ease(double progress) + { + return progress * progress; + } + } +} diff --git a/src/Avalonia.Animation/Easing/QuadraticEaseInOut.cs b/src/Avalonia.Animation/Easing/QuadraticEaseInOut.cs new file mode 100644 index 0000000000..384c3caf32 --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuadraticEaseInOut.cs @@ -0,0 +1,28 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piece-wise quadratic function. + /// + public class QuadraticEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (progress < 0.5d) + { + return 2d * p * p; + } + else + { + return (-2d * p * p) + (4d * p) - 1d; + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/QuadraticEaseOut.cs b/src/Avalonia.Animation/Easing/QuadraticEaseOut.cs new file mode 100644 index 0000000000..14fd877ad4 --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuadraticEaseOut.cs @@ -0,0 +1,19 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a quadratic function. + /// + public class QuadraticEaseOut : Easing + { + /// + public override double Ease(double progress) + { + return -(progress * (progress - 2d)); + } + + } +} diff --git a/src/Avalonia.Animation/Easing/QuarticEaseIn.cs b/src/Avalonia.Animation/Easing/QuarticEaseIn.cs new file mode 100644 index 0000000000..a5efa241be --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuarticEaseIn.cs @@ -0,0 +1,20 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a quartic equation. + /// + public class QuarticEaseIn : Easing + { + /// + public override double Ease(double progress) + { + return progress * progress * progress * progress; + + } + + } +} diff --git a/src/Avalonia.Animation/Easing/QuarticEaseInOut.cs b/src/Avalonia.Animation/Easing/QuarticEaseInOut.cs new file mode 100644 index 0000000000..d5cd2622cb --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuarticEaseInOut.cs @@ -0,0 +1,29 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piece-wise quartic equation. + /// + public class QuarticEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (p < 0.5d) + { + return 8d * p * p * p * p; + } + else + { + double f = (p - 1d); + return -8d * f * f * f * f + 1d; + } + } + + } +} diff --git a/src/Avalonia.Animation/Easing/QuarticEaseOut.cs b/src/Avalonia.Animation/Easing/QuarticEaseOut.cs new file mode 100644 index 0000000000..5ecb3a7a0b --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuarticEaseOut.cs @@ -0,0 +1,20 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a quartic equation. + /// + public class QuarticEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double f = (progress - 1d); + return f * f * f * (1d - progress) + 1d; + } + + } +} diff --git a/src/Avalonia.Animation/Easing/QuinticEaseIn.cs b/src/Avalonia.Animation/Easing/QuinticEaseIn.cs new file mode 100644 index 0000000000..8dc6ad6bc8 --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuinticEaseIn.cs @@ -0,0 +1,18 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using a quartic equation. + /// + public class QuinticEaseIn : Easing + { + /// + public override double Ease(double progress) + { + return progress * progress * progress * progress * progress; + } + } +} diff --git a/src/Avalonia.Animation/Easing/QuinticEaseInOut.cs b/src/Avalonia.Animation/Easing/QuinticEaseInOut.cs new file mode 100644 index 0000000000..87f3c38dad --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuinticEaseInOut.cs @@ -0,0 +1,28 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a piece-wise quartic equation. + /// + public class QuinticEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + double p = progress; + + if (progress < 0.5d) + { + return 16d * p * p * p * p * p; + } + else + { + double f = ((2d * p) - 2d); + return 0.5d * f * f * f * f * f + 1d; + } + } + } +} diff --git a/src/Avalonia.Animation/Easing/QuinticEaseOut.cs b/src/Avalonia.Animation/Easing/QuinticEaseOut.cs new file mode 100644 index 0000000000..f4054c8da2 --- /dev/null +++ b/src/Avalonia.Animation/Easing/QuinticEaseOut.cs @@ -0,0 +1,19 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using a quartic equation. + /// + public class QuinticEaseOut : Easing + { + /// + public override double Ease(double progress) + { + double f = (progress - 1d); + return f * f * f * f * f + 1d; + } + } +} diff --git a/src/Avalonia.Animation/Easing/SineEaseIn.cs b/src/Avalonia.Animation/Easing/SineEaseIn.cs new file mode 100644 index 0000000000..49c633ec5c --- /dev/null +++ b/src/Avalonia.Animation/Easing/SineEaseIn.cs @@ -0,0 +1,20 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases in a value + /// using the quarter-wave of sine function. + /// + public class SineEaseIn : Easing + { + /// + public override double Ease(double progress) + { + return Math.Sin((progress - 1) * EasingConstants.HALFPI) + 1; + } + } +} diff --git a/src/Avalonia.Animation/Easing/SineEaseInOut.cs b/src/Avalonia.Animation/Easing/SineEaseInOut.cs new file mode 100644 index 0000000000..94b528c728 --- /dev/null +++ b/src/Avalonia.Animation/Easing/SineEaseInOut.cs @@ -0,0 +1,20 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases a value + /// using a half sine wave function. + /// + public class SineEaseInOut : Easing + { + /// + public override double Ease(double progress) + { + return 0.5d * (1d - Math.Cos(progress * Math.PI)); + } + } +} diff --git a/src/Avalonia.Animation/Easing/SineEaseOut.cs b/src/Avalonia.Animation/Easing/SineEaseOut.cs new file mode 100644 index 0000000000..7d0658c389 --- /dev/null +++ b/src/Avalonia.Animation/Easing/SineEaseOut.cs @@ -0,0 +1,21 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Eases out a value + /// using the quarter-wave of sine function + /// with shifted phase. + /// + public class SineEaseOut : Easing + { + /// + public override double Ease(double progress) + { + return Math.Sin(progress * EasingConstants.HALFPI); + } + } +} diff --git a/src/Avalonia.Animation/Helpers/BounceEaseHelper.cs b/src/Avalonia.Animation/Helpers/BounceEaseHelper.cs new file mode 100644 index 0000000000..b0da648fd3 --- /dev/null +++ b/src/Avalonia.Animation/Helpers/BounceEaseHelper.cs @@ -0,0 +1,39 @@ +// 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. + +namespace Avalonia.Animation +{ + /// + /// Helper static class for BounceEase classes. + /// + internal static class BounceEaseHelper + { + /// + /// Returns the consequent value of + /// a simulated bounce function. + /// + /// The amount of progress from 0 to 1. + /// The result of the easing function + internal static double Bounce(double progress) + { + double p = progress; + if (p < 4d / 11.0d) + { + return (121d * p * p) / 16.0d; + } + else if (p < 8d / 11.0d) + { + return (363d / 40.0d * p * p) - (99d / 10.0d * p) + 17d / 5.0d; + } + else if (p < 9d / 10.0d) + { + return (4356d / 361.0d * p * p) - (35442d / 1805.0d * p) + 16061d / 1805.0d; + } + else + { + return (54d / 5.0d * p * p) - (513d / 25.0d * p) + 268d / 25.0d; + } + } + + } +} diff --git a/src/Avalonia.Animation/Helpers/DoubleHelper.cs b/src/Avalonia.Animation/Helpers/DoubleHelper.cs new file mode 100644 index 0000000000..9d4fd4955f --- /dev/null +++ b/src/Avalonia.Animation/Helpers/DoubleHelper.cs @@ -0,0 +1,18 @@ +// 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.Collections.Generic; +using System.Text; + +namespace Avalonia.Animation.Helpers +{ + internal static class DoubleHelper + { + internal static bool AboutEqual(double x, double y) + { + double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15; + return Math.Abs(x - y) <= epsilon; + } + } +} diff --git a/src/Avalonia.Animation/Helpers/EasingConstants.cs b/src/Avalonia.Animation/Helpers/EasingConstants.cs new file mode 100644 index 0000000000..b6a52ab4a4 --- /dev/null +++ b/src/Avalonia.Animation/Helpers/EasingConstants.cs @@ -0,0 +1,18 @@ +// 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; + +namespace Avalonia.Animation +{ + /// + /// Helper static class for easing mathematical constants. + /// + internal static class EasingConstants + { + /// + /// Half of + /// + internal static double HALFPI = Math.PI / 2d; + } +} diff --git a/src/Avalonia.Animation/Timing.cs b/src/Avalonia.Animation/Timing.cs new file mode 100644 index 0000000000..a22dc1a6a7 --- /dev/null +++ b/src/Avalonia.Animation/Timing.cs @@ -0,0 +1,93 @@ +// 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.Diagnostics; +using System.Linq; +using System.Reactive.Linq; +using Avalonia.Data; +using Avalonia.Threading; + +namespace Avalonia.Animation +{ + /// + /// Provides global timing functions for animations. + /// + public static class Timing + { + /// + /// The number of frames per second. + /// + public const int FramesPerSecond = 60; + + /// + /// The time span of each frame. + /// + private static readonly TimeSpan Tick = TimeSpan.FromSeconds(1.0 / FramesPerSecond); + + /// + /// Initializes static members of the class. + /// + static Timing() + { + Stopwatch = new Stopwatch(); + Stopwatch.Start(); + Timer = Observable.Interval(Tick, AvaloniaScheduler.Instance) + .Select(_ => Stopwatch.Elapsed) + .Publish() + .RefCount(); + } + + /// + /// The stopwatch used to track time. + /// + /// + /// The stopwatch used to track time. + /// + public static Stopwatch Stopwatch + { + get; + } + + /// + /// Gets the animation timer. + /// + /// + /// The animation timer ticks times per second. The + /// parameter passed to a subsciber is the time span since the animation system was + /// initialized. + /// + /// + /// The animation timer. + /// + public static IObservable Timer + { + get; + } + + /// + /// Gets a timer that fires every frame for the specified duration. + /// + /// The duration of the animation. + /// + /// An observable that notifies the subscriber of the progress along the animation. + /// + /// + /// The parameter passed to the subscriber is the progress along the animation, with + /// 0 being the start and 1 being the end. The observable is guaranteed to fire 0 + /// immediately on subscribe and 1 at the end of the duration. + /// + public static IObservable GetTimer(TimeSpan duration) + { + var startTime = Stopwatch.Elapsed.Ticks; + var endTime = startTime + duration.Ticks; + return Timer + .TakeWhile(x => x.Ticks < endTime) + .Select(x => (x.Ticks - startTime) / (double)duration.Ticks) + .StartWith(0.0) + .Concat(Observable.Return(1.0)); + } + + + } +} diff --git a/src/Avalonia.Animation/Transitions/DoubleTransition.cs b/src/Avalonia.Animation/Transitions/DoubleTransition.cs new file mode 100644 index 0000000000..fbe164aa90 --- /dev/null +++ b/src/Avalonia.Animation/Transitions/DoubleTransition.cs @@ -0,0 +1,32 @@ +// 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 Avalonia.Metadata; +using System; + +namespace Avalonia.Animation +{ + /// + /// Transitions object that handles properties with types. + /// + public class DoubleTransition : Transition + { + /// + public DoubleTransition() : base() + { + + } + + /// + public override AvaloniaProperty Property { get; set; } + + /// + public override void Apply(Animatable control) + { + //throw new NotImplementedException(); + + + + } + } +} diff --git a/src/Avalonia.Animation/Transitions/Transition.cs b/src/Avalonia.Animation/Transitions/Transition.cs new file mode 100644 index 0000000000..8a90940784 --- /dev/null +++ b/src/Avalonia.Animation/Transitions/Transition.cs @@ -0,0 +1,59 @@ +// 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 Avalonia.Metadata; +using System; + +namespace Avalonia.Animation +{ + internal interface ITransition + { + /// + /// Applies the transition to the specified . + /// + /// + void Apply(Animatable control); + + /// + /// Gets the property to be animated. + /// + AvaloniaProperty Property { get; set; } + } + + /// + /// Defines how a property should be animated using a transition. + /// + public abstract class Transition : ITransition + { + /// + /// Gets the duration of the animation. + /// + public TimeSpan Duration { get; set; } + + /// + /// Instantiates the base abstract class . + /// + public Transition() + { + if(!(typeof(T) == Property.PropertyType)) + { + throw new InvalidCastException + ($"Invalid property type {typeof(T).Name} for this {this.GetType().Name}"); + } + } + + /// + /// Gets the easing class to be used. + /// + public IEasing Easing { get; set; } + + /// + public abstract AvaloniaProperty Property { get; set; } + + /// + public abstract void Apply(Animatable control); + + } + + +} diff --git a/src/Avalonia.Animation/Transitions/Transitions.cs b/src/Avalonia.Animation/Transitions/Transitions.cs new file mode 100644 index 0000000000..50adf246ae --- /dev/null +++ b/src/Avalonia.Animation/Transitions/Transitions.cs @@ -0,0 +1,21 @@ +// 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 Avalonia.Collections; + +namespace Avalonia.Animation +{ + /// + /// A collection of definitions. + /// + public class Transitions : AvaloniaList + { + /// + /// Initializes a new instance of the class. + /// + public Transitions() + { + ResetBehavior = ResetBehavior.Remove; + } + } +} diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/EasingTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/EasingTypeConverter.cs new file mode 100644 index 0000000000..851d579581 --- /dev/null +++ b/src/Markup/Avalonia.Markup.Xaml/Converters/EasingTypeConverter.cs @@ -0,0 +1,24 @@ +// 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 Avalonia.Animation; +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Avalonia.Markup.Xaml.Converters +{ + + public class EasingTypeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + return sourceType == typeof(string); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + return Easing.Parse((string)value); + } + } +} \ No newline at end of file