using System; using UnityEngine; namespace Cryville.Common.Unity { public class PropertyTweener { readonly Func _getter; readonly Action _setter; readonly Tweener _tweener; public PropertyTweener(Func getter, Action setter, Tweener tweener) { _getter = getter; _setter = setter; _tweener = tweener; } public PropertyTweener Start(T endValue, float duration) { _tweener.Start(_getter(), endValue, duration); return this; } public void Advance(float deltaTime) { _setter(_tweener.Advance(deltaTime)); } } public class Tweener { readonly Func _addition; readonly Func _multiplication; public Tweener(Func addition, Func multiplication) { _addition = addition; _multiplication = multiplication; } public Func EasingFunction { get; set; } = EasingFunctions.Linear; public Tweener SetEasingFunction(Func easing) { EasingFunction = easing; return this; } T _startValue = default; T _endValue = default; float _duration = float.PositiveInfinity; float _time; public Tweener Start(T startValue, T endValue, float duration) { _startValue = startValue; _endValue = endValue; _duration = duration; _time = 0; return this; } public T Advance(float deltaTime) { _time += deltaTime; var ratio = EasingFunction(Math.Clamp(_time / _duration, 0, 1)); return _addition(_multiplication(1 - ratio, _startValue), _multiplication(ratio, _endValue)); } } public static class Tweeners { public static Tweener Int32 => new((a, b) => a + b, (k, v) => (int)(k * v)); public static Tweener Single => new((a, b) => a + b, (k, v) => k * v); public static Tweener Double => new((a, b) => a + b, (k, v) => k * v); public static Tweener Vector2 => new((a, b) => a + b, (k, v) => k * v); public static Tweener Vector3 => new((a, b) => a + b, (k, v) => k * v); public static Tweener Quaternion => new((a, b) => a * b, (k, v) => UnityEngine.Quaternion.Slerp(UnityEngine.Quaternion.identity, v, k)); } public static class EasingFunctions { public static float Linear(float x) => x; public static float InQuad(float x) => x * x; public static float InCubic(float x) => x * x * x; public static float InSine(float x) => 1 - OutSine(1 - x); public static float OutQuad(float x) => 1 - InQuad(1 - x); public static float OutCubic(float x) => 1 - InCubic(1 - x); public static float OutSine(float x) => MathF.Sin(x * MathF.PI / 2); } }