namespace Sandbox.Utility; /// /// Easing functions used for transitions. See https://easings.net/ for examples. /// public static class Easing { /// /// An easing function that transforms the linear input into non linear output. /// /// A linear input value from 0 to 1 /// The resulting non linear output value, from 0 to 1 public delegate float Function( float delta ); private static readonly Dictionary _functions = new Dictionary { { "linear", Linear }, { "ease", QuadraticInOut }, { "ease-in-out", ExpoInOut }, { "ease-out", QuadraticOut }, { "ease-in", QuadraticIn }, { "bounce-in", BounceIn }, { "bounce-out", BounceOut }, { "bounce-in-out", BounceInOut }, { "sin-ease-in", SineEaseIn }, { "sin-ease-out", SineEaseOut }, { "sin-ease-in-out", SineEaseInOut }, }; /// public static float EaseInOut( float f ) => ExpoInOut( f ); /// public static float EaseIn( float f ) => QuadraticIn( f ); /// public static float EaseOut( float f ) => QuadraticOut( f ); /// /// Linear easing function, x=y. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float Linear( float f ) => f; /// /// Quadratic ease in. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float QuadraticIn( float f ) => f * f; /// /// Quadratic ease out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float QuadraticOut( float f ) => f * (2.0f - f); /// /// Quadratic ease in and out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float QuadraticInOut( float f ) => (f *= 2.0f) < 1.0f ? 0.5f * f * f : -0.5f * ((f -= 1f) * (f - 2f) - 1f); /// /// Exponential ease in. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float ExpoIn( float f ) => f == 0f ? 0f : MathF.Pow( 1024f, f - 1f ); /// /// Exponential ease out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float ExpoOut( float f ) => f == 1f ? 1f : 1f - MathF.Pow( 2f, -10f * f ); /// /// Exponential ease in and out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float ExpoInOut( float f ) => f < 0.5 ? ExpoIn( f * 2.0f ) * 0.5f : ExpoOut( (f - 0.5f) * 2.0f ) * 0.5f + 0.5f; /// /// Bouncy ease in. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float BounceIn( float f ) => 1f - BounceOut( 1f - f ); /// /// Bouncy ease out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float BounceOut( float f ) => f < (1f / 2.75f) ? 7.5625f * f * f : f < (2f / 2.75f) ? 7.5625f * (f -= (1.5f / 2.75f)) * f + 0.75f : f < (2.5f / 2.75f) ? 7.5625f * (f -= (2.25f / 2.75f)) * f + 0.9375f : 7.5625f * (f -= (2.625f / 2.75f)) * f + 0.984375f; /// /// Bouncy ease in and out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float BounceInOut( float f ) => f < 0.5 ? BounceIn( f * 2.0f ) * 0.5f : BounceOut( (f - 0.5f) * 2.0f ) * 0.5f + 0.5f; /// /// Sine ease in. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float SineEaseIn( float f ) => 1.0f - MathF.Cos( (f * MathF.PI) * 0.5f ); /// /// Sine ease out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float SineEaseOut( float f ) => MathF.Sin( (f * MathF.PI) * 0.5f ); /// /// Sine ease in and out. /// /// Input in range of 0 to 1. /// Output in range 0 to 1. public static float SineEaseInOut( float f ) => -(MathF.Cos( MathF.PI * f ) - 1.0f) * 0.5f; /// /// Add an easing function. /// If the function already exists we silently return. /// internal static void AddFunction( string name, Function func ) { if ( _functions.ContainsKey( name ) ) return; _functions[name] = func; } /// /// Get an easing function by name (ie, "ease-in"). /// If the function doesn't exist we return QuadraticInOut /// public static Function GetFunction( string name ) { if ( _functions.TryGetValue( name, out var f ) ) return f; return QuadraticInOut; } /// /// Get an easing function by name (ie, "ease-in"). /// If the function exists we return true, otherwise return false. /// public static bool TryGetFunction( string name, out Function function ) { return _functions.TryGetValue( name, out function ); } }