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.
97 lines
3.8 KiB
C#
97 lines
3.8 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace Engine.Core;
|
|
|
|
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));
|
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
|
|
|
private readonly ActiveBehaviourCollectorOrdered<int, IFirstFrameUpdate> firstFrameUpdates = new(GetPriority(), SortByAscendingPriority());
|
|
private readonly ActiveBehaviourCollector<ILastFrameUpdate> lastFrameUpdates = new();
|
|
private readonly ActiveBehaviourCollectorOrdered<int, IPreUpdate> preUpdateEntities = new(GetPriority(), SortByAscendingPriority());
|
|
private readonly ActiveBehaviourCollectorOrdered<int, IUpdate> updateEntities = new(GetPriority(), SortByAscendingPriority());
|
|
private readonly ActiveBehaviourCollectorOrdered<int, IPostUpdate> postUpdateEntities = new(GetPriority(), SortByAscendingPriority());
|
|
|
|
private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
|
|
|
|
public void EnterUniverse(IUniverse universe)
|
|
{
|
|
firstFrameUpdates.Assign(universe);
|
|
lastFrameUpdates.Assign(universe);
|
|
preUpdateEntities.Assign(universe);
|
|
updateEntities.Assign(universe);
|
|
postUpdateEntities.Assign(universe);
|
|
|
|
universe.OnPreUpdate.AddListener(OnFirstUpdate, int.MaxValue);
|
|
universe.OnPreUpdate.AddListener(OnPreUpdate);
|
|
universe.OnUpdate.AddListener(OnUpdate);
|
|
universe.OnPostUpdate.AddListener(OnPostUpdate);
|
|
}
|
|
|
|
public void ExitUniverse(IUniverse universe)
|
|
{
|
|
firstFrameUpdates.Unassign();
|
|
lastFrameUpdates.Unassign();
|
|
preUpdateEntities.Unassign();
|
|
updateEntities.Unassign();
|
|
postUpdateEntities.Unassign();
|
|
|
|
universe.OnPreUpdate.RemoveListener(OnFirstUpdate);
|
|
universe.OnPreUpdate.RemoveListener(OnPreUpdate);
|
|
universe.OnUpdate.RemoveListener(OnUpdate);
|
|
universe.OnPostUpdate.RemoveListener(OnPostUpdate);
|
|
}
|
|
|
|
private void OnFirstUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
|
{
|
|
for (int i = toCallFirstFrameUpdates.Count - 1; i >= 0; i--)
|
|
{
|
|
toCallFirstFrameUpdates[i].FirstActiveFrame();
|
|
toCallFirstFrameUpdates.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
private void OnPreUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
|
{
|
|
for (int i = preUpdateEntities.Count - 1; i >= 0; i--)
|
|
preUpdateEntities[i].PreUpdate();
|
|
}
|
|
|
|
private void OnUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
|
{
|
|
for (int i = updateEntities.Count - 1; i >= 0; i--)
|
|
updateEntities[i].Update();
|
|
}
|
|
|
|
private void OnPostUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
|
{
|
|
for (int i = postUpdateEntities.Count - 1; i >= 0; i--)
|
|
postUpdateEntities[i].PostUpdate();
|
|
}
|
|
|
|
private void OnFirstFrameCollected(IBehaviourCollector<IFirstFrameUpdate> sender, IBehaviourCollector<IFirstFrameUpdate>.BehaviourCollectedArguments args)
|
|
{
|
|
toCallFirstFrameUpdates.Add(args.BehaviourCollected);
|
|
}
|
|
|
|
private void OnLastFrameRemoved(IBehaviourCollector<ILastFrameUpdate> sender, IBehaviourCollector<ILastFrameUpdate>.BehaviourRemovedArguments args)
|
|
{
|
|
args.BehaviourRemoved.LastActiveFrame();
|
|
}
|
|
|
|
private void CallLastFramesBeforeExit(object? sender, System.EventArgs e)
|
|
{
|
|
for (int i = lastFrameUpdates.Count - 1; i >= 0; i--)
|
|
lastFrameUpdates[i].LastActiveFrame();
|
|
}
|
|
|
|
public UpdateManager()
|
|
{
|
|
firstFrameUpdates.OnCollected.AddListener(OnFirstFrameCollected);
|
|
lastFrameUpdates.OnRemoved.AddListener(OnLastFrameRemoved);
|
|
System.AppDomain.CurrentDomain.ProcessExit += CallLastFramesBeforeExit;
|
|
}
|
|
}
|