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.
101 lines
2.3 KiB
C#
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;
|
|
}
|
|
}
|