using System.Collections; using System.Collections.Generic; using Syntriax.Engine.Core; namespace Syntriax.Engine.Systems.Tween; public class TweenManager : UniverseObject, ITweenManager { private CoroutineManager coroutineManager = null!; private readonly Queue queue = new(); private readonly Dictionary runningCoroutines = []; public ITween StartTween(float duration, ITweenManager.TweenSetCallback? setCallback = null) { Tween tween = Get(duration); tween.OnUpdated.AddListener(tween => setCallback?.Invoke(tween.Value)); runningCoroutines.Add(tween, coroutineManager.StartCoroutine(RunTween(tween))); return tween; } private Tween Get(float duration) { if (!queue.TryDequeue(out Tween? result)) result = new(duration); result.Duration = duration; return result; } private void Return(Tween tween) { if (queue.Contains(tween)) return; tween.Reset(); queue.Enqueue(tween); } private IEnumerator RunTween(Tween tween) { tween.State = TweenState.Playing; yield return null; while (true) { if (tween.State.CheckFlag(TweenState.Cancelled | TweenState.Completed)) break; if (tween.State.CheckFlag(TweenState.Paused)) { yield return null; continue; } tween.Counter += Universe.Time.DeltaTime; yield return null; } runningCoroutines.Remove(tween); Return(tween); } public void CancelTween(ITween tween) { if (!runningCoroutines.TryGetValue(tween, out IEnumerator? runningCoroutine)) return; tween.State = TweenState.Cancelled; coroutineManager.StopCoroutine(runningCoroutine); runningCoroutines.Remove(tween); } protected override void OnEnteringUniverse(IUniverse universe) { coroutineManager = universe.GetRequiredUniverseObject(); } protected override void OnExitingUniverse(IUniverse universe) { coroutineManager = null!; } }