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