diff --git a/Dalamud/Interface/Animation/Easing.cs b/Dalamud/Interface/Animation/Easing.cs new file mode 100644 index 000000000..93b909d98 --- /dev/null +++ b/Dalamud/Interface/Animation/Easing.cs @@ -0,0 +1,103 @@ +using System; +using System.Diagnostics; +using System.Numerics; + +namespace Dalamud.Interface.Animation +{ + public abstract class Easing + { + private readonly Stopwatch animationTimer = new(); + + private double valueInternal; + + /// + /// Initializes a new instance of the class with the specified duration. + /// + /// The animation duration. + protected Easing(TimeSpan duration) + { + this.Duration = duration; + } + + /// + /// Gets or sets the origin point of the animation. + /// + public Vector2? Point1 { get; set; } + + /// + /// Gets or sets the destination point of the animation. + /// + public Vector2? Point2 { get; set; } + + /// + /// Gets the resulting point at the current timestep. + /// + public Vector2 EasedPoint { get; private set; } + + /// + /// Gets the current value of the animation, from 0 to 1. + /// + public double Value + { + get => this.valueInternal; + set + { + this.valueInternal = Math.Min(value, 1); + + if (Point1.HasValue && Point2.HasValue) + EasedPoint = Lerp(Point1.Value, Point2.Value, (float)this.valueInternal); + } + } + + /// + /// Gets or sets the duration of the animation. + /// + public TimeSpan Duration { get; set; } + + /// + /// Gets the progress of the animation, from 0 to 1. + /// + protected double Progress => this.animationTimer.ElapsedMilliseconds / this.Duration.TotalMilliseconds; + + /// + /// Starts the animation from where it was last stopped, or from the start if it was never started before. + /// + public void Start() + { + this.animationTimer.Start(); + } + + /// + /// Stops the animation at the current point. + /// + public void Stop() + { + this.animationTimer.Stop(); + } + + /// + /// Restarts the animation. + /// + public void Restart() + { + this.animationTimer.Restart(); + } + + /// + /// Updates the animation. + /// + public abstract void Update(); + + private static float Lerp(float firstFloat, float secondFloat, float by) + { + return (firstFloat * (1 - @by)) + (secondFloat * by); + } + + private static Vector2 Lerp(Vector2 firstVector, Vector2 secondVector, float by) + { + var retX = Lerp(firstVector.X, secondVector.X, by); + var retY = Lerp(firstVector.Y, secondVector.Y, by); + return new Vector2(retX, retY); + } + } +} diff --git a/Dalamud/Interface/Animation/EasingFunctions/InOutCubic.cs b/Dalamud/Interface/Animation/EasingFunctions/InOutCubic.cs new file mode 100644 index 000000000..c6e14c3a5 --- /dev/null +++ b/Dalamud/Interface/Animation/EasingFunctions/InOutCubic.cs @@ -0,0 +1,28 @@ +using System; +using Serilog; + +namespace Dalamud.Interface.Animation.EasingFunctions +{ + /// + /// Class providing an "InOutCubic" easing animation. + /// + public class InOutCubic : Easing + { + /// + /// Initializes a new instance of the class. + /// + /// The duration of the animation. + public InOutCubic(TimeSpan duration) + : base(duration) + { + // ignored + } + + /// + public override void Update() + { + var p = this.Progress; + this.Value = p < 0.5 ? 4 * p * p * p : 1 - (Math.Pow((-2 * p) + 2, 3) / 2); + } + } +}