refactor: update & draw calls have been refactored into systems

This commit is contained in:
Syntriax 2025-05-22 23:51:08 +03:00
parent 37b87f0f85
commit e7bd924494
14 changed files with 216 additions and 90 deletions

View File

@ -3,25 +3,10 @@ using System.Collections.Generic;
namespace Syntriax.Engine.Core;
/// <summary>
/// Represents a controller for managing <see cref="IBehaviour"/>s and notify them accordingly about the engine's updates. Connected to an <see cref="IUniverseObject"/>.
/// Represents a controller for managing <see cref="IBehaviour"/>s. Connected to an <see cref="IUniverseObject"/>.
/// </summary>
public interface IBehaviourController : IEntity, IHasUniverseObject, IEnumerable<IBehaviour>
{
/// <summary>
/// Event triggered before the update of <see cref="IBehaviour"/>s.
/// </summary>
event PreUpdateEventHandler? OnPreUpdate;
/// <summary>
/// Event triggered during the update of <see cref="IBehaviour"/>s.
/// </summary>
event UpdateEventHandler? OnUpdate;
/// <summary>
/// Event triggered before the drawing phase.
/// </summary>
event PreDrawEventHandler? OnPreDraw;
/// <summary>
/// Event triggered when a <see cref="IBehaviour"/> is added to the <see cref="IBehaviourController"/>.
/// </summary>
@ -83,20 +68,6 @@ public interface IBehaviourController : IEntity, IHasUniverseObject, IEnumerable
/// <param name="behaviour">The <see cref="IBehaviour"/> to remove.</param>
void RemoveBehaviour<T>(T behaviour) where T : class, IBehaviour;
/// <summary>
/// Updates all <see cref="IBehaviour"/>s in the <see cref="IBehaviourController"/>.
/// </summary>
void Update();
/// <summary>
/// Performs pre-draw operations.
/// </summary>
void UpdatePreDraw();
delegate void PreUpdateEventHandler(IBehaviourController sender);
delegate void UpdateEventHandler(IBehaviourController sender);
delegate void PreDrawEventHandler(IBehaviourController sender);
delegate void BehaviourAddedEventHandler(IBehaviourController sender, IBehaviour behaviourAdded);
delegate void BehaviourRemovedEventHandler(IBehaviourController sender, IBehaviour behaviourRemoved);
}

View File

@ -1,9 +1,9 @@
namespace Syntriax.Engine.Core;
public abstract class Behaviour : BehaviourBase
public abstract class Behaviour : BehaviourBase, IFirstFrameUpdate,
IPreUpdate, IUpdate, IPostUpdate,
IPreDraw, IDraw, IPostDraw
{
private bool isInitializedThisFrame = false;
protected IUniverse Universe => BehaviourController.UniverseObject.Universe;
protected IUniverseObject UniverseObject => BehaviourController.UniverseObject;
@ -20,11 +20,6 @@ public abstract class Behaviour : BehaviourBase
protected virtual void OnInitialize() { }
protected virtual void OnInitialize(IInitializable _)
{
isInitializedThisFrame = true;
BehaviourController.OnPreUpdate += PreUpdate;
BehaviourController.OnPreDraw += PreDraw;
BehaviourController.OnUpdate += Update;
BehaviourController.UniverseObject.OnEnteredUniverse += EnteredUniverse;
BehaviourController.UniverseObject.OnExitedUniverse += ExitedUniverse;
@ -37,9 +32,6 @@ public abstract class Behaviour : BehaviourBase
protected virtual void OnFinalize() { }
protected virtual void OnFinalize(IInitializable _)
{
BehaviourController.OnPreUpdate -= PreUpdate;
BehaviourController.OnPreDraw -= PreDraw;
BehaviourController.OnUpdate -= Update;
BehaviourController.UniverseObject.OnEnteredUniverse -= EnteredUniverse;
BehaviourController.UniverseObject.OnExitedUniverse -= ExitedUniverse;
@ -49,9 +41,16 @@ public abstract class Behaviour : BehaviourBase
ExitedUniverse(UniverseObject, Universe);
}
protected virtual void OnFirstActiveFrame() { }
void IFirstFrameUpdate.FirstActiveFrame()
{
Debug.Assert.AssertInitialized(this);
OnFirstActiveFrame();
}
protected virtual void OnPreUpdatePreActiveCheck() { }
protected virtual void OnPreUpdate() { }
protected virtual void PreUpdate(IBehaviourController _)
void IPreUpdate.PreUpdate()
{
Debug.Assert.AssertInitialized(this);
@ -60,22 +59,12 @@ public abstract class Behaviour : BehaviourBase
if (!IsActive)
return;
if (isInitializedThisFrame)
FirstActiveFrame();
OnPreUpdate();
}
protected virtual void OnFirstActiveFrame() { }
protected virtual void FirstActiveFrame()
{
OnFirstActiveFrame();
isInitializedThisFrame = false;
}
protected virtual void OnUpdatePreActiveCheck() { }
protected virtual void OnUpdate() { }
protected virtual void Update(IBehaviourController _)
void IUpdate.Update()
{
Debug.Assert.AssertInitialized(this);
@ -87,9 +76,23 @@ public abstract class Behaviour : BehaviourBase
OnUpdate();
}
protected virtual void OnPostUpdatePreActiveCheck() { }
protected virtual void OnPostUpdate() { }
void IPostUpdate.PostUpdate()
{
Debug.Assert.AssertInitialized(this);
OnPostUpdatePreActiveCheck();
if (!StateEnable.Enabled)
return;
OnPostUpdate();
}
protected virtual void OnPreDrawPreActiveCheck() { }
protected virtual void OnPreDraw() { }
protected virtual void PreDraw(IBehaviourController _)
void IPreDraw.PreDraw()
{
Debug.Assert.AssertInitialized(this);
@ -101,6 +104,34 @@ public abstract class Behaviour : BehaviourBase
OnPreDraw();
}
protected virtual void OnDrawPreActiveCheck() { }
protected virtual void OnDraw() { }
void IDraw.Draw()
{
Debug.Assert.AssertInitialized(this);
OnDrawPreActiveCheck();
if (!StateEnable.Enabled)
return;
OnDraw();
}
protected virtual void OnPostDrawPreActiveCheck() { }
protected virtual void OnPostDraw() { }
void IPostDraw.PostDraw()
{
Debug.Assert.AssertInitialized(this);
OnPostDrawPreActiveCheck();
if (!StateEnable.Enabled)
return;
OnPostDraw();
}
protected virtual void OnEnteredUniverse(IUniverse universe) { }
protected virtual void EnteredUniverse(IUniverseObject sender, IUniverse universe) => OnEnteredUniverse(universe);

View File

@ -17,10 +17,6 @@ public abstract class Behaviour2D : Behaviour, IBehaviour2D
}
protected sealed override void OnUnassign(IAssignable assignable) => base.OnUnassign(assignable);
protected sealed override void PreUpdate(IBehaviourController behaviourController) => base.PreUpdate(behaviourController);
protected sealed override void FirstActiveFrame() => base.FirstActiveFrame();
protected sealed override void Update(IBehaviourController behaviourController) => base.Update(behaviourController);
protected sealed override void PreDraw(IBehaviourController behaviourController) => base.PreDraw(behaviourController);
protected sealed override void EnteredUniverse(IUniverseObject sender, IUniverse universe) => base.EnteredUniverse(sender, universe);
protected sealed override void ExitedUniverse(IUniverseObject sender, IUniverse universe) => base.ExitedUniverse(sender, universe);
}

View File

@ -8,10 +8,6 @@ namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
public class BehaviourController : BaseEntity, IBehaviourController
{
public event IBehaviourController.PreUpdateEventHandler? OnPreUpdate = null;
public event IBehaviourController.UpdateEventHandler? OnUpdate = null;
public event IBehaviourController.PreDrawEventHandler? OnPreDraw = null;
public event IBehaviourController.BehaviourAddedEventHandler? OnBehaviourAdded = null;
public event IBehaviourController.BehaviourRemovedEventHandler? OnBehaviourRemoved = null;
public event IHasUniverseObject.UniverseObjectAssignedEventHandler? OnUniverseObjectAssigned = null;
@ -128,27 +124,6 @@ public class BehaviourController : BaseEntity, IBehaviourController
behaviour.Finalize();
}
public void Update()
{
Debug.Assert.AssertInitialized(this);
if (!UniverseObject.StateEnable.Enabled || !StateEnable.Enabled)
return;
OnPreUpdate?.InvokeSafe(this);
OnUpdate?.InvokeSafe(this);
}
public void UpdatePreDraw()
{
Debug.Assert.AssertInitialized(this);
if (!UniverseObject.StateEnable.Enabled || !StateEnable.Enabled)
return;
OnPreDraw?.InvokeSafe(this);
}
public BehaviourController() { }
public BehaviourController(IUniverseObject universeObject) => Assign(universeObject);

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IDraw : IBehaviour
{
void Draw();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IFirstFrameUpdate : IBehaviour
{
void FirstActiveFrame();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IPostDraw : IBehaviour
{
void PostDraw();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IPostUpdate : IBehaviour
{
void PostUpdate();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IPreDraw : IBehaviour
{
void PreDraw();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IPreUpdate : IBehaviour
{
void PreUpdate();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core;
public interface IUpdate : IBehaviour
{
void Update();
}

View File

@ -0,0 +1,49 @@
namespace Syntriax.Engine.Core;
public class DrawManager : UniverseObject
{
private readonly BehaviourCollector<IPreDraw> preDrawEntities = new();
private readonly BehaviourCollector<IDraw> drawEntities = new();
private readonly BehaviourCollector<IPostDraw> postDrawEntities = new();
private void OnPreDraw(IUniverse sender)
{
for (int i = preDrawEntities.Behaviours.Count - 1; i >= 0; i--)
preDrawEntities.Behaviours[i].PreDraw();
}
private void OnDraw(IUniverse sender)
{
for (int i = drawEntities.Behaviours.Count - 1; i >= 0; i--)
drawEntities.Behaviours[i].Draw();
}
private void OnPostDraw(IUniverse sender)
{
for (int i = postDrawEntities.Behaviours.Count - 1; i >= 0; i--)
postDrawEntities.Behaviours[i].PostDraw();
}
protected override void OnEnteringUniverse(IUniverse universe)
{
preDrawEntities.Assign(universe);
drawEntities.Assign(universe);
postDrawEntities.Assign(universe);
universe.OnPreDraw += OnPreDraw;
universe.OnDraw += OnDraw;
universe.OnPostDraw += OnPostDraw;
}
protected override void OnExitingUniverse(IUniverse universe)
{
preDrawEntities.Unassign();
drawEntities.Unassign();
postDrawEntities.Unassign();
universe.OnPreDraw -= OnPreDraw;
universe.OnDraw -= OnDraw;
universe.OnPostDraw -= OnPostDraw;
}
}

View File

@ -0,0 +1,69 @@
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
public class UpdateManager : UniverseObject
{
private readonly BehaviourCollector<IFirstFrameUpdate> firstFrameUpdates = new();
private readonly BehaviourCollector<IPreUpdate> preUpdateEntities = new();
private readonly BehaviourCollector<IUpdate> updateEntities = new();
private readonly BehaviourCollector<IPostUpdate> postUpdateEntities = new();
private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = [];
protected override void OnEnteringUniverse(IUniverse universe)
{
firstFrameUpdates.Assign(universe);
preUpdateEntities.Assign(universe);
updateEntities.Assign(universe);
postUpdateEntities.Assign(universe);
universe.OnPreUpdate += OnPreUpdate;
universe.OnUpdate += OnUpdate;
universe.OnPostUpdate += OnPostUpdate;
}
protected override void OnExitingUniverse(IUniverse universe)
{
firstFrameUpdates.Unassign();
preUpdateEntities.Unassign();
updateEntities.Unassign();
postUpdateEntities.Unassign();
universe.OnPreUpdate -= OnPreUpdate;
universe.OnUpdate -= OnUpdate;
universe.OnPostUpdate -= OnPostUpdate;
}
private void OnPreUpdate(IUniverse sender, UniverseTime engineTime)
{
for (int i = toCallFirstFrameUpdates.Count - 1; i >= 0; i--)
toCallFirstFrameUpdates[i].FirstActiveFrame();
for (int i = preUpdateEntities.Behaviours.Count - 1; i >= 0; i--)
preUpdateEntities.Behaviours[i].PreUpdate();
}
private void OnUpdate(IUniverse sender, UniverseTime engineTime)
{
for (int i = updateEntities.Behaviours.Count - 1; i >= 0; i--)
updateEntities.Behaviours[i].Update();
}
private void OnPostUpdate(IUniverse sender, UniverseTime engineTime)
{
for (int i = postUpdateEntities.Behaviours.Count - 1; i >= 0; i--)
postUpdateEntities.Behaviours[i].PostUpdate();
}
private void OnFirstFrameCollected(IBehaviourCollector<IFirstFrameUpdate> sender, IFirstFrameUpdate behaviourCollected)
{
toCallFirstFrameUpdates.Add(behaviourCollected);
}
public UpdateManager()
{
firstFrameUpdates.OnCollected += OnFirstFrameCollected;
}
}

View File

@ -119,10 +119,6 @@ public class Universe : BaseEntity, IUniverse
Time = new(TimeSpan.FromTicks((long)(Time.TimeSinceStart.Ticks + engineTime.DeltaSpan.Ticks * TimeScale)), TimeSpan.FromTicks((long)(engineTime.DeltaSpan.Ticks * TimeScale)));
OnPreUpdate?.InvokeSafe(this, Time);
for (int i = 0; i < UniverseObjects.Count; i++)
UniverseObjects[i].BehaviourController.Update();
OnUpdate?.InvokeSafe(this, Time);
OnPostUpdate?.InvokeSafe(this, Time);
}
@ -131,9 +127,6 @@ public class Universe : BaseEntity, IUniverse
{
Debug.Assert.AssertInitialized(this);
for (int i = 0; i < UniverseObjects.Count; i++)
UniverseObjects[i].BehaviourController.UpdatePreDraw();
OnPreDraw?.InvokeSafe(this);
OnDraw?.InvokeSafe(this);
OnPostDraw?.InvokeSafe(this);