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.
This commit is contained in:
2025-10-22 16:50:19 +03:00
parent 2f32038f04
commit 988a6f67f2
23 changed files with 194 additions and 185 deletions

View File

@@ -1,50 +1,103 @@
namespace Engine.Core;
public abstract class Behaviour : BehaviourBase
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
public abstract class Behaviour : BaseEntity, IBehaviour
{
private readonly Event<IUniverseObject, IUniverseObject.EnteredUniverseArguments>.EventHandler delegateEnteredUniverse = null!;
private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateExitedUniverse = null!;
public Event<IBehaviour, IBehaviour.PriorityChangedArguments> OnPriorityChanged { get; } = new();
public Event<IActive, IActive.ActiveChangedArguments> OnActiveChanged { get; } = new();
public Event<IHasBehaviourController> OnBehaviourControllerAssigned { get; } = new();
public Behaviour()
private readonly Event<IHasUniverseObject>.EventHandler delegateOnUniverseObjectAssigned = null!;
private readonly Event<IActive, IActive.ActiveChangedArguments>.EventHandler delegateOnUniverseObjectActiveChanged = null!;
private readonly Event<IStateEnable, IStateEnable.EnabledChangedArguments>.EventHandler delegateOnStateEnabledChanged = null!;
public IUniverse Universe => BehaviourController.UniverseObject.Universe;
public IUniverseObject UniverseObject => BehaviourController.UniverseObject;
private IBehaviourController _behaviourController = null!;
public IBehaviourController BehaviourController => _behaviourController;
private int _priority = 0;
public int Priority
{
OnInitialized.AddListener(OnInitialize);
OnFinalized.AddListener(OnFinalize);
OnUnassigned.AddListener(OnUnassign);
get => _priority;
set
{
if (value == _priority)
return;
delegateEnteredUniverse = EnteredUniverse;
delegateExitedUniverse = ExitedUniverse;
int previousPriority = _priority;
_priority = value;
OnPriorityChanged?.Invoke(this, new(previousPriority));
}
}
protected virtual void OnUnassign() { }
protected void OnUnassign(IAssignable assignable) => OnUnassign();
private bool _isActive = false;
public bool IsActive => _isActive;
protected virtual void OnInitialize() { }
protected void OnInitialize(IInitializable _)
protected virtual void OnAssign(IBehaviourController behaviourController) { }
public bool Assign(IBehaviourController behaviourController)
{
BehaviourController.UniverseObject.OnEnteredUniverse.AddListener(delegateEnteredUniverse);
BehaviourController.UniverseObject.OnExitedUniverse.AddListener(delegateExitedUniverse);
if (IsInitialized)
return false;
OnInitialize();
if (UniverseObject.IsInUniverse)
EnteredUniverse(UniverseObject, new(Universe));
_behaviourController = behaviourController;
OnAssign(behaviourController);
behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
if (behaviourController.UniverseObject is not null)
OnUniverseObjectAssigned(behaviourController);
OnBehaviourControllerAssigned?.Invoke(this);
return true;
}
protected virtual void OnFinalize() { }
protected void OnFinalize(IInitializable _)
private void OnUniverseObjectAssigned(IHasUniverseObject sender)
{
BehaviourController.UniverseObject.OnEnteredUniverse.RemoveListener(delegateEnteredUniverse);
BehaviourController.UniverseObject.OnExitedUniverse.RemoveListener(delegateExitedUniverse);
OnFinalize();
if (UniverseObject.IsInUniverse)
ExitedUniverse(UniverseObject, new(Universe));
sender.UniverseObject.OnActiveChanged.AddListener(delegateOnUniverseObjectActiveChanged);
UpdateActive();
}
protected virtual void OnEnteredUniverse(IUniverse universe) { }
protected void EnteredUniverse(IUniverseObject sender, IUniverseObject.EnteredUniverseArguments args) => OnEnteredUniverse(args.Universe);
protected override void OnAssign(IStateEnable stateEnable)
{
base.OnAssign(stateEnable);
protected virtual void OnExitedUniverse(IUniverse universe) { }
protected void ExitedUniverse(IUniverseObject sender, IUniverseObject.ExitedUniverseArguments args) => OnExitedUniverse(args.Universe);
stateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
}
protected override void UnassignInternal()
{
BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
base.UnassignInternal();
_behaviourController = null!;
}
protected override void InitializeInternal()
{
Debug.Assert.AssertBehaviourControllerAssigned(this);
Debug.Assert.AssertStateEnableAssigned(this);
UpdateActive();
}
private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
private void OnUniverseObjectActiveChanged(IActive sender, IActive.ActiveChangedArguments args) => UpdateActive();
private void UpdateActive()
{
bool previousActive = IsActive;
_isActive = StateEnable.Enabled && _behaviourController.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
if (previousActive != IsActive)
OnActiveChanged?.Invoke(this, new(previousActive));
}
protected Behaviour()
{
delegateOnUniverseObjectAssigned = OnUniverseObjectAssigned;
delegateOnUniverseObjectActiveChanged = OnUniverseObjectActiveChanged;
delegateOnStateEnabledChanged = OnStateEnabledChanged;
}
}

View File

@@ -1,6 +1,7 @@
namespace Engine.Core;
public abstract class Behaviour2D : Behaviour, IBehaviour2D
// TODO this should not use independent behaviour, the OnInitialize usage for getting the transform can cause very unexpected issues
public abstract class Behaviour2D : Internal.BehaviourIndependent, IBehaviour2D
{
public ITransform2D Transform { get; private set; } = null!;

View File

@@ -1,103 +0,0 @@
namespace Engine.Core;
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
public abstract class BehaviourBase : BaseEntity, IBehaviour
{
public Event<IBehaviour, IBehaviour.PriorityChangedArguments> OnPriorityChanged { get; } = new();
public Event<IActive, IActive.ActiveChangedArguments> OnActiveChanged { get; } = new();
public Event<IHasBehaviourController> OnBehaviourControllerAssigned { get; } = new();
private readonly Event<IHasUniverseObject>.EventHandler delegateOnUniverseObjectAssigned = null!;
private readonly Event<IActive, IActive.ActiveChangedArguments>.EventHandler delegateOnUniverseObjectActiveChanged = null!;
private readonly Event<IStateEnable, IStateEnable.EnabledChangedArguments>.EventHandler delegateOnStateEnabledChanged = null!;
public IUniverse Universe => BehaviourController.UniverseObject.Universe;
public IUniverseObject UniverseObject => BehaviourController.UniverseObject;
private IBehaviourController _behaviourController = null!;
public IBehaviourController BehaviourController => _behaviourController;
private int _priority = 0;
public int Priority
{
get => _priority;
set
{
if (value == _priority)
return;
int previousPriority = _priority;
_priority = value;
OnPriorityChanged?.Invoke(this, new(previousPriority));
}
}
private bool _isActive = false;
public bool IsActive => _isActive;
protected virtual void OnAssign(IBehaviourController behaviourController) { }
public bool Assign(IBehaviourController behaviourController)
{
if (IsInitialized)
return false;
_behaviourController = behaviourController;
OnAssign(behaviourController);
behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
if (behaviourController.UniverseObject is not null)
OnUniverseObjectAssigned(behaviourController);
OnBehaviourControllerAssigned?.Invoke(this);
return true;
}
private void OnUniverseObjectAssigned(IHasUniverseObject sender)
{
sender.UniverseObject.OnActiveChanged.AddListener(delegateOnUniverseObjectActiveChanged);
UpdateActive();
}
protected override void OnAssign(IStateEnable stateEnable)
{
base.OnAssign(stateEnable);
stateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
}
protected override void UnassignInternal()
{
BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
base.UnassignInternal();
_behaviourController = null!;
}
protected override void InitializeInternal()
{
Debug.Assert.AssertBehaviourControllerAssigned(this);
Debug.Assert.AssertStateEnableAssigned(this);
UpdateActive();
}
private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
private void OnUniverseObjectActiveChanged(IActive sender, IActive.ActiveChangedArguments args) => UpdateActive();
private void UpdateActive()
{
bool previousActive = IsActive;
_isActive = StateEnable.Enabled && _behaviourController.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
if (previousActive != IsActive)
OnActiveChanged?.Invoke(this, new(previousActive));
}
protected BehaviourBase()
{
delegateOnUniverseObjectAssigned = OnUniverseObjectAssigned;
delegateOnUniverseObjectActiveChanged = OnUniverseObjectActiveChanged;
delegateOnStateEnabledChanged = OnStateEnabledChanged;
}
}

View File

@@ -0,0 +1,56 @@
namespace Engine.Core.Internal;
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
/// <summary>
/// This behaviour can be used for core managers like <see cref="UpdateManager"/> etc. which need to be able to work even
/// in a very bare minimum setup without the presence of <see cref="UniverseEntranceManager"/> to set themselves up on universe entrance.
/// I recommend not using this unless you know what you are doing but it might come in handy for some use cases.
/// </summary>
public abstract class BehaviourIndependent : Behaviour
{
private readonly Event<IUniverseObject, IUniverseObject.EnteredUniverseArguments>.EventHandler delegateEnteredUniverse = null!;
private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateExitedUniverse = null!;
public BehaviourIndependent()
{
OnInitialized.AddListener(OnInitialize);
OnFinalized.AddListener(OnFinalize);
OnUnassigned.AddListener(OnUnassign);
delegateEnteredUniverse = EnteredUniverse;
delegateExitedUniverse = ExitedUniverse;
}
protected virtual void OnUnassign() { }
protected void OnUnassign(IAssignable assignable) => OnUnassign();
protected virtual void OnInitialize() { }
protected void OnInitialize(IInitializable _)
{
BehaviourController.UniverseObject.OnEnteredUniverse.AddListener(delegateEnteredUniverse);
BehaviourController.UniverseObject.OnExitedUniverse.AddListener(delegateExitedUniverse);
OnInitialize();
if (UniverseObject.IsInUniverse)
EnteredUniverse(UniverseObject, new(Universe));
}
protected virtual void OnFinalize() { }
protected void OnFinalize(IInitializable _)
{
BehaviourController.UniverseObject.OnEnteredUniverse.RemoveListener(delegateEnteredUniverse);
BehaviourController.UniverseObject.OnExitedUniverse.RemoveListener(delegateExitedUniverse);
OnFinalize();
if (UniverseObject.IsInUniverse)
ExitedUniverse(UniverseObject, new(Universe));
}
protected virtual void OnEnteredUniverse(IUniverse universe) { }
protected void EnteredUniverse(IUniverseObject sender, IUniverseObject.EnteredUniverseArguments args) => OnEnteredUniverse(args.Universe);
protected virtual void OnExitedUniverse(IUniverse universe) { }
protected void ExitedUniverse(IUniverseObject sender, IUniverseObject.ExitedUniverseArguments args) => OnExitedUniverse(args.Universe);
}

View File

@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Engine.Core;
public class DrawManager : Behaviour
public class DrawManager : Behaviour, IEnterUniverse, IExitUniverse
{
// We use Descending order because draw calls are running from last to first
private static Comparer<int> SortByDescendingPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
@@ -30,7 +30,7 @@ public class DrawManager : Behaviour
postDrawEntities[i].PostDraw();
}
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
preDrawEntities.Assign(universe);
drawEntities.Assign(universe);
@@ -41,7 +41,7 @@ public class DrawManager : Behaviour
universe.OnPostDraw.AddListener(OnPostDraw);
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
preDrawEntities.Unassign();
drawEntities.Unassign();

View File

@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Engine.Core;
public class UniverseEntranceManager : Behaviour
public class UniverseEntranceManager : Internal.BehaviourIndependent
{
// We use Ascending order because we are using reverse for loop to call them
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));

View File

@@ -2,7 +2,7 @@ using System.Collections.Generic;
namespace Engine.Core;
public class UpdateManager : Behaviour
public class UpdateManager : Behaviour, IEnterUniverse, IExitUniverse
{
// We use Ascending order because we are using reverse for loop to call them
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
@@ -16,7 +16,7 @@ public class UpdateManager : Behaviour
private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
firstFrameUpdates.Assign(universe);
lastFrameUpdates.Assign(universe);
@@ -30,7 +30,7 @@ public class UpdateManager : Behaviour
universe.OnPostUpdate.AddListener(OnPostUpdate);
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
firstFrameUpdates.Unassign();
lastFrameUpdates.Unassign();

View File

@@ -56,17 +56,17 @@ public class LiteNetLibClient : LiteNetLibCommunicatorBase, INetworkCommunicator
return this;
}
protected override void OnEnteredUniverse(IUniverse universe)
public override void EnterUniverse(IUniverse universe)
{
base.OnEnteredUniverse(universe);
base.EnterUniverse(universe);
cancellationTokenSource = new CancellationTokenSource();
PollEvents(cancellationTokenSource.Token);
}
protected override void OnExitedUniverse(IUniverse universe)
public override void ExitUniverse(IUniverse universe)
{
base.OnExitedUniverse(universe);
base.ExitUniverse(universe);
cancellationTokenSource?.Cancel();
}

View File

@@ -9,7 +9,7 @@ using LiteNetLib.Utils;
namespace Engine.Systems.Network;
public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicator
public abstract class LiteNetLibCommunicatorBase : Behaviour, IEnterUniverse, IExitUniverse, INetworkCommunicator
{
protected readonly NetPacketProcessor netPacketProcessor = new();
@@ -33,15 +33,13 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat
return this;
}
protected override void OnEnteredUniverse(IUniverse universe)
public virtual void EnterUniverse(IUniverse universe)
{
base.OnEnteredUniverse(universe);
logger = universe.FindBehaviour<ILogger>();
}
protected override void OnExitedUniverse(IUniverse universe)
public virtual void ExitUniverse(IUniverse universe)
{
base.OnExitedUniverse(universe);
logger = null;
Stop();
}

View File

@@ -88,15 +88,15 @@ public class LiteNetLibServer : LiteNetLibCommunicatorBase, INetworkCommunicator
private void PollEvents(IUniverse sender, IUniverse.UpdateArguments args) => Manager.PollEvents();
protected override void OnEnteredUniverse(IUniverse universe)
public override void EnterUniverse(IUniverse universe)
{
base.OnEnteredUniverse(universe);
base.EnterUniverse(universe);
universe.OnPostUpdate.AddListener(PollEvents);
}
protected override void OnExitedUniverse(IUniverse universe)
public override void ExitUniverse(IUniverse universe)
{
base.OnExitedUniverse(universe);
base.ExitUniverse(universe);
universe.OnPostUpdate.RemoveListener(PollEvents);
}
}

View File

@@ -4,7 +4,7 @@ using Engine.Core;
namespace Engine.Integration.MonoGame;
public class LoadContentManager : Behaviour, IFirstFrameUpdate
public class LoadContentManager : Behaviour, IEnterUniverse, IExitUniverse, IFirstFrameUpdate
{
// We use Ascending order because we are using reverse for loop to call them
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
@@ -20,14 +20,14 @@ public class LoadContentManager : Behaviour, IFirstFrameUpdate
monoGameWindowContainer = Universe.FindRequiredBehaviour<MonoGameWindowContainer>();
}
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
loadContents.Assign(universe);
universe.OnPreUpdate.AddListener(OnPreUpdate);
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
loadContents.Unassign();

View File

@@ -5,7 +5,7 @@ using Engine.Core;
namespace Engine.Integration.MonoGame;
public class MonoGameCamera2D : BehaviourBase, ICamera2D, IFirstFrameUpdate, IPreDraw
public class MonoGameCamera2D : Behaviour, ICamera2D, IFirstFrameUpdate, IPreDraw
{
public Event<MonoGameCamera2D> OnMatrixTransformChanged { get; } = new();
public Event<MonoGameCamera2D> OnViewportChanged { get; } = new();

View File

@@ -5,7 +5,7 @@ using Engine.Core;
namespace Engine.Integration.MonoGame;
public class MonoGameCamera3D : BehaviourBase, ICamera3D, IFirstFrameUpdate, IPreDraw
public class MonoGameCamera3D : Behaviour, ICamera3D, IFirstFrameUpdate, IPreDraw
{
public Event<MonoGameCamera3D, ViewChangedArguments> OnViewChanged { get; } = new();
public Event<MonoGameCamera3D, ProjectionChangedArguments> OnProjectionChanged { get; } = new();

View File

@@ -4,7 +4,7 @@ using Engine.Core;
namespace Engine.Integration.MonoGame;
public class SpriteBatcher : BehaviourBase, IFirstFrameUpdate, IDraw
public class SpriteBatcher : Behaviour, IFirstFrameUpdate, IDraw
{
private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;

View File

@@ -6,7 +6,7 @@ using Engine.Core;
namespace Engine.Integration.MonoGame;
public class TriangleBatcher : BehaviourBase, ITriangleBatch, IFirstFrameUpdate, IDraw
public class TriangleBatcher : Behaviour, ITriangleBatch, IFirstFrameUpdate, IDraw
{
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;

View File

@@ -4,7 +4,7 @@ using Engine.Core.Serialization;
namespace Engine.Integration.MonoGame;
[IgnoreSerialization]
public class MonoGameWindowContainer(MonoGameWindow GameWindow) : BehaviourBase
public class MonoGameWindowContainer(MonoGameWindow GameWindow) : Behaviour
{
public MonoGameWindow Window { get; } = GameWindow;
}

View File

@@ -4,7 +4,7 @@ using Engine.Core;
namespace Engine.Physics2D;
public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
public class PhysicsEngine2D : Behaviour, IEnterUniverse, IExitUniverse, IPreUpdate, IPhysicsEngine2D
{
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; } = new();
@@ -224,7 +224,7 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
}
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
physicsPreUpdateCollector.Assign(universe);
physicsUpdateCollector.Assign(universe);
@@ -234,7 +234,7 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
rigidBodyCollector.Assign(universe);
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
physicsPreUpdateCollector.Unassign();
physicsUpdateCollector.Unassign();

View File

@@ -10,7 +10,7 @@ namespace Engine.Systems.Network;
/// <summary>
/// Intermediary manager that looks up in it's hierarchy for a <see cref="INetworkCommunicator"/> to route/broadcast it's received packets to their destinations.
/// </summary>
public class NetworkManager : Behaviour, INetworkManager
public class NetworkManager : Behaviour, IEnterUniverse, IExitUniverse, INetworkManager
{
private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> clientPacketArrivalMethods = [];
private readonly Dictionary<Type, Dictionary<Type, List<MethodInfo>>> serverPacketArrivalMethods = [];
@@ -230,8 +230,8 @@ public class NetworkManager : Behaviour, INetworkManager
UnregisterPacketRoutersFor(removedBehaviour, serverPacketRouters, serverPacketArrivalMethods);
}
protected override void OnExitedUniverse(IUniverse universe) => _networkEntityCollector.Unassign();
protected override void OnEnteredUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe) => _networkEntityCollector.Unassign();
public void EnterUniverse(IUniverse universe)
{
_networkEntityCollector.Assign(universe);
NetworkCommunicator = BehaviourController.GetRequiredBehaviourInParent<INetworkCommunicator>();

View File

@@ -2,7 +2,7 @@ using Engine.Core;
namespace Engine.Systems.Time;
public class Stopwatch : Behaviour, IUpdate, IStopwatch
public class Stopwatch : Behaviour, IUpdate, IEnterUniverse, IExitUniverse, IStopwatch
{
public Event<IReadOnlyStopwatch> OnStarted { get; } = new();
public Event<IReadOnlyStopwatch, IReadOnlyStopwatch.StopwatchDeltaArguments> OnDelta { get; } = new();
@@ -49,7 +49,7 @@ public class Stopwatch : Behaviour, IUpdate, IStopwatch
OnDelta?.Invoke(this, new(delta));
}
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
if (!shouldBeTicking || State is TimerState.Ticking)
return;
@@ -60,7 +60,7 @@ public class Stopwatch : Behaviour, IUpdate, IStopwatch
StartStopwatch();
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
if (!shouldBeTicking || State is not TimerState.Ticking)
return;
@@ -88,8 +88,10 @@ public class Stopwatch : Behaviour, IUpdate, IStopwatch
OnStarted?.Invoke(this);
}
protected override void OnFinalize()
protected override void FinalizeInternal()
{
base.FinalizeInternal();
Time = 0f;
State = TimerState.Idle;
shouldBeTicking = false;

View File

@@ -30,9 +30,9 @@ public class TickerStopwatch : Stopwatch, ITicker
}
}
protected override void OnFinalize()
protected override void FinalizeInternal()
{
base.OnFinalize();
base.FinalizeInternal();
TickCounter = 0;
nextTick = 0f;

View File

@@ -30,9 +30,9 @@ public class TickerTimer : Timer, ITicker
}
}
protected override void OnFinalize()
protected override void FinalizeInternal()
{
base.OnFinalize();
base.FinalizeInternal();
TickCounter = 0;
nextTick = 0f;

View File

@@ -2,7 +2,7 @@ using Engine.Core;
namespace Engine.Systems.Time;
public class Timer : Behaviour, IUpdate, ITimer
public class Timer : Behaviour, IUpdate, IEnterUniverse, IExitUniverse, ITimer
{
public Event<IReadOnlyTimer> OnStarted { get; } = new();
public Event<IReadOnlyTimer, IReadOnlyTimer.TimerDeltaArguments> OnDelta { get; } = new();
@@ -67,7 +67,7 @@ public class Timer : Behaviour, IUpdate, ITimer
Stop();
}
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
if (!shouldBeTicking || State is TimerState.Ticking)
return;
@@ -78,7 +78,7 @@ public class Timer : Behaviour, IUpdate, ITimer
StartTimer();
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
if (!shouldBeTicking || State is not TimerState.Ticking)
return;
@@ -106,8 +106,10 @@ public class Timer : Behaviour, IUpdate, ITimer
OnStarted?.Invoke(this);
}
protected override void OnFinalize()
protected override void FinalizeInternal()
{
base.FinalizeInternal();
StartTime = 0f;
Remaining = 0f;
State = TimerState.Idle;

View File

@@ -5,7 +5,7 @@ using Engine.Core;
namespace Engine.Systems.Tween;
public class TweenManager : Behaviour, ITweenManager
public class TweenManager : Behaviour, IEnterUniverse, IExitUniverse, ITweenManager
{
private CoroutineManager coroutineManager = null!;
@@ -73,12 +73,12 @@ public class TweenManager : Behaviour, ITweenManager
Return((Tween)tween);
}
protected override void OnEnteredUniverse(IUniverse universe)
public void EnterUniverse(IUniverse universe)
{
coroutineManager = universe.FindRequiredBehaviour<CoroutineManager>();
}
protected override void OnExitedUniverse(IUniverse universe)
public void ExitUniverse(IUniverse universe)
{
coroutineManager = null!;
}