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