using UnityEngine; namespace Watermelon { /// /// Core tween engine. Owns all instances and orchestrates /// tween registration, update routing, pause/resume, and factory helpers. /// (the MonoBehaviour) is a thin facade that delegates every call here. /// public class TweenManager { private TweensHolder[] holders; /// /// One per (index 0 = Update, 1 = FixedUpdate, 2 = LateUpdate). /// public TweensHolder[] Holders => holders; private TweenCaseCollection activeCollection; private bool isCollectionEnabled; /// /// Creates a manager with three instances — one per Unity update loop. /// /// Initial capacity for tweens. /// Initial capacity for tweens. /// Initial capacity for tweens. public TweenManager(int updateCount, int fixedCount, int lateCount) { holders = new TweensHolder[] { new TweensHolder(UpdateMethod.Update, updateCount), new TweensHolder(UpdateMethod.FixedUpdate, fixedCount), new TweensHolder(UpdateMethod.LateUpdate, lateCount) }; } // ----------------------------------------------------------- // Core tween management // ----------------------------------------------------------- /// /// Registers in the appropriate based on its /// . If a batch collection is active (see ), /// the tween is also added to it. /// public void AddTween(TweenCase tween) { holders[tween.UpdateMethodIndex].AddTween(tween); if (isCollectionEnabled) activeCollection.AddTween(tween); } /// /// Forwards the kill request to the appropriate for deferred removal. /// Called by . /// public void MarkForKilling(TweenCase tween) { holders[tween.UpdateMethodIndex].MarkForKilling(tween); } // ----------------------------------------------------------- // Pause / Resume / Remove // ----------------------------------------------------------- /// Pauses all tweens running in the specified loop. public void Pause(UpdateMethod tweenType) => holders[(int)tweenType].Pause(); /// Resumes all tweens running in the specified loop. public void Resume(UpdateMethod tweenType) => holders[(int)tweenType].Resume(); /// Kills all tweens running in the specified loop. public void Remove(UpdateMethod tweenType) => holders[(int)tweenType].Kill(); /// Pauses all tweens across every update loop. public void PauseAll() { foreach (var h in holders) h.Pause(); } /// Resumes all tweens across every update loop. public void ResumeAll() { foreach (var h in holders) h.Resume(); } /// Kills all tweens across every update loop. OnComplete callbacks are not fired. public void RemoveAll() { foreach (var h in holders) h.Kill(); } // ----------------------------------------------------------- // Collection batch tracking // ----------------------------------------------------------- /// /// Starts collecting every subsequently created tween into a new . /// Call to stop collecting. /// /// The newly created collection that will receive tweens until is called. public TweenCaseCollection BeginCollection() { isCollectionEnabled = true; activeCollection = new TweenCaseCollection(); return activeCollection; } /// Stops populating the active batch collection. Tweens created after this call are not added to any collection. public void EndCollection() { isCollectionEnabled = false; activeCollection = null; } // ----------------------------------------------------------- // Update — called by Tween MonoBehaviour each Unity event // ----------------------------------------------------------- /// Drives the holder. Called from MonoBehaviour.Update. public void UpdateRegular(float dt, float udt) => holders[0].Update(dt, udt); /// Drives the holder. Called from MonoBehaviour.FixedUpdate. public void UpdateFixed(float dt, float udt) => holders[1].Update(dt, udt); /// Drives the holder. Called from MonoBehaviour.LateUpdate. public void UpdateLate(float dt, float udt) => holders[2].Update(dt, udt); // ----------------------------------------------------------- // Lifecycle // ----------------------------------------------------------- /// /// Unloads all holders and resets collection state. /// Called when the MonoBehaviour is destroyed. /// public void Unload() { foreach (var h in holders) h.Unload(); activeCollection = null; isCollectionEnabled = false; } // ----------------------------------------------------------- // Factory helpers (mirrors Tween static API) // ----------------------------------------------------------- /// /// Schedules to be invoked after seconds. /// Returns null if delay is <= 0 (the callback is invoked immediately instead). /// Use the .KillActive() extension on the result to safely cancel without a null check. /// public TweenCase DelayedCall(float delay, SimpleCallback callback, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) { if (delay <= 0) { callback?.Invoke(); return null; } return new SystemTweenCases.Default() .SetDuration(delay) .SetUnscaledMode(unscaledTime) .OnComplete(callback) .SetUpdateMethod(tweenType) .StartTween(); } /// Interpolates a value from to over seconds, invoking each frame. public TweenCase DoColor(Color startValue, Color resultValue, float time, SystemTweenCases.ColorCase.TweenColorCallback callback, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) { return new SystemTweenCases.ColorCase(startValue, resultValue, callback) .SetDuration(time) .SetUnscaledMode(unscaledTime) .SetUpdateMethod(tweenType) .StartTween(); } /// Interpolates a value from to over seconds, invoking each frame. public TweenCase DoFloat(float startValue, float resultValue, float time, SystemTweenCases.Float.TweenFloatCallback callback, float delay = 0.0f, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) { return new SystemTweenCases.Float(startValue, resultValue, callback) .SetDelay(delay) .SetDuration(time) .SetUnscaledMode(unscaledTime) .SetUpdateMethod(tweenType) .StartTween(); } /// /// Runs every frame until it calls tweenCase.Complete(). /// Useful for polling conditions that don't have a fixed duration. /// public TweenCase DoWaitForCondition(SystemTweenCases.Condition.TweenConditionCallback callback, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) { return new SystemTweenCases.Condition(callback) .SetDuration(float.MaxValue) .SetUnscaledMode(unscaledTime) .SetUpdateMethod(tweenType) .StartTween(); } /// /// Invokes after frames have passed. /// Uses unscaled time by default so it works regardless of Time.timeScale. /// public TweenCase NextFrame(SimpleCallback callback, int framesOffset = 1, bool unscaledTime = true, UpdateMethod updateMethod = UpdateMethod.Update) { return new SystemTweenCases.NextFrame(callback, framesOffset) .SetDuration(float.MaxValue) .SetUnscaledMode(unscaledTime) .SetUpdateMethod(updateMethod) .StartTween(); } } }