182 lines
5.4 KiB
C#
182 lines
5.4 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Auspex;
|
|
|
|
public readonly struct AxAnimation
|
|
{
|
|
private readonly long _startTimestamp;
|
|
|
|
private readonly float _duration;
|
|
|
|
private readonly AxEasing _easing;
|
|
|
|
private readonly AxRepeatMode _repeatMode;
|
|
|
|
private readonly float _delay;
|
|
|
|
public float Progress
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
if (_duration <= 0f)
|
|
{
|
|
return 1f;
|
|
}
|
|
float num = (float)Stopwatch.GetElapsedTime(_startTimestamp).TotalSeconds - _delay;
|
|
if (num < 0f)
|
|
{
|
|
return 0f;
|
|
}
|
|
float num2 = num / _duration;
|
|
switch (_repeatMode)
|
|
{
|
|
case AxRepeatMode.Repeat:
|
|
num2 -= MathF.Floor(num2);
|
|
break;
|
|
case AxRepeatMode.PingPong:
|
|
{
|
|
int num3 = (int)MathF.Floor(num2);
|
|
num2 -= MathF.Floor(num2);
|
|
if (num3 % 2 == 1)
|
|
{
|
|
num2 = 1f - num2;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
num2 = Math.Clamp(num2, 0f, 1f);
|
|
break;
|
|
}
|
|
return ApplyEasing(num2, _easing);
|
|
}
|
|
}
|
|
|
|
public bool IsComplete
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
get
|
|
{
|
|
if (_repeatMode != AxRepeatMode.None)
|
|
{
|
|
return false;
|
|
}
|
|
if (_duration <= 0f)
|
|
{
|
|
return true;
|
|
}
|
|
return (float)Stopwatch.GetElapsedTime(_startTimestamp).TotalSeconds >= _delay + _duration;
|
|
}
|
|
}
|
|
|
|
private AxAnimation(float duration, AxEasing easing, AxRepeatMode repeatMode, float delay)
|
|
{
|
|
_startTimestamp = Stopwatch.GetTimestamp();
|
|
_duration = duration;
|
|
_easing = easing;
|
|
_repeatMode = repeatMode;
|
|
_delay = delay;
|
|
}
|
|
|
|
public static AxAnimation Start(float duration, AxEasing easing = AxEasing.Linear, AxRepeatMode repeatMode = AxRepeatMode.None, float delay = 0f)
|
|
{
|
|
return new AxAnimation(duration, easing, repeatMode, delay);
|
|
}
|
|
|
|
public static AxAnimation Start(float duration, AxEasing easing, bool repeat)
|
|
{
|
|
return new AxAnimation(duration, easing, repeat ? AxRepeatMode.Repeat : AxRepeatMode.None, 0f);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public uint FadeIn(uint color)
|
|
{
|
|
return AxColor.WithAlpha(color, Progress);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public uint FadeOut(uint color)
|
|
{
|
|
return AxColor.WithAlpha(color, 1f - Progress);
|
|
}
|
|
|
|
public uint Pulse(uint color, float minAlpha = 0f)
|
|
{
|
|
float num = (float)((color >> 24) & 0xFF) / 255f;
|
|
float num2 = 0.5f + 0.5f * MathF.Cos(Progress * 2f * (float)Math.PI);
|
|
uint num3 = (uint)(Math.Clamp(minAlpha + (num - minAlpha) * num2, 0f, 1f) * 255f);
|
|
return (color & 0xFFFFFF) | (num3 << 24);
|
|
}
|
|
|
|
public uint ColorLerp(uint from, uint to)
|
|
{
|
|
return AxColor.Lerp(from, to, Progress);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public float Lerp(float from, float to)
|
|
{
|
|
return from + (to - from) * Progress;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Vector2 Lerp(Vector2 from, Vector2 to)
|
|
{
|
|
return from + (to - from) * Progress;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public Vector3 Lerp(Vector3 from, Vector3 to)
|
|
{
|
|
return from + (to - from) * Progress;
|
|
}
|
|
|
|
internal static float ApplyEasing(float t, AxEasing easing)
|
|
{
|
|
return easing switch
|
|
{
|
|
AxEasing.EaseIn => t * t,
|
|
AxEasing.EaseOut => 1f - (1f - t) * (1f - t),
|
|
AxEasing.EaseInOut => t * t * (3f - 2f * t),
|
|
AxEasing.CubicIn => t * t * t,
|
|
AxEasing.CubicOut => 1f - (1f - t) * (1f - t) * (1f - t),
|
|
AxEasing.CubicInOut => (t < 0.5f) ? (4f * t * t * t) : (1f - MathF.Pow(-2f * t + 2f, 3f) / 2f),
|
|
AxEasing.SineIn => 1f - MathF.Cos(t * (float)Math.PI / 2f),
|
|
AxEasing.SineOut => MathF.Sin(t * (float)Math.PI / 2f),
|
|
AxEasing.SineInOut => (0f - (MathF.Cos((float)Math.PI * t) - 1f)) / 2f,
|
|
AxEasing.ExponentialIn => (t == 0f) ? 0f : MathF.Pow(2f, 10f * t - 10f),
|
|
AxEasing.ExponentialOut => (t == 1f) ? 1f : (1f - MathF.Pow(2f, -10f * t)),
|
|
AxEasing.ExponentialInOut => (t == 0f) ? 0f : ((t == 1f) ? 1f : ((t < 0.5f) ? (MathF.Pow(2f, 20f * t - 10f) / 2f) : ((2f - MathF.Pow(2f, -20f * t + 10f)) / 2f))),
|
|
AxEasing.BackIn => 2.70158f * t * t * t - 1.70158f * t * t,
|
|
AxEasing.BackOut => 1f + 2.70158f * (t - 1f) * (t - 1f) * (t - 1f) + 1.70158f * (t - 1f) * (t - 1f),
|
|
AxEasing.BackInOut => (t < 0.5f) ? (2f * t * (2f * t) * (7.189819f * t - 2.5949094f) / 2f) : (((2f * t - 2f) * (2f * t - 2f) * (3.5949094f * (2f * t - 2f) + 2.5949094f) + 2f) / 2f),
|
|
AxEasing.ElasticIn => (t == 0f) ? 0f : ((t == 1f) ? 1f : ((0f - MathF.Pow(2f, 10f * t - 10f)) * MathF.Sin((10f * t - 10.75f) * ((float)Math.PI * 2f / 3f)))),
|
|
AxEasing.ElasticOut => (t == 0f) ? 0f : ((t == 1f) ? 1f : (MathF.Pow(2f, -10f * t) * MathF.Sin((10f * t - 0.75f) * ((float)Math.PI * 2f / 3f)) + 1f)),
|
|
AxEasing.ElasticInOut => (t == 0f) ? 0f : ((t == 1f) ? 1f : ((t < 0.5f) ? ((0f - MathF.Pow(2f, 20f * t - 10f) * MathF.Sin((20f * t - 11.125f) * ((float)Math.PI * 4f / 9f))) / 2f) : (MathF.Pow(2f, -20f * t + 10f) * MathF.Sin((20f * t - 11.125f) * ((float)Math.PI * 4f / 9f)) / 2f + 1f))),
|
|
AxEasing.BounceIn => 1f - BounceOut(1f - t),
|
|
AxEasing.BounceOut => BounceOut(t),
|
|
AxEasing.BounceInOut => (t < 0.5f) ? ((1f - BounceOut(1f - 2f * t)) / 2f) : ((1f + BounceOut(2f * t - 1f)) / 2f),
|
|
_ => t,
|
|
};
|
|
}
|
|
|
|
private static float BounceOut(float t)
|
|
{
|
|
if (t < 0.36363637f)
|
|
{
|
|
return 7.5625f * t * t;
|
|
}
|
|
if (t < 0.72727275f)
|
|
{
|
|
return 7.5625f * (t -= 0.54545456f) * t + 0.75f;
|
|
}
|
|
if (t < 0.90909094f)
|
|
{
|
|
return 7.5625f * (t -= 0.8181818f) * t + 0.9375f;
|
|
}
|
|
return 7.5625f * (t -= 21f / 22f) * t + 63f / 64f;
|
|
}
|
|
}
|