using Syntriax.Engine.Core; using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Systems.Time; public class StopwatchBehaviour : Behaviour, IStopwatch { public event IReadOnlyStopwatch.StopwatchEventHandler? OnStarted = null; public event IReadOnlyStopwatch.StopwatchDeltaEventHandler? OnDelta = null; public event IReadOnlyStopwatch.StopwatchEventHandler? OnStopped = null; public event IReadOnlyStopwatch.StopwatchEventHandler? OnPaused = null; public event IReadOnlyStopwatch.StopwatchEventHandler? OnResumed = null; 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); } protected override void OnUpdate() { if (State is not TimerState.Ticking) return; double delta = GameManager.Time.DeltaSpan.TotalSeconds; Time += delta; OnDelta?.Invoke(this, delta); } protected override void OnEnteredHierarchy(IGameManager gameManager) { if (!shouldBeTicking || State is TimerState.Ticking) return; if (hasStartedTickingBefore) Resume(); else StartStopwatch(); } protected override void OnExitedHierarchy(IGameManager gameManager) { 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; } }