Files
GhostEngine/Ghost.Entities/Templates/EntityQuery.ComponentIterator.gen.cs

1772 lines
66 KiB
C#

using Ghost.Core;
using Misaki.HighPerformance.LowLevel;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using System.Runtime.CompilerServices;
namespace Ghost.Entities;
public unsafe partial struct EntityQuery
{
public readonly ref struct ComponentIterator<T0>
where T0 : unmanaged, IComponent
{
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[1];
private fixed int _offsets[1];
private fixed long _compBasePtrs[1];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(1, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 1; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public ref T0 Current => 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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0> GetComponentIterator<T0>()
where T0 : unmanaged, IComponent
{
return new ComponentIterator<T0>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1>
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
public ref struct QueryItem
{
public ref T0 component0;
public ref T1 component1;
internal QueryItem(ref T0 component0, ref T1 component1)
{
this.component0 = ref component0;
this.component1 = ref component1;
}
public void Deconstruct(out Ref<T0> component0, out Ref<T1> component1)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[2];
private fixed int _offsets[2];
private fixed long _compBasePtrs[2];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(2, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 2; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1> GetComponentIterator<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
return new ComponentIterator<T0, T1>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1, T2>
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
public ref struct QueryItem
{
public ref T0 component0;
public ref T1 component1;
public ref T2 component2;
internal QueryItem(ref T0 component0, ref T1 component1, ref T2 component2)
{
this.component0 = ref component0;
this.component1 = ref component1;
this.component2 = ref component2;
}
public void Deconstruct(out Ref<T0> component0, out Ref<T1> component1, out Ref<T2> component2)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
component2 = new Ref<T2>(ref this.component2);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[3];
private fixed int _offsets[3];
private fixed long _compBasePtrs[3];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(3, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 3; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1, T2> GetComponentIterator<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
{
return new ComponentIterator<T0, T1, T2>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1, T2, T3>
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
where T3 : unmanaged, IComponent
{
public ref struct QueryItem
{
public ref T0 component0;
public ref T1 component1;
public ref T2 component2;
public ref T3 component3;
internal QueryItem(ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3)
{
this.component0 = ref component0;
this.component1 = ref component1;
this.component2 = ref component2;
this.component3 = ref component3;
}
public void Deconstruct(out Ref<T0> component0, out Ref<T1> component1, out Ref<T2> component2, out Ref<T3> component3)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
component2 = new Ref<T2>(ref this.component2);
component3 = new Ref<T3>(ref this.component3);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[4];
private fixed int _offsets[4];
private fixed long _compBasePtrs[4];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(4, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 4; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1, T2, T3> GetComponentIterator<T0, T1, T2, T3>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
where T3 : unmanaged, IComponent
{
return new ComponentIterator<T0, T1, T2, T3>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1, T2, T3, T4>
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 ref T0 component0;
public ref T1 component1;
public ref T2 component2;
public ref T3 component3;
public ref T4 component4;
internal QueryItem(ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4)
{
this.component0 = ref component0;
this.component1 = ref component1;
this.component2 = ref component2;
this.component3 = ref component3;
this.component4 = ref component4;
}
public void Deconstruct(out Ref<T0> component0, out Ref<T1> component1, out Ref<T2> component2, out Ref<T3> component3, out Ref<T4> component4)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
component2 = new Ref<T2>(ref this.component2);
component3 = new Ref<T3>(ref this.component3);
component4 = new Ref<T4>(ref this.component4);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[5];
private fixed int _offsets[5];
private fixed long _compBasePtrs[5];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(5, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 5; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1, T2, T3, T4> GetComponentIterator<T0, T1, T2, T3, T4>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
where T3 : unmanaged, IComponent
where T4 : unmanaged, IComponent
{
return new ComponentIterator<T0, T1, T2, T3, T4>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1, T2, T3, T4, T5>
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 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(ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4, ref T5 component5)
{
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 Ref<T0> component0, out Ref<T1> component1, out Ref<T2> component2, out Ref<T3> component3, out Ref<T4> component4, out Ref<T5> component5)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
component2 = new Ref<T2>(ref this.component2);
component3 = new Ref<T3>(ref this.component3);
component4 = new Ref<T4>(ref this.component4);
component5 = new Ref<T5>(ref this.component5);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[6];
private fixed int _offsets[6];
private fixed long _compBasePtrs[6];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(6, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 6; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1, T2, T3, T4, T5> GetComponentIterator<T0, T1, T2, T3, T4, T5>()
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 ComponentIterator<T0, T1, T2, T3, T4, T5>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1, T2, T3, T4, T5, T6>
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 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(ref T0 component0, ref T1 component1, ref T2 component2, ref T3 component3, ref T4 component4, ref T5 component5, ref T6 component6)
{
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 Ref<T0> component0, out Ref<T1> component1, out Ref<T2> component2, out Ref<T3> component3, out Ref<T4> component4, out Ref<T5> component5, out Ref<T6> component6)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
component2 = new Ref<T2>(ref this.component2);
component3 = new Ref<T3>(ref this.component3);
component4 = new Ref<T4>(ref this.component4);
component5 = new Ref<T5>(ref this.component5);
component6 = new Ref<T6>(ref this.component6);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[7];
private fixed int _offsets[7];
private fixed long _compBasePtrs[7];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_compTypeIDs[6] = ComponentTypeID<T6>.value;
_offsets[6] = 0;
_compBasePtrs[6] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(7, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 7; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1, T2, T3, T4, T5, T6> GetComponentIterator<T0, T1, T2, T3, T4, T5, T6>()
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 ComponentIterator<T0, T1, T2, T3, T4, T5, T6>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
public readonly ref struct ComponentIterator<T0, T1, T2, T3, T4, T5, T6, T7>
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 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(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.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 Ref<T0> component0, out Ref<T1> component1, out Ref<T2> component2, out Ref<T3> component3, out Ref<T4> component4, out Ref<T5> component5, out Ref<T6> component6, out Ref<T7> component7)
{
component0 = new Ref<T0>(ref this.component0);
component1 = new Ref<T1>(ref this.component1);
component2 = new Ref<T2>(ref this.component2);
component3 = new Ref<T3>(ref this.component3);
component4 = new Ref<T4>(ref this.component4);
component5 = new Ref<T5>(ref this.component5);
component6 = new Ref<T6>(ref this.component6);
component7 = new Ref<T7>(ref this.component7);
}
}
public ref struct Enumerator : IDisposable
{
private fixed int _compTypeIDs[8];
private fixed int _offsets[8];
private fixed long _compBasePtrs[8];
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
private readonly Stack.Scope _scope;
private UnsafeList<int> _changedComponentIDs;
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<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_compTypeIDs[0] = ComponentTypeID<T0>.value;
_offsets[0] = 0;
_compBasePtrs[0] = 0;
_compTypeIDs[1] = ComponentTypeID<T1>.value;
_offsets[1] = 0;
_compBasePtrs[1] = 0;
_compTypeIDs[2] = ComponentTypeID<T2>.value;
_offsets[2] = 0;
_compBasePtrs[2] = 0;
_compTypeIDs[3] = ComponentTypeID<T3>.value;
_offsets[3] = 0;
_compBasePtrs[3] = 0;
_compTypeIDs[4] = ComponentTypeID<T4>.value;
_offsets[4] = 0;
_compBasePtrs[4] = 0;
_compTypeIDs[5] = ComponentTypeID<T5>.value;
_offsets[5] = 0;
_compBasePtrs[5] = 0;
_compTypeIDs[6] = ComponentTypeID<T6>.value;
_offsets[6] = 0;
_compBasePtrs[6] = 0;
_compTypeIDs[7] = ComponentTypeID<T7>.value;
_offsets[7] = 0;
_compBasePtrs[7] = 0;
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
_scope = AllocationManager.CreateStackScope();
_changedComponentIDs = new UnsafeList<int>(8, _scope.AllocationHandle);
var it = _mask.writeAccess.GetIterator();
while (it.Next(out var id))
{
for (var i = 0; i < 8; i++)
{
if (id == _compTypeIDs[i])
{
_changedComponentIDs.Add(id);
break;
}
}
}
Reset();
}
public QueryItem Current => new(
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();
_offsets[index] = layout.offset;
_compBasePtrs[index] = (long)(_chunkBasePtr + _offsets[index]);
}
for (var i = 0; i < _changedComponentIDs.Count; i++)
{
_currentArchetype.MarkChanged(_currentChunkIndex, _changedComponentIDs[i], _world.Version);
}
}
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<Archetype>();
_currentChunk = ref Unsafe.NullRef<Chunk>();
_currentArchetypeIndex = 0;
_currentChunkIndex = 0;
_currentEntityIndex = -1;
if (_matchingArchetypes.Count > 0)
{
_currentArchetype = ref _world.GetArchetypeReference(_matchingArchetypes[0]);
if (_currentArchetype.ChunkCount > 0)
{
SetChunk(0);
}
}
}
public readonly void Dispose()
{
_scope.Dispose();
}
}
private readonly ReadOnlyUnsafeCollection<Identifier<Archetype>> _matchingArchetypes;
private readonly EntityQueryMask _mask;
private readonly World _world;
internal ComponentIterator(ReadOnlyUnsafeCollection<Identifier<Archetype>> matchingArchetypes, EntityQueryMask mask, World world)
{
_matchingArchetypes = matchingArchetypes;
_mask = mask;
_world = world;
}
public Enumerator GetEnumerator()
{
return new Enumerator(_matchingArchetypes, _mask, _world);
}
}
public readonly ComponentIterator<T0, T1, T2, T3, T4, T5, T6, T7> GetComponentIterator<T0, T1, T2, T3, T4, T5, T6, T7>()
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 ComponentIterator<T0, T1, T2, T3, T4, T5, T6, T7>(_matchingArchetypes.AsReadOnly(), _mask, World.GetWorld(_worldID).GetValueOrThrow());
}
}