using Syntriax.Engine.Core; using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Systems.Time; public class TimerBehaviour : Behaviour, ITimer { public event IReadOnlyTimer.TimerEventHandler? OnStarted = null; public event IReadOnlyTimer.TimerDeltaEventHandler? OnDelta = null; public event IReadOnlyTimer.TimerEventHandler? OnStopped = null; public event IReadOnlyTimer.TimerEventHandler? OnPaused = null; public event IReadOnlyTimer.TimerEventHandler? OnResumed = null; public TimerState State { get; protected set; } = TimerState.Idle; public double StartTime { get; protected set; } = 0f; public float Percentage => (float)(1f - (Remaining / StartTime)); private double _remaining = 0f; public double Remaining { get => _remaining; protected set { if (value < .0f) value = .0f; _remaining = value; } } private bool shouldBeTicking = false; private bool hasStartedTickingBefore = false; public virtual void Start(double time) { StartTime = time; Remaining = time; shouldBeTicking = true; hasStartedTickingBefore = false; if (IsActive) StartTimer(); } 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; Remaining -= delta; OnDelta?.Invoke(this, delta); if (Remaining <= .0f) Stop(); } protected override void OnEnteredHierarchy(IGameManager gameManager) { if (!shouldBeTicking || State is TimerState.Ticking) return; if (hasStartedTickingBefore) Resume(); else StartTimer(); } 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 StartTimer() { hasStartedTickingBefore = true; State = TimerState.Ticking; OnStarted?.Invoke(this); } protected override void OnFinalize() { StartTime = 0f; Remaining = 0f; State = TimerState.Idle; shouldBeTicking = false; hasStartedTickingBefore = false; } }