namespace RhythmBase.Components.Easing { /// /// The EaseType enumeration represents various types of easing functions. /// These functions are used to create smooth transitions in animations. /// public enum EaseType { /// /// Unset. /// Unset = -1, /// ///Ease Linear. /// Linear, /// ///Ease InSine. /// InSine, /// ///Ease OutSine. /// OutSine, /// ///Ease InOutSine. /// InOutSine, /// ///Ease InQuad. /// InQuad, /// ///Ease OutQuad. /// OutQuad, /// ///Ease InOutQuad. /// InOutQuad, /// ///Ease InCubic. /// InCubic, /// ///Ease OutCubic. /// OutCubic, /// ///Ease InOutCubic. /// InOutCubic, /// ///Ease InQuart. /// InQuart, /// ///Ease OutQuart. /// OutQuart, /// ///Ease InOutQuart. /// InOutQuart, /// ///Ease InQuint. /// InQuint, /// ///Ease OutQuint. /// OutQuint, /// ///Ease InOutQuint. /// InOutQuint, /// ///Ease InExpo. /// InExpo, /// ///Ease OutExpo. /// OutExpo, /// ///Ease InOutExpo. /// InOutExpo, /// ///Ease InCirc. /// InCirc, /// ///Ease OutCirc. /// OutCirc, /// ///Ease InOutCirc. /// InOutCirc, /// ///Ease InElastic. /// InElastic, /// ///Ease OutElastic. /// OutElastic, /// ///Ease InOutElastic. /// InOutElastic, /// ///Ease InBack. /// InBack, /// ///Ease OutBack. /// OutBack, /// ///Ease InOutBack. /// InOutBack, /// ///Ease InBounce. /// InBounce, /// ///Ease OutBounce. /// OutBounce, /// ///Ease InOutBounce. /// InOutBounce, /// ///Ease SmoothStep. /// SmoothStep, } /// /// Ease Calculate module. /// public static class Ease { /// /// Calculates the value with the specified ease type. /// /// Ease type. /// A doubleing-point number in the range of 0 to 1. /// Easing result. public static double Calculate(this EaseType type, double x) => type switch { EaseType.Unset => EaseFunction.None(x), EaseType.Linear => EaseFunction.Linear(x), EaseType.InSine => EaseFunction.InSine(x), EaseType.OutSine => EaseFunction.OutSine(x), EaseType.InOutSine => EaseFunction.InOutSine(x), EaseType.InQuad => EaseFunction.InQuad(x), EaseType.OutQuad => EaseFunction.OutQuad(x), EaseType.InOutQuad => EaseFunction.InOutQuad(x), EaseType.InCubic => EaseFunction.InCubic(x), EaseType.OutCubic => EaseFunction.OutCubic(x), EaseType.InOutCubic => EaseFunction.InOutCubic(x), EaseType.InQuart => EaseFunction.InQuart(x), EaseType.OutQuart => EaseFunction.OutQuart(x), EaseType.InOutQuart => EaseFunction.InOutQuart(x), EaseType.InQuint => EaseFunction.InQuint(x), EaseType.OutQuint => EaseFunction.OutQuint(x), EaseType.InOutQuint => EaseFunction.InOutQuint(x), EaseType.InExpo => EaseFunction.InExpo(x), EaseType.OutExpo => EaseFunction.OutExpo(x), EaseType.InOutExpo => EaseFunction.InOutExpo(x), EaseType.InCirc => EaseFunction.InCirc(x), EaseType.OutCirc => EaseFunction.OutCirc(x), EaseType.InOutCirc => EaseFunction.InOutCirc(x), EaseType.InElastic => EaseFunction.InElastic(x), EaseType.OutElastic => EaseFunction.OutElastic(x), EaseType.InOutElastic => EaseFunction.InOutElastic(x), EaseType.InBack => EaseFunction.InBack(x), EaseType.OutBack => EaseFunction.OutBack(x), EaseType.InOutBack => EaseFunction.InOutBack(x), EaseType.InBounce => EaseFunction.InBounce(x), EaseType.OutBounce => EaseFunction.OutBounce(x), EaseType.InOutBounce => EaseFunction.InOutBounce(x), EaseType.SmoothStep => EaseFunction.SmoothStep(x), _ => 0, }; /// /// Calculates the value with the specified ease type. /// /// Ease type. /// A doubleing-point number in the range of 0 to 1. /// The starting value of the easing result. /// The endding value of the easing result /// Easing result. public static double Calculate(this EaseType Type, double x, double from, double to) => Type.Calculate(x) * (to - from) + from; /// /// Ease types. /// private static class EaseFunction { private const double c1 = 1.525; private const double c2 = 1.70158; public static double None(double x) => 0; public static double Linear(double x) => x; public static double InSine(double x) => 1 - Math.Cos(x * double.Pi / 2); public static double OutSine(double x) => Math.Sin(x * double.Pi / 2); public static double InOutSine(double x) => -(Math.Cos(x * double.Pi) - 1) / 2; public static double InQuad(double x) => Math.Pow(x, 2); public static double OutQuad(double x) => 1 - Math.Pow(1 - x, 2); public static double InOutQuad(double x) => x < 0.5 ? 2 * Math.Pow(x, 2) : 1 - Math.Pow(-2 * x + 2, 2) / 2; public static double InCubic(double x) => Math.Pow(x, 3); public static double OutCubic(double x) => 1 - Math.Pow(1 - x, 3); public static double InOutCubic(double x) => x < 0.5 ? 4 * Math.Pow(x, 3) : 1 - Math.Pow(-2 * x + 2, 3) / 2; public static double InQuart(double x) => Math.Pow(x, 4); public static double OutQuart(double x) => 1 - Math.Pow(1 - x, 4); public static double InOutQuart(double x) => x < 0.5 ? 8 * Math.Pow(x, 4) : 1 - Math.Pow(-2 * x + 2, 4) / 2; public static double InQuint(double x) => Math.Pow(x, 5); public static double OutQuint(double x) => 1 - Math.Pow(1 - x, 5); public static double InOutQuint(double x) => x < 0.5 ? 16 * Math.Pow(x, 5) : 1 - Math.Pow(-2 * x + 2, 5) / 2; public static double InExpo(double x) => x == 0 ? 0 : Math.Pow(2, 10 * x - 10); public static double OutExpo(double x) => x == 1 ? 1 : 1 - Math.Pow(2, -10 * x); public static double InOutExpo(double x) => x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? Math.Pow(2, 20 * x - 10) / 2 : (2 - Math.Pow(2, -20 * x + 10)) / 2; public static double InCirc(double x) => 1 - Math.Sqrt(1 - Math.Pow(x, 2)); public static double OutCirc(double x) => Math.Sqrt(1 - Math.Pow(x - 1, 2)); public static double InOutCirc(double x) => x < 0.5 ? (1 - Math.Sqrt(1 - Math.Pow(2 * x, 2))) / 2 : (Math.Sqrt(1 - Math.Pow(-2 * x + 2, 2)) + 1) / 2; public static double InElastic(double x) => x == 0 ? 0 : x == 1 ? 1 : -Math.Pow(2, 10 * x - 10) * Math.Sin((x * 10 - 10.75) * (2 * double.Pi / 3)); public static double OutElastic(double x) => x == 0 ? 0 : x == 1 ? 1 : Math.Pow(2, -10 * x) * Math.Sin((x * 10 - 0.75) * (2 * double.Pi / 3)) + 1; public static double InOutElastic(double x) => x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? -(Math.Pow(2, 20 * x - 10) * Math.Sin((20 * x - 11.125) * (2 * double.Pi / 4.5))) / 2 : Math.Pow(2, -20 * x + 10) * Math.Sin((20 * x - 11.125) * (2 * double.Pi / 4.5)) / 2 + 1; public static double InBack(double x) => (c2 + 1) * x * x * x - c2 * x * x; public static double OutBack(double x) => 1 + (c2 + 1) * Math.Pow(x - 1, 3) + c2 * Math.Pow(x - 1, 2); public static double InOutBack(double x) => x < 0.5 ? Math.Pow(2 * x, 2) * ((c2 * c1 + 1) * 2 * x - c2 * c1) / 2 : (Math.Pow(2 * x - 2, 2) * ((c2 * c1 + 1) * (x * 2 - 2) + c2 * c1) + 2) / 2; public static double InBounce(double x) => 1 - OutBounce(1 - x); public static double OutBounce(double x) { const double n1 = 7.5625; const double d1 = 2.75; return x switch { < 1 / d1 => n1 * x * x, < 2 / d1 => n1 * (x -= 1.5 / d1) * x + 0.75, < 2.5 / d1 => n1 * (x -= 2.25 / d1) * x + 0.9375, _ => n1 * (x -= 2.625 / d1) * x + 0.984375, }; } public static double InOutBounce(double x) => x < 0.5 ? (1 - OutBounce(1 - 2 * x)) / 2 : (1 + OutBounce(2 * x - 1)) / 2; public static double SmoothStep(double x) => (3 - 2 * x) * Math.Pow(x, 2); } } }