diff --git a/Engine.Systems/Tween/Easings.cs b/Engine.Systems/Tween/Easings.cs index becb41a..a629c1f 100644 --- a/Engine.Systems/Tween/Easings.cs +++ b/Engine.Systems/Tween/Easings.cs @@ -1,5 +1,7 @@ // Reference: https://easings.net +using Syntriax.Engine.Core; + namespace Syntriax.Engine.Systems.Tween; internal static class EaseConstants @@ -7,52 +9,54 @@ internal static class EaseConstants internal const float c1 = 1.70158f; internal const float c2 = c1 * 1.525f; internal const float c3 = c1 + 1f; - internal const float c4 = 2f * Core.Math.PI / 3f; - internal const float c5 = 2f * Core.Math.PI / 4.5f; + internal const float c4 = 2f * Math.PI / 3f; + internal const float c5 = 2f * Math.PI / 4.5f; } -public readonly struct EaseLinear : IEasing { public readonly float Evaluate(float x) => x; } +public abstract class EasingBase where T : IEasing, new() { public static readonly T Instance = new(); } -public readonly struct EaseInQuad : IEasing { public readonly float Evaluate(float x) => x * x; } -public readonly struct EaseOutQuad : IEasing { public readonly float Evaluate(float x) => 1f - (1f - x) * (1f - x); } -public readonly struct EaseInOutQuad : IEasing { public readonly float Evaluate(float x) => x < .5f ? 2f * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 2f) * .5f; } +public class EaseLinear : EasingBase, IEasing { public float Evaluate(float x) => x; } -public readonly struct EaseInCubic : IEasing { public readonly float Evaluate(float x) => x * x * x; } -public readonly struct EaseOutCubic : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Pow(1f - x, 3f); } -public readonly struct EaseInOutCubic : IEasing { public readonly float Evaluate(float x) => x < .5f ? 4f * x * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 3f) * .5f; } +public class EaseInQuad : EasingBase, IEasing { public float Evaluate(float x) => x * x; } +public class EaseOutQuad : EasingBase, IEasing { public float Evaluate(float x) => 1f - (1f - x) * (1f - x); } +public class EaseInOutQuad : EasingBase, IEasing { public float Evaluate(float x) => x < .5f ? 2f * x * x : 1f - Math.Pow(-2f * x + 2f, 2f) * .5f; } -public readonly struct EaseInQuart : IEasing { public readonly float Evaluate(float x) => x * x * x * x; } -public readonly struct EaseOutQuart : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Pow(1f - x, 4f); } -public readonly struct EaseInOutQuart : IEasing { public readonly float Evaluate(float x) => x < .5f ? 8f * x * x * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 4f) * .5f; } +public class EaseInCubic : EasingBase, IEasing { public float Evaluate(float x) => x * x * x; } +public class EaseOutCubic : EasingBase, IEasing { public float Evaluate(float x) => 1f - Math.Pow(1f - x, 3f); } +public class EaseInOutCubic : EasingBase, IEasing { public float Evaluate(float x) => x < .5f ? 4f * x * x * x : 1f - Math.Pow(-2f * x + 2f, 3f) * .5f; } -public readonly struct EaseInQuint : IEasing { public readonly float Evaluate(float x) => x * x * x * x * x; } -public readonly struct EaseOutQuint : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Pow(1f - x, 5f); } -public readonly struct EaseInOutQuint : IEasing { public readonly float Evaluate(float x) => x < .5f ? 16f * x * x * x * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 5f) * .5f; } +public class EaseInQuart : EasingBase, IEasing { public float Evaluate(float x) => x * x * x * x; } +public class EaseOutQuart : EasingBase, IEasing { public float Evaluate(float x) => 1f - Math.Pow(1f - x, 4f); } +public class EaseInOutQuart : EasingBase, IEasing { public float Evaluate(float x) => x < .5f ? 8f * x * x * x * x : 1f - Math.Pow(-2f * x + 2f, 4f) * .5f; } -public readonly struct EaseInSine : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Cos(x * Core.Math.PI * .5f); } -public readonly struct EaseOutSine : IEasing { public readonly float Evaluate(float x) => Core.Math.Sin(x * Core.Math.PI * .5f); } -public readonly struct EaseInOutSine : IEasing { public readonly float Evaluate(float x) => -(Core.Math.Cos(Core.Math.PI * x) - 1f) * .5f; } +public class EaseInQuint : EasingBase, IEasing { public float Evaluate(float x) => x * x * x * x * x; } +public class EaseOutQuint : EasingBase, IEasing { public float Evaluate(float x) => 1f - Math.Pow(1f - x, 5f); } +public class EaseInOutQuint : EasingBase, IEasing { public float Evaluate(float x) => x < .5f ? 16f * x * x * x * x * x : 1f - Math.Pow(-2f * x + 2f, 5f) * .5f; } -public readonly struct EaseInExpo : IEasing { public readonly float Evaluate(float x) => x == 0f ? 0f : Core.Math.Pow(2f, 10f * x - 10f); } -public readonly struct EaseOutExpo : IEasing { public readonly float Evaluate(float x) => x == 1f ? 1f : 1f - Core.Math.Pow(2f, -10f * x); } -public readonly struct EaseInOutExpo : IEasing { public readonly float Evaluate(float x) => x == 0f ? 0f : x == 1f ? 1f : x < .5f ? Core.Math.Pow(2f, 20f * x - 10f) * .5f : (2f - Core.Math.Pow(2f, -20f * x + 10f)) * .5f; } +public class EaseInSine : EasingBase, IEasing { public float Evaluate(float x) => 1f - Math.Cos(x * Math.PI * .5f); } +public class EaseOutSine : EasingBase, IEasing { public float Evaluate(float x) => Math.Sin(x * Math.PI * .5f); } +public class EaseInOutSine : EasingBase, IEasing { public float Evaluate(float x) => -(Math.Cos(Math.PI * x) - 1f) * .5f; } -public readonly struct EaseInCirc : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Sqrt(1f - Core.Math.Pow(x, 2f)); } -public readonly struct EaseOutCirc : IEasing { public readonly float Evaluate(float x) => Core.Math.Sqrt(1f - Core.Math.Pow(x - 1f, 2f)); } -public readonly struct EaseInOutCirc : IEasing { public readonly float Evaluate(float x) => x < .5f ? (1f - Core.Math.Sqrt(1f - Core.Math.Pow(2f * x, 2f))) * .5f : (Core.Math.Sqrt(1f - Core.Math.Pow(-2f * x + 2f, 2f)) + 1f) * .5f; } +public class EaseInExpo : EasingBase, IEasing { public float Evaluate(float x) => x == 0f ? 0f : Math.Pow(2f, 10f * x - 10f); } +public class EaseOutExpo : EasingBase, IEasing { public float Evaluate(float x) => x == 1f ? 1f : 1f - Math.Pow(2f, -10f * x); } +public class EaseInOutExpo : EasingBase, IEasing { public float Evaluate(float x) => x == 0f ? 0f : x == 1f ? 1f : x < .5f ? Math.Pow(2f, 20f * x - 10f) * .5f : (2f - Math.Pow(2f, -20f * x + 10f)) * .5f; } -public readonly struct EaseInBack : IEasing { public readonly float Evaluate(float x) => EaseConstants.c3 * x * x * x - EaseConstants.c1 * x * x; } -public readonly struct EaseOutBack : IEasing { public readonly float Evaluate(float x) => 1f + EaseConstants.c3 * Core.Math.Pow(x - 1f, 3f) + EaseConstants.c1 * Core.Math.Pow(x - 1f, 2f); } -public readonly struct EaseInOutBack : IEasing { public readonly float Evaluate(float x) => x < .5f ? Core.Math.Pow(2f * x, 2f) * ((EaseConstants.c2 + 1f) * 2f * x - EaseConstants.c2) * .5f : (Core.Math.Pow(2f * x - 2f, 2f) * ((EaseConstants.c2 + 1f) * (x * 2f - 2f) + EaseConstants.c2) + 2f) * .5f; } +public class EaseInCirc : EasingBase, IEasing { public float Evaluate(float x) => 1f - Math.Sqrt(1f - Math.Pow(x, 2f)); } +public class EaseOutCirc : EasingBase, IEasing { public float Evaluate(float x) => Math.Sqrt(1f - Math.Pow(x - 1f, 2f)); } +public class EaseInOutCirc : EasingBase, IEasing { public float Evaluate(float x) => x < .5f ? (1f - Math.Sqrt(1f - Math.Pow(2f * x, 2f))) * .5f : (Math.Sqrt(1f - Math.Pow(-2f * x + 2f, 2f)) + 1f) * .5f; } -public readonly struct EaseInElastic : IEasing { public readonly float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : -Core.Math.Pow(2f, 10f * x - 10f) * Core.Math.Sin((x * 10f - 10.75f) * EaseConstants.c4); } -public readonly struct EaseOutElastic : IEasing { public readonly float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : Core.Math.Pow(2f, -10f * x) * Core.Math.Sin((x * 10f - .75f) * EaseConstants.c4) + 1f; } -public readonly struct EaseInOutElastic : IEasing { public readonly float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : x < .5f ? -(Core.Math.Pow(2f, 20f * x - 10f) * Core.Math.Sin((20f * x - 11.125f) * EaseConstants.c5)) * .5f : Core.Math.Pow(2f, -20f * x + 10f) * Core.Math.Sin((20f * x - 11.125f) * EaseConstants.c5) * .5f + 1f; } +public class EaseInBack : EasingBase, IEasing { public float Evaluate(float x) => EaseConstants.c3 * x * x * x - EaseConstants.c1 * x * x; } +public class EaseOutBack : EasingBase, IEasing { public float Evaluate(float x) => 1f + EaseConstants.c3 * Math.Pow(x - 1f, 3f) + EaseConstants.c1 * Math.Pow(x - 1f, 2f); } +public class EaseInOutBack : EasingBase, IEasing { public float Evaluate(float x) => x < .5f ? Math.Pow(2f * x, 2f) * ((EaseConstants.c2 + 1f) * 2f * x - EaseConstants.c2) * .5f : (Math.Pow(2f * x - 2f, 2f) * ((EaseConstants.c2 + 1f) * (x * 2f - 2f) + EaseConstants.c2) + 2f) * .5f; } -public readonly struct EaseInBounce : IEasing { public readonly float Evaluate(float x) => 1f - new EaseOutBounce().Evaluate(1f - x); } -public readonly struct EaseOutBounce : IEasing +public class EaseInElastic : EasingBase, IEasing { public float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : -Math.Pow(2f, 10f * x - 10f) * Math.Sin((x * 10f - 10.75f) * EaseConstants.c4); } +public class EaseOutElastic : EasingBase, IEasing { public float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : Math.Pow(2f, -10f * x) * Math.Sin((x * 10f - .75f) * EaseConstants.c4) + 1f; } +public class EaseInOutElastic : EasingBase, IEasing { public float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : x < .5f ? -(Math.Pow(2f, 20f * x - 10f) * Math.Sin((20f * x - 11.125f) * EaseConstants.c5)) * .5f : Math.Pow(2f, -20f * x + 10f) * Math.Sin((20f * x - 11.125f) * EaseConstants.c5) * .5f + 1f; } + +public class EaseInBounce : EasingBase, IEasing { public float Evaluate(float x) => 1f - EaseOutBounce.Instance.Evaluate(1f - x); } +public class EaseOutBounce : EasingBase, IEasing { - public readonly float Evaluate(float x) + public float Evaluate(float x) { const float n1 = 7.5625f; const float d1 = 2.75f; @@ -69,4 +73,4 @@ public readonly struct EaseOutBounce : IEasing return n1 * (x -= 2.625f / d1) * x + .984375f; } } -public readonly struct EaseInOutBounce : IEasing { public readonly float Evaluate(float x) => x < .5f ? (1f - new EaseOutBounce().Evaluate(1f - 2f * x)) * .5f : (1f + new EaseOutBounce().Evaluate(2f * x - 1f)) * .5f; } +public class EaseInOutBounce : IEasing { public float Evaluate(float x) => x < .5f ? (1f - EaseOutBounce.Instance.Evaluate(1f - 2f * x)) * .5f : (1f + EaseOutBounce.Instance.Evaluate(2f * x - 1f)) * .5f; } diff --git a/Engine.Systems/Tween/Tween.cs b/Engine.Systems/Tween/Tween.cs index a93448d..b9f708a 100644 --- a/Engine.Systems/Tween/Tween.cs +++ b/Engine.Systems/Tween/Tween.cs @@ -43,7 +43,7 @@ internal class Tween : ITween public float Progress { get; internal set; } = 0f; private float _counter = 0f; - public IEasing Easing { get; set; } = new EaseLinear(); + public IEasing Easing { get; set; } = EaseLinear.Instance; public float Value => Easing.Evaluate(Progress); public float Counter