diff --git a/TinyEcs.slnx b/TinyEcs.slnx
index 5d047c7f..33561469 100644
--- a/TinyEcs.slnx
+++ b/TinyEcs.slnx
@@ -10,6 +10,6 @@
-
+
diff --git a/samples/MyBattleground/MyBattleground.csproj b/samples/MyBattleground/MyBattleground.csproj
index 109c3d15..4653ad91 100644
--- a/samples/MyBattleground/MyBattleground.csproj
+++ b/samples/MyBattleground/MyBattleground.csproj
@@ -8,6 +8,9 @@
preview
enable
true
+
+ true
+ $(BaseIntermediateOutputPath)\Generated
@@ -33,6 +36,7 @@
+
diff --git a/samples/MyBattleground/Program.cs b/samples/MyBattleground/Program.cs
index fe68ffbc..f7c604a6 100644
--- a/samples/MyBattleground/Program.cs
+++ b/samples/MyBattleground/Program.cs
@@ -3,14 +3,41 @@
using TinyEcs;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using System.Numerics;
const int ENTITIES_COUNT = (524_288 * 2 * 1);
using var ecs = new World();
-var scheduler = new Scheduler(ecs);
+var scheduler = new Scheduler(ecs, ThreadingMode.Single);
+// var sys = new HelloSystem();
+// sys.Initialize(ecs);
+// sys.ExecuteOnReady(ecs, ecs.Ticks.ThisRun);
+scheduler.AddResource(new CustomResource());
+
+// scheduler.AddSystem2(Stages.Startup, new SetupSystem(ENTITIES_COUNT));
+// scheduler.AddSystem2(Stages.Update);
+//
+// scheduler.AddSystem2(Stages.Update, new HelloSystem());
+
+scheduler.AddPlugin(new TestPlugin() { Count = ENTITIES_COUNT });
+
+
+// scheduler.AddPlugin();
+// scheduler.AddPlugin();
+
+// scheduler.AddPlugin();
+// scheduler.AddPlugin();
+// scheduler.RunOnce();
+//
+//
+// return;
+// ecs.Entity();
+// ecs.Entity().Delete();
+// var xx = ecs.Entity().Add();
+//
+// xx.Get();
+// Console.WriteLine("");
// scheduler.OnUpdate((Query, Changed> query) =>
// {
@@ -21,8 +48,8 @@
// }, ThreadingMode.Single);
-var ab = ecs.Entity()
- .Set(new Position()).Set(new Velocity());
+// var ab = ecs.Entity()
+// .Set(new Position()).Set(new Velocity());
// ecs.Entity()
// .Set(new Position() { X = -1 });
// // var q = ecs.QueryBuilder()
@@ -49,7 +76,7 @@
// scheduler.RunOnce();
// scheduler.RunOnce();
-ab.Set(new Position() { X = 2 });
+// ab.Set(new Position() { X = 2 });
// scheduler.RunOnce();
// scheduler.AddState(GameState.Loading);
@@ -96,47 +123,75 @@
// while (true)
// scheduler.RunOnce();
-for (int i = 0; i < ENTITIES_COUNT; i++)
- ecs.Entity()
- .Set(new Position())
- .Set(new Velocity());
+// for (var i = 0; i < ENTITIES_COUNT; i++)
+// ecs.Entity()
+// .Set(new Position())
+// .Set(new Velocity());
// ecs.Entity().Set(new Position()).Set(new Velocity()).Set(new Mass());
+// ecs.Entity()
+// .Set(new Velocity());
+// ecs.Entity()
+// .Set(new Position());
-
-scheduler.AddSystem((
- Query, With> q,
- Query, Added> added
-) =>
-{
- foreach ((var pos, var vel) in q)
- {
- pos.Ref.X *= vel.Ref.X;
- pos.Ref.Y *= vel.Ref.Y;
-
- // pos.Ref.X *= vel.Ref.X;
- // pos.Ref.Y *= vel.Ref.Y;
-
- // if (pos.IsChanged)
- // pos.ClearState();
- }
-
- // foreach ((var pos, var vel) in added)
- // {
- // pos.Ref.X *= vel.Ref.X;
- // pos.Ref.Y *= vel.Ref.Y;
-
- // // if (pos.IsAdded)
- // // pos.ClearState();
- // }
-}, threadingType: ThreadingMode.Single);
-
+// ecs.Entity().Set(new Velocity()).Set(new Position());
+// scheduler.AddSystem([TinySystem] (
+// Query> q,
+// Query, Added> added
+// ) =>
+// {
+//
+// // foreach ((var pos, var vel) in or)
+// // {
+// // if (pos.IsValid())
+// // {
+// // Console.Write("pos is valid ");
+// // }
+// // else
+// // {
+//
+// // }
+//
+// // if (vel.IsValid())
+// // {
+// // Console.Write("vel is valid");
+// // }
+// // else
+// // {
+//
+// // }
+//
+// // Console.WriteLine();
+// // }
+//
+// foreach (var (pos, vel) in q)
+// {
+// pos.Ref.X *= vel.Ref.X;
+// pos.Ref.Y *= vel.Ref.Y;
+//
+// // pos.Ref.X *= vel.Ref.X;
+// // pos.Ref.Y *= vel.Ref.Y;
+//
+// // if (pos.IsChanged)
+// // pos.ClearState();
+// }
+//
+// // foreach ((var pos, var vel) in added)
+// // {
+// // pos.Ref.X *= vel.Ref.X;
+// // pos.Ref.Y *= vel.Ref.Y;
+//
+// // // if (pos.IsAdded)
+// // // pos.ClearState();
+// // }
+// }, threadingType: ThreadingMode.Single);
+//
var query = ecs.QueryBuilder()
- .With()
- .With()
- .Build();
+ .With()
+ .With()
+ .Build();
var sw = Stopwatch.StartNew();
var start = 0f;
@@ -144,78 +199,80 @@ Query, Added> added
while (true)
{
- for (int i = 0; i < 3600; ++i)
- {
- scheduler.RunOnce();
+ for (int i = 0; i < 3600; ++i)
+ {
+ scheduler.RunOnce();
- // Execute(query);
- // ExecuteIterator(query);
+ // Execute(query);
+ // ExecuteIterator(query);
- // var it = query.Iter();
- // while (it.Next())
- // {
- // var count = it.Count;
+ // var it = query.Iter();
+ // while (it.Next())
+ // {
+ // var count = it.Count;
- // ref var pos = ref it.DataRef(0);
- // ref var vel = ref it.DataRef(1);
- // ref var lastPos = ref Unsafe.Add(ref pos, count);
+ // ref var pos = ref it.DataRef(0);
+ // ref var vel = ref it.DataRef(1);
+ // ref var lastPos = ref Unsafe.Add(ref pos, count);
- // while (Unsafe.IsAddressLessThan(ref pos, ref lastPos))
- // {
- // pos.X *= vel.X;
- // pos.Y *= vel.Y;
+ // while (Unsafe.IsAddressLessThan(ref pos, ref lastPos))
+ // {
+ // pos.X *= vel.X;
+ // pos.Y *= vel.Y;
- // pos = ref Unsafe.Add(ref pos, 1);
- // vel = ref Unsafe.Add(ref vel, 1);
- // }
- // }
- }
+ // pos = ref Unsafe.Add(ref pos, 1);
+ // vel = ref Unsafe.Add(ref vel, 1);
+ // }
+ // }
+ }
- last = start;
- start = sw.ElapsedMilliseconds;
+ last = start;
+ start = sw.ElapsedMilliseconds;
- Console.WriteLine("query done in {0} ms", start - last);
+ Console.WriteLine("query done in {0} ms", start - last);
}
static void Execute(Query query)
{
- foreach ((var pos, var vel) in Data.CreateIterator(query.Iter()))
- {
- pos.Ref.X *= vel.Ref.X;
- pos.Ref.Y *= vel.Ref.Y;
- }
+ foreach (var (pos, vel) in Data.CreateIterator(query.Iter()))
+ {
+ pos.Ref.X *= vel.Ref.X;
+ pos.Ref.Y *= vel.Ref.Y;
+ }
}
-static void ExecuteIterator(Query query)
-{
- var it = query.Iter();
-
- while (it.Next())
- {
- var span0 = it.Data(0);
- var span1 = it.Data(1);
- var count = it.Count;
- for (var i = 0; i < count; ++i)
- {
- ref var pos = ref span0[i];
- ref var vel = ref span1[i];
- pos.X *= vel.X;
- pos.Y *= vel.Y;
- }
- }
-}
-
-struct Position
+// static void ExecuteIterator(Query query)
+// {
+// var it = query.Iter();
+//
+// while (it.Next())
+// {
+// var span0 = it.Data(0);
+// var span1 = it.Data(1);
+// var count = it.Count;
+//
+// for (var i = 0; i < count; ++i)
+// {
+// ref var pos = ref span0[i];
+// ref var vel = ref span1[i];
+//
+// pos.X *= vel.X;
+// pos.Y *= vel.Y;
+// }
+// }
+// }
+
+public struct Position
{
- public float X, Y, Z;
+ public float X, Y, Z;
}
-struct Velocity
+public struct Velocity
{
- public float X, Y;
+ public float X, Y;
}
struct Mass { public float Value; }
@@ -225,13 +282,102 @@ struct Tag { }
enum GameState
{
- Loading,
- Playing,
- Menu,
- Menu2
+ Loading,
+ Playing,
+ Menu,
+ Menu2
}
enum AnotherState
{
- A, B, C
+ A, B, C
+}
+
+
+class SYSTEMS
+{
+ [TinySystem]
+ public bool CheckThis()
+ {
+ new CheckThisAdapter(this);
+ return true;
+ }
+}
+
+
+internal sealed class TestPlugin : IPlugin
+{
+ public int Count { get; init; }
+
+ public void Build(Scheduler scheduler)
+ {
+ scheduler.AddState(GameState.Loading);
+
+ scheduler
+ .AddSystems(Stage.Startup, new SetupAdapter(this))
+ .AddSystems(Stage.Update, new MoveEntitiesAdapter()
+ .RunIf(new CanRunAdapter(this)))
+ .AddSystem(Stage.Update);
+
+ scheduler.AddStageAfterOf(Stage.Update, "AFTER_UPDATE");
+ scheduler.AddSystems("AFTER_UPDATE", new AcceptAdapter(this));
+
+ //scheduler.AddSystems(Stage.OnEnter, new TinyStateSystemAdapter(GameState.Playing));
+ scheduler.AddSystems(Stage.OnEnter(GameState.Playing), new OnEnterAdapter(this));
+ scheduler.AddSystems(Stage.OnExit(GameState.Loading), new OnExitAdapter(this));
+ }
+
+
+ [TinySystem]
+ public void Setup(World world)
+ {
+ for (var i = 0; i < Count; i++)
+ world.Entity()
+ .Set(new Position())
+ .Set(new Velocity());
+ }
+
+ [TinySystem]
+ public static void MoveEntities(Query> query)
+ {
+ foreach ((var pos, var vel) in query)
+ {
+ pos.Ref.X *= vel.Ref.X;
+ pos.Ref.Y *= vel.Ref.Y;
+ }
+ }
+
+ [TinySystem]
+ public static void PrintSomething(State state)
+ {
+ state.Set(GameState.Playing);
+ }
+
+ [TinySystem]
+ public void OnEnter(State state)
+ {
+ Console.WriteLine("on enter {0}", state.Current);
+ }
+
+ [TinySystem]
+ public void OnExit(State state)
+ {
+ Console.WriteLine("on exit {0}", state.Current);
+ }
+
+ [TinySystem]
+ public bool CanRun()
+ => true;
+
+ [TinySystem]
+ public void Accept()
+ {
+ }
+}
+
+
+
+public class CustomResource
+{
+
}
diff --git a/samples/TinyEcsGame/Program.cs b/samples/TinyEcsGame/Program.cs
index 3aaa1490..7dc4e3b7 100644
--- a/samples/TinyEcsGame/Program.cs
+++ b/samples/TinyEcsGame/Program.cs
@@ -3,7 +3,7 @@
using Raylib_cs;
-using var app = new App();
+using var app = new App(ThreadingMode.Multi);
app.AddPlugin(new RaylibPlugin()
{
WindowSize = new() { Value = { X = 800, Y = 600 } },
@@ -17,14 +17,14 @@
Velocity = 250
});
-app.Run(() => Raylib.WindowShouldClose(), Raylib.CloseWindow);
+app.Run(() => Raylib.IsWindowReady() && Raylib.WindowShouldClose(), Raylib.CloseWindow);
// =================================================================================
sealed class App : Scheduler, IDisposable
{
- public App() : base(new()) { }
+ public App(ThreadingMode threadingMode = ThreadingMode.Auto) : base(new(), threadingMode) { }
public void Dispose() => World?.Dispose();
}
@@ -54,6 +54,17 @@ struct RaylibPlugin : IPlugin
public bool VSync { get; set; }
public readonly void Build(Scheduler scheduler)
+ {
+ scheduler.AddSystemParam(new Time());
+ scheduler.AddResource(WindowSize);
+ scheduler.AddResource(new AssetsManager());
+
+ scheduler.AddSystems(Stage.Startup, new CreateWindowAdapter(this) { Configuration = { ThreadingMode = ThreadingMode.Single } });
+ scheduler.AddSystems(Stage.BeforeUpdate, new UpdateTimeAdapter(this));
+ }
+
+ [TinySystem]
+ public void CreateWindow()
{
ConfigFlags flags = 0;
if (VSync)
@@ -61,16 +72,13 @@ public readonly void Build(Scheduler scheduler)
Raylib.SetConfigFlags(flags);
Raylib.InitWindow((int)WindowSize.Value.X, (int)WindowSize.Value.Y, Title);
+ }
- scheduler.AddSystemParam(new Time());
- scheduler.AddResource(WindowSize);
- scheduler.AddResource(new AssetsManager());
-
- scheduler.AddSystem((Time time) =>
- {
- time.Frame = Raylib.GetFrameTime();
- time.Total += time.Frame;
- }, Stages.BeforeUpdate);
+ [TinySystem]
+ public void UpdateTime(Time time)
+ {
+ time.Frame = Raylib.GetFrameTime();
+ time.Total += time.Frame;
}
}
// =================================================================================
@@ -93,16 +101,14 @@ struct GameplayPlugin : IPlugin
public void Build(Scheduler scheduler)
{
- var init = SpawnEntities;
- var fn0 = MoveSystem;
- var fn1 = CheckBounds;
-
- scheduler.AddSystem(init, Stages.Startup);
- scheduler.AddSystem(fn0);
- scheduler.AddSystem(fn1);
+ scheduler
+ .AddSystems(Stage.Startup, new SpawnEntitiesAdapter(this) { Configuration = { ThreadingMode = ThreadingMode.Single } }
+ .RunIf(new CheckIfWindowReadyAdapter()))
+ .AddSystems(Stage.Update, new MoveSystemAdapter(), new CheckBoundsAdapter());
}
- static void MoveSystem(Time time, Query> query)
+ [TinySystem]
+ public static void MoveSystem(Time time, Query> query)
{
foreach ((var pos, var vel, var rot) in query)
{
@@ -111,7 +117,8 @@ static void MoveSystem(Time time, Query> quer
}
}
- static void CheckBounds(Query> query, Res windowSize)
+ [TinySystem]
+ public static void CheckBounds(Query> query, Res windowSize)
{
foreach ((var pos, var vel) in query)
{
@@ -139,7 +146,14 @@ static void CheckBounds(Query> query, Res w
}
}
- void SpawnEntities(World ecs, SchedulerState scheduler, Res size, Res assetsManager)
+ [TinySystem]
+ public static bool CheckIfWindowReady()
+ {
+ return Raylib.IsWindowReady();
+ }
+
+ [TinySystem]
+ public void SpawnEntities(World ecs, SchedulerState scheduler, Res size, Res assetsManager)
{
var rnd = Random.Shared;
var texture = Raylib.LoadTexture(Path.Combine(AppContext.BaseDirectory, "Content", "pepe.png"));
@@ -189,29 +203,33 @@ void SpawnEntities(World ecs, SchedulerState scheduler, Res size, Re
{
public void Build(Scheduler scheduler)
{
- var fn2 = BeginRenderer;
- var fn3 = RenderEntities;
- var fn4 = DrawText;
- var fn5 = EndRenderer;
-
- var begin = scheduler.AddSystem(fn2, stage: Stages.FrameEnd, threadingType: ThreadingMode.Single);
- var renderEntities = scheduler.AddSystem(fn3, stage: Stages.FrameEnd, threadingType: ThreadingMode.Single);
- var renderText = scheduler.AddSystem(fn4, stage: Stages.FrameEnd, threadingType: ThreadingMode.Single);
- var end = scheduler.AddSystem(fn5, stage: Stages.FrameEnd, threadingType: ThreadingMode.Single);
+ scheduler
+ .AddSystems(Stage.FrameEnd,
+ SystemOrder.Chain
+ (
+ new BeginRendererAdapter(),
+ new RenderEntitiesAdapter(),
+ new DrawTextAdapter(),
+ new EndRendererAdapter()
+ )
+ .RunIf(new CheckIfWindowReadyAdapter()));
}
- static void BeginRenderer()
+ [TinySystem]
+ public static void BeginRenderer()
{
Raylib.BeginDrawing();
Raylib.ClearBackground(Color.Black);
}
- static void EndRenderer()
+ [TinySystem]
+ public static void EndRenderer()
{
Raylib.EndDrawing();
}
- static void RenderEntities(Query> query, Res assetsManager)
+ [TinySystem]
+ public static void RenderEntities(Query> query, Res assetsManager)
{
var currTextureId = 0u;
Texture2D? texture = null;
@@ -229,7 +247,8 @@ static void RenderEntities(Query> query, Res text, Local timeout)
+ [TinySystem]
+ public static void DrawText(World ecs, Time time, Local text, Local timeout)
{
//if (time.Total > timeout)
{
diff --git a/samples/TinyEcsGame/TinyEcsGame.csproj b/samples/TinyEcsGame/TinyEcsGame.csproj
index b2e49a5e..bd3745c2 100644
--- a/samples/TinyEcsGame/TinyEcsGame.csproj
+++ b/samples/TinyEcsGame/TinyEcsGame.csproj
@@ -40,6 +40,7 @@
+
diff --git a/src/Bevy.cs b/src/Bevy.cs
index d8ee7a44..588e0817 100644
--- a/src/Bevy.cs
+++ b/src/Bevy.cs
@@ -6,166 +6,287 @@ namespace TinyEcs;
#if NET9_0_OR_GREATER
-public sealed partial class FuncSystem where TArg : notnull
+[Obsolete("Use the Stage class instead.")]
+public enum Stages
{
- private readonly TArg _arg;
- private readonly Func, bool> _fn;
- private readonly List> _conditions;
- private readonly Func _validator;
- private readonly Func _checkInUse;
- private readonly Stages _stage;
- private readonly ThreadingMode _threadingType;
- private readonly LinkedList> _after = new();
- private readonly LinkedList> _before = new();
- internal LinkedListNode>? Node { get; set; }
- internal SystemTicks Ticks { get; } = new();
-
-
- internal FuncSystem(TArg arg, Func, bool> fn, Func checkInUse, Stages stage, ThreadingMode threadingType)
- {
- _arg = arg;
- _fn = fn;
- _conditions = new();
- _validator = ValidateConditions;
- _checkInUse = checkInUse;
- _threadingType = threadingType;
- _stage = stage;
- }
+ Startup,
+ FrameStart,
+ BeforeUpdate,
+ Update,
+ AfterUpdate,
+ FrameEnd,
- internal void Run(uint ticks)
- {
- Ticks.ThisRun = ticks;
+ OnEnter,
+ OnExit
+}
- foreach (var s in _before)
- s.Run(ticks);
+public enum ThreadingMode
+{
+ Auto,
+ Single,
+ Multi
+}
- if (_fn(Ticks, _arg, _validator))
- {
- foreach (var s in _after)
- s.Run(ticks);
- }
+public sealed class SystemTicks
+{
+ public uint LastRun { get; internal set; }
+ public uint ThisRun { get; internal set; }
+}
- Ticks.LastRun = Ticks.ThisRun;
+
+public class Stage
+{
+ internal Stage(string name, bool runOnce)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ throw new ArgumentException("Stage name cannot be null or whitespace.", nameof(name));
+ Name = name;
+ RunOnce = runOnce;
}
- public FuncSystem RunIf(Func condition)
+ public string Name { get; }
+ public bool RunOnce { get; }
+
+
+ public static readonly Stage Startup = new(nameof(Startup), true);
+ public static readonly Stage FrameStart = new(nameof(FrameStart), false);
+ public static readonly Stage BeforeUpdate = new(nameof(BeforeUpdate), false);
+ public static readonly Stage Update = new(nameof(Update), false);
+ public static readonly Stage AfterUpdate = new(nameof(AfterUpdate), false);
+ public static readonly Stage FrameEnd = new(nameof(FrameEnd), false);
+
+ // These are useful just to headers for the custom OnEnter/OnExit stages
+ internal static readonly Stage OnEnterInner = new(nameof(OnEnterInner), false);
+ internal static readonly Stage OnExitInner = new(nameof(OnExitInner), false);
+
+ public static Stage OnEnter(TState state)
+ where TState : struct, Enum
{
- _conditions.Add((_, _) => condition());
- return this;
+ var stage = new OnEnterStage(state, $"__pvt_on_enter_{typeof(TState).ToString()}.{Enum.GetName(state)}", false);
+ return stage;
}
- public FuncSystem RunAfter(FuncSystem parent)
+ public static Stage OnExit(TState state)
+ where TState : struct, Enum
{
- if (this == parent || Contains(parent, s => s._after))
- throw new InvalidOperationException("Circular dependency detected");
+ var stage = new OnExitStage(state, $"__pvt_on_exit_{typeof(TState).ToString()}.{Enum.GetName(state)}", false);
+ return stage;
+ }
+}
+
+public interface IStateStage
+{
+ ITinySystem CreateSystem(ITinySystem sys);
+}
- Node?.List?.Remove(Node);
- Node = parent._after.AddLast(this);
+public interface IStateEnter : IStateStage { }
+public interface IStateExit : IStateStage { }
+
+internal sealed class OnEnterStage(TState state, string name, bool runOnce = false) : Stage(name, runOnce), IStateEnter
+ where TState : struct, Enum
+{
+ public ITinySystem CreateSystem(ITinySystem sys)
+ => new TinyOnEnterSystem(state, sys);
+}
+
+internal sealed class OnExitStage(TState state, string name, bool runOnce = false) : Stage(name, runOnce), IStateExit
+ where TState : struct, Enum
+{
+ public ITinySystem CreateSystem(ITinySystem sys)
+ => new TinyOnExitSystem(state, sys);
+}
- return this;
- }
- public FuncSystem RunAfter(params ReadOnlySpan> systems)
+internal sealed class StageHandler(Stage stage)
+{
+ private bool _initialized;
+
+ public Stage Stage { get; } = stage;
+ internal List Systems { get; } = [];
+
+
+ public void AddSystem(ITinySystem system)
+ => Systems.Add(system);
+
+ public void Initialize(RunHandler runner, World world)
{
- foreach (var system in systems)
- system.RunAfter(this);
+ if (!_initialized)
+ {
+ runner.Initialize(Systems, world);
- return this;
+ _initialized = true;
+ }
}
- public FuncSystem RunBefore(FuncSystem parent)
+ public void Run(RunHandler runner, World world, uint ticks)
{
- if (this == parent || Contains(parent, s => s._before))
- throw new InvalidOperationException("Circular dependency detected");
+ runner.Run(Systems, world, ticks);
- Node?.List?.Remove(Node);
- Node = parent._before.AddLast(this);
+ if (Stage.RunOnce)
+ Systems.Clear();
+ }
+}
- return this;
+internal interface IRunHandler
+{
+ void Initialize(IEnumerable systems, World world);
+ void Run(IEnumerable systems, World world, uint ticks);
+}
+
+internal sealed class RunHandler : IRunHandler
+{
+ private readonly List _singleThreads = new();
+ private readonly List _multiThreads = new();
+
+ private static readonly int ProcessorCount = Environment.ProcessorCount;
+
+ public void Initialize(IEnumerable systems, World world)
+ {
+ foreach (var sys in systems)
+ sys.Initialize(world);
}
- public FuncSystem RunBefore(params ReadOnlySpan> systems)
+ public void Run(IEnumerable systems, World world, uint ticks)
{
- foreach (var system in systems)
- system.RunBefore(this);
+ _singleThreads.Clear();
+ _multiThreads.Clear();
- return this;
+ foreach (var sys in systems)
+ {
+ if (ProcessorCount <= 1 || sys.ParamsAreLocked())
+ {
+ _singleThreads.Add(sys);
+ }
+ else
+ {
+ _multiThreads.Add(sys);
+ }
+ }
+
+ if (_multiThreads.Count != 0)
+ Parallel.ForEach(_multiThreads, system => system.ExecuteOnReady(world, ticks));
+
+ foreach (var system in _singleThreads)
+ system.ExecuteOnReady(world, ticks);
+ }
+}
+
+
+internal sealed class StageContainer
+{
+ internal List Stages { get; } = new();
+ internal Dictionary StageMap { get; } = new();
+
+ public Stage Get(string name)
+ {
+ if (StageMap.TryGetValue(name, out var handler))
+ return handler.Stage;
+ throw new InvalidOperationException($"Stage '{name}' not found.");
}
- private bool Contains(FuncSystem system, Func, LinkedList>> direction)
+ internal void Add(Stage stage)
{
- var current = this;
- while (current != null)
+ if (!Contains(stage))
{
- if (current == system)
- return true;
-
- var nextNode = direction(current)?.First;
- current = nextNode?.Value;
+ var handler = new StageHandler(stage);
+ Stages.Add(handler);
+ StageMap.Add(stage.Name, handler);
+ }
+ else
+ {
+ throw new InvalidOperationException($"Stage '{stage.Name}' already exists.");
}
- return false;
}
- internal bool IsResourceInUse()
+ public StageHandler AddBeforeOf(Stage parent, Stage stage)
{
- return _threadingType switch
- {
- ThreadingMode.Multi => false,
- ThreadingMode.Single => true,
- _ or ThreadingMode.Auto => _checkInUse()
- };
+ if (!Contains(parent))
+ throw new InvalidOperationException($"Parent stage '{parent.Name}' not found.");
+
+ if (Contains(stage))
+ throw new InvalidOperationException($"Stage '{stage.Name}' already exists.");
+
+ var index = Stages.FindIndex(s => s.Stage == parent);
+ if (index == -1)
+ throw new InvalidOperationException($"Parent stage '{parent.Name}' not found.");
+
+ var handler = new StageHandler(stage);
+ Stages.Insert(index, handler);
+ StageMap.Add(stage.Name, handler);
+ return handler;
}
- private bool ValidateConditions(SystemTicks ticks, TArg args)
+ public StageHandler AddAfterOf(Stage parent, Stage stage)
{
- foreach (var fn in _conditions)
- if (!fn(ticks, args))
- return false;
- return true;
+ if (!Contains(parent))
+ throw new InvalidOperationException($"Parent stage '{parent.Name}' not found.");
+
+ if (Contains(stage))
+ throw new InvalidOperationException($"Stage '{stage.Name}' already exists.");
+
+ var index = Stages.FindIndex(s => s.Stage == parent);
+ if (index == -1)
+ throw new InvalidOperationException($"Parent stage '{parent.Name}' not found.");
+
+ var handler = new StageHandler(stage);
+ Stages.Insert(index + 1, handler);
+ StageMap.Add(stage.Name, handler);
+ return handler;
}
-}
-public enum Stages
-{
- Startup,
- FrameStart,
- BeforeUpdate,
- Update,
- AfterUpdate,
- FrameEnd,
+ public void AddSystem(ITinySystem system, Stage stage)
+ {
+ if (!StageMap.TryGetValue(stage.Name, out var handler))
+ {
+ // TODO: is there a better way to handle these special cases?
+ // the AddAfterOf makes the current stage to be added on head instead of tail.
+ if (stage is IStateEnter)
+ {
+ handler = AddAfterOf(Stage.OnEnterInner, stage);
+ }
+ else if (stage is IStateExit)
+ {
+ handler = AddAfterOf(Stage.OnExitInner, stage);
+ }
+ else
+ {
+ throw new InvalidOperationException($"Stage '{stage.Name}' not found.");
+ }
+ }
- OnEnter,
- OnExit
-}
+ if (stage is IStateStage stStage)
+ {
+ system = stStage.CreateSystem(system);
+ }
-public enum ThreadingMode
-{
- Auto,
- Single,
- Multi
-}
+ handler.AddSystem(system);
+ }
-public sealed class SystemTicks
-{
- public uint LastRun { get; set; }
- public uint ThisRun { get; set; }
+ private bool Contains(Stage stage)
+ => StageMap.ContainsKey(stage.Name);
}
public partial class Scheduler
{
private readonly World _world;
- private readonly LinkedList>[] _systems = new LinkedList>[(int)Stages.OnExit + 1];
- private readonly List> _singleThreads = new();
- private readonly List> _multiThreads = new();
private readonly Dictionary _events = new();
+ private readonly StageContainer _stageContainer = new();
+ private readonly RunHandler _runHandler = new();
+ private bool _initialized;
public Scheduler(World world, ThreadingMode threadingMode = ThreadingMode.Auto)
{
_world = world;
ThreadingExecutionMode = threadingMode;
- for (var i = 0; i < _systems.Length; ++i)
- _systems[i] = new LinkedList>();
+ _stageContainer.Add(Stage.Startup);
+ _stageContainer.Add(Stage.OnExitInner);
+ _stageContainer.Add(Stage.OnEnterInner);
+ _stageContainer.Add(Stage.FrameStart);
+ _stageContainer.Add(Stage.BeforeUpdate);
+ _stageContainer.Add(Stage.Update);
+ _stageContainer.Add(Stage.AfterUpdate);
+ _stageContainer.Add(Stage.FrameEnd);
AddSystemParam(world);
AddSystemParam(new SchedulerState(this));
@@ -176,6 +297,7 @@ public Scheduler(World world, ThreadingMode threadingMode = ThreadingMode.Auto)
public ThreadingMode ThreadingExecutionMode { get; }
+
public void Run(Func checkForExitFn, Action? cleanupFn = null)
{
while (!checkForExitFn())
@@ -186,78 +308,113 @@ public void Run(Func checkForExitFn, Action? cleanupFn = null)
public void RunOnce()
{
+ if (!_initialized)
+ {
+ foreach (var stageHandler in _stageContainer.Stages)
+ stageHandler.Initialize(_runHandler, _world);
+
+ _initialized = true;
+ }
+
var ticks = _world.Update();
foreach ((_, var ev) in _events)
ev.Clear();
- RunStage(Stages.Startup, ticks);
- _systems[(int)Stages.Startup].Clear();
+ foreach (var stageHandler in _stageContainer.Stages)
+ stageHandler.Run(_runHandler, _world, ticks);
+ }
- RunStage(Stages.OnExit, ticks);
- RunStage(Stages.OnEnter, ticks);
+ public Stage AddStageBeforeOf(string parentStageName, string name, bool oneShot = false)
+ {
+ var stage = _stageContainer.Get(parentStageName);
+ if (stage == null)
+ throw new InvalidOperationException($"Stage '{parentStageName}' not found.");
- for (var stage = Stages.FrameStart; stage <= Stages.FrameEnd; stage += 1)
- RunStage(stage, ticks);
+ return AddStageBeforeOf(stage, name, oneShot);
}
- private void RunStage(Stages stage, uint ticks)
+ public Stage AddStageBeforeOf(Stage parent, string name, bool oneShot = false)
{
- _singleThreads.Clear();
- _multiThreads.Clear();
+ var stage = new Stage(name, oneShot);
+ _stageContainer.AddBeforeOf(parent, stage);
- var systems = _systems[(int)stage];
+ return stage;
+ }
- if (systems.Count == 0)
- return;
+ public Stage AddStageAfterOf(string parentStageName, string name, bool oneShot = false)
+ {
+ var stage = _stageContainer.Get(parentStageName);
+ if (stage == null)
+ throw new InvalidOperationException($"Stage '{parentStageName}' not found.");
+ return AddStageAfterOf(stage, name, oneShot);
+ }
- foreach (var sys in systems)
- {
- if (sys.IsResourceInUse())
- {
- _singleThreads.Add(sys);
- }
- else
- {
- _multiThreads.Add(sys);
- }
- }
+ public Stage AddStageAfterOf(Stage parent, string name, bool oneShot = false)
+ {
+ var stage = new Stage(name, oneShot);
+ _stageContainer.AddAfterOf(parent, stage);
+
+ return stage;
+ }
+
+ private void Add(ITinySystem sys, Stages stage)
+ => Add(sys, GetStage(stage));
+
+ private void Add(ITinySystem sys, Stage stage)
+ {
+ sys.Configuration.ThreadingMode ??= ThreadingExecutionMode;
+ _stageContainer.AddSystem(sys, stage);
+ }
- var multithreading = _multiThreads;
- var singlethreading = _singleThreads;
+ public Scheduler AddSystem(Stage stage) where T : ITinySystem, new()
+ {
+ var system = new T();
+ Add(system, stage);
+ return this;
+ }
- if (multithreading.Count > 0)
- Parallel.ForEach(multithreading, s => s.Run(ticks));
+ public Scheduler AddSystem(string stageName) where T : ITinySystem, new()
+ {
+ var stage = _stageContainer.Get(stageName);
+ if (stage == null)
+ throw new InvalidOperationException($"Stage '{stageName}' not found.");
+ return AddSystem(stage);
+ }
- foreach (var system in singlethreading)
- system.Run(ticks);
+ public Scheduler AddSystems(string stageName, params ITinySystem[] systems)
+ {
+ var stage = _stageContainer.Get(stageName);
+ if (stage == null)
+ throw new InvalidOperationException($"Stage '{stageName}' not found.");
+ return AddSystems(stage, systems);
}
- internal void Add(FuncSystem sys, Stages stage)
+ public Scheduler AddSystems(Stage stage, params ITinySystem[] systems)
{
- sys.Node = _systems[(int)stage].AddLast(sys);
+ foreach (var system in systems)
+ Add(system, stage);
+
+ return this;
}
- public FuncSystem AddSystem(Action system, Stages stage = Stages.Update, ThreadingMode? threadingType = null)
+ public ITinySystem AddSystem(Action system, Stages stage = Stages.Update, ThreadingMode? threadingType = null)
{
if (!threadingType.HasValue)
threadingType = ThreadingExecutionMode;
- var sys = new FuncSystem(_world, (ticks, args, runIf) =>
+ var sys = new TinyDelegateSystem((args, ticks) =>
{
- if (runIf?.Invoke(ticks, args) ?? true)
- {
- system();
- return true;
- }
- return false;
- }, () => false, stage, threadingType.Value);
+ system();
+ return true;
+ });
+ sys.Configuration.ThreadingMode = threadingType;
Add(sys, stage);
return sys;
}
- public FuncSystem OnEnter(TState st, Action system, ThreadingMode? threadingType = null)
+ public ITinySystem OnEnter(TState st, Action system, ThreadingMode? threadingType = null)
where TState : struct, Enum
{
if (!threadingType.HasValue)
@@ -265,23 +422,20 @@ public FuncSystem OnEnter(TState st, Action system, ThreadingMode
var stateChangeId = -1;
- var sys = new FuncSystem(_world, (ticks, args, runIf) =>
+ var sys = new TinyDelegateSystem((args, ticks) =>
{
- if (runIf?.Invoke(ticks, args) ?? true)
- {
- system();
- return true;
- }
- return false;
- }, () => false, Stages.OnEnter, threadingType.Value)
+ system();
+ return true;
+ })
+ { Configuration = { ThreadingMode = threadingType } }
.RunIf((State state) => state.ShouldEnter(st, ref stateChangeId));
- Add(sys, Stages.OnEnter);
+ Add(sys, Stage.OnEnterInner);
return sys;
}
- public FuncSystem OnExit(TState st, Action system, ThreadingMode? threadingType = null)
+ public ITinySystem OnExit(TState st, Action system, ThreadingMode? threadingType = null)
where TState : struct, Enum
{
if (!threadingType.HasValue)
@@ -289,26 +443,23 @@ public FuncSystem OnExit(TState st, Action system, ThreadingMode?
var stateChangeId = -1;
- var sys = new FuncSystem(_world, (ticks, args, runIf) =>
+ var sys = new TinyDelegateSystem((args, ticks) =>
{
- if (runIf?.Invoke(ticks, args) ?? true)
- {
- system();
- return true;
- }
- return false;
- }, () => false, Stages.OnExit, threadingType.Value)
+ system();
+ return true;
+ })
+ { Configuration = { ThreadingMode = threadingType } }
.RunIf((State state) => state.ShouldExit(st, ref stateChangeId));
- Add(sys, Stages.OnExit);
+ Add(sys, Stage.OnExitInner);
return sys;
}
- public Scheduler AddPlugin() where T : notnull, IPlugin, new()
+ public Scheduler AddPlugin() where T : IPlugin, new()
=> AddPlugin(new T());
- public Scheduler AddPlugin(T plugin) where T : IPlugin
+ public Scheduler AddPlugin(IPlugin plugin)
{
plugin.Build(this);
@@ -336,14 +487,14 @@ public Scheduler AddResource(T resource) where T : notnull
return AddSystemParam(new Res() { Value = resource });
}
- public Scheduler AddSystemParam(T param) where T : notnull, ISystemParam
+ public Scheduler AddSystemParam(T param) where T : ISystemParam
{
_world.Entity>().Set(new Placeholder() { Value = param });
return this;
}
- internal bool ResourceExists() where T : notnull, ISystemParam
+ internal bool ResourceExists() where T : ISystemParam
{
return _world.Entity>().Has>();
}
@@ -354,9 +505,25 @@ internal bool InState(T state) where T : struct, Enum
return false;
return _world.Entity>>().Get>>().Value.InState(state);
}
+
+ private static Stage GetStage(Stages stage)
+ {
+ return stage switch
+ {
+ Stages.Startup => Stage.Startup,
+ Stages.FrameStart => Stage.FrameStart,
+ Stages.BeforeUpdate => Stage.BeforeUpdate,
+ Stages.Update => Stage.Update,
+ Stages.AfterUpdate => Stage.AfterUpdate,
+ Stages.FrameEnd => Stage.FrameEnd,
+ Stages.OnEnter => Stage.OnEnterInner,
+ Stages.OnExit => Stage.OnExitInner,
+ _ => throw new ArgumentOutOfRangeException(nameof(stage), stage, null)
+ };
+ }
}
-internal struct Placeholder where T : ISystemParam { public T Value; }
+internal struct Placeholder where T : ISystemParam { public T Value; }
public interface IPlugin
@@ -395,7 +562,6 @@ public interface ISystemParam
public interface ISystemParam : ISystemParam
{
-
}
public interface IIntoSystemParam
@@ -494,8 +660,6 @@ public static ISystemParam Generate(World arg)
partial class World : SystemParam, IIntoSystemParam
{
- public World() : this(256) { }
-
public static ISystemParam Generate(World arg)
{
return arg;
@@ -716,12 +880,11 @@ public sealed class Res : SystemParam, IIntoSystemParam
public static ISystemParam Generate(World arg)
{
- if (arg.Entity>>().Has>>())
- return arg.Entity>>().Get>>().Value;
+ var ent = arg.Entity>>();
+ if (ent.Has>>())
+ return ent.Get>>().Value;
- var res = new Res();
- arg.Entity>>().Set(new Placeholder>() { Value = res });
- return res;
+ return null;
}
public static implicit operator T?(Res reference)
@@ -1294,7 +1457,11 @@ internal QueryIter(uint lastRun, uint thisRun, QueryIterator iterator)
}
[UnscopedRef]
- public ref D Current => ref _dataIterator;
+ public ref D Current
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => ref _dataIterator;
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
@@ -1315,4 +1482,352 @@ public bool MoveNext()
public readonly QueryIter GetEnumerator() => this;
}
+
+[AttributeUsage(AttributeTargets.Method)]
+public sealed class TinySystemAttribute : Attribute
+{
+}
+
+public sealed class SystemParamBuilder(World world)
+{
+ private readonly List> _params = [];
+ private readonly List>> _paramsFns = [];
+
+ public T Add() where T : ISystemParam, IIntoSystemParam
+ {
+ var param = (T)T.Generate(world);
+ _params.Add(param);
+ _paramsFns.Add(() => (T)T.Generate(world));
+ return param;
+ }
+
+ public (ISystemParam[], Func>[]) Build()
+ => ([.. _params], [.. _paramsFns]);
+}
+
+public sealed class SystemParamRef where T : ISystemParam, IIntoSystemParam
+{
+ private readonly World _world;
+ private T? _t;
+ internal SystemParamRef(World world) => _world = world;
+
+ public T Get() => _t ??= (T)T.Generate(_world);
+}
+
+public sealed class SystemConfiguration
+{
+ public HashSet Conditionals { get; } = [];
+ public ThreadingMode? ThreadingMode { get; set; }
+}
+
+public sealed class SystemOrder
+{
+ public LinkedList BeforeSystems { get; internal set; } = new();
+ public LinkedList AfterSystems { get; internal set; } = new();
+ public LinkedListNode? Node { get; internal set; }
+
+
+ public static ITinySystem Chain(params ITinySystem[] systems)
+ {
+ if (systems.Length == 0)
+ throw new ArgumentException("At least one system is required to create a chain.", nameof(systems));
+
+ var first = systems[0];
+ for (var i = 1; i < systems.Length; i++)
+ systems[i].RunAfter(first);
+ return first;
+ }
+}
+
+
+public interface ITinyMeta
+{
+ ISystemParam[] SystemParams { get; set; }
+ SystemTicks Ticks { get; }
+ SystemConfiguration Configuration { get; }
+
+
+ bool ParamsAreLocked();
+ void Initialize(World world);
+ bool ExecuteOnReady(World world, uint ticks);
+
+ bool BeforeExecute(World world);
+ bool AfterExecute(World world);
+}
+
+public interface ITinySystem : ITinyMeta
+{
+ SystemOrder OrderConfiguration { get; }
+
+ bool ParamsAreReady();
+ ITinySystem RunIf() where T : ITinyConditionalSystem, new();
+ ITinySystem RunIf(params ITinyConditionalSystem[] conditionals);
+ ITinySystem RunAfter(ITinySystem sys);
+ ITinySystem RunBefore(ITinySystem sys);
+}
+
+public interface ITinyConditionalSystem : ITinyMeta
+{
+}
+
+
+public abstract class TinySystemBase : ITinyMeta
+{
+ private bool _initialized;
+ private Func>[] _paramsFns = [];
+
+ public ISystemParam[] SystemParams { get; set; } = [];
+ public SystemTicks Ticks { get; } = new();
+ public SystemConfiguration Configuration { get; } = new();
+
+ public virtual void Initialize(World world)
+ {
+ if (_initialized)
+ throw new Exception("Already initialized");
+
+ _initialized = true;
+
+ var builder = new SystemParamBuilder(world);
+ Setup(builder);
+ (SystemParams, _paramsFns) = builder.Build();
+
+ foreach (var conditional in Configuration.Conditionals)
+ {
+ conditional.Initialize(world);
+ }
+ }
+
+ public virtual bool BeforeExecute(World world)
+ => true;
+
+ public virtual bool AfterExecute(World world)
+ => true;
+
+ public bool ExecuteOnReady(World world, uint ticks)
+ {
+ if (!ParamsAreReady())
+ {
+ for (var i = 0; i < SystemParams.Length; i++)
+ {
+ if (SystemParams[i] == null && i < _paramsFns.Length)
+ {
+ SystemParams[i] = _paramsFns[i]();
+ }
+ }
+
+ if (!ParamsAreReady())
+ return false;
+ }
+
+ Ticks.ThisRun = ticks;
+ var canRun = BeforeExecute(world);
+
+ if (canRun)
+ {
+ foreach (var conditional in Configuration.Conditionals)
+ {
+ if (!conditional.ExecuteOnReady(world, ticks))
+ {
+ canRun = false;
+ break;
+ }
+ }
+
+ if (canRun)
+ {
+ canRun = Execute(world);
+ }
+
+ if (canRun)
+ {
+ canRun = AfterExecute(world);
+ }
+ }
+
+ Ticks.LastRun = Ticks.ThisRun;
+
+ return canRun;
+ }
+
+ public bool ParamsAreReady()
+ {
+ foreach (var param in SystemParams)
+ if (param == null)
+ return false;
+
+ return true;
+ }
+
+ public bool ParamsAreLocked()
+ {
+ return Configuration.ThreadingMode switch
+ {
+ ThreadingMode.Single => true,
+ ThreadingMode.Multi => false,
+ _ => SystemParams.Any(static p => p is { UseIndex: > 0 })
+ };
+ }
+
+ protected void Lock()
+ {
+ foreach (var param in SystemParams)
+ param.Lock(Ticks);
+ }
+
+ protected void Unlock()
+ {
+ foreach (var param in SystemParams)
+ param.Unlock();
+ }
+
+ protected abstract void Setup(SystemParamBuilder builder);
+ protected abstract bool Execute(World world);
+}
+
+public abstract class TinySystem : TinySystemBase, ITinySystem
+{
+ public SystemOrder OrderConfiguration { get; } = new();
+
+ public override void Initialize(World world)
+ {
+ base.Initialize(world);
+
+ foreach (var afterSys in OrderConfiguration.AfterSystems)
+ {
+ afterSys.Initialize(world);
+ }
+ }
+
+ public override bool BeforeExecute(World world)
+ {
+ var ticks = Ticks.ThisRun;
+ foreach (var beforeSys in OrderConfiguration.BeforeSystems)
+ {
+ if (!beforeSys.ExecuteOnReady(world, ticks))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public override bool AfterExecute(World world)
+ {
+ var ticks = Ticks.ThisRun;
+ foreach (var afterSys in OrderConfiguration.AfterSystems)
+ {
+ if (!afterSys.ExecuteOnReady(world, ticks))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ public ITinySystem RunIf() where T : ITinyConditionalSystem, new()
+ => RunIf(new T());
+
+ public ITinySystem RunIf(params ITinyConditionalSystem[] conditionals)
+ {
+ // TODO: Check for duplicates?
+ foreach (var sys in conditionals)
+ _ = Configuration.Conditionals.Add(sys);
+ return this;
+ }
+
+ public ITinySystem RunAfter(ITinySystem sys)
+ {
+ OrderConfiguration.Node?.List?.Remove(OrderConfiguration.Node);
+ OrderConfiguration.Node = sys.OrderConfiguration.AfterSystems.AddLast(this);
+ return this;
+ }
+
+ public ITinySystem RunBefore(ITinySystem sys)
+ {
+ OrderConfiguration.Node?.List?.Remove(OrderConfiguration.Node);
+ OrderConfiguration.Node = sys.OrderConfiguration.BeforeSystems.AddLast(this);
+ return this;
+ }
+}
+
+public abstract class TinyConditionalSystem : TinySystemBase, ITinyConditionalSystem
+{
+}
+
+public sealed partial class TinyDelegateSystem : TinySystem, ITinyConditionalSystem
+{
+ private readonly Func _fn;
+
+ public TinyDelegateSystem(Func fn)
+ {
+ _fn = fn;
+ }
+
+ protected override void Setup(SystemParamBuilder builder)
+ {
+ }
+
+ protected override bool Execute(World world)
+ {
+ return _fn(world, Ticks);
+ }
+}
+
+internal abstract class TinyStateSystemAdapter(ITinySystem sys) : TinySystem
+ where TState : struct, Enum
+{
+ protected State _state;
+ protected int _stateChangedId = -1;
+
+ public override void Initialize(World world)
+ {
+ base.Initialize(world);
+ sys.Initialize(world);
+ }
+
+ protected override void Setup(SystemParamBuilder builder)
+ {
+ _state = builder.Add>();
+ }
+}
+
+internal sealed class TinyOnEnterSystem(TState st, ITinySystem sys) : TinyStateSystemAdapter(sys)
+ where TState : struct, Enum
+{
+ protected override bool Execute(World world)
+ {
+ Lock();
+ world.BeginDeferred();
+ var result = _state.ShouldEnter(st, ref _stateChangedId);
+ if (result)
+ {
+ _ = sys.ExecuteOnReady(world, Ticks.ThisRun);
+ }
+ world.EndDeferred();
+ Unlock();
+ return result;
+ }
+}
+
+internal sealed class TinyOnExitSystem(TState st, ITinySystem sys) : TinyStateSystemAdapter(sys)
+ where TState : struct, Enum
+{
+ protected override bool Execute(World world)
+ {
+ Lock();
+ world.BeginDeferred();
+ var result = _state.ShouldExit(st, ref _stateChangedId);
+ if (result)
+ {
+ _ = sys.ExecuteOnReady(world, Ticks.ThisRun);
+ }
+ world.EndDeferred();
+ Unlock();
+ return result;
+ }
+}
+
#endif
diff --git a/src/TinyEcs.QueryIteratorEach.g.cs b/src/TinyEcs.QueryIteratorEach.g.cs
index 14bb32fe..6120af7b 100644
--- a/src/TinyEcs.QueryIteratorEach.g.cs
+++ b/src/TinyEcs.QueryIteratorEach.g.cs
@@ -1,4 +1,4 @@
-#pragma warning disable 1591
+#pragma warning disable 1591
#nullable enable
using System;
diff --git a/src/TinyEcs.Systems.DataAndFilter.g.cs b/src/TinyEcs.Systems.DataAndFilter.g.cs
index df6c25c9..e00864e0 100644
--- a/src/TinyEcs.Systems.DataAndFilter.g.cs
+++ b/src/TinyEcs.Systems.DataAndFilter.g.cs
@@ -1,4 +1,4 @@
-#pragma warning disable 1591
+#pragma warning disable 1591
#nullable enable
using System;
diff --git a/src/TinyEcs.Systems.Interfaces.g.cs b/src/TinyEcs.Systems.Interfaces.g.cs
index 62acf267..25fcf6c1 100644
--- a/src/TinyEcs.Systems.Interfaces.g.cs
+++ b/src/TinyEcs.Systems.Interfaces.g.cs
@@ -1,4 +1,4 @@
-#pragma warning disable 1591
+#pragma warning disable 1591
#nullable enable
using System;
@@ -9,87 +9,95 @@
namespace TinyEcs
{
#if NET9_0_OR_GREATER
- public sealed partial class FuncSystem
+ public sealed partial class TinyDelegateSystem
{
- public FuncSystem RunIf(Func condition)
- where T0 : class, ISystemParam, IIntoSystemParam
+ public ITinySystem RunIf(Func condition)
+ where T0 : class, ISystemParam, IIntoSystemParam
{
T0? obj0 = null;
- var fn = (SystemTicks ticks, TArg args) => {
+ var fn = (World args, SystemTicks ticks) => {
obj0 ??= (T0)T0.Generate(args);
return condition(obj0);
};
- _conditions.Add(fn);
+
+ var sys = new TinyDelegateSystem(fn);
+ Configuration.Conditionals.Add(sys);
return this;
}
- public FuncSystem RunIf(Func condition)
- where T0 : class, ISystemParam, IIntoSystemParam
- where T1 : class, ISystemParam, IIntoSystemParam
+ public ITinySystem RunIf(Func condition)
+ where T0 : class, ISystemParam, IIntoSystemParam
+ where T1 : class, ISystemParam, IIntoSystemParam
{
T0? obj0 = null;
T1? obj1 = null;
- var fn = (SystemTicks ticks, TArg args) => {
+ var fn = (World args, SystemTicks ticks) => {
obj0 ??= (T0)T0.Generate(args);
obj1 ??= (T1)T1.Generate(args);
return condition(obj0, obj1);
};
- _conditions.Add(fn);
+
+ var sys = new TinyDelegateSystem(fn);
+ Configuration.Conditionals.Add(sys);
return this;
}
- public FuncSystem RunIf(Func condition)
- where T0 : class, ISystemParam, IIntoSystemParam
- where T1 : class, ISystemParam, IIntoSystemParam
- where T2 : class, ISystemParam, IIntoSystemParam
+ public ITinySystem RunIf(Func condition)
+ where T0 : class, ISystemParam, IIntoSystemParam
+ where T1 : class, ISystemParam, IIntoSystemParam
+ where T2 : class, ISystemParam, IIntoSystemParam
{
T0? obj0 = null;
T1? obj1 = null;
T2? obj2 = null;
- var fn = (SystemTicks ticks, TArg args) => {
+ var fn = (World args, SystemTicks ticks) => {
obj0 ??= (T0)T0.Generate(args);
obj1 ??= (T1)T1.Generate(args);
obj2 ??= (T2)T2.Generate(args);
return condition(obj0, obj1, obj2);
};
- _conditions.Add(fn);
+
+ var sys = new TinyDelegateSystem(fn);
+ Configuration.Conditionals.Add(sys);
return this;
}
- public FuncSystem RunIf(Func condition)
- where T0 : class, ISystemParam, IIntoSystemParam
- where T1 : class, ISystemParam, IIntoSystemParam
- where T2 : class, ISystemParam