From 97d1118caac1987858741ef0a2d08b4e6685abd7 Mon Sep 17 00:00:00 2001 From: Misaki Date: Tue, 9 Dec 2025 15:10:10 +0900 Subject: [PATCH] Remove old project and continue improving ecs. Updated packages version; Removed Ghost.SparseEntities; Added new EntityQuery.EntityComponentIterator; Added new thread local command buffer in World; Changed commands in EntityCommandBuffer from UnsafeList to UnsafeList for better performance; Changed the name of IJobEntityParallel to IJobEntity; --- Ghost.Core/Ghost.Core.csproj | 2 +- Ghost.Entities.Test/ArcEntityTest.cs | 92 - Ghost.Entities.Test/EntityTest.cs | 206 +- .../Ghost.Entities.Test.csproj | 1 - Ghost.Entities.Test/Program.cs | 4 +- Ghost.Entities/EntityCommandBuffer.cs | 232 ++- Ghost.Entities/System.cs | 46 +- ...EntityQuery.EntityComponentIterator.gen.cs | 1610 ++++++++++++++++ .../EntityQuery.EntityComponentIterator.tt | 199 ++ ...el.gen.cs => EntityQuery.JobEntity.gen.cs} | 48 +- ...tyParallel.tt => EntityQuery.JobEntity.tt} | 6 +- Ghost.Entities/World.cs | 48 + Ghost.SparseEntities/AssemblyInfo.cs | 12 - .../Components/ComponentStorage.cs | 715 ------- .../Components/IComponentData.cs | 5 - .../Components/ScriptComponent.cs | 110 -- Ghost.SparseEntities/Entity.cs | 82 - Ghost.SparseEntities/EntityManager.cs | 360 ---- .../Ghost.SparseEntities.csproj | 113 -- Ghost.SparseEntities/Query/QueryBuilder.cs | 42 - Ghost.SparseEntities/Query/QueryFilter.cs | 97 - .../Query/QueryTypeParameter.cs | 73 - Ghost.SparseEntities/Systems/ISystem.cs | 27 - .../Systems/SystemDependencyBuilder.cs | 105 - Ghost.SparseEntities/Systems/SystemState.cs | 10 - Ghost.SparseEntities/Systems/SystemStorage.cs | 93 - Ghost.SparseEntities/Template/ForEach.cs | 12 - Ghost.SparseEntities/Template/ForEach.tt | 16 - .../Template/Helpers.ttinclude | 128 -- .../Template/QueryEnumerable.cs | 1706 ----------------- .../Template/QueryEnumerable.tt | 175 -- Ghost.SparseEntities/Template/QueryItem.cs | 319 --- Ghost.SparseEntities/Template/QueryItem.tt | 61 - .../Template/QueryRefComponent.cs | 22 - .../Template/QueryRefComponent.tt | 21 - Ghost.SparseEntities/Template/World.Query.cs | 242 --- Ghost.SparseEntities/Template/World.Query.tt | 54 - Ghost.SparseEntities/World.cs | 164 -- 38 files changed, 2093 insertions(+), 5165 deletions(-) delete mode 100644 Ghost.Entities.Test/ArcEntityTest.cs create mode 100644 Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.gen.cs create mode 100644 Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.tt rename Ghost.Entities/Templates/{EntityQuery.JobEntityParallel.gen.cs => EntityQuery.JobEntity.gen.cs} (97%) rename Ghost.Entities/Templates/{EntityQuery.JobEntityParallel.tt => EntityQuery.JobEntity.tt} (96%) delete mode 100644 Ghost.SparseEntities/AssemblyInfo.cs delete mode 100644 Ghost.SparseEntities/Components/ComponentStorage.cs delete mode 100644 Ghost.SparseEntities/Components/IComponentData.cs delete mode 100644 Ghost.SparseEntities/Components/ScriptComponent.cs delete mode 100644 Ghost.SparseEntities/Entity.cs delete mode 100644 Ghost.SparseEntities/EntityManager.cs delete mode 100644 Ghost.SparseEntities/Ghost.SparseEntities.csproj delete mode 100644 Ghost.SparseEntities/Query/QueryBuilder.cs delete mode 100644 Ghost.SparseEntities/Query/QueryFilter.cs delete mode 100644 Ghost.SparseEntities/Query/QueryTypeParameter.cs delete mode 100644 Ghost.SparseEntities/Systems/ISystem.cs delete mode 100644 Ghost.SparseEntities/Systems/SystemDependencyBuilder.cs delete mode 100644 Ghost.SparseEntities/Systems/SystemState.cs delete mode 100644 Ghost.SparseEntities/Systems/SystemStorage.cs delete mode 100644 Ghost.SparseEntities/Template/ForEach.cs delete mode 100644 Ghost.SparseEntities/Template/ForEach.tt delete mode 100644 Ghost.SparseEntities/Template/Helpers.ttinclude delete mode 100644 Ghost.SparseEntities/Template/QueryEnumerable.cs delete mode 100644 Ghost.SparseEntities/Template/QueryEnumerable.tt delete mode 100644 Ghost.SparseEntities/Template/QueryItem.cs delete mode 100644 Ghost.SparseEntities/Template/QueryItem.tt delete mode 100644 Ghost.SparseEntities/Template/QueryRefComponent.cs delete mode 100644 Ghost.SparseEntities/Template/QueryRefComponent.tt delete mode 100644 Ghost.SparseEntities/Template/World.Query.cs delete mode 100644 Ghost.SparseEntities/Template/World.Query.tt delete mode 100644 Ghost.SparseEntities/World.cs diff --git a/Ghost.Core/Ghost.Core.csproj b/Ghost.Core/Ghost.Core.csproj index a7dfc8f..b2696fc 100644 --- a/Ghost.Core/Ghost.Core.csproj +++ b/Ghost.Core/Ghost.Core.csproj @@ -21,7 +21,7 @@ - + diff --git a/Ghost.Entities.Test/ArcEntityTest.cs b/Ghost.Entities.Test/ArcEntityTest.cs deleted file mode 100644 index 0c48168..0000000 --- a/Ghost.Entities.Test/ArcEntityTest.cs +++ /dev/null @@ -1,92 +0,0 @@ -using Ghost.Test.Core; -using Misaki.HighPerformance.Jobs; -using Misaki.HighPerformance.LowLevel.Buffer; -using Misaki.HighPerformance.Mathematics; - -namespace Ghost.Entities.Test; - -internal struct TestEntityQueryJob : IJobEntityParallel -{ - public readonly void Execute(Entity entity, ref Transform transform) - { - transform.position += new float3(10, 10, 10); - } -} - -public partial class ArcEntityTest : ITest -{ - private JobScheduler _jobScheduler = null!; - private World _world = null!; - - public void Setup() - { - _jobScheduler = new JobScheduler(4); - _world = World.Create(_jobScheduler); - } - - public void Run() - { - var entity1 = _world.EntityManager.CreateEntity(ComponentTypeID.value); - _world.EntityCommandBuffer.AddComponent(entity1, new Mesh { index = 1 }); - - // var entity2 = _world.EntityManager.CreateEntity(ComponentTypeID.value); - // _world.EntityManager.SetComponentData(entity2, new Transform { position = new float3(1, 2, 3) }); - - Console.WriteLine($"Entity {entity1} hash Mesh: {_world.EntityManager.HasComponent(entity1)}"); - - _world.EntityCommandBuffer.Playback(); - Console.WriteLine($"Entity {entity1} hash Mesh: {_world.EntityManager.HasComponent(entity1)}"); - - _world.EntityCommandBuffer.RemoveComponent(entity1); - Console.WriteLine($"Entity {entity1} hash Mesh: {_world.EntityManager.HasComponent(entity1)}"); - - _world.EntityCommandBuffer.Playback(); - Console.WriteLine($"Entity {entity1} hash Mesh: {_world.EntityManager.HasComponent(entity1)}"); - - // var queryID = new QueryBuilder().WithAll().Build(_world); - // ref var query = ref _world.GetEntityQueryReference(queryID); - - // var testJob = new TestEntityQueryJob(); - // var handle = query.ScheduleEntityParallel(_jobScheduler, testJob, Allocator.Temp, 64, JobHandle.Invalid); - // _jobScheduler.WaitComplete(handle); - // - // query.ForEach((e, ref t) => - // { - // Console.WriteLine($"Entity {e} Has Position: {t.position}"); - // }); - // - // foreach (ref var transform in query.GetComponentIterator()) - // { - // Console.WriteLine($"Entity Updated Position: {transform.position}"); - // } - // - // foreach (var chunk in query.GetChunkIterator()) - // { - // var transforms = chunk.GetComponentData(); - // var entities = chunk.GetEntities(); - // var bits = chunk.GetEnableBits(); - // - // var it = bits.GetIterator(); - // while (it.Next(out var index) && index < chunk.Count) - // { - // Console.WriteLine($"Entity {entities[index]} Updated Position: {transforms[index].position}"); - // } - // } - } - - public void Cleanup() - { - _world.Dispose(); - _jobScheduler.Dispose(); - } -} - -public struct Transform : IEnableableComponent -{ - public float3 position; -} - -public struct Mesh : IComponent -{ - public int index; -} diff --git a/Ghost.Entities.Test/EntityTest.cs b/Ghost.Entities.Test/EntityTest.cs index 039e2d8..07e91dc 100644 --- a/Ghost.Entities.Test/EntityTest.cs +++ b/Ghost.Entities.Test/EntityTest.cs @@ -1,193 +1,85 @@ -#if false -using Ghost.SparseEntities.Components; -using Ghost.SparseEntities.Query; -using Ghost.SparseEntities.Systems; using Ghost.Test.Core; -using System.Numerics; +using Misaki.HighPerformance.Jobs; +using Misaki.HighPerformance.LowLevel.Buffer; +using Misaki.HighPerformance.Mathematics; +using System.Runtime.CompilerServices; namespace Ghost.Entities.Test; +internal struct TestEntityQueryJob : IJobEntity +{ + public readonly void Execute(Entity entity, ref Transform transform) + { + transform.position += new float3(10, 10, 10); + } +} + public partial class EntityTest : ITest { + private JobScheduler _jobScheduler = null!; private World _world = null!; public void Setup() { - _world = World.Create(); + _jobScheduler = new JobScheduler(4); + _world = World.Create(_jobScheduler); + + Console.WriteLine(Unsafe.SizeOf()); } public void Run() { - var entity1 = _world.EntityManager.CreateEntity(); - var entity2 = _world.EntityManager.CreateEntity(); - var entity3 = _world.EntityManager.CreateEntity(); + var entity1 = _world.EntityManager.CreateEntity(ComponentTypeID.value); + _world.EntityManager.AddComponent(entity1, new Mesh { index = 1 }); - _world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) }); - _world.EntityManager.AddComponent(entity1, new Mesh { index = 42 }); - _world.EntityManager.AddScript(entity1); - _world.EntityManager.AddScript(entity1); + var entity2 = _world.EntityManager.CreateEntity(ComponentTypeID.value); + _world.EntityManager.SetComponent(entity2, new Transform { position = new float3(1, 2, 3) }); - _world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) }); - _world.EntityManager.AddComponent(entity2, new Mesh { index = 43 }); - _world.EntityManager.AddScript(entity2); + var queryID = new QueryBuilder().WithAll().Build(_world); + ref var query = ref _world.GetEntityQueryReference(queryID); - _world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) }); - _world.EntityManager.AddScript(entity3); + var testJob = new TestEntityQueryJob(); + var handle = query.ScheduleEntityParallel(testJob, Allocator.Temp, 64, JobHandle.Invalid); + _jobScheduler.WaitComplete(handle); - foreach (var (_, transform) in _world.Query()) + query.ForEach((e, ref t) => { - transform.ValueRW.position += new Vector3(1, 1, 1); + Console.WriteLine($"Entity {e} Has Position: {t.position}"); + }); + + foreach (var (entity, transform) in query.GetEntityComponentIterator()) + { + Console.WriteLine($"Entity {entity} Updated Position: {transform.Get().position}"); } - var filter = new QueryBuilder() - .WithAll() - .Build(); - - foreach (var (_, mesh) in _world.QueryFilter(in filter)) + foreach (var chunk in query.GetChunkIterator()) { - mesh.ValueRW.index += 1; + var transforms = chunk.GetComponentData(); + var entities = chunk.GetEntities(); + var bits = chunk.GetEnableBits(); + + var it = bits.GetIterator(); + while (it.Next(out var index) && index < chunk.Count) + { + Console.WriteLine($"Entity {entities[index]} Updated Position: {transforms[index].position}"); + } } - - _world.EntityManager.RemoveEntity(ref entity2); - - var entity4 = _world.EntityManager.CreateEntity(); - _world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) }); - _world.EntityManager.AddComponent(entity4, new Mesh { index = 45 }); - _world.EntityManager.AddScript(entity4); - - _world.SystemStorage.AddSystem(); - _world.SystemStorage.AddSystem(); - - _world.SystemStorage.CreateSystems(); - _world.SystemStorage.UpdateSystems(); } public void Cleanup() { _world.Dispose(); + _jobScheduler.Dispose(); + JobScheduler.ReleaseTempAllocator(); } } -public class TestSystem : ISystem +public struct Transform : IEnableableComponent { - public void OnCreate(in SystemState state) - { - } - - public void OnUpdate(in SystemState state) - { - foreach (var (entity, transform) in state.World.Query()) - { - Console.WriteLine($"Entity {entity}: Transform Position = {transform.ValueRO.position}"); - } - } - - public void OnDestroy(in SystemState state) - { - } + public float3 position; } -[DependsOn(typeof(TestSystem))] -public class TestSystem2 : ISystem +public struct Mesh : IComponent { - public void OnCreate(in SystemState state) - { - } - - public void OnUpdate(in SystemState state) - { - foreach (var (entity, mesh) in state.World.Query()) - { - Console.WriteLine($"Entity {entity}: Mesh Index = {mesh.ValueRO.index}"); - } - } - - public void OnDestroy(in SystemState state) - { - } + public int index; } - -public struct Transform : IComponentData -{ - public Vector3 position; - public Quaternion rotation; - public Vector3 scale; -} - -public struct Mesh : IComponentData -{ - public uint index; -} - -public class UserScript : ScriptComponent -{ - public override int ExecutionOrder => -1; - - public override void OnEnable() - { - Console.WriteLine("UserScript enabled for entity: " + Owner); - EntityManager.GetComponent(Owner).ValueRW.position += new Vector3(10, 10, 10); - } - - public override void OnDisable() - { - Console.WriteLine("UserScript disabled for entity: " + Owner); - } - - public override void Initialize() - { - Console.WriteLine("UserScript initialized for entity: " + Owner); - } - - public override void Start() - { - Console.WriteLine("UserScript started for entity: " + Owner); - } - - public override void Update() - { - Console.WriteLine("UserScript updating for entity: " + Owner); - } - - public override void OnDestroy() - { - Console.WriteLine("UserScript destroyed for entity: " + Owner); - } -} - -public class UIManager : ScriptComponent -{ - public override void Start() - { - Console.WriteLine("UIManager started for entity: " + Owner); - } - - public override void Update() - { - Console.WriteLine("UIManager updating for entity: " + Owner); - } - - public override void OnDestroy() - { - Console.WriteLine("UIManager destroyed for entity: " + Owner); - } -} - -public class EventManager : ScriptComponent -{ - public override void Start() - { - Console.WriteLine("EventManager started for entity: " + Owner); - } - - public override void Update() - { - Console.WriteLine("EventManager updating for entity: " + Owner); - } - - public override void OnDestroy() - { - Console.WriteLine("EventManager destroyed for entity: " + Owner); - } -} -#endif \ No newline at end of file diff --git a/Ghost.Entities.Test/Ghost.Entities.Test.csproj b/Ghost.Entities.Test/Ghost.Entities.Test.csproj index f1e1ac5..65612d3 100644 --- a/Ghost.Entities.Test/Ghost.Entities.Test.csproj +++ b/Ghost.Entities.Test/Ghost.Entities.Test.csproj @@ -9,7 +9,6 @@ - diff --git a/Ghost.Entities.Test/Program.cs b/Ghost.Entities.Test/Program.cs index 12c3a1b..83bec0b 100644 --- a/Ghost.Entities.Test/Program.cs +++ b/Ghost.Entities.Test/Program.cs @@ -3,5 +3,5 @@ using Ghost.Test.Core; using Misaki.HighPerformance.LowLevel.Buffer; AllocationManager.EnableDebugLayer(); -TestRunner.Run(); -AllocationManager.Dispose(); \ No newline at end of file +TestRunner.Run(); +AllocationManager.Dispose(); diff --git a/Ghost.Entities/EntityCommandBuffer.cs b/Ghost.Entities/EntityCommandBuffer.cs index e01d322..cc2bee0 100644 --- a/Ghost.Entities/EntityCommandBuffer.cs +++ b/Ghost.Entities/EntityCommandBuffer.cs @@ -2,37 +2,30 @@ using Ghost.Core; using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; using Misaki.HighPerformance.LowLevel.Utilities; -using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace Ghost.Entities; public unsafe class EntityCommandBuffer : IDisposable { - private enum CommandType + private enum ECBOpCode : byte { CreateEntity, + CreateEntityWithComponents, DestroyEntity, AddComponent, RemoveComponent, SetComponent, } - private struct Command - { - public UnsafeArray data; - public Entity entity; - public CommandType type; - public Identifier componentTypeID; - } - private readonly EntityManager _entityManager; - private UnsafeList _commands; // TODO: Maybe use UnsafeArray directly to save additional memory allocation in Unsafe data inside Command struct. + private UnsafeList _buffer; private bool _disposed; public EntityCommandBuffer(EntityManager entityManager) { _entityManager = entityManager; - _commands = new UnsafeList(32, Allocator.Persistent); + _buffer = new UnsafeList(4096, Allocator.Persistent); } ~EntityCommandBuffer() @@ -40,115 +33,165 @@ public unsafe class EntityCommandBuffer : IDisposable Dispose(); } + private void WriteHeader(ECBOpCode op) + { + _buffer.Add((byte)op); + } + + private void Write(T value) + where T : unmanaged + { + var size = sizeof(T); + var idx = _buffer.Count; + + if (idx + size > _buffer.Capacity) + { + _buffer.Resize(idx + size); + } + + MemoryUtility.MemCpy((byte*)_buffer.GetUnsafePtr() + idx, &value, (nuint)size); + } + + private void WriteSpan(ReadOnlySpan span) + where T : unmanaged + { + var size = sizeof(T) * span.Length; + var idx = _buffer.Count; + + if (idx + size > _buffer.Capacity) + { + _buffer.Resize(idx + size); + } + + fixed (T* ptr = span) + { + MemoryUtility.MemCpy((byte*)_buffer.GetUnsafePtr() + idx, ptr, (nuint)size); + } + } + + private T Read(ref int cursor) + where T : unmanaged + { + var size = sizeof(T); + var ptr = (byte*)_buffer.GetUnsafePtr(); + + var value = *(T*)&ptr[cursor]; + cursor += size; + + return value; + } + + private Span ReadSpan(ref int cursor, int length) + where T : unmanaged + { + var size = sizeof(T) * length; + var ptr = (byte*)_buffer.GetUnsafePtr(); + + var span = new Span(&ptr[cursor], length); + cursor += size; + + return span; + } + + private void* ReadBuffer(ref int cursor, int size) + { + var ptr = (byte*)_buffer.GetUnsafePtr(); + var bufferPtr = ptr + cursor; + cursor += size; + + return bufferPtr; + } + public void CreateEntity() { - var command = new Command - { - type = CommandType.CreateEntity, - data = default, - entity = default, - componentTypeID = -1 - }; - - _commands.Add(command); + WriteHeader(ECBOpCode.CreateEntity); } public void CreateEntity(params ReadOnlySpan> componentTypeIDs) { - var data = new UnsafeArray(componentTypeIDs.Length * sizeof(int), Allocator.Temp); - MemoryMarshal.Cast, byte>(componentTypeIDs).CopyTo(data.AsSpan()); - - var command = new Command - { - type = CommandType.CreateEntity, - data = data, - entity = Entity.Invalid, - componentTypeID = Identifier.Invalid - }; - - _commands.Add(command); + WriteHeader(ECBOpCode.CreateEntityWithComponents); + Write(componentTypeIDs.Length); + WriteSpan(componentTypeIDs); } public void DestroyEntity(Entity entity) { - _commands.Add(new Command - { - type = CommandType.DestroyEntity, - data = default, - entity = entity, - componentTypeID = Identifier.Invalid - }); + WriteHeader(ECBOpCode.DestroyEntity); + Write(entity); } public void AddComponent(Entity entity, T component = default) where T : unmanaged, IComponent { - var data = new UnsafeArray(sizeof(T), Allocator.Temp); - MemoryUtility.MemCpy(data.GetUnsafePtr(), &component, (nuint)sizeof(T)); - - _commands.Add(new Command - { - type = CommandType.AddComponent, - data = data, - entity = entity, - componentTypeID = ComponentTypeID.value - }); + WriteHeader(ECBOpCode.AddComponent); + Write(entity); + Write(ComponentTypeID.value); + Write(component); } public void RemoveComponent(Entity entity) where T : unmanaged, IComponent { - _commands.Add(new Command - { - type = CommandType.RemoveComponent, - data = default, - entity = entity, - componentTypeID = ComponentTypeID.value - }); + WriteHeader(ECBOpCode.RemoveComponent); + Write(entity); + Write(ComponentTypeID.value); } public void SetComponent(Entity entity, T component) where T : unmanaged, IComponent { - var data = new UnsafeArray(sizeof(T), Allocator.Temp); - MemoryUtility.MemCpy(data.GetUnsafePtr(), &component, (nuint)sizeof(T)); - - _commands.Add(new Command - { - type = CommandType.SetComponent, - data = data, - entity = entity, - componentTypeID = ComponentTypeID.value - }); + WriteHeader(ECBOpCode.SetComponent); + Write(entity); + Write(ComponentTypeID.value); + Write(component); } internal void Playback() { - foreach (ref var command in _commands) + var cursor = 0; + var length = _buffer.Count; + var ptr = (byte*)_buffer.GetUnsafePtr(); + + while (cursor < length) { - switch (command.type) + var op = *(ECBOpCode*)ptr[cursor]; + cursor += sizeof(ECBOpCode); + + switch (op) { - case CommandType.CreateEntity: - if (command.data.Count > 0) - { - _entityManager.CreateEntity(MemoryMarshal.Cast>(command.data.AsSpan())); - } - else - { - _entityManager.CreateEntity(); - } + case ECBOpCode.CreateEntity: + _entityManager.CreateEntity(); break; - case CommandType.DestroyEntity: - _entityManager.DestroyEntity(command.entity); + + case ECBOpCode.CreateEntityWithComponents: + var compCount = Read(ref cursor); + var compTypeIDs = ReadSpan>(ref cursor, compCount); + _entityManager.CreateEntity(compTypeIDs); break; - case CommandType.AddComponent: - _entityManager.AddComponent(command.entity, command.componentTypeID, command.data.GetUnsafePtr()); + + case ECBOpCode.DestroyEntity: + var entityToDestroy = Read(ref cursor); + _entityManager.DestroyEntity(entityToDestroy); break; - case CommandType.RemoveComponent: - _entityManager.RemoveComponent(command.entity, command.componentTypeID); + + case ECBOpCode.AddComponent: + var entityToAdd = Read(ref cursor); + var addCompTypeID = Read>(ref cursor); + var pAddCompData = ReadBuffer(ref cursor, ComponentRegister.GetComponentInfo(addCompTypeID).size); + _entityManager.AddComponent(entityToAdd, addCompTypeID, pAddCompData); break; - case CommandType.SetComponent: - _entityManager.SetComponent(command.entity, command.componentTypeID, command.data.GetUnsafePtr()); + + case ECBOpCode.RemoveComponent: + var entityToRemove = Read(ref cursor); + var removeCompTypeID = Read>(ref cursor); + _entityManager.RemoveComponent(entityToRemove, removeCompTypeID); + break; + + case ECBOpCode.SetComponent: + var entityToSet = Read(ref cursor); + var setCompTypeID = Read>(ref cursor); + var pSetCompData = ReadBuffer(ref cursor, ComponentRegister.GetComponentInfo(setCompTypeID).size); + _entityManager.SetComponent(entityToSet, setCompTypeID, pSetCompData); break; } } @@ -156,14 +199,10 @@ public unsafe class EntityCommandBuffer : IDisposable Reset(); } - public void Reset() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void Reset() { - foreach (ref var command in _commands) - { - command.data.Dispose(); - } - - _commands.Clear(); + _buffer.Clear(); } public void Dispose() @@ -173,12 +212,7 @@ public unsafe class EntityCommandBuffer : IDisposable return; } - foreach (ref var command in _commands) - { - command.data.Dispose(); - } - - _commands.Dispose(); + _buffer.Dispose(); _disposed = true; GC.SuppressFinalize(this); diff --git a/Ghost.Entities/System.cs b/Ghost.Entities/System.cs index ffc27ae..a86c69f 100644 --- a/Ghost.Entities/System.cs +++ b/Ghost.Entities/System.cs @@ -19,9 +19,7 @@ public readonly ref struct SystemAPI public interface ISystem { void Initialize(ref readonly SystemAPI systemAPI); - void PreUpdate(ref readonly SystemAPI systemAPI); void Update(ref readonly SystemAPI systemAPI); - void PostUpdate(ref readonly SystemAPI systemAPI); void Cleanup(ref readonly SystemAPI systemAPI); } @@ -207,16 +205,6 @@ public abstract class SystemGroup : ISystem } } - public void PreUpdate(ref readonly SystemAPI systemAPI) - { - ThrowIfNotSorted(); - - foreach (var system in _sortedSystems!) - { - system.PreUpdate(in systemAPI); - } - } - public void Update(ref readonly SystemAPI systemAPI) { ThrowIfNotSorted(); @@ -227,16 +215,6 @@ public abstract class SystemGroup : ISystem } } - public void PostUpdate(ref readonly SystemAPI systemAPI) - { - ThrowIfNotSorted(); - - foreach (var system in _sortedSystems!) - { - system.PostUpdate(in systemAPI); - } - } - public void Cleanup(ref readonly SystemAPI systemAPI) { ThrowIfNotSorted(); @@ -282,4 +260,28 @@ public class SystemManager throw new InvalidOperationException($"System of type {typeof(T).FullName} not found in SystemManager."); } + + internal void InitializeAll(ref readonly SystemAPI systemAPI) + { + foreach (var system in _systems) + { + system.Initialize(in systemAPI); + } + } + + internal void UpdateAll(ref readonly SystemAPI systemAPI) + { + foreach (var system in _systems) + { + system.Update(in systemAPI); + } + } + + internal void CleanupAll(ref readonly SystemAPI systemAPI) + { + foreach (var system in _systems) + { + system.Cleanup(in systemAPI); + } + } } diff --git a/Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.gen.cs b/Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.gen.cs new file mode 100644 index 0000000..78db574 --- /dev/null +++ b/Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.gen.cs @@ -0,0 +1,1610 @@ +using Ghost.Core; +using Misaki.HighPerformance.LowLevel; +using Misaki.HighPerformance.LowLevel.Collections; +using System.Runtime.CompilerServices; + +namespace Ghost.Entities; + +public unsafe partial struct EntityQuery +{ + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + internal QueryItem(Entity entity, ref T0 component0) + { + this.entity = entity; + + this.component0 = ref component0; + } + + public void Deconstruct(out Entity entity, out Ref component0) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[1]; + private fixed int _offsets[1]; + private fixed long _compBasePtrs[1]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 1; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[2]; + private fixed int _offsets[2]; + private fixed long _compBasePtrs[2]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 2; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + public ref T2 component2; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1, ref T2 component2) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + this.component2 = ref component2; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1, out Ref component2) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + component2 = new Ref(ref this.component2); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[3]; + private fixed int _offsets[3]; + private fixed long _compBasePtrs[3]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _compTypeIDs[2] = ComponentTypeID.value; + _offsets[2] = 0; + _compBasePtrs[2] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)), + ref *(T2*)(_compBasePtrs[2] + _currentEntityIndex * sizeof(T2)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 3; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + public ref T2 component2; + public ref T3 component3; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + this.component2 = ref component2; + this.component3 = ref component3; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1, out Ref component2, out Ref component3) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + component2 = new Ref(ref this.component2); + component3 = new Ref(ref this.component3); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[4]; + private fixed int _offsets[4]; + private fixed long _compBasePtrs[4]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _compTypeIDs[2] = ComponentTypeID.value; + _offsets[2] = 0; + _compBasePtrs[2] = 0; + + _compTypeIDs[3] = ComponentTypeID.value; + _offsets[3] = 0; + _compBasePtrs[3] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)), + ref *(T2*)(_compBasePtrs[2] + _currentEntityIndex * sizeof(T2)), + ref *(T3*)(_compBasePtrs[3] + _currentEntityIndex * sizeof(T3)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 4; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + public ref T2 component2; + public ref T3 component3; + public ref T4 component4; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + this.component2 = ref component2; + this.component3 = ref component3; + this.component4 = ref component4; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1, out Ref component2, out Ref component3, out Ref component4) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + component2 = new Ref(ref this.component2); + component3 = new Ref(ref this.component3); + component4 = new Ref(ref this.component4); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[5]; + private fixed int _offsets[5]; + private fixed long _compBasePtrs[5]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _compTypeIDs[2] = ComponentTypeID.value; + _offsets[2] = 0; + _compBasePtrs[2] = 0; + + _compTypeIDs[3] = ComponentTypeID.value; + _offsets[3] = 0; + _compBasePtrs[3] = 0; + + _compTypeIDs[4] = ComponentTypeID.value; + _offsets[4] = 0; + _compBasePtrs[4] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)), + ref *(T2*)(_compBasePtrs[2] + _currentEntityIndex * sizeof(T2)), + ref *(T3*)(_compBasePtrs[3] + _currentEntityIndex * sizeof(T3)), + ref *(T4*)(_compBasePtrs[4] + _currentEntityIndex * sizeof(T4)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 5; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + where T5 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + public ref T2 component2; + public ref T3 component3; + public ref T4 component4; + public ref T5 component5; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4, ref T5 component5) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + this.component2 = ref component2; + this.component3 = ref component3; + this.component4 = ref component4; + this.component5 = ref component5; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1, out Ref component2, out Ref component3, out Ref component4, out Ref component5) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + component2 = new Ref(ref this.component2); + component3 = new Ref(ref this.component3); + component4 = new Ref(ref this.component4); + component5 = new Ref(ref this.component5); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[6]; + private fixed int _offsets[6]; + private fixed long _compBasePtrs[6]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _compTypeIDs[2] = ComponentTypeID.value; + _offsets[2] = 0; + _compBasePtrs[2] = 0; + + _compTypeIDs[3] = ComponentTypeID.value; + _offsets[3] = 0; + _compBasePtrs[3] = 0; + + _compTypeIDs[4] = ComponentTypeID.value; + _offsets[4] = 0; + _compBasePtrs[4] = 0; + + _compTypeIDs[5] = ComponentTypeID.value; + _offsets[5] = 0; + _compBasePtrs[5] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)), + ref *(T2*)(_compBasePtrs[2] + _currentEntityIndex * sizeof(T2)), + ref *(T3*)(_compBasePtrs[3] + _currentEntityIndex * sizeof(T3)), + ref *(T4*)(_compBasePtrs[4] + _currentEntityIndex * sizeof(T4)), + ref *(T5*)(_compBasePtrs[5] + _currentEntityIndex * sizeof(T5)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 6; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + where T5 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + where T5 : unmanaged, IComponent + where T6 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + public ref T2 component2; + public ref T3 component3; + public ref T4 component4; + public ref T5 component5; + public ref T6 component6; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4, ref T5 component5, ref T6 component6) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + this.component2 = ref component2; + this.component3 = ref component3; + this.component4 = ref component4; + this.component5 = ref component5; + this.component6 = ref component6; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1, out Ref component2, out Ref component3, out Ref component4, out Ref component5, out Ref component6) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + component2 = new Ref(ref this.component2); + component3 = new Ref(ref this.component3); + component4 = new Ref(ref this.component4); + component5 = new Ref(ref this.component5); + component6 = new Ref(ref this.component6); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[7]; + private fixed int _offsets[7]; + private fixed long _compBasePtrs[7]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _compTypeIDs[2] = ComponentTypeID.value; + _offsets[2] = 0; + _compBasePtrs[2] = 0; + + _compTypeIDs[3] = ComponentTypeID.value; + _offsets[3] = 0; + _compBasePtrs[3] = 0; + + _compTypeIDs[4] = ComponentTypeID.value; + _offsets[4] = 0; + _compBasePtrs[4] = 0; + + _compTypeIDs[5] = ComponentTypeID.value; + _offsets[5] = 0; + _compBasePtrs[5] = 0; + + _compTypeIDs[6] = ComponentTypeID.value; + _offsets[6] = 0; + _compBasePtrs[6] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)), + ref *(T2*)(_compBasePtrs[2] + _currentEntityIndex * sizeof(T2)), + ref *(T3*)(_compBasePtrs[3] + _currentEntityIndex * sizeof(T3)), + ref *(T4*)(_compBasePtrs[4] + _currentEntityIndex * sizeof(T4)), + ref *(T5*)(_compBasePtrs[5] + _currentEntityIndex * sizeof(T5)), + ref *(T6*)(_compBasePtrs[6] + _currentEntityIndex * sizeof(T6)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 7; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + where T5 : unmanaged, IComponent + where T6 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + + public readonly ref struct EntityComponentIterator + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + where T5 : unmanaged, IComponent + where T6 : unmanaged, IComponent + where T7 : unmanaged, IComponent + { + public ref struct QueryItem + { + public Entity entity; + + public ref T0 component0; + public ref T1 component1; + public ref T2 component2; + public ref T3 component3; + public ref T4 component4; + public ref T5 component5; + public ref T6 component6; + public ref T7 component7; + internal QueryItem(Entity entity, ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4, ref T5 component5, ref T6 component6, ref T7 component7) + { + this.entity = entity; + + this.component0 = ref component0; + this.component1 = ref component1; + this.component2 = ref component2; + this.component3 = ref component3; + this.component4 = ref component4; + this.component5 = ref component5; + this.component6 = ref component6; + this.component7 = ref component7; + } + + public void Deconstruct(out Entity entity, out Ref component0, out Ref component1, out Ref component2, out Ref component3, out Ref component4, out Ref component5, out Ref component6, out Ref component7) + { + entity = this.entity; + + component0 = new Ref(ref this.component0); + component1 = new Ref(ref this.component1); + component2 = new Ref(ref this.component2); + component3 = new Ref(ref this.component3); + component4 = new Ref(ref this.component4); + component5 = new Ref(ref this.component5); + component6 = new Ref(ref this.component6); + component7 = new Ref(ref this.component7); + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[8]; + private fixed int _offsets[8]; + private fixed long _compBasePtrs[8]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _compTypeIDs[0] = ComponentTypeID.value; + _offsets[0] = 0; + _compBasePtrs[0] = 0; + + _compTypeIDs[1] = ComponentTypeID.value; + _offsets[1] = 0; + _compBasePtrs[1] = 0; + + _compTypeIDs[2] = ComponentTypeID.value; + _offsets[2] = 0; + _compBasePtrs[2] = 0; + + _compTypeIDs[3] = ComponentTypeID.value; + _offsets[3] = 0; + _compBasePtrs[3] = 0; + + _compTypeIDs[4] = ComponentTypeID.value; + _offsets[4] = 0; + _compBasePtrs[4] = 0; + + _compTypeIDs[5] = ComponentTypeID.value; + _offsets[5] = 0; + _compBasePtrs[5] = 0; + + _compTypeIDs[6] = ComponentTypeID.value; + _offsets[6] = 0; + _compBasePtrs[6] = 0; + + _compTypeIDs[7] = ComponentTypeID.value; + _offsets[7] = 0; + _compBasePtrs[7] = 0; + + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), + ref *(T0*)(_compBasePtrs[0] + _currentEntityIndex * sizeof(T0)), + ref *(T1*)(_compBasePtrs[1] + _currentEntityIndex * sizeof(T1)), + ref *(T2*)(_compBasePtrs[2] + _currentEntityIndex * sizeof(T2)), + ref *(T3*)(_compBasePtrs[3] + _currentEntityIndex * sizeof(T3)), + ref *(T4*)(_compBasePtrs[4] + _currentEntityIndex * sizeof(T4)), + ref *(T5*)(_compBasePtrs[5] + _currentEntityIndex * sizeof(T5)), + ref *(T6*)(_compBasePtrs[6] + _currentEntityIndex * sizeof(T6)), + ref *(T7*)(_compBasePtrs[7] + _currentEntityIndex * sizeof(T7)) + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < 8; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator GetEntityComponentIterator() + where T0 : unmanaged, IComponent + where T1 : unmanaged, IComponent + where T2 : unmanaged, IComponent + where T3 : unmanaged, IComponent + where T4 : unmanaged, IComponent + where T5 : unmanaged, IComponent + where T6 : unmanaged, IComponent + where T7 : unmanaged, IComponent + { + return new EntityComponentIterator(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + +} diff --git a/Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.tt b/Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.tt new file mode 100644 index 0000000..f45e28e --- /dev/null +++ b/Ghost.Entities/Templates/EntityQuery.EntityComponentIterator.tt @@ -0,0 +1,199 @@ +<#@ template language="C#" #> +<#@ output extension="gen.cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ include file="Helpers.ttinclude" #> +using Ghost.Core; +using Misaki.HighPerformance.LowLevel; +using Misaki.HighPerformance.LowLevel.Collections; +using System.Runtime.CompilerServices; + +namespace Ghost.Entities; + +public unsafe partial struct EntityQuery +{ +<# for (var i = 1; i <= Amount; i++) +{ + var generics = AppendParameters(i, "T{0}"); + var compGenerics = AppendParameters(i, "ref T{0} component{0}"); + var deconstrictOutPrams = AppendParameters(i, "out Ref component{0}"); + var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2); +#> + public readonly ref struct EntityComponentIterator<<#= generics #>> +<#= restrictions #> + { + public ref struct QueryItem + { + public Entity entity; + +<# for (var j = 0; j < i; j++) { #> + public ref T<#= j #> component<#= j #>; +<# } #> + internal QueryItem(Entity entity, <#= compGenerics #>) + { + this.entity = entity; + +<# for (var j = 0; j < i; j++) { #> + this.component<#= j #> = ref component<#= j #>; +<# } #> + } + + public void Deconstruct(out Entity entity, <#= deconstrictOutPrams #>) + { + entity = this.entity; + +<# for (var j = 0; j < i; j++) { #> + component<#= j #> = new Ref>(ref this.component<#= j #>); +<# } #> + } + } + + public ref struct Enumerator + { + private fixed int _compTypeIDs[<#= i #>]; + private fixed int _offsets[<#= i #>]; + private fixed long _compBasePtrs[<#= i #>]; + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + private ref Archetype _currentArchetype; + private ref Chunk _currentChunk; + private byte* _chunkBasePtr; + + private int _currentChunkEntityCount; + private int _currentArchetypeIndex; + private int _currentChunkIndex; + private int _currentEntityIndex; + + internal Enumerator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { +<# for (var j = 0; j < i; j++) { #> + _compTypeIDs[<#= j #>] = ComponentTypeID>.value; + _offsets[<#= j #>] = 0; + _compBasePtrs[<#= j #>] = 0; + +<# } #> + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + + Reset(); + } + + public QueryItem Current => new( + *(Entity*)(_chunkBasePtr + _currentArchetype.EntityIDsOffset + _currentEntityIndex * sizeof(Entity)), +<# for (var j = 0; j < i; j++) { #> + ref *(T<#= j #>*)(_compBasePtrs[<#= j #>] + _currentEntityIndex * sizeof(T<#= j #>))<#= j < i - 1 ? "," : "" #> +<# } #> + ); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SetChunk(int chunkIndex) + { + _currentChunk = ref _currentArchetype.GetChunkReference(chunkIndex); + _chunkBasePtr = _currentChunk.GetUnsafePtr(); + _currentChunkEntityCount = _currentChunk.Count; + + for (var index = 0; index < <#= i #>; index++) + { + var layout = _currentArchetype.GetLayout(_compTypeIDs[index]) + .GetValueOrThrow(ResultStatus.Success); + _offsets[index] = layout.offset; + _compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]); + } + } + + public bool MoveNext() + { + while (true) + { + _currentEntityIndex++; + if (_currentEntityIndex < _currentChunk.Count) + { + var pChunkData = _currentChunk.GetUnsafePtr(); + if (IsEntityValid(pChunkData, _currentEntityIndex, in _currentArchetype, in _mask)) + { + return true; + } + + continue; + } + + _currentChunkIndex++; + if (!Unsafe.IsNullRef(ref _currentArchetype) && _currentChunkIndex < _currentArchetype.ChunkCount) + { + SetChunk(_currentChunkIndex); + _currentEntityIndex = -1; // Reset for new chunk + + continue; + } + + _currentArchetypeIndex++; + if (_currentArchetypeIndex < _matchingArchetypes.Count) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[_currentArchetypeIndex]); + + _currentChunkIndex = 0; + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + _currentEntityIndex = -1; + continue; + } + + // If archetype has no chunks, loop will try next archetype + } + else + { + return false; // End of all data + } + } + } + + public void Reset() + { + _currentArchetype = ref Unsafe.NullRef(); + _currentChunk = ref Unsafe.NullRef(); + _currentArchetypeIndex = 0; + _currentChunkIndex = 0; + _currentEntityIndex = -1; + + if (_matchingArchetypes.Count > 0) + { + _currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]); + if (_currentArchetype.ChunkCount > 0) + { + SetChunk(0); + } + } + } + } + + private readonly ReadOnlyUnsafeCollection> _matchingArchetypes; + private readonly EntityQueryMask _mask; + private readonly World _world; + + internal EntityComponentIterator(ReadOnlyUnsafeCollection> matchingArchetypes, EntityQueryMask mask, World world) + { + _matchingArchetypes = matchingArchetypes; + _mask = mask; + _world = world; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_matchingArchetypes, _mask, _world); + } + } + + public readonly EntityComponentIterator<<#= generics#>> GetEntityComponentIterator<<#= generics#>>() +<#= restrictions #> + { + return new EntityComponentIterator<<#= generics#>>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success)); + } + +<# } #> +} diff --git a/Ghost.Entities/Templates/EntityQuery.JobEntityParallel.gen.cs b/Ghost.Entities/Templates/EntityQuery.JobEntity.gen.cs similarity index 97% rename from Ghost.Entities/Templates/EntityQuery.JobEntityParallel.gen.cs rename to Ghost.Entities/Templates/EntityQuery.JobEntity.gen.cs index a0af3e5..6566a27 100644 --- a/Ghost.Entities/Templates/EntityQuery.JobEntityParallel.gen.cs +++ b/Ghost.Entities/Templates/EntityQuery.JobEntity.gen.cs @@ -5,14 +5,14 @@ using Misaki.HighPerformance.LowLevel.Collections; namespace Ghost.Entities; -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent { void Execute(Entity entity, ref T0 component0); } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent { public TJob userJob; @@ -48,7 +48,7 @@ internal unsafe struct JobEntityBatch : IJobParallelFor } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent { @@ -56,7 +56,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent { @@ -105,7 +105,7 @@ internal unsafe struct JobEntityBatch : IJobParallelFor } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -114,7 +114,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -176,7 +176,7 @@ internal unsafe struct JobEntityBatch : IJobParallelFor } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -186,7 +186,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -261,7 +261,7 @@ internal unsafe struct JobEntityBatch : IJobParallelFor } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -272,7 +272,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -360,7 +360,7 @@ internal unsafe struct JobEntityBatch : IJobParallelFo } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -372,7 +372,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -473,7 +473,7 @@ internal unsafe struct JobEntityBatch : IJobParall } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -486,7 +486,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -600,7 +600,7 @@ internal unsafe struct JobEntityBatch : IJobPa } } -public interface IJobEntityParallel +public interface IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -614,7 +614,7 @@ public interface IJobEntityParallel } internal unsafe struct JobEntityBatch : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -765,7 +765,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent { var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success); @@ -867,7 +867,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent { @@ -990,7 +990,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -1134,7 +1134,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -1299,7 +1299,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -1485,7 +1485,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -1692,7 +1692,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent @@ -1920,7 +1920,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel + where TJob : unmanaged, IJobEntity where T0 : unmanaged, IComponent where T1 : unmanaged, IComponent where T2 : unmanaged, IComponent diff --git a/Ghost.Entities/Templates/EntityQuery.JobEntityParallel.tt b/Ghost.Entities/Templates/EntityQuery.JobEntity.tt similarity index 96% rename from Ghost.Entities/Templates/EntityQuery.JobEntityParallel.tt rename to Ghost.Entities/Templates/EntityQuery.JobEntity.tt index f5ff328..f4763ac 100644 --- a/Ghost.Entities/Templates/EntityQuery.JobEntityParallel.tt +++ b/Ghost.Entities/Templates/EntityQuery.JobEntity.tt @@ -16,14 +16,14 @@ namespace Ghost.Entities; var generics = AppendGenerics(i); var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 1); #> -public interface IJobEntityParallel<<#= generics #>> +public interface IJobEntity<<#= generics #>> <#= restrictions #> { void Execute(Entity entity, <#= AppendParameters(i, "ref T{0} component{0}") #>); } internal unsafe struct JobEntityBatch> : IJobParallelFor - where TJob : unmanaged, IJobEntityParallel<<#= generics #>> + where TJob : unmanaged, IJobEntity<<#= generics #>> <#= restrictions #> { public TJob userJob; @@ -101,7 +101,7 @@ public unsafe partial struct EntityQuery } public JobHandle ScheduleEntityParallel>(TJob jobData, Allocator allocator, int batchSize, JobHandle dependency) - where TJob : unmanaged, IJobEntityParallel<<#= generics #>> + where TJob : unmanaged, IJobEntity<<#= generics #>> <#= restrictions #> { var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success); diff --git a/Ghost.Entities/World.cs b/Ghost.Entities/World.cs index 303ef76..0b88779 100644 --- a/Ghost.Entities/World.cs +++ b/Ghost.Entities/World.cs @@ -72,6 +72,7 @@ public partial class World : IIdentifierType, IDisposable, IEquatable private readonly EntityManager _entityManager; private readonly EntityCommandBuffer _entityCommandBuffer; + private readonly EntityCommandBuffer[] _threadLocalECBs; private UnsafeList _archetypes; private UnsafeList _entityQueries; @@ -83,9 +84,24 @@ public partial class World : IIdentifierType, IDisposable, IEquatable internal int ArchetypeCount => _archetypes.Count; + /// + /// Gets the unique identifier of this world. + /// public Identifier ID => _id; + + /// + /// Gets the job scheduler associated with this world. + /// public JobScheduler JobScheduler => _jobScheduler; + + /// + /// Gets the publicntity manager for this world. + /// public EntityManager EntityManager => _entityManager; + + /// + /// Gets the main entity command buffer for this world. + /// public EntityCommandBuffer EntityCommandBuffer => _entityCommandBuffer; private World(Identifier id, int entityCapacity, JobScheduler jobScheduler) @@ -101,6 +117,12 @@ public partial class World : IIdentifierType, IDisposable, IEquatable _entityManager = new EntityManager(this, entityCapacity); _entityCommandBuffer = new EntityCommandBuffer(_entityManager); + _threadLocalECBs = new EntityCommandBuffer[jobScheduler.WorkerCount]; + + for (var i = 0; i < jobScheduler.WorkerCount; i++) + { + _threadLocalECBs[i] = new EntityCommandBuffer(_entityManager); + } // Create the empty archetype CreateArchetype(ReadOnlySpan>.Empty, 0); @@ -171,12 +193,34 @@ public partial class World : IIdentifierType, IDisposable, IEquatable return Identifier.Invalid; } + internal void PlaybackEntityCommandBuffers() + { + _entityCommandBuffer.Playback(); + + for (var i = 0; i < _threadLocalECBs.Length; i++) + { + _threadLocalECBs[i].Playback(); + } + } + + /// + /// Gets a reference to the entity query with the specified identifier. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref EntityQuery GetEntityQueryReference(Identifier id) { return ref _entityQueries[id.value]; } + /// + /// Gets the thread-local entity command buffer for the specified thread index. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public EntityCommandBuffer GetThreadLocalEntityCommandBuffer(int threadIndex) + { + return _threadLocalECBs[threadIndex]; + } + public bool Equals(World? other) { return other is not null && _id == other._id; @@ -221,6 +265,10 @@ public partial class World : IIdentifierType, IDisposable, IEquatable _entityManager.Dispose(); _entityCommandBuffer.Dispose(); + for (var i = 0; i < _threadLocalECBs.Length; i++) + { + _threadLocalECBs[i].Dispose(); + } _archetypes.Dispose(); _entityQueries.Dispose(); diff --git a/Ghost.SparseEntities/AssemblyInfo.cs b/Ghost.SparseEntities/AssemblyInfo.cs deleted file mode 100644 index 6c605e9..0000000 --- a/Ghost.SparseEntities/AssemblyInfo.cs +++ /dev/null @@ -1,12 +0,0 @@ -global using EntityID = System.Int32; -global using GenerationID = System.UInt16; -global using WorldID = System.UInt16; - -using Ghost.Core.Attributes; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Ghost.Engine")] -[assembly: InternalsVisibleTo("Ghost.Editor.Core")] -[assembly: InternalsVisibleTo("Ghost.Entities.Test")] - -[assembly: EngineAssembly] \ No newline at end of file diff --git a/Ghost.SparseEntities/Components/ComponentStorage.cs b/Ghost.SparseEntities/Components/ComponentStorage.cs deleted file mode 100644 index c2319b1..0000000 --- a/Ghost.SparseEntities/Components/ComponentStorage.cs +++ /dev/null @@ -1,715 +0,0 @@ -using Ghost.Core; -using Misaki.HighPerformance.LowLevel.Collections; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Ghost.SparseEntities.Components; - -internal static class SingletonContainer - where T : unmanaged, IComponentData -{ - public static readonly Dictionary container = new(); -} - -internal interface IComponentPool : IDisposable -{ - public EntityID Count - { - get; - } - - public void Add(Entity entity, IComponentData component); - public bool Remove(Entity entity); - public bool Has(Entity entity); - public IComponentData Get(Entity entity); - public IntPtr GetUnsafe(Entity entity); - public void Set(Entity entity, in IComponentData component); - - public IEnumerable<(Entity entity, IComponentData component)> Enumerate(); -} - -internal interface IComponentPool : IComponentPool - where T : IComponentData -{ - public void Add(Entity entity, T Component); - public void Set(Entity entity, in T component); -} - -internal class ComponentPool : IComponentPool - where T : unmanaged, IComponentData -{ - private struct ComponentMetadata - { - public T data; - public Entity owner; - } - - private EntityID _nextId; - private EntityID _capacity; - - private ComponentMetadata[] _components; - private EntityID[] _lookup; - - public EntityID Count => _nextId; - - public ComponentPool(int initialSize) - { - _nextId = 0; - _capacity = initialSize; - - _components = new ComponentMetadata[initialSize]; - _lookup = new EntityID[initialSize]; - - _lookup.AsSpan().Fill(Entity.INVALID_ID); - } - - public ComponentPool() - : this(16) - { - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static EntityID GetLookupIndex(Entity entity) - { - return entity.ID; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private EntityID GetComponentIndex(Entity entity) - { - return _lookup[GetLookupIndex(entity)]; - } - - public void Add(Entity entity, IComponentData component) - { - if (component is not T typedComponent) - { - throw new ArgumentException($"Component type mismatch. Expected {typeof(T)}, but got {component.GetType()}."); - } - - Add(entity, typedComponent); - } - - public void Add(Entity entity, T component) - { - if (!entity.IsValid) - { - return; - } - - var lookupIndex = GetLookupIndex(entity); - var componentIndex = GetComponentIndex(entity); - - if (componentIndex != Entity.INVALID_ID) - { - // Overwrite the old data if generation is larger - if (entity.Generation > _components[componentIndex].owner.Generation) - { - var index = _lookup[lookupIndex]; - _components[index].data = component; - _components[index].owner = entity; - } - - return; - } - - if (_nextId >= _capacity) - { - var newCapacity = _capacity * 2; - Array.Resize(ref _components, newCapacity); - Array.Resize(ref _lookup, newCapacity); - _lookup.AsSpan(_capacity, newCapacity - _capacity).Fill(Entity.INVALID_ID); - - _capacity = newCapacity; - } - - _lookup[lookupIndex] = _nextId; - _components[_nextId] = new ComponentMetadata - { - data = component, - owner = entity - }; - - _nextId++; - } - - public bool Remove(Entity entity) - { - // We do not remove anything here, the generation of the entity will be used to determine if the component is valid. - return true; - } - - public IComponentData Get(Entity entity) - { - return GetRef(entity); - } - - public unsafe IntPtr GetUnsafe(Entity entity) - { - return (IntPtr)Unsafe.AsPointer(ref GetRef(entity)); - } - - public ref T GetRef(Entity entity) - { - if (!entity.IsValid) - { - return ref Unsafe.NullRef(); - } - - var index = GetComponentIndex(entity); - return ref _components[index].data; - } - - public bool Has(Entity entity) - { - if (entity.ID >= _lookup.Length) - { - return false; - } - - var index = GetComponentIndex(entity); - return index != Entity.INVALID_ID && _components[index].owner.Generation == entity.Generation; - } - - public void Set(Entity entity, in IComponentData component) - { - if (component is not T typedComponent) - { - throw new ArgumentException($"Component type mismatch. Expected {typeof(T)}, but got {component.GetType()}."); - } - Set(entity, typedComponent); - } - - public void Set(Entity entity, in T component) - { - if (!entity.IsValid || entity.ID >= _lookup.Length || GetComponentIndex(entity) == Entity.INVALID_ID) - { - return; - } - - var index = GetComponentIndex(entity); - _components[index].data = component; - _components[index].owner = entity; - } - - public IEnumerable<(Entity entity, IComponentData component)> Enumerate() - { - for (var i = 0; i < _nextId; i++) - { - if (_components[i].owner.IsValid) - { - yield return (_components[i].owner, _components[i].data); - } - } - } - - public void Dispose() - { - _components = Array.Empty(); - _lookup = Array.Empty(); - _nextId = 0; - _capacity = 0; - } -} - -internal class ScriptComponentPool : IComponentPool -{ - private Dictionary>? _scriptComponents; - private List? _executionList; - - private readonly World _world; - - internal IReadOnlyDictionary>? ScriptComponents => _scriptComponents; - internal IReadOnlyList? ExecutionList => _executionList; - - public bool IsInitialized => _scriptComponents != null; - public int Count => _scriptComponents?.Keys.Count ?? 0; - - public ScriptComponentPool(World world) - { - _world = world; - } - - internal void Initialize(int capacity = 16) - { - _scriptComponents ??= new(capacity); - } - - internal void RebuildExecutionList() - { - if (_scriptComponents == null) - { - return; - } - - _executionList ??= new List(_scriptComponents.Count); - _executionList.Clear(); - - foreach (var kvp in _scriptComponents) - { - _executionList.AddRange(kvp.Value); - } - - _executionList.Sort((a, b) => a.ExecutionOrder.CompareTo(b.ExecutionOrder)); - } - - public void Add(Entity entity, IComponentData component) - { - if (component is not ScriptComponent scriptComponent) - { - throw new ArgumentException($"Component type mismatch. Expected {typeof(ScriptComponent)}, but got {component.GetType()}."); - } - - Add(entity, scriptComponent); - } - - public void Add(Entity entity, ScriptComponent component) - { - if (!IsInitialized) - { - Initialize(); - } - - ref var scriptList = ref CollectionsMarshal.GetValueRefOrAddDefault(_scriptComponents!, entity, out var exists); - scriptList ??= new List(); - - scriptList.Add(component); - - component.Owner = entity; - component._world = _world; - component.Enable = true; - component.Initialize(); - } - - public bool Remove(Entity entity) - where T : ScriptComponent - { - if (!Has(entity) - || !_scriptComponents!.TryGetValue(entity, out var scriptList) - || scriptList == null) - { - return false; - } - - var scriptToRemove = scriptList.FirstOrDefault(script => script is T); - if (scriptToRemove == null) - { - return false; - } - - scriptToRemove.OnDestroy(); - scriptList.Remove(scriptToRemove); - if (scriptList.Count == 0) - { - _scriptComponents.Remove(entity); - } - - return true; - } - - public bool RemoveAt(Entity entity, int index) - { - if (!Has(entity) - || !_scriptComponents!.TryGetValue(entity, out var scriptList) - || scriptList == null) - { - return false; - } - - if (index < 0 || index > scriptList.Count) - { - return false; - } - - scriptList.RemoveAt(index); - if (scriptList.Count == 0) - { - _scriptComponents.Remove(entity); - } - - return true; - } - - public bool Remove(Entity entity) - { - if (!Has(entity) - || !_scriptComponents!.TryGetValue(entity, out var scriptList) - || scriptList == null) - { - return false; - } - - foreach (var script in scriptList) - { - script.OnDestroy(); - } - - _scriptComponents.Remove(entity); - return true; - } - - public bool Has(Entity entity) - { - return _scriptComponents?.ContainsKey(entity) ?? false; - } - - [Obsolete("Use GetAll instead of Get for ScriptComponentPool.")] - public IComponentData Get(Entity entity) - { - if (!Has(entity) - || !_scriptComponents!.TryGetValue(entity, out var scriptList) - || scriptList == null - || scriptList.Count == 0) - { - return null!; - } - - return scriptList[0]; - } - - [Obsolete("Use GetAll instead of GetUnsafe for ScriptComponentPool.")] - public unsafe IntPtr GetUnsafe(Entity entity) - { - if (!Has(entity) - || !_scriptComponents!.TryGetValue(entity, out var scriptList) - || scriptList == null - || scriptList.Count == 0) - { - return IntPtr.Zero; - } - - return (IntPtr)Unsafe.AsPointer(ref CollectionsMarshal.AsSpan(scriptList)[0]); - } - - public void Set(Entity entity, in IComponentData component) - { - if (component is not ScriptComponent scriptComponent) - { - throw new ArgumentException($"Component type mismatch. Expected {typeof(ScriptComponent)}, but got {component.GetType()}."); - } - Set(entity, scriptComponent); - } - - public void Set(Entity entity, in ScriptComponent component) - { - if (!Has(entity) - || !_scriptComponents!.TryGetValue(entity, out var scriptList) - || scriptList == null) - { - return; - } - var index = scriptList.IndexOf(component); - if (index >= 0) - { - scriptList[index] = component; - component.Owner = entity; - } - } - - public IEnumerable<(Entity entity, IComponentData component)> Enumerate() - { - if (_scriptComponents == null) - { - yield break; - } - - foreach (var kvp in _scriptComponents) - { - foreach (var script in kvp.Value) - { - yield return (kvp.Key, script); - } - } - } - - public IReadOnlyList? GetAll(Entity entity) - { - if (_scriptComponents == null - || !_scriptComponents.TryGetValue(entity, out var scriptList)) - { - return null; - } - - return scriptList; - } - - public void Dispose() - { - if (_scriptComponents != null) - { - if (_executionList != null) - { - foreach (var script in _executionList) - { - script.OnDestroy(); - } - - _executionList.Clear(); - } - else - { - foreach (var scriptList in _scriptComponents.Values) - { - if (scriptList == null) - { - continue; - } - - foreach (var script in scriptList) - { - script.OnDestroy(); - } - } - - } - - _scriptComponents.Clear(); - } - } -} - -[SkipLocalsInit] -internal struct ComponentStorage : IDisposable -{ - private static int s_nextId = 0; - private static class TypeID - { - public static readonly int value = s_nextId++; - } - - private int _currentCapacity = 16; - - private IComponentPool?[] _componentPools = new IComponentPool[16]; - private UnsafeBitSet[] _componentEntityMasks = new UnsafeBitSet[16]; - - private readonly Dictionary _typeIDMap = new(16); - private readonly Dictionary _typeHandleMap = new(16); - - private readonly ScriptComponentPool _scriptComponentPool; - - private readonly World _world; - - internal ComponentStorage(World world) - { - _world = world; - _scriptComponentPool = new ScriptComponentPool(world); - } - - internal readonly IReadOnlyList ComponentPools => _componentPools; - internal readonly IReadOnlyList ComponentEntityMasks => _componentEntityMasks; - internal readonly ScriptComponentPool ScriptComponentPool => _scriptComponentPool; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private readonly int GetTypeID(TypeHandle typeHandle) - { - if (_typeIDMap.TryGetValue(typeHandle, out var id)) - { - return id; - } - - return typeof(TypeID<>).MakeGenericType(typeHandle!) - .GetField("value", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public) - ?.GetValue(null) as int? ?? -1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private readonly int GetTypeID() - { - return TypeID.value; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Resize(int newCapacity) - { - Array.Resize(ref _componentPools, newCapacity); - Array.Resize(ref _componentEntityMasks, newCapacity); - _currentCapacity = newCapacity; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal readonly TypeHandle GetComponentPoolType(int poolIndex) - { - if (poolIndex < 0 || poolIndex >= _currentCapacity) - { - throw new ArgumentOutOfRangeException(nameof(poolIndex), "Invalid pool index."); - } - - return _typeHandleMap[poolIndex]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool TryGetPool(TypeHandle typeHandle, [NotNullWhen(true)] out IComponentPool? pool) - { - var result = _typeIDMap.TryGetValue(typeHandle, out var id); - if (!result || id >= _currentCapacity) - { - pool = null; - return false; - } - - pool = _componentPools[id]; - return pool != null; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool TryGetPool(Type type, [NotNullWhen(true)] out IComponentPool? pool) - { - return TryGetPool(TypeHandle.Get(type), out pool); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool TryGetPool([NotNullWhen(true)] out ComponentPool? pool) - where T : unmanaged, IComponentData - { - var id = TypeID.value; - if (id >= _currentCapacity) - { - pool = null; - return false; - } - - pool = (ComponentPool?)_componentPools[id]; - return pool != null; - } - - public IComponentPool GetOrCreateComponentPool(Type type) - { - var typeHandle = TypeHandle.Get(type); - if (_typeIDMap.TryGetValue(typeHandle, out var id)) - { - if (id < _currentCapacity && _componentPools[id] is IComponentPool existingPool) - { - return existingPool; - } - } - else - { - id = GetTypeID(typeHandle); - } - - if (id >= _currentCapacity) - { - Resize(_currentCapacity * 2); - _typeIDMap[typeHandle] = id; - _typeHandleMap[id] = typeHandle; - } - else if (_componentPools[id] is IComponentPool existingPool) - { - return existingPool; - } - - var pool = Activator.CreateInstance(typeof(ComponentPool<>).MakeGenericType(type)) as IComponentPool - ?? throw new InvalidOperationException($"Failed to create component pool for type {type.FullName}"); - - _componentPools[id] = pool; - - return pool; - } - - public ComponentPool GetOrCreateComponentPool() - where T : unmanaged, IComponentData - { - var id = TypeID.value; - var typeHandle = TypeHandle.Get(); - - if (id >= _currentCapacity) - { - Resize(_currentCapacity * 2); - _typeIDMap[typeHandle] = id; - _typeHandleMap[id] = typeHandle; - } - else if (_componentPools[id] is ComponentPool existingPool) - { - return existingPool; - } - - var pool = new ComponentPool(); - _componentPools[id] = pool; - - return pool; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool TryGetMask(TypeHandle typeHandle, [NotNullWhen(true)] out UnsafeBitSet? bitSet) - { - if (!_typeIDMap.TryGetValue(typeHandle, out var id) - || id >= _currentCapacity) - { - bitSet = null; - return false; - } - - bitSet = _componentEntityMasks[id]; - return bitSet.HasValue; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool TryGetMask([NotNullWhen(true)] out UnsafeBitSet? bitSet) - where T : unmanaged, IComponentData - { - return TryGetMask(TypeHandle.Get(), out bitSet); - } - - public ref UnsafeBitSet GetOrCreateMask(TypeHandle typeHandle) - { - if (!_typeIDMap.TryGetValue(typeHandle, out var id)) - { - id = GetTypeID(typeHandle); - _typeIDMap[typeHandle] = id; - _typeHandleMap[id] = typeHandle; - } - - if (id >= _currentCapacity) - { - Resize(_currentCapacity * 2); - } - - ref var set = ref _componentEntityMasks[id]; - if (!set.IsCreated) - { - set = new UnsafeBitSet(); - } - - return ref set; - } - - public ref UnsafeBitSet GetOrCreateMask() - where T : unmanaged, IComponentData - { - return ref GetOrCreateMask(TypeHandle.Get()); - } - - public ref UnsafeBitSet GetOrCreateMask(Type type) - { - return ref GetOrCreateMask(TypeHandle.Get(type)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void RebuildExecutionList() - { - _scriptComponentPool.RebuildExecutionList(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Remove(Entity entity) - { - _scriptComponentPool.Remove(entity); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void Dispose() - { - foreach (var pool in _componentPools) - { - pool?.Dispose(); - } - - foreach (var bitSet in _componentEntityMasks) - { - bitSet.Dispose(); - } - - _scriptComponentPool.Dispose(); - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Components/IComponentData.cs b/Ghost.SparseEntities/Components/IComponentData.cs deleted file mode 100644 index 7afcf83..0000000 --- a/Ghost.SparseEntities/Components/IComponentData.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Ghost.SparseEntities.Components; - -public interface IComponentData -{ -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Components/ScriptComponent.cs b/Ghost.SparseEntities/Components/ScriptComponent.cs deleted file mode 100644 index 950fee1..0000000 --- a/Ghost.SparseEntities/Components/ScriptComponent.cs +++ /dev/null @@ -1,110 +0,0 @@ -namespace Ghost.SparseEntities.Components; - -public abstract class ScriptComponent : IComponentData -{ - private bool _enable; - - internal World _world = null!; - - /// - /// Gets or sets a Value indicating whether this script component is enabled. - /// - public bool Enable - { - get => _enable; - set - { - if (_enable == value) - { - return; - } - - _enable = value; - if (_enable) - { - OnEnable(); - } - else - { - OnDisable(); - } - } - } - - /// - /// Gets the entity that owns this script component. - /// - public Entity Owner - { - get; - internal set; - } - - /// - /// Gets the EntityManager instance associated with the current world. - /// - protected EntityManager EntityManager => _world.EntityManager; - - /// - /// Gets or sets the priority of the script component. - /// Change this during runtime does not affect the execution order. - /// - public virtual int ExecutionOrder => 0; - - /// - /// Called when the script component is enabled. - /// - public virtual void OnEnable() - { - } - - /// - /// Called when the script component is disabled. - /// - public virtual void OnDisable() - { - } - - /// - /// Called when the script component is initialized. - /// - public virtual void Initialize() - { - } - - /// - /// Called when the script component is started. - /// - public virtual void Start() - { - } - - /// - /// Called every frame. - /// - public virtual void Update() - { - } - - /// - /// Called every frame after all Update methods have been called. - /// - public virtual void LateUpdate() - { - } - - /// - /// Called at a fixed interval. - /// This method is called at a fixed time step, independent of the frame rate. - /// - public virtual void FixedUpdate() - { - } - - /// - /// Called when the script component is destroyed. - /// - public virtual void OnDestroy() - { - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Entity.cs b/Ghost.SparseEntities/Entity.cs deleted file mode 100644 index df07cd0..0000000 --- a/Ghost.SparseEntities/Entity.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Text.Json.Serialization; - -namespace Ghost.SparseEntities; - -[SkipLocalsInit] -public struct Entity : IEquatable, IComparable -{ - public const EntityID INVALID_ID = -1; - - [JsonInclude] - private EntityID _id; - private GenerationID _generation; - - public readonly EntityID ID - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _id; - } - - public readonly GenerationID Generation - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _generation; - } - - public readonly bool IsValid - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ID != INVALID_ID; - } - - public static Entity Invalid - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(INVALID_ID, GenerationID.MaxValue); - } - - internal Entity(EntityID id, GenerationID generation) - { - _id = id; - _generation = generation; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void IncrementGeneration() => _generation++; - - public readonly bool Equals(Entity other) - { - return _id == other._id && _generation == other._generation; - } - - public readonly int CompareTo(Entity other) - { - return _id.CompareTo(other._id); - } - - public override readonly bool Equals(object? obj) - { - return obj is Entity other && Equals(other); - } - - public override readonly int GetHashCode() - { - return _id.GetHashCode(); - } - - public static bool operator ==(Entity left, Entity right) - { - return left.Equals(right); - } - - public static bool operator !=(Entity left, Entity right) - { - return !(left == right); - } - - public override readonly string ToString() - { - return $"Entity {{ Index: {ID}, Generation: {Generation} }}"; - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/EntityManager.cs b/Ghost.SparseEntities/EntityManager.cs deleted file mode 100644 index 2a68e9a..0000000 --- a/Ghost.SparseEntities/EntityManager.cs +++ /dev/null @@ -1,360 +0,0 @@ -using Ghost.Core; -using Ghost.SparseEntities.Components; -using Ghost.SparseEntities.Query; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Ghost.SparseEntities; - -public readonly struct EntityManager : IDisposable -{ - private readonly List _entities; - private readonly Queue _freeEntitySlots; - - private readonly World _world; - - public readonly int EntityCount => _entities.Count; - public readonly ReadOnlySpan Entities => CollectionsMarshal.AsSpan(_entities); - - internal EntityManager(World world, int initialCapacity) - { - _entities = new(initialCapacity); - _freeEntitySlots = new(initialCapacity); - _world = world; - } - - /// - /// Adds a new to the world. - /// - /// The created . - public readonly Entity CreateEntity() - { - Entity entity; - if (_freeEntitySlots.TryDequeue(out var id)) - { - entity = _entities[id]; - } - else - { - id = _entities.Count; - entity = new Entity(id, 0); - _entities.Add(entity); - } - - return entity; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal readonly void AddEntityInternal(Entity entity) - { - _entities.Add(entity); - } - - /// - /// Removes the specified from the world. - /// - /// - public readonly void RemoveEntity(ref Entity entity) - { - if (entity.ID >= _entities.Count || _entities[entity.ID].Generation != entity.Generation) - { - return; - } - - _world.ComponentStorage.Remove(entity); - - var slot = _entities[entity.ID]; - slot.IncrementGeneration(); - _entities[entity.ID] = slot; - _freeEntitySlots.Enqueue(entity.ID); - - entity = Entity.Invalid; - } - - /// - /// Checks if the given is valid and belongs to this . - /// - /// The entity to check. - /// True if the entity is valid and belongs to this world; otherwise, false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool HasEntity(Entity entity) - { - if (!entity.IsValid - || entity.ID >= _entities.Count) - { - return false; - } - - return _entities[entity.ID].Generation == entity.Generation; - } - - /// - /// Adds a component of the specified type to the given entity. - /// - /// - /// This method use reflection to determine the type of the component being added. Use generic as much as possible. - /// - /// The entity to which the component will be added. - /// The component data to associate with the entity. - /// The type of the component being added. This must match the type of . - public readonly void AddComponent(Entity entity, IComponentData component, Type componentType) - { - _world.ComponentStorage.GetOrCreateComponentPool(componentType).Add(entity, component); - _world.ComponentStorage.GetOrCreateMask(componentType).SetBit(entity.ID); - } - - /// - /// Adds a component of type to the given . - /// - /// The type of the component to set. - /// The entity for which the component is to be add. - /// The component Value to add. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void AddComponent(Entity entity, T component) - where T : unmanaged, IComponentData - { - _world.ComponentStorage.GetOrCreateComponentPool().Add(entity, component); - _world.ComponentStorage.GetOrCreateMask().SetBit(entity.ID); - } - - /// - /// Removes a component of type from the given . - /// - /// The type of the component to remove. - /// The entity for which the component is to be remove. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool RemoveComponent(Entity entity) - where T : unmanaged, IComponentData - { - if (!_world.ComponentStorage.TryGetPool(out var pool) || !pool.Has(entity)) - { - return false; - } - - if (!pool.Remove(entity)) - { - return false; - } - - _world.ComponentStorage.GetOrCreateMask().ClearBit(entity.ID); - - return true; - } - - /// - /// Sets a component of the specified type for the given . - /// - /// The entity for which the component is to be set. - /// The component Value to set. - /// The type of the component to set. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void SetComponent(Entity entity, IComponentData component, Type type) - { - var typeHandle = TypeHandle.Get(type); - if (!_world.ComponentStorage.TryGetPool(typeHandle, out var pool)) - { - return; - } - - if (!pool.Has(entity)) - { - return; - } - - pool.Set(entity, component); - } - - /// - /// Sets a component of type for the given . - /// - /// The type of the component to set. - /// The entity for which the component is to be set. - /// The component Value to set. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void SetComponent(Entity entity, in T component) - where T : unmanaged, IComponentData - { - _world.ComponentStorage.GetOrCreateComponentPool().Set(entity, in component); - } - - /// - /// Checks if the given has a component of the specified type. - /// - /// The entity to check. - /// The handle of the component type. - /// True if the entity has the component; otherwise, false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool HasComponent(Entity entity, TypeHandle typeHandle) - { - return _world.ComponentStorage.TryGetMask(typeHandle, out var bitSet) && bitSet.Value.IsSet(entity.ID); - } - - /// - /// Retrieves a reference to a component of type associated with the given . - /// - /// The type of the component to retrieve. - /// The entity whose component is to be retrieved. - /// A to the component, or a null reference if the component does not exist. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly CompRef GetComponent(Entity entity) - where T : unmanaged, IComponentData - { - if (_world.ComponentStorage.TryGetPool(out var pool) && pool.Has(entity)) - { - return new CompRef(ref pool.GetRef(entity)); - } - else - { - return new CompRef(ref Unsafe.NullRef(), false); - } - } - - /// - /// Retrieves all components associated with the specified entity. - /// - /// This method iterates through all available component pools to find components associated - /// with the given entity. It is designed to lazily yield components, making it efficient for scenarios where only - /// a subset of components may be needed. - /// The entity for which components are to be retrieved. - /// An enumerable collection of components associated with the specified entity. If the entity has no components, - /// the collection will be empty. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IEnumerable GetComponents(Entity entity) - { - foreach (var pool in _world.ComponentStorage.ComponentPools) - { - if (pool == null) - { - continue; - } - - if (pool.Has(entity)) - { - yield return pool.Get(entity); - } - } - } - - /// - /// Retrieves an enumerable collection of raw pointers to the components associated with the specified entity. - /// - /// This method provides direct access to the memory locations of components, bypassing type - /// safety. Use with caution, as improper handling of raw pointers can lead to undefined behavior or memory - /// corruption. Ensure that the entity is valid and exists within the current world context before calling this - /// method. - /// The entity whose components are to be retrieved. - /// An enumerable collection of representing the memory addresses of the components associated - /// with the specified entity. The collection will be empty if the entity has no associated components. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly IEnumerable<(TypeHandle, IntPtr)> GetComponentsUnsafe(Entity entity) - { - for (var i = 0; i < _world.ComponentStorage.ComponentPools.Count; i++) - { - var pool = _world.ComponentStorage.ComponentPools[i]; - if (pool == null) - { - continue; - } - - if (pool.Has(entity)) - { - yield return (_world.ComponentStorage.GetComponentPoolType(i), pool.GetUnsafe(entity)); - } - } - } - - /// - /// Adds a script of type to the given . - /// - /// The type of the script to add. - /// The entity to which the script is to be added. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void AddScript(Entity entity) - where T : ScriptComponent, new() - { - _world.ComponentStorage.ScriptComponentPool.Add(entity, new T()); - } - - /// - /// Adds a script of the specified type to the given . - /// - /// The entity to which the script is to be added. - /// The type of the script to add. - /// Thrown if the specified type does not inherit from . - /// Thrown if the script instance could not be created. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void AddScript(Entity entity, Type type) - { - if (!typeof(ScriptComponent).IsAssignableFrom(type)) - { - throw new ArgumentException($"Type {type} must inherit from ScriptComponent.", nameof(type)); - } - - var instance = (ScriptComponent?)Activator.CreateInstance(type) ?? throw new InvalidOperationException($"Failed to create instance of {type}."); - _world.ComponentStorage.ScriptComponentPool.Add(entity, instance); - } - - /// - /// Removes a script of type from the given . - /// - /// The type of the script to remove. - /// The entity from which the script is to be removed. - /// True if the script was successfully removed; otherwise, false. - public readonly bool RemoveScript(Entity entity) - where T : ScriptComponent - { - if (!_world.ComponentStorage.ScriptComponentPool.Remove(entity)) - { - return false; - } - - return true; - } - - /// - /// Removes a script at the specified index from the given . - /// - /// The entity from which the script is to be removed. - /// The index of the script to remove. - /// True if the script was successfully removed; otherwise, false. - public readonly bool RemoveScriptAt(Entity entity, int index) - { - if (!_world.ComponentStorage.ScriptComponentPool.RemoveAt(entity, index)) - { - return false; - } - - return true; - } - - /// - /// Retrieves the first script of type associated with the given . - /// - /// The type of the script to retrieve. - /// The entity whose script is to be retrieved. - /// The script of type , or null if no such script exists. - public readonly T? GetScript(Entity entity) - where T : ScriptComponent - { - return (T?)_world.ComponentStorage.ScriptComponentPool.GetAll(entity)? - .FirstOrDefault(script => script is T tScript); - } - - /// - /// Retrieves all scripts of type associated with the given . - /// - /// The type of the scripts to retrieve. - /// The entity whose scripts are to be retrieved. - /// An enumerable of scripts of type . - public readonly IEnumerable GetScripts(Entity entity) - where T : ScriptComponent - { - return (IEnumerable?)_world.ComponentStorage.ScriptComponentPool.GetAll(entity)?.Where(script => script is T tScript) ?? Enumerable.Empty(); - } - - public readonly void Dispose() - { - _entities.Clear(); - _freeEntitySlots.Clear(); - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Ghost.SparseEntities.csproj b/Ghost.SparseEntities/Ghost.SparseEntities.csproj deleted file mode 100644 index 451e5e1..0000000 --- a/Ghost.SparseEntities/Ghost.SparseEntities.csproj +++ /dev/null @@ -1,113 +0,0 @@ - - - - net10.0 - enable - enable - True - - - - True - - - - True - - - - - True - True - ForEach.tt - - - True - True - QueryItem.tt - - - True - True - QueryRefComponent.tt - - - True - True - World.Query.tt - - - - - - TextTemplatingFileGenerator - ForEach.cs - - - TextTemplatingFileGenerator - QueryEnumerable.cs - - - TextTemplatingFilePreprocessor - Helpers.cs - - - TextTemplatingFileGenerator - QueryItem.cs - - - TextTemplatingFileGenerator - QueryRefComponent.cs - - - TextTemplatingFileGenerator - World.Query.cs - - - - - - - - - - True - True - ForEach.tt - - - True - True - Helpers.tt - - - True - True - QueryEnumerable.tt - - - True - True - QueryItem.tt - - - True - True - QueryRefComponent.tt - - - True - True - World.Query.tt - - - - - - - - - - - - diff --git a/Ghost.SparseEntities/Query/QueryBuilder.cs b/Ghost.SparseEntities/Query/QueryBuilder.cs deleted file mode 100644 index 3e7d6ad..0000000 --- a/Ghost.SparseEntities/Query/QueryBuilder.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Ghost.Core; - -namespace Ghost.SparseEntities.Query; - -public struct QueryBuilder -{ - private QueryFilter _filter; - - public QueryBuilder() - { - _filter = new QueryFilter(); - } - - public QueryBuilder WithAll() - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryBuilder WithAny() - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryBuilder WithAbsent() - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryBuilder WithDisabled() - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public readonly QueryFilter Build() - { - return _filter; - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Query/QueryFilter.cs b/Ghost.SparseEntities/Query/QueryFilter.cs deleted file mode 100644 index 69ece4e..0000000 --- a/Ghost.SparseEntities/Query/QueryFilter.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Ghost.Core; -using Misaki.HighPerformance.LowLevel.Buffer; -using Misaki.HighPerformance.LowLevel.Collections; - -namespace Ghost.SparseEntities.Query; - -public struct QueryFilter : IDisposable -{ - //private readonly Stack.Scope _scope; - - internal UnsafeList _all; - internal UnsafeList _any; - internal UnsafeList _absent; - internal UnsafeList _disabled; - - public QueryFilter() - { - //_scope = AllocationManager.CreateStackScope(); - - _all = new UnsafeList(4, Allocator.Stack); - _any = new UnsafeList(4, Allocator.Stack); - _absent = new UnsafeList(4, Allocator.Stack); - _disabled = new UnsafeList(4, Allocator.Stack); - } - - public readonly UnsafeBitSet ComputeFilterBitMask(World world, Allocator allocator) - { - UnsafeBitSet allMask = default; - UnsafeBitSet anyMask = default; - UnsafeBitSet absentMask = default; - - var result = new UnsafeBitSet(world.EntityManager.EntityCount, allocator); - result.ClearAll(); - - using (AllocationManager.CreateStackScope()) - { - foreach (var typeHandle in _all) - { - var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - - if (!allMask.IsCreated) - { - allMask = new UnsafeBitSet(mask.Count, Allocator.Stack, AllocationOption.None); - allMask.SetAll(); - } - - allMask.And(mask); - } - - foreach (var typeHandle in _any) - { - var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - - if (!anyMask.IsCreated) - { - anyMask = new UnsafeBitSet(mask.Count, Allocator.Stack); - } - - anyMask.And(mask); - } - - foreach (var typeHandle in _absent) - { - var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - - if (!absentMask.IsCreated) - { - absentMask = new UnsafeBitSet(mask.Count, Allocator.Stack); - } - - absentMask.Or(mask); - } - - if (allMask.IsCreated) - { - result.And(allMask); - } - - if (anyMask.IsCreated) - { - result.And(anyMask); - } - - if (absentMask.IsCreated) - { - result.ANDC(absentMask); - } - } - - return result; - } - - public readonly void Dispose() - { - //_scope.Dispose(); - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Query/QueryTypeParameter.cs b/Ghost.SparseEntities/Query/QueryTypeParameter.cs deleted file mode 100644 index 9cc059a..0000000 --- a/Ghost.SparseEntities/Query/QueryTypeParameter.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Ghost.SparseEntities.Components; -using System.Runtime.CompilerServices; - -namespace Ghost.SparseEntities.Query; - -public interface IQueryTypeParameter - where T : IComponentData -{ -} - -public ref struct CompRef : IQueryTypeParameter - where T : IComponentData -{ - internal ref T _value; - - public ref T ValueRW - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref _value; - } - - public readonly ref T ValueRO - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref _value; - } - - public readonly bool IsValid - { - get; - init; - } - - public CompRef(ref T value, bool isValid) - { - _value = ref value; - IsValid = isValid; - } - - public CompRef(ref T value) - : this(ref value, true) - { - } -} - -public readonly ref struct CompRO : IQueryTypeParameter - where T : IComponentData -{ - internal readonly ref T _value; - - public readonly ref T ValueRO - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref _value; - } - - public readonly bool IsValid - { - get; - init; - } - - public CompRO(ref T value, bool isValid) - { - _value = ref value; - IsValid = isValid; - } - - public CompRO(ref T value) - : this(ref value, true) - { - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Systems/ISystem.cs b/Ghost.SparseEntities/Systems/ISystem.cs deleted file mode 100644 index b39ca6d..0000000 --- a/Ghost.SparseEntities/Systems/ISystem.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Ghost.SparseEntities.Systems; - -/// -/// Attribute to declare that a system depends on one or more other systems. -/// -[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple = false)] -public class DependsOnAttribute : Attribute -{ - public Type[] Prerequisites - { - get; - } - - public DependsOnAttribute(params Type[] prerequisites) - { - Prerequisites = prerequisites; - } -} - -public interface ISystem -{ - public void OnCreate(in SystemState state); - - public void OnUpdate(in SystemState state); - - public void OnDestroy(in SystemState state); -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Systems/SystemDependencyBuilder.cs b/Ghost.SparseEntities/Systems/SystemDependencyBuilder.cs deleted file mode 100644 index 217c781..0000000 --- a/Ghost.SparseEntities/Systems/SystemDependencyBuilder.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System.Reflection; - -namespace Ghost.SparseEntities.Systems; - -internal class SystemDependencyBuilder -{ - private readonly Dictionary> _dependencies = new(); - private readonly List _systemTypes; - - public SystemDependencyBuilder(List allSystemTypes) - { - _systemTypes = allSystemTypes; - } - - /// - /// Builds a dependency graph for all system types that implement the interface. - /// - /// This method analyzes all system types and their dependencies, as defined by the . It validates that each system type is a concrete implementation of and constructs a mapping of each system type to its direct dependencies. - /// Thrown if a type in allSystemTypes is not a concrete implementation of . - public void BuildDependencyGraph() - { - foreach (var systemType in _systemTypes) - { - if (!typeof(ISystem).IsAssignableFrom(systemType) || systemType.IsAbstract || systemType.IsInterface) - { - throw new ArgumentException($"{systemType.Name} is not a concrete ISystem type."); - } - - var directDependencies = new List(); - var dependsOnAttributes = systemType.GetCustomAttributes(false); - foreach (var attr in dependsOnAttributes) - { - directDependencies.AddRange(attr.Prerequisites); - } - - _dependencies[systemType] = directDependencies; - } - } - - private void Visit(Type systemType, HashSet visited, HashSet permanentMark, List executionOrder) - { - if (permanentMark.Contains(systemType)) - { - return; - } - - if (visited.Contains(systemType)) - { - throw new InvalidOperationException($"Circular dependency detected involving system: {systemType.Name}"); - } - - visited.Add(systemType); // Mark as currently visiting - - if (_dependencies.TryGetValue(systemType, out var directDependencies)) - { - foreach (var dependencyType in directDependencies) - { - // Ensure the dependency is a registered system type - if (!_systemTypes.Contains(dependencyType)) - { - throw new InvalidOperationException($"System {systemType.Name} depends on unregistered system {dependencyType.Name}."); - } - - Visit(dependencyType, visited, permanentMark, executionOrder); - } - } - - visited.Remove(systemType); // Done visiting this node in the current path - permanentMark.Add(systemType); // Mark as permanently processed - executionOrder.Add(systemType); // Add to the sorted list (this will be reversed later for correct order) - } - - /// - /// Builds the topological order of systems. - /// - /// A list of system types in the order they should be executed. - /// Thrown if a circular dependency is detected." - public List BuildExecutionOrder() - { - var executionOrder = new List(_systemTypes.Count); - var visited = new HashSet(); // Tracks visited nodes in the current DFS path (for cycle detection) - var permanentMark = new HashSet(); // Tracks nodes whose dependencies have been fully resolved - - // Initialize dependencies for all registered systems, even those without explicit attributes - foreach (var sysType in _systemTypes) - { - if (!_dependencies.ContainsKey(sysType)) - { - _dependencies[sysType] = new(); - } - } - - foreach (var systemType in _systemTypes) - { - if (!permanentMark.Contains(systemType)) - { - Visit(systemType, visited, permanentMark, executionOrder); - } - } - - return executionOrder; - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Systems/SystemState.cs b/Ghost.SparseEntities/Systems/SystemState.cs deleted file mode 100644 index a18d26e..0000000 --- a/Ghost.SparseEntities/Systems/SystemState.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ghost.SparseEntities.Systems; - -public struct SystemState -{ - public World World - { - get; - init; - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Systems/SystemStorage.cs b/Ghost.SparseEntities/Systems/SystemStorage.cs deleted file mode 100644 index d7ba08e..0000000 --- a/Ghost.SparseEntities/Systems/SystemStorage.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Ghost.SparseEntities.Systems; - -[SkipLocalsInit] -public readonly struct SystemStorage -{ - private readonly List _systems = new(); - private readonly List _executionList = new(); - - private readonly World _world; - - internal ReadOnlySpan Systems => CollectionsMarshal.AsSpan(_systems); - - internal SystemStorage(World world) - { - _world = world; - } - - public readonly void AddSystem(Type systemType) - { - _systems.Add(systemType); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void AddSystem() - where T : ISystem, new() - { - AddSystem(typeof(T)); - } - - public readonly void RemoveSystem(Type systemType) - { - _systems.Remove(systemType); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly void RemoveSystem() - where T : ISystem, new() - { - RemoveSystem(typeof(T)); - } - - internal void CreateSystems() - { - var builder = new SystemDependencyBuilder(_systems); - builder.BuildDependencyGraph(); - var executionOrder = builder.BuildExecutionOrder(); - - var state = new SystemState() - { - World = _world, - }; - - foreach (var systemType in executionOrder) - { - var system = (ISystem?)Activator.CreateInstance(systemType) ?? throw new InvalidOperationException($"Failed to create instance of system type {systemType.Name}."); - - _executionList.Add(system); - system.OnCreate(in state); - } - } - - internal void UpdateSystems() - { - var state = new SystemState() - { - World = _world, - }; - - foreach (var system in _executionList) - { - system.OnUpdate(in state); - } - } - - internal void Dispose() - { - var state = new SystemState() - { - World = _world, - }; - - foreach (var system in _executionList) - { - system.OnDestroy(in state); - } - - _systems.Clear(); - _executionList.Clear(); - } -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Template/ForEach.cs b/Ghost.SparseEntities/Template/ForEach.cs deleted file mode 100644 index 4251f6e..0000000 --- a/Ghost.SparseEntities/Template/ForEach.cs +++ /dev/null @@ -1,12 +0,0 @@ - - -namespace Ghost.SparseEntities; - -public delegate void ForEach(ref T0 t0Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component); -public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component); diff --git a/Ghost.SparseEntities/Template/ForEach.tt b/Ghost.SparseEntities/Template/ForEach.tt deleted file mode 100644 index 045c196..0000000 --- a/Ghost.SparseEntities/Template/ForEach.tt +++ /dev/null @@ -1,16 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ include file="Helpers.ttinclude" #> - -namespace Ghost.Entities; - -<# for (var i = 1; i <= Amount; i++) -{ - var generics = AppendGenerics(i); - var compGenerics = AppendGenericRefParameters(i); -#> -public delegate void ForEach<<#= generics #>>(<#= compGenerics #>); -<# } #> \ No newline at end of file diff --git a/Ghost.SparseEntities/Template/Helpers.ttinclude b/Ghost.SparseEntities/Template/Helpers.ttinclude deleted file mode 100644 index 568a02e..0000000 --- a/Ghost.SparseEntities/Template/Helpers.ttinclude +++ /dev/null @@ -1,128 +0,0 @@ -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Collections.Generic" #> -<#+ - - public int Amount = 8; - public int ExtensionAmount = 3; - - public string Indent(StringBuilder sb, int spaces) - { - var indent = new string(' ', spaces); - return sb.ToString().Replace("\n", "\n" + indent); - } - - string AppendGenerics(int amount, string template) - { - var sb = new StringBuilder(); - for (var i = 0; i < amount; i++) - { - if (i > 0) sb.Append(", "); - sb.Append(string.Format(template, i)); - } - return sb.ToString(); - } - - string AppendGenerics(int amount) - { - return AppendGenerics(amount, "T{0}"); - } - - public StringBuilder AppendGenericRefParameters(int amount) - { - var sb = new StringBuilder(); - for (var localIndex = 0; localIndex < amount; localIndex++) - { - sb.Append($"ref T{localIndex} t{localIndex}Component,"); - } - - sb.Length--; - return sb; - } - - public StringBuilder AppendRefParameters(int amount) - { - var sb = new StringBuilder(); - for (var localIndex = 0; localIndex < amount; localIndex++) - { - sb.Append($"ref component{localIndex},"); - } - - sb.Length--; - return sb; - } - - public StringBuilder AppendGenericRestrictions(int amount, string Ttemplate, string template) - { - var sb = new StringBuilder(); - for (var localIndex = 0; localIndex < amount; localIndex++) - { - sb.Append($"where {Ttemplate}{localIndex} : {template}"); - if (localIndex < amount - 1) - { - sb.Append(' '); - } - } - return sb; - } - - public StringBuilder AppendGenericRestrictions(int amount, string template) - { - return AppendGenericRestrictions(amount, "T", template); - } - - public StringBuilder TryGetComponentPools(int amount) - { - var sb = new StringBuilder(); - for (var localIndex = 0; localIndex < amount; localIndex++) - { - sb.Append($"_componentStorage.TryGetPool(out var pool{localIndex})"); - if (localIndex < amount - 1) - { - sb.Append(" && "); - } - } - return sb; - } - - public StringBuilder HasEntity(int amount) - { - var sb = new StringBuilder(); - for (var localIndex = 1; localIndex < amount; localIndex++) - { - sb.Append($"pool{localIndex}.Has(entity)"); - if (localIndex < amount - 1) - { - sb.Append(" && "); - } - } - return sb; - } - - public StringBuilder GetComponent(int amount) - { - var sb = new StringBuilder(); - for (var localIndex = 0; localIndex < amount; localIndex++) - { - sb.Append($"pool{localIndex}.GetRef(entity)"); - if (localIndex < amount - 1) - { - sb.Append(", "); - } - } - return sb; - } - - public StringBuilder GetComponentRef(int amount) - { - var sb = new StringBuilder(); - for (var localIndex = 0; localIndex < amount; localIndex++) - { - sb.Append($"ref pool{localIndex}.GetRef(entity)"); - if (localIndex < amount - 1) - { - sb.Append(", "); - } - } - return sb; - } -#> \ No newline at end of file diff --git a/Ghost.SparseEntities/Template/QueryEnumerable.cs b/Ghost.SparseEntities/Template/QueryEnumerable.cs deleted file mode 100644 index ce321ef..0000000 --- a/Ghost.SparseEntities/Template/QueryEnumerable.cs +++ /dev/null @@ -1,1706 +0,0 @@ - - -using Ghost.Core; -using Ghost.SparseEntities.Components; -using Ghost.SparseEntities.Query; -using Misaki.HighPerformance.LowLevel.Buffer; -using Misaki.HighPerformance.LowLevel.Collections; - -namespace Ghost.SparseEntities; - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4, _pool5); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly ComponentPool _pool6; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly ComponentPool _pool6; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - -public unsafe ref struct QueryEnumerable - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData -{ - private QueryFilter _filter; - - private readonly World _world; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly ComponentPool _pool6; - private readonly ComponentPool _pool7; - private readonly int _count; - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count) - { - _filter = new(); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - _pool7 = pool7; - - _count = count; - } - - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - _pool7 = pool7; - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _pool7, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly ComponentPool _pool6; - private readonly ComponentPool _pool7; - - private int _index; - private int _count; - - public QueryItem Current - { - get; - private set; - } - - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - _pool7 = pool7; - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _pool7); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - _filter._all.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - _filter._any.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - _filter._absent.Add(TypeHandle.Get()); - return this; - } - - public QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - _filter._disabled.Add(TypeHandle.Get()); - return this; - } -} - diff --git a/Ghost.SparseEntities/Template/QueryEnumerable.tt b/Ghost.SparseEntities/Template/QueryEnumerable.tt deleted file mode 100644 index a2a7960..0000000 --- a/Ghost.SparseEntities/Template/QueryEnumerable.tt +++ /dev/null @@ -1,175 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Text" #> -<#@ import namespace="System.Linq" #> -<#@ include file="Helpers.ttinclude" #> - -using Ghost.Core; -using Ghost.Entities.Components; -using Ghost.Entities.Query; -using Misaki.HighPerformance.LowLevel.Buffer; -using Misaki.HighPerformance.LowLevel.Collections; - -namespace Ghost.Entities; - -<# for (int arity = 1; arity <= Amount; arity++) { -var generics = AppendGenerics(arity); -var restrictions = AppendGenericRestrictions(arity, "unmanaged, IComponentData"); -var poolParams = Enumerable.Range(0, arity) - .Select(i => $"ComponentPool pool{i}") - .Aggregate((a, b) => a + ", " + b); -var constructorParams = Enumerable.Range(0, arity) - .Select(i => $"_pool{i}") - .Aggregate((a, b) => a + ", " + b); - -#> -public unsafe ref struct QueryEnumerable<<#= generics #>> - <#= restrictions #> -{ - private QueryFilter _filter; - - private readonly World _world; - -<# for (int i = 0; i < arity; i++){ #> - private readonly ComponentPool> _pool<#= i #>; -<# } #> - private readonly int _count; - - internal QueryEnumerable(World world, <#= poolParams #>, int count) - { - _filter = new(); -<# for (int i = 0; i < arity; i++) {#> - _filter._all.Add(TypeHandle.Get>()); -<# } #> - - _world = world; - -<# for (int i = 0; i < arity; i++) { #> - _pool<#= i #> = pool<#= i #>; -<# } #> - - _count = count; - } - - internal QueryEnumerable(World world, <#= poolParams #>, int count, ref readonly QueryFilter filter) - { - _filter = filter; - - _world = world; - -<# for (int i = 0; i < arity; i++) { #> - _pool<#= i #> = pool<#= i #>; -<# } #> - - _count = count; - } - -#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference - public Enumerator GetEnumerator() => new(_world, <#= constructorParams #>, _count, ref _filter); -#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference - - public ref struct Enumerator - { - private ref QueryFilter _filter; - private UnsafeBitSet _filterMask; - - private readonly ReadOnlySpan _entities; - private readonly Stack.Scope _stackScope; - -<# for (int i = 0; i < arity; i++){ #> - private readonly ComponentPool> _pool<#= i #>; -<# } #> - - private int _index; - private int _count; - - public QueryItem<<#= generics #>> Current - { - get; - private set; - } - - internal Enumerator(World world, <#= poolParams #>, int count, ref QueryFilter filter) - { - _stackScope = AllocationManager.CreateStackScope(); - - _filter = ref filter; - _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); - - _entities = world.EntityManager.Entities; - -<# for (int i = 0; i < arity; i++){ #> - _pool<#= i #> = pool<#= i #>; -<# } #> - - _count = count; - _index = -1; - - Current = default; - } - - public bool MoveNext() - { - _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _count <= 0) - { - return false; - } - - _count--; - Current = new QueryItem<<#= generics #>>(_entities[_index], <#= constructorParams #>); - - return true; - } - - public readonly void Dispose() - { - _stackScope.Dispose(); - _filter.Dispose(); - } - } -<# for (int i = 1; i <= ExtensionAmount; i++) { -var compGenerics = AppendGenerics(i, "TComponent"); -var compRestrictions = AppendGenericRestrictions(i, "TComponent", "unmanaged, IComponentData"); -#> - - public QueryEnumerable<<#= generics #>> WithAll<<#= compGenerics #>>() - <#= compRestrictions #> - { -<# for (int j = 0; j < i; j++) {#> - _filter._all.Add(TypeHandle.Get>()); -<# } #> - return this; - } - - public QueryEnumerable<<#= generics #>> WithAny<<#= compGenerics #>>() - <#= compRestrictions #> - { -<# for (int j = 0; j < i; j++) {#> - _filter._any.Add(TypeHandle.Get>()); -<# } #> - return this; - } - - public QueryEnumerable<<#= generics #>> WithAbsent<<#= compGenerics #>>() - <#= compRestrictions #> - { -<# for (int j = 0; j < i; j++) {#> - _filter._absent.Add(TypeHandle.Get>()); -<# } #> - return this; - } - - public QueryEnumerable<<#= generics #>> WithDisabled<<#= compGenerics #>>() - <#= compRestrictions #> - { -<# for (int j = 0; j < i; j++) {#> - _filter._disabled.Add(TypeHandle.Get>()); -<# } #> - return this; - } -<# } #> -} - -<# } #> \ No newline at end of file diff --git a/Ghost.SparseEntities/Template/QueryItem.cs b/Ghost.SparseEntities/Template/QueryItem.cs deleted file mode 100644 index fee73c5..0000000 --- a/Ghost.SparseEntities/Template/QueryItem.cs +++ /dev/null @@ -1,319 +0,0 @@ - - -using Ghost.SparseEntities.Components; -using Ghost.SparseEntities.Query; - -namespace Ghost.SparseEntities; - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - - internal QueryItem(Entity entity, ComponentPool pool0) - { - _entity = entity; - _pool0 = pool0; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - public ref T2 Component2 => ref _pool2.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1, out CompRef c2) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - c2 = new (ref _pool2.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - public ref T2 Component2 => ref _pool2.GetRef(_entity); - public ref T3 Component3 => ref _pool3.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1, out CompRef c2, out CompRef c3) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - c2 = new (ref _pool2.GetRef(_entity)); - c3 = new (ref _pool3.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - public ref T2 Component2 => ref _pool2.GetRef(_entity); - public ref T3 Component3 => ref _pool3.GetRef(_entity); - public ref T4 Component4 => ref _pool4.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1, out CompRef c2, out CompRef c3, out CompRef c4) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - c2 = new (ref _pool2.GetRef(_entity)); - c3 = new (ref _pool3.GetRef(_entity)); - c4 = new (ref _pool4.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - public ref T2 Component2 => ref _pool2.GetRef(_entity); - public ref T3 Component3 => ref _pool3.GetRef(_entity); - public ref T4 Component4 => ref _pool4.GetRef(_entity); - public ref T5 Component5 => ref _pool5.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1, out CompRef c2, out CompRef c3, out CompRef c4, out CompRef c5) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - c2 = new (ref _pool2.GetRef(_entity)); - c3 = new (ref _pool3.GetRef(_entity)); - c4 = new (ref _pool4.GetRef(_entity)); - c5 = new (ref _pool5.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly ComponentPool _pool6; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - public ref T2 Component2 => ref _pool2.GetRef(_entity); - public ref T3 Component3 => ref _pool3.GetRef(_entity); - public ref T4 Component4 => ref _pool4.GetRef(_entity); - public ref T5 Component5 => ref _pool5.GetRef(_entity); - public ref T6 Component6 => ref _pool6.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1, out CompRef c2, out CompRef c3, out CompRef c4, out CompRef c5, out CompRef c6) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - c2 = new (ref _pool2.GetRef(_entity)); - c3 = new (ref _pool3.GetRef(_entity)); - c4 = new (ref _pool4.GetRef(_entity)); - c5 = new (ref _pool5.GetRef(_entity)); - c6 = new (ref _pool6.GetRef(_entity)); - } -} - -public readonly struct QueryItem - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData -{ - private readonly Entity _entity; - private readonly ComponentPool _pool0; - private readonly ComponentPool _pool1; - private readonly ComponentPool _pool2; - private readonly ComponentPool _pool3; - private readonly ComponentPool _pool4; - private readonly ComponentPool _pool5; - private readonly ComponentPool _pool6; - private readonly ComponentPool _pool7; - - internal QueryItem(Entity entity, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7) - { - _entity = entity; - _pool0 = pool0; - _pool1 = pool1; - _pool2 = pool2; - _pool3 = pool3; - _pool4 = pool4; - _pool5 = pool5; - _pool6 = pool6; - _pool7 = pool7; - } - - public Entity Entity => _entity; - - public ref T0 Component0 => ref _pool0.GetRef(_entity); - public ref T1 Component1 => ref _pool1.GetRef(_entity); - public ref T2 Component2 => ref _pool2.GetRef(_entity); - public ref T3 Component3 => ref _pool3.GetRef(_entity); - public ref T4 Component4 => ref _pool4.GetRef(_entity); - public ref T5 Component5 => ref _pool5.GetRef(_entity); - public ref T6 Component6 => ref _pool6.GetRef(_entity); - public ref T7 Component7 => ref _pool7.GetRef(_entity); - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, out CompRef c0, out CompRef c1, out CompRef c2, out CompRef c3, out CompRef c4, out CompRef c5, out CompRef c6, out CompRef c7) - { - entity = _entity; - - c0 = new (ref _pool0.GetRef(_entity)); - c1 = new (ref _pool1.GetRef(_entity)); - c2 = new (ref _pool2.GetRef(_entity)); - c3 = new (ref _pool3.GetRef(_entity)); - c4 = new (ref _pool4.GetRef(_entity)); - c5 = new (ref _pool5.GetRef(_entity)); - c6 = new (ref _pool6.GetRef(_entity)); - c7 = new (ref _pool7.GetRef(_entity)); - } -} - diff --git a/Ghost.SparseEntities/Template/QueryItem.tt b/Ghost.SparseEntities/Template/QueryItem.tt deleted file mode 100644 index bbd991a..0000000 --- a/Ghost.SparseEntities/Template/QueryItem.tt +++ /dev/null @@ -1,61 +0,0 @@ -<#@ template language="C#" debug="false" hostspecific="true" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ include file="Helpers.ttinclude" #> -<#@ output extension=".cs" #> - -using Ghost.Entities.Components; -using Ghost.Entities.Query; - -namespace Ghost.Entities; - -<# for (int arity = 1; arity <= Amount; arity++) -{ -var generics = AppendGenerics(arity); -var restrictions = AppendGenericRestrictions(arity, "unmanaged, IComponentData"); -var constructorParams = Enumerable.Range(0, arity) - .Select(i => $"ComponentPool pool{i}") - .Aggregate((a, b) => a + ", " + b); -var deconstructParams = Enumerable.Range(0, arity) - .Select(i => { - var name = $"c{i}"; - return arity == 1 - ? $"out CompRef {name}" - : $"out CompRef {name}"; - }) - .Aggregate((a, b) => a + ", " + b); -#> -public readonly struct QueryItem<<#= generics #>> - <#= restrictions #> -{ - private readonly Entity _entity; -<# for (int i = 0; i < arity; i++){ #> - private readonly ComponentPool> _pool<#= i #>; -<# } #> - - internal QueryItem(Entity entity, <#= constructorParams #>) - { - _entity = entity; -<# for (int i = 0; i < arity; i++){ #> - _pool<#= i #> = pool<#= i #>; -<# } #> - } - - public Entity Entity => _entity; - -<# for (int i = 0; i < arity; i++){ #> - public ref T<#= i #> Component<#= i #> => ref _pool<#= i #>.GetRef(_entity); -<# } #> - - // Deconstruct into tuple-like values - public void Deconstruct(out Entity entity, <#= deconstructParams #>) - { - entity = _entity; - -<# for (int i = 0; i < arity; i++){ #> - c<#= i #> = new (ref _pool<#= i #>.GetRef(_entity)); -<# } #> - } -} - -<# } #> diff --git a/Ghost.SparseEntities/Template/QueryRefComponent.cs b/Ghost.SparseEntities/Template/QueryRefComponent.cs deleted file mode 100644 index 0a12253..0000000 --- a/Ghost.SparseEntities/Template/QueryRefComponent.cs +++ /dev/null @@ -1,22 +0,0 @@ - - -using Ghost.SparseEntities.Components; - -namespace Ghost.SparseEntities; - -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component) - where T0 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData; -public delegate void QueryRefComponent(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData; diff --git a/Ghost.SparseEntities/Template/QueryRefComponent.tt b/Ghost.SparseEntities/Template/QueryRefComponent.tt deleted file mode 100644 index 5cb6324..0000000 --- a/Ghost.SparseEntities/Template/QueryRefComponent.tt +++ /dev/null @@ -1,21 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ import namespace="System.Text" #> -<#@ include file="Helpers.ttinclude" #> - -using Ghost.Entities.Components; - -namespace Ghost.Entities; - -<# -for (var index = 1; index <= Amount; index++) -{ - var generics = AppendGenerics(index); - var parameters = AppendGenericRefParameters(index); - var restrictions = AppendGenericRestrictions(index, "unmanaged, IComponentData"); -#> -public delegate void QueryRefComponent<<#= generics #>>(Entity entity, <#= parameters.ToString() #>) - <#= restrictions.ToString() #>; -<# -} -#> \ No newline at end of file diff --git a/Ghost.SparseEntities/Template/World.Query.cs b/Ghost.SparseEntities/Template/World.Query.cs deleted file mode 100644 index 055c9fb..0000000 --- a/Ghost.SparseEntities/Template/World.Query.cs +++ /dev/null @@ -1,242 +0,0 @@ - - -using Ghost.SparseEntities.Components; -using Ghost.SparseEntities.Query; - -namespace Ghost.SparseEntities; - -public partial class World -{ - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, pool5, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, pool5, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, pool5, pool6, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, pool5, pool6, - pool0.Count, - in filter); - } - - public QueryEnumerable Query() - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6) && _componentStorage.TryGetPool(out var pool7))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, pool5, pool6, pool7, - pool0.Count); - } - - public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) - where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData - { - if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6) && _componentStorage.TryGetPool(out var pool7))) - { - return default; - } - - return new QueryEnumerable( - this, - pool0, pool1, pool2, pool3, pool4, pool5, pool6, pool7, - pool0.Count, - in filter); - } - -} \ No newline at end of file diff --git a/Ghost.SparseEntities/Template/World.Query.tt b/Ghost.SparseEntities/Template/World.Query.tt deleted file mode 100644 index e6abd39..0000000 --- a/Ghost.SparseEntities/Template/World.Query.tt +++ /dev/null @@ -1,54 +0,0 @@ -<#@ template language="C#" #> -<#@ output extension=".cs" #> -<#@ assembly name="System.Core" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Text" #> -<#@ include file="Helpers.ttinclude" #> - -using Ghost.Entities.Components; -using Ghost.Entities.Query; - -namespace Ghost.Entities; - -public partial class World -{ -<# for (var index = 1; index <= Amount; index++) { - var generics = AppendGenerics(index); - var restrictions = AppendGenericRestrictions(index, "unmanaged, IComponentData"); - var tryGetPools = TryGetComponentPools(index); - var poolParams = Enumerable.Range(0, index) - .Select(i => $"pool{i}") - .Aggregate((a,b)=> a + ", " + b); - var countSource = "pool0.Count"; -#> - public QueryEnumerable<<#= generics #>> Query<<#= generics #>>() - <#= restrictions #> - { - if (!(<#= tryGetPools #>)) - { - return default; - } - - return new QueryEnumerable<<#= generics #>>( - this, - <#= poolParams #>, - <#= countSource #>); - } - - public QueryEnumerable<<#= generics #>> QueryFilter<<#= generics #>>(ref readonly QueryFilter filter) - <#= restrictions #> - { - if (!(<#= tryGetPools #>)) - { - return default; - } - - return new QueryEnumerable<<#= generics #>>( - this, - <#= poolParams #>, - <#= countSource #>, - in filter); - } - -<# } #> -} \ No newline at end of file diff --git a/Ghost.SparseEntities/World.cs b/Ghost.SparseEntities/World.cs deleted file mode 100644 index 64aa51a..0000000 --- a/Ghost.SparseEntities/World.cs +++ /dev/null @@ -1,164 +0,0 @@ -using Ghost.SparseEntities.Components; -using Ghost.SparseEntities.Query; -using Ghost.SparseEntities.Systems; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Ghost.SparseEntities; - -// TODO: Archetype system for better performance -public partial class World -{ - private static List s_worlds = new(4); - private static Queue s_freeWorldSlots = new(); - - public static int WorldCount => s_worlds.Count - s_freeWorldSlots.Count; - - public static World Create(int entityCapacity = 16) - { - lock (s_worlds) - { - if (s_freeWorldSlots.TryDequeue(out var index)) - { - s_worlds[index] = new World(index, entityCapacity); - } - else - { - if (s_worlds.Count >= WorldID.MaxValue) - { - throw new InvalidOperationException("Maximum number of worlds reached"); - } - - index = (WorldID)s_worlds.Count; - s_worlds.Add(new World(index, entityCapacity)); - } - - return s_worlds[index]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static World GetWorld(int index) - { - return s_worlds[index]; - } -} - -public partial class World : IDisposable, IEquatable -{ - private readonly WorldID _id; - private readonly EntityManager _entityManager; - private readonly ComponentStorage _componentStorage; - private readonly SystemStorage _systemStorage; - - private bool _isDisposed = false; - - internal ComponentStorage ComponentStorage => _componentStorage; - - public WorldID ID => _id; - public EntityManager EntityManager => _entityManager; - public SystemStorage SystemStorage => _systemStorage; - - public event Action? ComponentChanged; - - private World(WorldID id, int entityCapacity) - { - _id = id; - _entityManager = new EntityManager(this, entityCapacity); - _componentStorage = new ComponentStorage(this); - _systemStorage = new SystemStorage(this); - } - - ~World() - { - Dispose(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CompRef GetSingleton() - where T : unmanaged, IComponentData - { - ref var component = ref CollectionsMarshal.GetValueRefOrAddDefault(SingletonContainer.container, _id, out _); - return new CompRef(ref component); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable QueryScript() - { - if (_componentStorage.ScriptComponentPool.IsInitialized) - { - return _componentStorage.ScriptComponentPool.ExecutionList!; - } - - return Enumerable.Empty(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [Conditional("GHOST_EDITOR")] - public void NotifyComponentChanged(Entity entity, Type type) - { - ComponentChanged?.Invoke(this, entity, type); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [Conditional("GHOST_EDITOR")] - public void NotifyComponentChanged(Entity entity) - where T : unmanaged, IComponentData - { - NotifyComponentChanged(entity, typeof(T)); - } - - public bool Equals(World? other) - { - if (other is null) - { - return false; - } - - if (ReferenceEquals(this, other)) - { - return true; - } - - return _id == other._id; - } - - public override int GetHashCode() - { - return _id.GetHashCode(); - } - - public override bool Equals(object? obj) - { - return obj is World other && Equals(other); - } - - public static bool operator ==(World? left, World? right) - { - return left?.Equals(right) ?? right is null; - } - - public static bool operator !=(World? left, World? right) - { - return !(left == right); - } - - public void Dispose() - { - if (_isDisposed) - { - return; - } - - _entityManager.Dispose(); - _componentStorage.Dispose(); - _systemStorage.Dispose(); - - s_freeWorldSlots.Enqueue(_id); - - _isDisposed = true; - - GC.SuppressFinalize(this); - } -} \ No newline at end of file