using System.Runtime.CompilerServices; using Unity.Burst; using Unity.Mathematics; namespace OctoberStudio.Easing { [BurstCompile] public static class EasingFunctions { public static readonly FunctionPointer[] Functions; public delegate float EasingFunction(float t); static EasingFunctions() { Functions = new FunctionPointer[] { BurstCompiler.CompileFunctionPointer(Linear), BurstCompiler.CompileFunctionPointer(QuadIn), BurstCompiler.CompileFunctionPointer(QuadOut), BurstCompiler.CompileFunctionPointer(QuadOutIn), BurstCompiler.CompileFunctionPointer(CubicIn), BurstCompiler.CompileFunctionPointer(CubicOut), BurstCompiler.CompileFunctionPointer(CubicInOut), BurstCompiler.CompileFunctionPointer(QuartIn), BurstCompiler.CompileFunctionPointer(QuartOut), BurstCompiler.CompileFunctionPointer(QuartInOut), BurstCompiler.CompileFunctionPointer(QuintIn), BurstCompiler.CompileFunctionPointer(QuintOut), BurstCompiler.CompileFunctionPointer(QuintInOut), BurstCompiler.CompileFunctionPointer(SineIn), BurstCompiler.CompileFunctionPointer(SineOut), BurstCompiler.CompileFunctionPointer(SineInOut), BurstCompiler.CompileFunctionPointer(CircIn), BurstCompiler.CompileFunctionPointer(CircOut), BurstCompiler.CompileFunctionPointer(CircInOut), BurstCompiler.CompileFunctionPointer(ExpoIn), BurstCompiler.CompileFunctionPointer(ExpoOut), BurstCompiler.CompileFunctionPointer(ExpoInOut), BurstCompiler.CompileFunctionPointer(ElasticIn), BurstCompiler.CompileFunctionPointer(ElasticOut), BurstCompiler.CompileFunctionPointer(ElasticInOut), BurstCompiler.CompileFunctionPointer(BackIn), BurstCompiler.CompileFunctionPointer(BackOut), BurstCompiler.CompileFunctionPointer(BackInOut), BurstCompiler.CompileFunctionPointer(BounceIn), BurstCompiler.CompileFunctionPointer(BounceOut), BurstCompiler.CompileFunctionPointer(BounceInOut), }; } public static float ApplyEasing(float t, EasingType easingType) { switch (easingType) { case EasingType.Linear: return Linear(t); case EasingType.QuadIn: return QuadIn(t); case EasingType.QuadOut: return QuadOut(t); case EasingType.QuadOutIn: return QuadOutIn(t); case EasingType.CubicIn: return CubicIn(t); case EasingType.CubicOut: return CubicOut(t); case EasingType.CubicInOut: return CubicInOut(t); case EasingType.QuartIn: return QuartIn(t); case EasingType.QuartOut: return QuartOut(t); case EasingType.QuartInOut: return QuartInOut(t); case EasingType.QuintIn: return QuintIn(t); case EasingType.QuintOut: return QuintOut(t); case EasingType.QuintInOut: return QuintInOut(t); case EasingType.SineIn: return SineIn(t); case EasingType.SineOut: return SineOut(t); case EasingType.SineInOut: return SineInOut(t); case EasingType.CircIn: return CircIn(t); case EasingType.CircOut: return CircOut(t); case EasingType.CircInOut: return CircInOut(t); case EasingType.ExpoIn: return ExpoIn(t); case EasingType.ExpoOut: return ExpoOut(t); case EasingType.ExpoInOut: return ExpoInOut(t); case EasingType.ElasticIn: return ElasticIn(t); case EasingType.ElasticOut: return ElasticOut(t); case EasingType.ElasticInOut: return ElasticInOut(t); case EasingType.BackIn: return BackIn(t); case EasingType.BackOut: return BackOut(t); case EasingType.BackInOut: return BackInOut(t); case EasingType.BounceIn: return BounceIn(t); case EasingType.BounceOut: return BounceOut(t); case EasingType.BounceInOut: return BounceInOut(t); } return t; } [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Linear(float t) => t; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuadIn(float t) => t * t; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuadOut(float t) => -(t * (t - 2)); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuadOutIn(float t) => t < 0.5f ? 2 * t * t : (-2 * t * t) + (4 * t) - 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float CubicIn(float t) => t * t * t; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float CubicOut(float t) => (t - 1) * (t - 1) * (t - 1) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float CubicInOut(float t) => t < 0.5f ? 4 * t * t * t : 0.5f * ((2 * t) - 2) * ((2 * t) - 2) * ((2 * t) - 2) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuartIn(float t) => t * t * t * t; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuartOut(float t) => (t - 1) * (t - 1) * (t - 1) * (1 - t) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuartInOut(float t) => t < 0.5f ? 8 * t * t * t * t : -8 * (t - 1) * (t - 1) * (t - 1) * (t - 1) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuintIn(float t) => t * t * t * t * t; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuintOut(float t) => (t - 1) * (t - 1) * (t - 1) * (t - 1) * (t - 1) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float QuintInOut(float t) => t < 0.5f ? 16 * t * t * t * t * t : 0.5f * ((2 * t) - 2) * ((2 * t) - 2) * ((2 * t) - 2) * ((2 * t) - 2) * ((2 * t) - 2) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float SineIn(float t) => math.sin((t - 1) * math.PI / 2f) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float SineOut(float t) => math.sin(t * math.PI / 2f); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float SineInOut(float t) => 0.5f * (1 - math.cos(t * math.PI)); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float CircIn(float t) => 1 - math.sqrt(1 - (t * t)); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float CircOut(float t) => math.sqrt((2 - t) * t); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float CircInOut(float t) => t < 0.5f ? 0.5f * (1 - math.sqrt(1 - 4 * (t * t))) : 0.5f * (math.sqrt(-((2 * t) - 3) * ((2 * t) - 1)) + 1); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ExpoIn(float t) => Approximately(t, 0.0f) ? t : math.pow(2, 10 * (t - 1)); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ExpoOut(float t) => Approximately(t, 1.0f) ? t : 1 - math.pow(2, -10 * t); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ExpoInOut(float t) => (Approximately(t, 0.0f) || Approximately(t, 1.0f)) ? t : t < 0.5f ? 0.5f * math.pow(2, (20 * t) - 10) : -0.5f * math.pow(2, (-20 * t) + 10) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ElasticIn(float t) => math.sin(13 * math.PI / 2 * t) * math.pow(2, 10 * (t - 1)); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ElasticOut(float t) => math.sin(-13 * math.PI / 2 * (t + 1)) * math.pow(2, -10 * t) + 1; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float ElasticInOut(float t) => t < 0.5f ? 0.5f * math.sin(13 * math.PI / 2 * (2 * t)) * math.pow(2, 10 * ((2 * t) - 1)) : 0.5f * (math.sin(-13 * math.PI / 2 * ((2 * t - 1) + 1)) * math.pow(2, -10 * (2 * t - 1)) + 2); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float BackIn(float t) => t * t * t - t * math.sin(t * math.PI); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float BackOut(float t) => 1 - ((1 - t) * (1 - t) * (1 - t) - (1 - t) * math.sin((1 - t) * math.PI)); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float BackInOut(float t) => t < 0.5f ? 0.5f * (2 * t * 2 * t * 2 * t - 2 * t * math.sin(2 * t * math.PI)) : 0.5f * (1 - ((1 - (2 * t - 1)) * (1 - (2 * t - 1)) * (1 - (2 * t - 1)) - (1 - (2 * t - 1)) * math.sin((1 - (2 * t - 1)) * math.PI))) + 0.5f; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float BounceIn(float t) => 1 - BounceOut(1 - t); [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float BounceInOut(float t) => t < 0.5f ? 0.5f * BounceIn(t * 2) : 0.5f * BounceOut(t * 2 - 1) + 0.5f; [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float BounceOut(float t) { if (t < 4 / 11.0f) { return (121 * t * t) / 16.0f; } else if (t < 8 / 11.0f) { return (363 / 40.0f * t * t) - (99 / 10.0f * t) + 17 / 5.0f; } else if (t < 9 / 10.0f) { return (4356 / 361.0f * t * t) - (35442 / 1805.0f * t) + 16061 / 1805.0f; } else { return (54 / 5.0f * t * t) - (513 / 25.0f * t) + 268 / 25.0f; } } [BurstCompile] [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool Approximately(float a, float b) { return math.abs(a - b) < 1e-5f; // same default epsilon as Mathf.Approximately } } }