using UnityEngine; using System.Collections; namespace Watermelon { /// /// MonoBehaviour facade for the tween system. /// Hosts Unity lifecycle hooks (Update / FixedUpdate / LateUpdate) and coroutine support. /// All state and logic lives in ; this class is intentionally thin. /// /// Usage: call once (typically from ), then use /// the static extension methods on Unity objects (e.g. transform.DOMove(...)) or the static /// factory helpers (, , etc.). /// public class Tween : MonoBehaviour { private static Tween instance; private static TweenManager manager; /// /// Direct access to the underlying array (indexed by ). /// Primarily used by tests and advanced tooling; prefer the static API for normal usage. /// public static TweensHolder[] Tweens => manager?.Holders; /// /// Initialises the tween system with pre-allocated arrays for each Unity update loop. /// Must be called exactly once before any tweens are created (done automatically by ). /// /// Initial capacity for tweens. /// Initial capacity for tweens. /// Initial capacity for tweens. public void Init(int tweensUpdateCount, int tweensFixedUpdateCount, int tweensLateUpdateCount) { instance = this; manager = new TweenManager(tweensUpdateCount, tweensFixedUpdateCount, tweensLateUpdateCount); // DontDestroyOnLoad is only valid in Play Mode. // Edit Mode tests (NUnit) skip this without affecting runtime behaviour. if (Application.isPlaying) DontDestroyOnLoad(gameObject); } // ----------------------------------------------------------- // Unity lifecycle — delegate to manager // ----------------------------------------------------------- private void Update() => manager?.UpdateRegular(Time.deltaTime, Time.unscaledDeltaTime); private void FixedUpdate() => manager?.UpdateFixed(Time.fixedDeltaTime, Time.fixedUnscaledDeltaTime); private void LateUpdate() => manager?.UpdateLate(Time.deltaTime, Time.unscaledDeltaTime); private void OnDestroy() { manager?.Unload(); manager = null; instance = null; } // ----------------------------------------------------------- // Static facade — all delegate to manager // ----------------------------------------------------------- /// Registers a tween with the system. Called internally by . public static void AddTween(TweenCase tween) => manager?.AddTween(tween); /// Enqueues a tween for deferred removal. Called internally by . public static void MarkForKilling(TweenCase tween) => manager?.MarkForKilling(tween); /// Pauses all tweens in the specified update loop. public static void Pause(UpdateMethod tweenType) => manager?.Pause(tweenType); /// Pauses all active tweens across every update loop. public static void PauseAll() => manager?.PauseAll(); /// Resumes all tweens in the specified update loop. public static void Resume(UpdateMethod tweenType) => manager?.Resume(tweenType); /// Resumes all paused tweens across every update loop. public static void ResumeAll() => manager?.ResumeAll(); /// Kills all tweens in the specified update loop. public static void Remove(UpdateMethod tweenType) => manager?.Remove(tweenType); /// Kills all active tweens across every update loop. OnComplete callbacks are not fired. public static void RemoveAll() => manager?.RemoveAll(); /// /// Immediately clears all tweens and resets internal state without destroying the MonoBehaviour or its manager. /// Use this before scene reloads instead of — defers cleanup /// to the next Update, which can cause index errors if new tweens are added before that update runs. /// public static void KillAll() => manager?.Unload(); /// /// Begins collecting every subsequently created tween into a single . /// Call to stop collecting. /// /// The collection that will receive all tweens started before is called. public static TweenCaseCollection BeginTweenCaseCollection() => manager?.BeginCollection(); /// Stops populating the active batch collection started by . public static void EndTweenCaseCollection() => manager?.EndCollection(); /// /// Schedules to be invoked after seconds. /// Returns null if <= 0 (the callback is invoked immediately instead). /// Use the .KillActive() extension on the result to safely cancel without a null check. /// public static TweenCase DelayedCall(float delay, SimpleCallback callback, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) => manager?.DelayedCall(delay, callback, unscaledTime, tweenType); /// Interpolates a value and invokes each frame. public static TweenCase DoColor(Color startValue, Color resultValue, float time, SystemTweenCases.ColorCase.TweenColorCallback callback, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) => manager?.DoColor(startValue, resultValue, time, callback, unscaledTime, tweenType); /// Interpolates a value and invokes each frame. public static TweenCase DoFloat(float startValue, float resultValue, float time, SystemTweenCases.Float.TweenFloatCallback callback, float delay = 0.0f, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) => manager?.DoFloat(startValue, resultValue, time, callback, delay, unscaledTime, tweenType); /// /// Runs every frame until it calls tweenCase.Complete(). /// Useful for polling a condition without a fixed duration. /// public static TweenCase DoWaitForCondition(SystemTweenCases.Condition.TweenConditionCallback callback, bool unscaledTime = false, UpdateMethod tweenType = UpdateMethod.Update) => manager?.DoWaitForCondition(callback, unscaledTime, tweenType); /// /// Invokes after frames have elapsed. /// Uses unscaled time by default so it fires regardless of Time.timeScale. /// public static TweenCase NextFrame(SimpleCallback callback, int framesOffset = 1, bool unscaledTime = true, UpdateMethod updateMethod = UpdateMethod.Update) => manager?.NextFrame(callback, framesOffset, unscaledTime, updateMethod); /// Starts a coroutine on the MonoBehaviour, allowing non-MonoBehaviour scripts to run coroutines. public static Coroutine InvokeCoroutine(IEnumerator enumerator) { if (instance == null) return null; return instance.StartCoroutine(enumerator); } /// Stops a coroutine previously started via . public static void StopCustomCoroutine(Coroutine coroutine) { if (instance == null) return; instance.StopCoroutine(coroutine); } /// Stops all coroutines and unloads all tween holders. Used for manual cleanup (e.g. before scene reload). public static void DestroyObject() { if (instance != null) instance.StopAllCoroutines(); manager?.Unload(); } } }