Files
Syntriax.Engine/Engine.Systems/Time/Stopwatch.cs
Syntriax 988a6f67f2 BREAKING CHANGE: renamed original Behaviour class to BehaviourInternal, and replaced it with BehaviourBase
Original Behaviour was using old methods for detecting entering/exiting universe,
they are now all under the same hood and the original is kept for UniverseEntranceManager
because it needs to enter the universe without itself. The internal behaviour kept under
a subnamespace of "Core.Internal" for the purpose that it might come in handy for other use cases.
2025-10-22 16:50:19 +03:00

101 lines
2.3 KiB
C#

using Engine.Core;
namespace Engine.Systems.Time;
public class Stopwatch : Behaviour, IUpdate, IEnterUniverse, IExitUniverse, IStopwatch
{
public Event<IReadOnlyStopwatch> OnStarted { get; } = new();
public Event<IReadOnlyStopwatch, IReadOnlyStopwatch.StopwatchDeltaArguments> OnDelta { get; } = new();
public Event<IReadOnlyStopwatch> OnStopped { get; } = new();
public Event<IReadOnlyStopwatch> OnPaused { get; } = new();
public Event<IReadOnlyStopwatch> 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));
}
public void EnterUniverse(IUniverse universe)
{
if (!shouldBeTicking || State is TimerState.Ticking)
return;
if (hasStartedTickingBefore)
Resume();
else
StartStopwatch();
}
public void ExitUniverse(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 FinalizeInternal()
{
base.FinalizeInternal();
Time = 0f;
State = TimerState.Idle;
shouldBeTicking = false;
hasStartedTickingBefore = false;
}
}