using Syntriax.Engine.Core; namespace Syntriax.Engine.Systems.Time; public class StopwatchBehaviour : Behaviour, IUpdate, IStopwatch { public Event OnStarted { get; } = new(); public Event OnDelta { get; } = new(); public Event OnStopped { get; } = new(); public Event OnPaused { get; } = new(); public Event OnResumed { get; } = new(); public double Time { get; protected set; } = 0f; public TimerState State { get; protected set; } = TimerState.Idle; private bool shouldBeTicking = false; private bool hasStartedTickingBefore = false; public virtual void Start() { Time = 0f; shouldBeTicking = true; hasStartedTickingBefore = false; if (IsActive) StartStopwatch(); } public virtual void Stop() { if (!shouldBeTicking) return; shouldBeTicking = false; State = TimerState.Stopped; OnStopped?.Invoke(this); } public virtual void Update() { if (State is not TimerState.Ticking) return; double delta = Universe.Time.DeltaSpan.TotalSeconds; Time += delta; OnDelta?.Invoke(this, new(delta)); } protected override void OnEnteredUniverse(IUniverse universe) { if (!shouldBeTicking || State is TimerState.Ticking) return; if (hasStartedTickingBefore) Resume(); else StartStopwatch(); } protected override void OnExitedUniverse(IUniverse universe) { if (!shouldBeTicking || State is not TimerState.Ticking) return; Pause(); } public virtual void Pause() { State = TimerState.Paused; OnPaused?.Invoke(this); } public virtual void Resume() { State = TimerState.Ticking; OnResumed?.Invoke(this); } private void StartStopwatch() { hasStartedTickingBefore = true; State = TimerState.Ticking; OnStarted?.Invoke(this); } protected override void OnFinalize() { Time = 0f; State = TimerState.Idle; shouldBeTicking = false; hasStartedTickingBefore = false; } }