using System; using System.Diagnostics; using System.Linq.Expressions; using MonoGame.Extended.Animations; namespace MonoGame.Extended.Tweening { public class PropertyTween : Animation where T : struct { protected static Func Add; protected static Func Subtract; protected static Func Multiply; private readonly Func _getValue; private readonly Action _setValue; private float _currentMultiplier; private T? _initialValue; static PropertyTween() { var a = Expression.Parameter(typeof(T)); var b = Expression.Parameter(typeof(T)); var c = Expression.Parameter(typeof(float)); Add = Expression.Lambda>(Expression.Add(a, b), a, b).Compile(); Subtract = Expression.Lambda>(Expression.Subtract(a, b), a, b).Compile(); Multiply = Expression.Lambda>(Expression.Multiply(a, c), a, c).Compile(); } public PropertyTween(Func getValue, Action setValue, T targetValue, float duration, EasingFunction easingFunction) : base(null, true) { _getValue = getValue; _setValue = setValue; TargetValue = targetValue; Duration = duration; EasingFunction = easingFunction; } public T TargetValue { get; } public float Duration { get; } public EasingFunction EasingFunction { get; set; } protected override bool OnUpdate(float deltaTime) { if (!_initialValue.HasValue) _initialValue = _getValue(); _currentMultiplier = EasingFunction(CurrentTime/Duration); var isComplete = CurrentTime >= Duration; if (isComplete) { CurrentTime = Duration; _currentMultiplier = 1.0f; } // ReSharper disable PossibleInvalidOperationException var difference = Subtract(TargetValue, _initialValue.Value); var multiply = Multiply(difference, _currentMultiplier); var newValue = Add(_initialValue.Value, multiply); // ReSharper restore PossibleInvalidOperationException _setValue(newValue); return isComplete; } } }