Refactor ECS framework and improve performance
Refactored `ArcEntityTest` to use updated `Transform` and `Mesh` components, improving query logic with `GetChunkIterator` and introducing `ForEach` methods for better modularity. Enhanced `Chunk` and `Archetype` structs with `readonly` properties and memory optimizations. Fixed bugs in memory copy logic and entity relocation. Improved `EntityManager` with proper disposal handling, added a destructor, and fixed pointer usage in `AddComponent` and `SetComponentData`. Refactored `EntityQuery` to use `ChunkIterator` and `ChunkView` for better abstraction. Simplified `EntityQueryMask` logic for performance. Introduced templated `ForEach` methods and `ForEachWithEntity` methods, dynamically generated using T4 templates for scalability. Added disposal logic for archetypes and queries in `World`. Updated `Program.cs` to include memory debugging setup. Integrated T4 templates for dynamic code generation and added helper functions for template generation. Updated project file to include templates and generated outputs. General improvements include enforcing immutability, optimizing memory management, and adding debugging/logging for better traceability.
This commit is contained in:
@@ -14,24 +14,29 @@ public partial class ArcEntityTest : ITest
|
||||
|
||||
public void Run()
|
||||
{
|
||||
var entity1 = _world.EntityManager.CreateEntity(ComponentTypeID<TransformData>.value);
|
||||
var mesh = new MeshData { index = 1 };
|
||||
_world.EntityManager.AddComponent<MeshData>(entity1, ref mesh);
|
||||
var entity1 = _world.EntityManager.CreateEntity(ComponentTypeID<Transform>.value);
|
||||
Console.WriteLine(entity1);
|
||||
_world.EntityManager.AddComponent<Mesh>(entity1, new Mesh { index = 1 });
|
||||
|
||||
var queryID = new QueryBuilder().WithAll<TransformData>().Build(_world);
|
||||
var queryID = new QueryBuilder().WithAll<Transform>().Build(_world);
|
||||
ref var query = ref _world.GetEntityQueryReference(queryID);
|
||||
|
||||
foreach (var item in query)
|
||||
foreach (var chunk in query.GetChunkIterator())
|
||||
{
|
||||
var transforms = item.GetComponentData<TransformData>();
|
||||
Console.WriteLine($"Item Count: {item.Count}");
|
||||
for (var i = 0; i < item.Count; i++)
|
||||
var transforms = chunk.GetComponentData<Transform>();
|
||||
var entities = chunk.GetEntities();
|
||||
|
||||
for (var i = 0; i < chunk.Count; i++)
|
||||
{
|
||||
Console.WriteLine($"Entity Position: {transforms[i].position}");
|
||||
Console.WriteLine($"Entity {entities[i]} Position: {transforms[i].position}");
|
||||
transforms[i].position = new float3(1, 2, 3);
|
||||
Console.WriteLine($"Updated Entity Position: {transforms[i].position}");
|
||||
}
|
||||
}
|
||||
|
||||
query.ForEach<Transform>((e, ref t) =>
|
||||
{
|
||||
Console.WriteLine($"Entity {e} Updated Position: {t.position}");
|
||||
});
|
||||
}
|
||||
|
||||
public void Cleanup()
|
||||
@@ -40,12 +45,12 @@ public partial class ArcEntityTest : ITest
|
||||
}
|
||||
}
|
||||
|
||||
public struct TransformData : IComponent
|
||||
public struct Transform : IComponent
|
||||
{
|
||||
public float3 position;
|
||||
}
|
||||
|
||||
public struct MeshData : IComponent
|
||||
public struct Mesh : IComponent
|
||||
{
|
||||
public int index;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Ghost.Entities.Test;
|
||||
using Ghost.Test.Core;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
|
||||
TestRunner.Run<ArcEntityTest>();
|
||||
AllocationManager.EnableDebugLayer();
|
||||
TestRunner.Run<ArcEntityTest>();
|
||||
AllocationManager.Dispose();
|
||||
@@ -16,21 +16,21 @@ internal unsafe struct Chunk : IDisposable
|
||||
|
||||
public int Count
|
||||
{
|
||||
get => _count;
|
||||
readonly get => _count;
|
||||
set => _count = value;
|
||||
}
|
||||
|
||||
public int Capacity => _capacity;
|
||||
public readonly int Capacity => _capacity;
|
||||
|
||||
public Chunk(int size, int capacity)
|
||||
{
|
||||
_data = new UnsafeArray<byte>(size, Allocator.Persistent);
|
||||
_data = new UnsafeArray<byte>(size, Allocator.Persistent, AllocationOption.Clear);
|
||||
_capacity = capacity;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte* GetUnsafePtr()
|
||||
public readonly byte* GetUnsafePtr()
|
||||
{
|
||||
return (byte*)_data.GetUnsafePtr();
|
||||
}
|
||||
@@ -68,15 +68,16 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
private UnsafeList<Edge> _edgesAdd;
|
||||
private UnsafeList<Edge> _edgesRemove;
|
||||
|
||||
private int _hash;
|
||||
private readonly int _hash;
|
||||
private int _entityCapacity;
|
||||
private int _maxComponentID;
|
||||
private int _entityIdsOffset;
|
||||
|
||||
public Identifier<Archetype> ID => _id;
|
||||
public readonly Identifier<Archetype> ID => _id;
|
||||
|
||||
public int EntityCapacity => _entityCapacity;
|
||||
public int ChunkCount => _chunks.Count;
|
||||
public readonly int EntityCapacity => _entityCapacity;
|
||||
public readonly int ChunkCount => _chunks.Count;
|
||||
public readonly int EntityIDsOffset => _entityIdsOffset;
|
||||
|
||||
public Archetype(Identifier<Archetype> id, Identifier<World> worldID, ReadOnlySpan<Identifier<IComponent>> componentIds)
|
||||
{
|
||||
@@ -204,7 +205,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
{
|
||||
for (var i = 0; i < _chunks.Count; i++)
|
||||
{
|
||||
var chunk = _chunks[i];
|
||||
ref var chunk = ref _chunks[i];
|
||||
if (chunk.Count < _entityCapacity)
|
||||
{
|
||||
rowIndex = chunk.Count;
|
||||
@@ -226,7 +227,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetEntity(int chunkIndex, int rowIndex, Entity entity)
|
||||
public readonly void SetEntity(int chunkIndex, int rowIndex, Entity entity)
|
||||
{
|
||||
var chunk = _chunks[chunkIndex];
|
||||
var chunkBase = chunk.GetUnsafePtr();
|
||||
@@ -236,7 +237,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetComponentData(int chunkIndex, int rowIndex, Identifier<IComponent> componentID, void* pComponent)
|
||||
public readonly void SetComponentData(int chunkIndex, int rowIndex, Identifier<IComponent> componentID, void* pComponent)
|
||||
{
|
||||
var offset = _componentIDToOffset[componentID];
|
||||
var chunk = _chunks[chunkIndex];
|
||||
@@ -249,7 +250,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void* GetComponentDataPtr(int chunkIndex, int rowIndex, Identifier<IComponent> componentID)
|
||||
public readonly void* GetComponentDataPtr(int chunkIndex, int rowIndex, Identifier<IComponent> componentID)
|
||||
{
|
||||
var offset = _componentIDToOffset[componentID];
|
||||
var chunk = _chunks[chunkIndex];
|
||||
@@ -268,7 +269,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetOffset(int componentId)
|
||||
public readonly int GetOffset(int componentId)
|
||||
{
|
||||
if (componentId >= _componentIDToOffset.Count)
|
||||
{
|
||||
@@ -326,7 +327,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool HasComponent(Identifier<IComponent> componentID)
|
||||
public readonly bool HasComponent(Identifier<IComponent> componentID)
|
||||
{
|
||||
return _signature.IsSet(componentID);
|
||||
}
|
||||
@@ -342,7 +343,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Identifier<Archetype> GetEdgeAdd(Identifier<IComponent> componentID)
|
||||
public readonly Identifier<Archetype> GetEdgeAdd(Identifier<IComponent> componentID)
|
||||
{
|
||||
for (var i = 0; i < _edgesAdd.Count; i++)
|
||||
{
|
||||
@@ -367,7 +368,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Identifier<Archetype> GetEdgeRemove(Identifier<IComponent> componentID)
|
||||
public readonly Identifier<Archetype> GetEdgeRemove(Identifier<IComponent> componentID)
|
||||
{
|
||||
for (var i = 0; i < _edgesRemove.Count; i++)
|
||||
{
|
||||
@@ -382,7 +383,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<T> GetComponentArray<T>(int chunkIndex)
|
||||
public readonly Span<T> GetComponentArray<T>(int chunkIndex)
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
var id = ComponentTypeID<T>.value;
|
||||
@@ -401,7 +402,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
||||
return new Span<T>((T*)((byte*)chunk.GetUnsafePtr() + offset), chunk.Count);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
public override readonly int GetHashCode()
|
||||
{
|
||||
return _hash;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public struct ComponentInfo
|
||||
public Identifier<IComponent> id;
|
||||
}
|
||||
|
||||
public static unsafe class ComponentTypeID<T>
|
||||
public static class ComponentTypeID<T>
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
public static readonly Identifier<IComponent> value = ComponentRegister.GetOrRegisterComponent<T>();
|
||||
|
||||
@@ -15,13 +15,19 @@ public unsafe class EntityManager : IDisposable
|
||||
public int rowIndex;
|
||||
}
|
||||
|
||||
private World _world;
|
||||
private readonly World _world;
|
||||
private UnsafeSlotMap<EntityLocation> _entityLocations;
|
||||
private bool _disposed;
|
||||
|
||||
internal EntityManager(World world, int initialCapacity)
|
||||
{
|
||||
_world = world;
|
||||
_entityLocations = new UnsafeSlotMap<EntityLocation>(initialCapacity, Allocator.Persistent);
|
||||
_entityLocations = new UnsafeSlotMap<EntityLocation>(initialCapacity, Allocator.Persistent, AllocationOption.Clear);
|
||||
}
|
||||
|
||||
~EntityManager()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
internal ResultStatus UpdateEntityLocation(Entity entity, Identifier<Archetype> newArchetypeID, int newChunkIndex, int newRowIndex)
|
||||
@@ -115,8 +121,8 @@ public unsafe class EntityManager : IDisposable
|
||||
var layout = oldArch._layouts[i];
|
||||
|
||||
var src = oldArch._chunks[oldChunk].GetUnsafePtr() + layout.offset + (layout.size * oldRow);
|
||||
var newOffset = newArch.GetOffset(layout.componentID); // O(1) Lookup
|
||||
var dst = oldArch._chunks[oldChunk].GetUnsafePtr() + newOffset + (layout.size * newRow);
|
||||
var newOffset = newArch.GetOffset(layout.componentID); // O(1) Looku
|
||||
var dst = newArch._chunks[newChunk].GetUnsafePtr() + newOffset + (layout.size * newRow);
|
||||
|
||||
MemoryUtility.MemCpy(src, dst, (nuint)layout.size);
|
||||
}
|
||||
@@ -217,10 +223,10 @@ public unsafe class EntityManager : IDisposable
|
||||
return ResultStatus.Success;
|
||||
}
|
||||
|
||||
public ResultStatus AddComponent<T>(Entity entity, ref T component)
|
||||
public ResultStatus AddComponent<T>(Entity entity, T component)
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
return AddComponent(entity, ComponentTypeID<T>.value, UnsafeUtility.AddressOf(ref component));
|
||||
return AddComponent(entity, ComponentTypeID<T>.value, &component);
|
||||
}
|
||||
|
||||
public ResultStatus SetComponentData(Entity entity, Identifier<IComponent> componentID, void* pComponent)
|
||||
@@ -236,10 +242,10 @@ public unsafe class EntityManager : IDisposable
|
||||
return ResultStatus.Success;
|
||||
}
|
||||
|
||||
public ResultStatus SetComponentData<T>(Entity entity, ref T component)
|
||||
public ResultStatus SetComponentData<T>(Entity entity, T component)
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
return SetComponentData(entity, ComponentTypeID<T>.value, UnsafeUtility.AddressOf(ref component));
|
||||
return SetComponentData(entity, ComponentTypeID<T>.value, &component);
|
||||
}
|
||||
|
||||
public bool HasComponent(Entity entity, Identifier<IComponent> componentID)
|
||||
@@ -261,6 +267,14 @@ public unsafe class EntityManager : IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_entityLocations.Dispose();
|
||||
_disposed = true;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ public unsafe class EntityQueryy<T1, T2>
|
||||
struct ArchetypeCache
|
||||
{
|
||||
public Archetype Archetype;
|
||||
public int Offset1; // Offset for T1
|
||||
public int Offset1; // Offset for T0
|
||||
public int Offset2; // Offset for T2
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,53 @@
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Templates\ForEach.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Templates\EntityQuery.ForEach.gen.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>EntityQuery.ForEach.tt</DependentUpon>
|
||||
</None>
|
||||
<None Include="Templates\ForEach.gen.cs">
|
||||
<DependentUpon>ForEach.tt</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ghost.Core\Ghost.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Templates\EntityQuery.ForEach.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>EntityQuery.ForEach.gen.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Update="Templates\ForEach.tt">
|
||||
<LastGenOutput>ForEach.gen.cs</LastGenOutput>
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Templates\EntityQuery.ForEach.gen.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>EntityQuery.ForEach.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Templates\ForEach.gen.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>ForEach.tt</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Ghost.Core;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ghost.Entities;
|
||||
|
||||
@@ -10,30 +11,15 @@ public struct EntityQueryMask : IDisposable
|
||||
public UnsafeBitSet any;
|
||||
public UnsafeBitSet absent;
|
||||
|
||||
public bool Matches(UnsafeBitSet archetypeSignature)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly bool Matches(UnsafeBitSet archetypeSignature)
|
||||
{
|
||||
// 1. Check All: Archetype must have ALL bits set
|
||||
if (all.IsCreated && !archetypeSignature.All(all))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Check None: Archetype must have NONE of these bits set
|
||||
if (absent.IsCreated && archetypeSignature.Any(absent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. Check Any: Archetype must have AT LEAST ONE of these bits (if Any is defined)
|
||||
if (any.IsCreated && any.Count != 0 && !archetypeSignature.Any(any))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return (!all.IsCreated || all.All(archetypeSignature))
|
||||
&& (!absent.IsCreated || absent.None(archetypeSignature))
|
||||
&& (!any.IsCreated || any.Count == 0 || any.Any(archetypeSignature));
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
public readonly override int GetHashCode()
|
||||
{
|
||||
var hash = 17;
|
||||
if (all.IsCreated) hash = hash * 23 + all.GetHashCode();
|
||||
@@ -51,90 +37,114 @@ public struct EntityQueryMask : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe struct EntityQuery : IIdentifierType, IDisposable
|
||||
public unsafe partial struct EntityQuery : IIdentifierType, IDisposable
|
||||
{
|
||||
public readonly ref struct QueryItem
|
||||
public readonly ref struct ChunkIterator
|
||||
{
|
||||
private readonly ref Archetype _archetype;
|
||||
private readonly ref Chunk _chunk;
|
||||
|
||||
public readonly int Count => _chunk.Count;
|
||||
|
||||
internal QueryItem(ref Archetype archetype, int chunkIndex)
|
||||
public readonly ref struct ChunkView
|
||||
{
|
||||
_archetype = ref archetype;
|
||||
_chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
}
|
||||
private readonly ref Archetype _archetype;
|
||||
private readonly ref Chunk _chunk;
|
||||
|
||||
public readonly Span<T> GetComponentData<T>()
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
var offset = _archetype.GetOffset(ComponentTypeID<T>.value);
|
||||
if (offset < 0)
|
||||
public readonly int Count => _chunk.Count;
|
||||
|
||||
internal ChunkView(ref Archetype archetype, int chunkIndex)
|
||||
{
|
||||
throw new InvalidOperationException($"Archetype does not contain component of type {typeof(T)}");
|
||||
_archetype = ref archetype;
|
||||
_chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
}
|
||||
|
||||
var ptr = (byte*)_chunk.GetUnsafePtr() + offset;
|
||||
return new Span<T>(ptr, _chunk.Count);
|
||||
public readonly ReadOnlySpan<Entity> GetEntities()
|
||||
{
|
||||
var ptr = _chunk.GetUnsafePtr();
|
||||
var pEntity = (Entity*)(ptr + _archetype.EntityIDsOffset);
|
||||
return new ReadOnlySpan<Entity>(pEntity, _chunk.Count);
|
||||
}
|
||||
|
||||
public readonly Span<T> GetComponentData<T>()
|
||||
where T : unmanaged, IComponent
|
||||
{
|
||||
var offset = _archetype.GetOffset(ComponentTypeID<T>.value);
|
||||
if (offset < 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Archetype does not contain component of type {typeof(T)}");
|
||||
}
|
||||
|
||||
var ptr = (byte*)_chunk.GetUnsafePtr() + offset;
|
||||
return new Span<T>(ptr, _chunk.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ref struct ChunkEnumerator
|
||||
{
|
||||
private ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
|
||||
private World _world;
|
||||
private int _archetypeIndex;
|
||||
private int _chunkIndex;
|
||||
public ref struct Enumerator
|
||||
{
|
||||
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
|
||||
private readonly World _world;
|
||||
private int _archetypeIndex;
|
||||
private int _chunkIndex;
|
||||
|
||||
internal ChunkEnumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, World world)
|
||||
internal Enumerator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, World world)
|
||||
{
|
||||
_matchingArchetypes = matchingArchetypes;
|
||||
_world = world;
|
||||
_archetypeIndex = 0;
|
||||
_chunkIndex = -1;
|
||||
}
|
||||
|
||||
public readonly ChunkView Current
|
||||
{
|
||||
get
|
||||
{
|
||||
ref var archetype = ref _world.GetArchetypeReference(_matchingArchetypes[_archetypeIndex]);
|
||||
return new ChunkView(ref archetype, _chunkIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
_chunkIndex++;
|
||||
|
||||
while (_archetypeIndex < _matchingArchetypes.Count)
|
||||
{
|
||||
ref var archetype = ref _world.GetArchetypeReference(_matchingArchetypes[_archetypeIndex]);
|
||||
if (_chunkIndex < archetype.ChunkCount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_chunkIndex = 0;
|
||||
_archetypeIndex++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_archetypeIndex = 0;
|
||||
_chunkIndex = -1;
|
||||
}
|
||||
|
||||
public readonly void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
|
||||
private readonly World _world;
|
||||
|
||||
internal ChunkIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, World world)
|
||||
{
|
||||
_matchingArchetypes = matchingArchetypes;
|
||||
_world = world;
|
||||
_archetypeIndex = 0;
|
||||
_chunkIndex = -1;
|
||||
}
|
||||
|
||||
public QueryItem Current
|
||||
{
|
||||
get
|
||||
{
|
||||
ref var archetype = ref _world.GetArchetypeReference(_matchingArchetypes[_archetypeIndex]);
|
||||
return new QueryItem(ref archetype, _chunkIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
_chunkIndex++;
|
||||
|
||||
while (_archetypeIndex < _matchingArchetypes.Count)
|
||||
{
|
||||
ref var archetype = ref _world.GetArchetypeReference(_matchingArchetypes[_archetypeIndex]);
|
||||
if (_chunkIndex < archetype.ChunkCount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_chunkIndex = 0;
|
||||
_archetypeIndex++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_archetypeIndex = 0;
|
||||
_chunkIndex = -1;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public readonly Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(_matchingArchetypes, _world);
|
||||
}
|
||||
}
|
||||
|
||||
private Identifier<World> _worldID;
|
||||
private readonly Identifier<World> _worldID;
|
||||
private EntityQueryMask _mask;
|
||||
private UnsafeList<Identifier<Archetype>> _matchingArchetypes;
|
||||
|
||||
@@ -145,7 +155,6 @@ public unsafe struct EntityQuery : IIdentifierType, IDisposable
|
||||
_matchingArchetypes = new UnsafeList<Identifier<Archetype>>(8, Allocator.Persistent);
|
||||
}
|
||||
|
||||
// Called by World when a new archetype is created
|
||||
internal void AddArchetypeIfMatch(Archetype archetype)
|
||||
{
|
||||
if (_mask.Matches(archetype._signature))
|
||||
@@ -154,10 +163,10 @@ public unsafe struct EntityQuery : IIdentifierType, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkEnumerator GetEnumerator()
|
||||
public readonly ChunkIterator GetChunkIterator()
|
||||
{
|
||||
var world = World.GetWorld(_worldID).Value;
|
||||
return new ChunkEnumerator(_matchingArchetypes.AsReadOnly(), world);
|
||||
return new ChunkIterator(_matchingArchetypes.AsReadOnly(), world);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -169,7 +178,7 @@ public unsafe struct EntityQuery : IIdentifierType, IDisposable
|
||||
|
||||
public ref struct QueryBuilder
|
||||
{
|
||||
private Stack.Scope _scope;
|
||||
private readonly Stack.Scope _scope;
|
||||
|
||||
private UnsafeList<Identifier<IComponent>> _all;
|
||||
private UnsafeList<Identifier<IComponent>> _any;
|
||||
@@ -244,7 +253,7 @@ public ref struct QueryBuilder
|
||||
return queryID;
|
||||
}
|
||||
|
||||
private void FindMax(UnsafeList<Identifier<IComponent>> list, ref int max)
|
||||
private static void FindMax(UnsafeList<Identifier<IComponent>> list, ref int max)
|
||||
{
|
||||
foreach (var id in list)
|
||||
{
|
||||
|
||||
881
Ghost.Entities/Templates/EntityQuery.ForEach.gen.cs
Normal file
881
Ghost.Entities/Templates/EntityQuery.ForEach.gen.cs
Normal file
@@ -0,0 +1,881 @@
|
||||
|
||||
using Ghost.Core;
|
||||
|
||||
namespace Ghost.Entities;
|
||||
|
||||
public unsafe partial struct EntityQuery
|
||||
{
|
||||
public readonly void ForEach<T0>(ForEach<T0> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value };
|
||||
var offsets = stackalloc int[1];
|
||||
var basePtrs = stackalloc byte*[1];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 1; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 1; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
|
||||
action(ref *pComp0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1>(ForEach<T0, T1> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value };
|
||||
var offsets = stackalloc int[2];
|
||||
var basePtrs = stackalloc byte*[2];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 2; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 2; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2>(ForEach<T0, T1, T2> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value };
|
||||
var offsets = stackalloc int[3];
|
||||
var basePtrs = stackalloc byte*[3];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 3; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 3; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3>(ForEach<T0, T1, T2, T3> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
where T3 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value };
|
||||
var offsets = stackalloc int[4];
|
||||
var basePtrs = stackalloc byte*[4];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 4; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 4; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4>(ForEach<T0, T1, T2, T3, T4> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
where T3 : unmanaged, IComponent
|
||||
where T4 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value };
|
||||
var offsets = stackalloc int[5];
|
||||
var basePtrs = stackalloc byte*[5];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 5; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 5; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4, T5>(ForEach<T0, T1, T2, T3, T4, T5> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
where T3 : unmanaged, IComponent
|
||||
where T4 : unmanaged, IComponent
|
||||
where T5 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value };
|
||||
var offsets = stackalloc int[6];
|
||||
var basePtrs = stackalloc byte*[6];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 6; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 6; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4, T5, T6>(ForEach<T0, T1, T2, T3, T4, T5, T6> action)
|
||||
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
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value, ComponentTypeID<T6>.value };
|
||||
var offsets = stackalloc int[7];
|
||||
var basePtrs = stackalloc byte*[7];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 7; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 7; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(ForEach<T0, T1, T2, T3, T4, T5, T6, T7> action)
|
||||
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
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value, ComponentTypeID<T6>.value, ComponentTypeID<T7>.value };
|
||||
var offsets = stackalloc int[8];
|
||||
var basePtrs = stackalloc byte*[8];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 8; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 8; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
var pComp7 = (T7*)(basePtrs[7] + (sizeof(T7) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6,ref *pComp7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public readonly void ForEach<T0>(ForEachWithEntity<T0> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value };
|
||||
var offsets = stackalloc int[1];
|
||||
var basePtrs = stackalloc byte*[1];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 1; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 1; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1>(ForEachWithEntity<T0, T1> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value };
|
||||
var offsets = stackalloc int[2];
|
||||
var basePtrs = stackalloc byte*[2];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 2; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 2; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2>(ForEachWithEntity<T0, T1, T2> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value };
|
||||
var offsets = stackalloc int[3];
|
||||
var basePtrs = stackalloc byte*[3];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 3; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 3; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3>(ForEachWithEntity<T0, T1, T2, T3> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
where T3 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value };
|
||||
var offsets = stackalloc int[4];
|
||||
var basePtrs = stackalloc byte*[4];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 4; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 4; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4>(ForEachWithEntity<T0, T1, T2, T3, T4> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
where T3 : unmanaged, IComponent
|
||||
where T4 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value };
|
||||
var offsets = stackalloc int[5];
|
||||
var basePtrs = stackalloc byte*[5];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 5; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 5; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4, T5>(ForEachWithEntity<T0, T1, T2, T3, T4, T5> action)
|
||||
where T0 : unmanaged, IComponent
|
||||
where T1 : unmanaged, IComponent
|
||||
where T2 : unmanaged, IComponent
|
||||
where T3 : unmanaged, IComponent
|
||||
where T4 : unmanaged, IComponent
|
||||
where T5 : unmanaged, IComponent
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value };
|
||||
var offsets = stackalloc int[6];
|
||||
var basePtrs = stackalloc byte*[6];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 6; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 6; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4, T5, T6>(ForEachWithEntity<T0, T1, T2, T3, T4, T5, T6> action)
|
||||
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
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value, ComponentTypeID<T6>.value };
|
||||
var offsets = stackalloc int[7];
|
||||
var basePtrs = stackalloc byte*[7];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 7; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 7; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(ForEachWithEntity<T0, T1, T2, T3, T4, T5, T6, T7> action)
|
||||
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
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value, ComponentTypeID<T6>.value, ComponentTypeID<T7>.value };
|
||||
var offsets = stackalloc int[8];
|
||||
var basePtrs = stackalloc byte*[8];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < 8; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < 8; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
var pComp7 = (T7*)(basePtrs[7] + (sizeof(T7) * entityIndex));
|
||||
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6,ref *pComp7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
127
Ghost.Entities/Templates/EntityQuery.ForEach.tt
Normal file
127
Ghost.Entities/Templates/EntityQuery.ForEach.tt
Normal file
@@ -0,0 +1,127 @@
|
||||
<#@ 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;
|
||||
|
||||
namespace Ghost.Entities;
|
||||
|
||||
public unsafe partial struct EntityQuery
|
||||
{
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var compGenerics = AppendGenericRefParameters(i);
|
||||
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2);
|
||||
#>
|
||||
public readonly void ForEach<<#= generics #>>(ForEach<<#= generics #>> action)
|
||||
<#= restrictions #>
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { <#= AppendGenerics(i, "ComponentTypeID<T{0}>.value") #> };
|
||||
var offsets = stackalloc int[<#= i #>];
|
||||
var basePtrs = stackalloc byte*[<#= i #>];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
|
||||
var pComp<#= localIndex #> = (T<#= localIndex #>*)(basePtrs[<#= localIndex #>] + (sizeof(T<#= localIndex #>) * entityIndex));
|
||||
<# } #>
|
||||
|
||||
action(<#= AppendRefParameters(i, "*pComp{0}") #>);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var compGenerics = AppendGenericRefParameters(i);
|
||||
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2);
|
||||
#>
|
||||
public readonly void ForEach<<#= generics #>>(ForEachWithEntity<<#= generics #>> action)
|
||||
<#= restrictions #>
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { <#= AppendGenerics(i, "ComponentTypeID<T{0}>.value") #> };
|
||||
var offsets = stackalloc int[<#= i #>];
|
||||
var basePtrs = stackalloc byte*[<#= i #>];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
|
||||
var pComp<#= localIndex #> = (T<#= localIndex #>*)(basePtrs[<#= localIndex #>] + (sizeof(T<#= localIndex #>) * entityIndex));
|
||||
<# } #>
|
||||
|
||||
action(*pEntity, <#= AppendRefParameters(i, "*pComp{0}") #>);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
}
|
||||
21
Ghost.Entities/Templates/ForEach.gen.cs
Normal file
21
Ghost.Entities/Templates/ForEach.gen.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
|
||||
namespace Ghost.Entities;
|
||||
|
||||
public delegate void ForEach<T0>(ref T0 t0Component);
|
||||
public delegate void ForEach<T0, T1>(ref T0 t0Component,ref T1 t1Component);
|
||||
public delegate void ForEach<T0, T1, T2>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component);
|
||||
public delegate void ForEach<T0, T1, T2, T3>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component);
|
||||
public delegate void ForEach<T0, T1, T2, T3, T4>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component);
|
||||
public delegate void ForEach<T0, T1, T2, T3, T4, T5>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component);
|
||||
public delegate void ForEach<T0, T1, T2, T3, T4, T5, T6>(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<T0, T1, T2, T3, T4, T5, T6, T7>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component);
|
||||
|
||||
public delegate void ForEachWithEntity<T0>(Entity entity, ref T0 t0Component);
|
||||
public delegate void ForEachWithEntity<T0, T1>(Entity entity, ref T0 t0Component,ref T1 t1Component);
|
||||
public delegate void ForEachWithEntity<T0, T1, T2>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component);
|
||||
public delegate void ForEachWithEntity<T0, T1, T2, T3>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component);
|
||||
public delegate void ForEachWithEntity<T0, T1, T2, T3, T4>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component);
|
||||
public delegate void ForEachWithEntity<T0, T1, T2, T3, T4, T5>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component);
|
||||
public delegate void ForEachWithEntity<T0, T1, T2, T3, T4, T5, T6>(Entity entity, ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component);
|
||||
public delegate void ForEachWithEntity<T0, T1, T2, T3, T4, T5, T6, T7>(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);
|
||||
24
Ghost.Entities/Templates/ForEach.tt
Normal file
24
Ghost.Entities/Templates/ForEach.tt
Normal file
@@ -0,0 +1,24 @@
|
||||
<#@ template language="C#" #>
|
||||
<#@ output extension="gen.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 #>);
|
||||
<# } #>
|
||||
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var compGenerics = AppendGenericRefParameters(i);
|
||||
#>
|
||||
public delegate void ForEachWithEntity<<#= generics #>>(Entity entity, <#= compGenerics #>);
|
||||
<# } #>
|
||||
149
Ghost.Entities/Templates/Helpers.ttinclude
Normal file
149
Ghost.Entities/Templates/Helpers.ttinclude
Normal file
@@ -0,0 +1,149 @@
|
||||
<#@ 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, string template)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (var localIndex = 0; localIndex < amount; localIndex++)
|
||||
{
|
||||
sb.Append($"ref {string.Format(template, 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 AppendGenericRestrictionsMultiline(int amount, string Ttemplate, string template, int indentation)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var spaces = new string(' ', indentation * 4);
|
||||
|
||||
for (var localIndex = 0; localIndex < amount; localIndex++)
|
||||
{
|
||||
sb.Append($"{spaces}where {Ttemplate}{localIndex} : {template}");
|
||||
if (localIndex < amount - 1)
|
||||
{
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
public StringBuilder AppendGenericRestrictionsMultiline(int amount, string template, int indentation)
|
||||
{
|
||||
return AppendGenericRestrictionsMultiline(amount, "T", template, indentation);
|
||||
}
|
||||
|
||||
public StringBuilder TryGetComponentPools(int amount)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (var localIndex = 0; localIndex < amount; localIndex++)
|
||||
{
|
||||
sb.Append($"_componentStorage.TryGetPool<T{localIndex}>(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;
|
||||
}
|
||||
#>
|
||||
@@ -196,6 +196,16 @@ public partial class World : IIdentifierType, IDisposable, IEquatable<World>
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var archetype in _archetypes)
|
||||
{
|
||||
archetype.Dispose();
|
||||
}
|
||||
|
||||
foreach (var query in _entityQueries)
|
||||
{
|
||||
query.Dispose();
|
||||
}
|
||||
|
||||
_entityManager.Dispose();
|
||||
_entityCommandBuffer.Dispose();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#+
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
for (var i = 0; i < amount; i++)
|
||||
{
|
||||
if (i > 0) sb.Append(", ");
|
||||
sb.Append($"{template}{i}");
|
||||
sb.Append(string.Format(template, i));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
string AppendGenerics(int amount)
|
||||
{
|
||||
return AppendGenerics(amount, "T");
|
||||
return AppendGenerics(amount, "T{0}");
|
||||
}
|
||||
|
||||
public StringBuilder AppendGenericRefParameters(int amount)
|
||||
|
||||
Reference in New Issue
Block a user