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); } } }