using T3.Core.Animation; using T3.Core.Utils; using static T3.Core.Utils.EasingFunctions; namespace Lib.numbers.@vec3.process; [Guid("0ecb95ca-7db2-4a11-a6e5-214ae91ec268")] internal sealed class EaseVec3Keys : Instance { [Output(Guid = "b022aed3-1667-474f-b24e-107b3257e13c", DirtyFlagTrigger = DirtyFlagTrigger.Animated)] public readonly Slot Result = new(); public EaseVec3Keys() { Result.UpdateAction = Update; } private void Update(EvaluationContext context) { var inputValue = Value.GetValue(context); if (!TryFindCurves(out var curves)) { Result.Value = inputValue; return; } var easeMode = Interpolation.GetEnumValue(context); // Easing function selector var easeDirection = Direction.GetEnumValue(context); var currentTime = context.LocalTime; for (var i = 0; i < curves.Length; i++) { var curve = curves[i]; _keyframes = curve.GetVDefinitions().ToList(); float duration; if ( TryFindClosestKeys(currentTime, curve, out var nearestKeys) && nearestKeys.Item1.OutInterpolation != VDefinition.KeyInterpolation.Constant ) { var (previousKey, nextKey) = nearestKeys; _startTime[i] = (float)previousKey.U; _initialValue[i] = (float)previousKey.Value; _targetValue[i] = (float)nextKey.Value; duration = Math.Max((float)(nextKey.U - previousKey.U), 0.0001f); } else { Result.Value[i] = inputValue[i]; continue; } // Calculate progress based on elapsed time and duration var elapsedTime = (float)currentTime - _startTime[i]; var progress = (elapsedTime / duration).Clamp(0f, 1f); var easedProgress = ApplyEasing(progress, easeDirection, easeMode); Result.Value[i] = MathUtils.Lerp(_initialValue[i], _targetValue[i], easedProgress); } } private bool TryFindCurves(out Curve[] curves) { curves = null; var animator = Parent.Symbol.Animator; _keyframes.Clear(); if (!animator.IsAnimated(SymbolChildId, Value.Id)) return false; if (!animator.TryGetCurvesForInputSlot(Value, out var _curves)) return false; if (_curves.Length == 0) return false; curves = _curves; return true; } private static bool TryFindClosestKeys(double time, Curve curve, out Tuple closestKeys) { closestKeys = null; curve.TryGetPreviousKey(time, out var previousKey); curve.TryGetNextKey(time, out var nextKey); if (previousKey == null || nextKey == null) { return false; } closestKeys = new(previousKey, nextKey); return true; } private List _keyframes = []; // Ease.cs private Vector3 _startTime = Vector3.Zero; private Vector3 _initialValue = Vector3.Zero; private Vector3 _targetValue = Vector3.Zero; [Input(Guid = "48d7bfd8-54c3-4c1b-bee4-92aaa735cc85")] public readonly InputSlot Value = new(); [Input(Guid = "fa9c6388-a7eb-4424-956b-dc1b7f2486bc", MappedType = typeof(EaseDirection))] public readonly InputSlot Direction = new(); [Input(Guid = "4b8c9c9b-37fa-4c50-ac65-4c5a20e56d2f", MappedType = typeof(Interpolations))] public readonly InputSlot Interpolation = new(); }