2026-07-18 19:33:05 +08:00
|
|
|
namespace OECS;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Manages a group of systems, running them in registration order
|
|
|
|
|
/// against a specific <see cref="World"/>.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class SystemGroup
|
|
|
|
|
{
|
|
|
|
|
private readonly World _world;
|
|
|
|
|
private readonly List<ISystem> _systems = new();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates a system group bound to the given world.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public SystemGroup(World world)
|
|
|
|
|
{
|
|
|
|
|
_world = world ?? throw new ArgumentNullException(nameof(world));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The number of systems in this group.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public int Count => _systems.Count;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Adds a system to the group. Systems execute in the order they are added.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Add(ISystem system)
|
|
|
|
|
{
|
|
|
|
|
_systems.Add(system);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Removes a system from the group.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void Remove(ISystem system)
|
|
|
|
|
{
|
|
|
|
|
_systems.Remove(system);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Runs all systems with a timed tick.
|
|
|
|
|
/// Systems that implement <see cref="ITickedSystem"/> receive the tick data;
|
|
|
|
|
/// plain <see cref="ISystem"/> implementations receive only the world.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void RunTimed(float deltaTime)
|
|
|
|
|
{
|
|
|
|
|
RunAll(Tick.Timed(deltaTime));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Runs all systems with a logical tick.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void RunLogical()
|
|
|
|
|
{
|
|
|
|
|
RunAll(Tick.Logical());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RunAll(Tick tick)
|
|
|
|
|
{
|
|
|
|
|
foreach (var system in _systems)
|
|
|
|
|
{
|
|
|
|
|
if (system is ITickedSystem ticked)
|
|
|
|
|
{
|
|
|
|
|
ticked.Run(_world, tick);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
system.Run(_world);
|
|
|
|
|
}
|
2026-07-18 19:38:10 +08:00
|
|
|
|
|
|
|
|
// Drain commands after each system so subsequent systems
|
|
|
|
|
// see the effects of commands enqueued by prior systems.
|
|
|
|
|
_world.ExecuteCommands();
|
2026-07-18 19:50:31 +08:00
|
|
|
|
|
|
|
|
// Post changes after each system so subscribers see
|
|
|
|
|
// incremental updates.
|
|
|
|
|
_world.PostChanges();
|
2026-07-18 19:33:05 +08:00
|
|
|
}
|
2026-07-18 19:38:10 +08:00
|
|
|
|
|
|
|
|
// Drain any remaining commands (e.g., those enqueued outside systems).
|
|
|
|
|
_world.ExecuteCommands();
|
2026-07-18 19:50:31 +08:00
|
|
|
|
|
|
|
|
// Post any remaining changes (e.g., from command execution).
|
|
|
|
|
_world.PostChanges();
|
2026-07-18 19:33:05 +08:00
|
|
|
}
|
|
|
|
|
}
|