Per-component versioning and change tracking for ECS
Introduce per-component versioning in chunks and world for efficient change detection. - Add version arrays to chunks and global version to world. - Update queries and ForEach to mark written components as changed. - Extend QueryBuilder with WithAllRW/WithPresentRW for write access. - Expose change tracking API in ChunkView. - Improve thread safety and debug code. - Update tests and examples to demonstrate new features.
This commit is contained in:
@@ -39,7 +39,7 @@ public partial class EntityTest : ITest
|
|||||||
var entity2 = _world.EntityManager.CreateEntity(ComponentTypeID<Transform>.value);
|
var entity2 = _world.EntityManager.CreateEntity(ComponentTypeID<Transform>.value);
|
||||||
_world.EntityManager.SetComponent(entity2, new Transform { position = new float3(1, 2, 3) });
|
_world.EntityManager.SetComponent(entity2, new Transform { position = new float3(1, 2, 3) });
|
||||||
|
|
||||||
var queryID = new QueryBuilder().WithAll<Transform>().Build(_world);
|
var queryID = new QueryBuilder().WithAllRW<Transform>().WithAbsent<Mesh>().Build(_world);
|
||||||
ref var query = ref _world.GetEntityQueryReference(queryID);
|
ref var query = ref _world.GetEntityQueryReference(queryID);
|
||||||
|
|
||||||
// var testJob = new TestEntityQueryJob();
|
// var testJob = new TestEntityQueryJob();
|
||||||
@@ -49,28 +49,32 @@ public partial class EntityTest : ITest
|
|||||||
_world.EntityManager.AddScriptComponent<TestScriptComponent>(entity1);
|
_world.EntityManager.AddScriptComponent<TestScriptComponent>(entity1);
|
||||||
_world.EntityManager.RemoveComponent<ManagedEntityRef>(entity1); // This should destory the managed entity and call OnDestroy
|
_world.EntityManager.RemoveComponent<ManagedEntityRef>(entity1); // This should destory the managed entity and call OnDestroy
|
||||||
|
|
||||||
|
_world.AdvanceVersion();
|
||||||
|
|
||||||
query.ForEach<Transform>((e, ref t) =>
|
query.ForEach<Transform>((e, ref t) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Entity {e} Has Position: {t.position}");
|
Console.WriteLine($"Entity {e} Has Position: {t.position}");
|
||||||
});
|
});
|
||||||
|
|
||||||
// foreach (var (entity, transform) in query.GetEntityComponentIterator<Transform>())
|
//foreach (var (entity, transform) in query.GetEntityComponentIterator<Transform>())
|
||||||
// {
|
//{
|
||||||
// Console.WriteLine($"Entity {entity} Updated Position: {transform.Get().position}");
|
// Console.WriteLine($"Entity {entity} Updated Position: {transform.Get().position}");
|
||||||
// }
|
//}
|
||||||
//
|
|
||||||
// foreach (var chunk in query.GetChunkIterator())
|
foreach (var chunk in query.GetChunkIterator())
|
||||||
// {
|
{
|
||||||
// var transforms = chunk.GetComponentData<Transform>();
|
var transforms = chunk.GetComponentData<Transform>();
|
||||||
// var entities = chunk.GetEntities();
|
var entities = chunk.GetEntities();
|
||||||
// var bits = chunk.GetEnableBits<Transform>();
|
var bits = chunk.GetEnableBits<Transform>();
|
||||||
//
|
|
||||||
// var it = bits.GetIterator();
|
var changed = chunk.HasChanged<Transform>(0);
|
||||||
// while (it.Next(out var index) && index < chunk.Count)
|
|
||||||
// {
|
var it = bits.GetIterator();
|
||||||
// Console.WriteLine($"Entity {entities[index]} Updated Position: {transforms[index].position}");
|
while (it.Next(out var index) && index < chunk.Count)
|
||||||
// }
|
{
|
||||||
// }
|
Console.WriteLine($"Entity {entities[index]} Updated Position: {transforms[index].position}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_world.EntityManager.DestroyEntity(entity1);
|
_world.EntityManager.DestroyEntity(entity1);
|
||||||
_world.EntityManager.DestroyEntity(entity2);
|
_world.EntityManager.DestroyEntity(entity2);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ internal unsafe sealed class ChunkDebugView
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if !(DEBUG || GHOST_EDITOR)
|
||||||
#else
|
#else
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
#endif
|
#endif
|
||||||
@@ -56,9 +56,7 @@ internal unsafe sealed class ChunkDebugView
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS0162 // Unreachable code detected
|
|
||||||
var views = new List<object>();
|
var views = new List<object>();
|
||||||
#pragma warning restore CS0162 // Unreachable code detected
|
|
||||||
ref var archetype = ref World.GetWorld(worldID).GetValueOrThrow()
|
ref var archetype = ref World.GetWorld(worldID).GetValueOrThrow()
|
||||||
.GetArchetypeReference(archetypeID);
|
.GetArchetypeReference(archetypeID);
|
||||||
|
|
||||||
@@ -108,8 +106,8 @@ internal unsafe struct Chunk : IDisposable
|
|||||||
public const int BIT_ALIGNMENT_MINUS_ONE = BIT_ALIGNMENT - 1;
|
public const int BIT_ALIGNMENT_MINUS_ONE = BIT_ALIGNMENT - 1;
|
||||||
|
|
||||||
private UnsafeArray<byte> _data;
|
private UnsafeArray<byte> _data;
|
||||||
|
private UnsafeArray<int> _versions;
|
||||||
|
|
||||||
internal int _version;
|
|
||||||
internal int _count;
|
internal int _count;
|
||||||
internal readonly int _capacity;
|
internal readonly int _capacity;
|
||||||
|
|
||||||
@@ -119,11 +117,26 @@ internal unsafe struct Chunk : IDisposable
|
|||||||
internal int _archetypeID;
|
internal int _archetypeID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public Chunk(int bufferSize, int capacity)
|
public Chunk(int bufferSize, int capacity, int componentCount, int globalVersion)
|
||||||
{
|
{
|
||||||
_data = new UnsafeArray<byte>(bufferSize, Allocator.Persistent, AllocationOption.Clear);
|
_data = new UnsafeArray<byte>(bufferSize, Allocator.Persistent, AllocationOption.Clear);
|
||||||
|
_versions = new UnsafeArray<int>(componentCount, Allocator.Persistent);
|
||||||
_capacity = capacity;
|
_capacity = capacity;
|
||||||
_count = 0;
|
_count = 0;
|
||||||
|
|
||||||
|
_versions.AsSpan().Fill(globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void MarkChanged(int componentTypeId, int globalVersion)
|
||||||
|
{
|
||||||
|
_versions[componentTypeId] = globalVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public readonly int GetVersion(int componentTypeId)
|
||||||
|
{
|
||||||
|
return _versions[componentTypeId];
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -132,9 +145,16 @@ internal unsafe struct Chunk : IDisposable
|
|||||||
return (byte*)_data.GetUnsafePtr();
|
return (byte*)_data.GetUnsafePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public readonly int* GetVersionUnsafePtr()
|
||||||
|
{
|
||||||
|
return (int*)_versions.GetUnsafePtr();
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_data.Dispose();
|
_data.Dispose();
|
||||||
|
_versions.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,8 +344,10 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
|
||||||
// Need to allocate a new chunk
|
// Need to allocate a new chunk
|
||||||
var newChunk = new Chunk(Chunk.CHUNK_BUFFER_SIZE, _entityCapacity);
|
var newChunk = new Chunk(Chunk.CHUNK_BUFFER_SIZE, _entityCapacity, _layouts.Count, world.Version);
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if DEBUG || GHOST_EDITOR
|
||||||
newChunk._worldID = _worldID;
|
newChunk._worldID = _worldID;
|
||||||
newChunk._archetypeID = _id;
|
newChunk._archetypeID = _id;
|
||||||
@@ -370,7 +392,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
var offset = r.Value.offset;
|
var offset = r.Value.offset;
|
||||||
var chunk = _chunks[chunkIndex];
|
ref var chunk = ref _chunks[chunkIndex];
|
||||||
|
|
||||||
var chunkBase = chunk.GetUnsafePtr();
|
var chunkBase = chunk.GetUnsafePtr();
|
||||||
var size = ComponentRegister.GetComponentInfo(componentID).size;
|
var size = ComponentRegister.GetComponentInfo(componentID).size;
|
||||||
@@ -378,6 +400,9 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
|||||||
|
|
||||||
MemoryUtility.MemCpy(dst, pComponent, (nuint)size);
|
MemoryUtility.MemCpy(dst, pComponent, (nuint)size);
|
||||||
|
|
||||||
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
chunk.MarkChanged(componentID, world.Version);
|
||||||
|
|
||||||
return ErrorStatus.None;
|
return ErrorStatus.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,13 +463,8 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable
|
|||||||
var pLastEntity = chunkBase + _entityIdsOffset + (sizeof(Entity) * lastIndex);
|
var pLastEntity = chunkBase + _entityIdsOffset + (sizeof(Entity) * lastIndex);
|
||||||
var pRowEntity = chunkBase + _entityIdsOffset + (sizeof(Entity) * rowIndex);
|
var pRowEntity = chunkBase + _entityIdsOffset + (sizeof(Entity) * rowIndex);
|
||||||
|
|
||||||
var wroldResult = World.GetWorld(_worldID);
|
var wrold = World.GetWorldUncheck(_worldID);
|
||||||
if (wroldResult.Error != ErrorStatus.None)
|
var result = wrold.EntityManager.UpdateEntityLocation(*(Entity*)pLastEntity, _id, chunkIndex, rowIndex);
|
||||||
{
|
|
||||||
return wroldResult.Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = wroldResult.Value.EntityManager.UpdateEntityLocation(*(Entity*)pLastEntity, _id, chunkIndex, rowIndex);
|
|
||||||
if (result != ErrorStatus.None)
|
if (result != ErrorStatus.None)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ public struct ComponentInfo
|
|||||||
public Identifier<IComponent> id;
|
public Identifier<IComponent> id;
|
||||||
public int size;
|
public int size;
|
||||||
public int alignment;
|
public int alignment;
|
||||||
|
public int lastWriteVersion;
|
||||||
public bool isEnableable;
|
public bool isEnableable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +79,7 @@ internal static class ComponentRegister
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Identifier<IComponent> GetComponentID(Type type)
|
public static Identifier<IComponent> GetComponentID(Type type)
|
||||||
{
|
{
|
||||||
var typeHandle = type.TypeHandle.Value;
|
var typeHandle = type.TypeHandle.Value;
|
||||||
@@ -91,9 +94,24 @@ internal static class ComponentRegister
|
|||||||
throw new KeyNotFoundException($"Component type {type} is not registered.");
|
throw new KeyNotFoundException($"Component type {type} is not registered.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ComponentInfo GetComponentInfo(Identifier<IComponent> typeId)
|
public static ComponentInfo GetComponentInfo(Identifier<IComponent> typeId)
|
||||||
{
|
{
|
||||||
return s_registeredComponents[typeId];
|
lock (s_registeredComponents)
|
||||||
|
{
|
||||||
|
return s_registeredComponents[typeId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SetComponentLastWrite(Identifier<IComponent> typeId, int version)
|
||||||
|
{
|
||||||
|
lock (s_registeredComponents)
|
||||||
|
{
|
||||||
|
var info = s_registeredComponents[typeId];
|
||||||
|
info.lastWriteVersion = version;
|
||||||
|
s_registeredComponents[typeId] = info;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetHashCode(params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
|
public static int GetHashCode(params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
public struct EntityQueryMask : IDisposable, IEquatable<EntityQueryMask>
|
internal struct EntityQueryMask : IDisposable, IEquatable<EntityQueryMask>
|
||||||
{
|
{
|
||||||
public UnsafeBitSet structuralAll;
|
public UnsafeBitSet structuralAll;
|
||||||
public UnsafeBitSet structuralAny;
|
public UnsafeBitSet structuralAny;
|
||||||
@@ -15,6 +15,8 @@ public struct EntityQueryMask : IDisposable, IEquatable<EntityQueryMask>
|
|||||||
public UnsafeBitSet requireDisabled;
|
public UnsafeBitSet requireDisabled;
|
||||||
public UnsafeBitSet rejectIfEnabled;
|
public UnsafeBitSet rejectIfEnabled;
|
||||||
|
|
||||||
|
public UnsafeBitSet writeAccess;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly bool Matches(ref readonly UnsafeBitSet archetypeSignature)
|
public readonly bool Matches(ref readonly UnsafeBitSet archetypeSignature)
|
||||||
{
|
{
|
||||||
@@ -33,6 +35,7 @@ public struct EntityQueryMask : IDisposable, IEquatable<EntityQueryMask>
|
|||||||
if (requireEnabled.IsCreated) hash = hash * 23 + requireEnabled.GetHashCode();
|
if (requireEnabled.IsCreated) hash = hash * 23 + requireEnabled.GetHashCode();
|
||||||
if (requireDisabled.IsCreated) hash = hash * 23 + requireDisabled.GetHashCode();
|
if (requireDisabled.IsCreated) hash = hash * 23 + requireDisabled.GetHashCode();
|
||||||
if (rejectIfEnabled.IsCreated) hash = hash * 23 + rejectIfEnabled.GetHashCode();
|
if (rejectIfEnabled.IsCreated) hash = hash * 23 + rejectIfEnabled.GetHashCode();
|
||||||
|
if (writeAccess.IsCreated) hash = hash * 23 + writeAccess.GetHashCode();
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
@@ -44,7 +47,8 @@ public struct EntityQueryMask : IDisposable, IEquatable<EntityQueryMask>
|
|||||||
&& structuralAbsent.Equals(other.structuralAbsent)
|
&& structuralAbsent.Equals(other.structuralAbsent)
|
||||||
&& requireEnabled.Equals(other.requireEnabled)
|
&& requireEnabled.Equals(other.requireEnabled)
|
||||||
&& requireDisabled.Equals(other.requireDisabled)
|
&& requireDisabled.Equals(other.requireDisabled)
|
||||||
&& rejectIfEnabled.Equals(other.rejectIfEnabled);
|
&& rejectIfEnabled.Equals(other.rejectIfEnabled)
|
||||||
|
&& writeAccess.Equals(other.writeAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override readonly bool Equals(object? obj)
|
public override readonly bool Equals(object? obj)
|
||||||
@@ -71,6 +75,8 @@ public struct EntityQueryMask : IDisposable, IEquatable<EntityQueryMask>
|
|||||||
requireEnabled.Dispose();
|
requireEnabled.Dispose();
|
||||||
requireDisabled.Dispose();
|
requireDisabled.Dispose();
|
||||||
rejectIfEnabled.Dispose();
|
rejectIfEnabled.Dispose();
|
||||||
|
|
||||||
|
writeAccess.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,21 +88,11 @@ public readonly unsafe ref struct ChunkView
|
|||||||
{
|
{
|
||||||
private readonly ReadOnlyUnsafeCollection<Archetype.ComponentMemoryLayout> _layouts;
|
private readonly ReadOnlyUnsafeCollection<Archetype.ComponentMemoryLayout> _layouts;
|
||||||
private readonly byte* _pChunkData;
|
private readonly byte* _pChunkData;
|
||||||
|
private readonly int* _pVersion;
|
||||||
private readonly int _entityOffset;
|
private readonly int _entityOffset;
|
||||||
private readonly int _entityCount;
|
private readonly int _entityCount;
|
||||||
private readonly int _version;
|
|
||||||
|
|
||||||
public readonly int Count => _entityCount;
|
public readonly int Count => _entityCount;
|
||||||
public readonly int Version => _version;
|
|
||||||
|
|
||||||
internal ChunkView(ReadOnlyUnsafeCollection<Archetype.ComponentMemoryLayout> layouts, byte* pChunkData, int entityOffset, int entityCount, int version)
|
|
||||||
{
|
|
||||||
_layouts = layouts;
|
|
||||||
_pChunkData = pChunkData;
|
|
||||||
_entityOffset = entityOffset;
|
|
||||||
_entityCount = entityCount;
|
|
||||||
_version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ChunkView(ref readonly Archetype archetype, ref readonly Chunk chunk)
|
internal ChunkView(ref readonly Archetype archetype, ref readonly Chunk chunk)
|
||||||
{
|
{
|
||||||
@@ -104,19 +100,63 @@ public readonly unsafe ref struct ChunkView
|
|||||||
_pChunkData = chunk.GetUnsafePtr();
|
_pChunkData = chunk.GetUnsafePtr();
|
||||||
_entityOffset = archetype.EntityIDsOffset;
|
_entityOffset = archetype.EntityIDsOffset;
|
||||||
_entityCount = chunk._count;
|
_entityCount = chunk._count;
|
||||||
_version = chunk._version;
|
_pVersion = chunk.GetVersionUnsafePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We do not have a proper versioning system yet.
|
/// <summary>
|
||||||
public bool HasChanged(int version)
|
/// Determines whether the specified component has changed since the given version.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier of the component to check for changes.</param>
|
||||||
|
/// <param name="version">The version number to compare against the component's current version. Must be greater than or equal to zero.</param>
|
||||||
|
/// <returns>true if the component's current version is less than or equal to the specified version; otherwise, false.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool HasChanged(Identifier<IComponent> id, int version)
|
||||||
{
|
{
|
||||||
return _version != version;
|
return version < _pVersion[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified version indicates that the component of type <typeparamref name="T"/> has
|
||||||
|
/// changed since the last recorded version.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of component to check for changes. Must be an unmanaged type that implements <see cref="IComponent"/>.</typeparam>
|
||||||
|
/// <param name="version">The version number to compare against the current version of the component.</param>
|
||||||
|
/// <returns>true if the component of type T has changed since the specified version; otherwise, false.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public readonly bool HasChanged<T>(int version)
|
||||||
|
where T : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
return version < _pVersion[ComponentTypeID<T>.value];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current version number associated with the specified component identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier of the component for which to retrieve the version number. Must reference a valid component.</param>
|
||||||
|
/// <returns>The version number of the specified component.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public readonly int GetComponentVersion(Identifier<IComponent> id)
|
||||||
|
{
|
||||||
|
return _pVersion[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current version number associated with the specified component type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The component type for which to retrieve the version. Must be an unmanaged type that implements <see cref="IComponent"/>.</typeparam>
|
||||||
|
/// <returns>The version number of the component type <typeparamref name="T"/>.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public readonly int GetComponentVersion<T>()
|
||||||
|
where T : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
return _pVersion[ComponentTypeID<T>.value];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a read-only span containing structuralAll entities stored in the current chunk.
|
/// Returns a read-only span containing structuralAll entities stored in the current chunk.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A read-only span of <see cref="Entity"/> values representing the entities in the chunk.</returns>
|
/// <returns>A read-only span of <see cref="Entity"/> values representing the entities in the chunk.</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ReadOnlySpan<Entity> GetEntities()
|
public ReadOnlySpan<Entity> GetEntities()
|
||||||
{
|
{
|
||||||
var pEntity = (Entity*)(_pChunkData + _entityOffset);
|
var pEntity = (Entity*)(_pChunkData + _entityOffset);
|
||||||
@@ -129,6 +169,7 @@ public readonly unsafe ref struct ChunkView
|
|||||||
/// <typeparam name="T">The type of component to access. Must be an unmanaged type that implements <see cref="Component"/>.</typeparam>
|
/// <typeparam name="T">The type of component to access. Must be an unmanaged type that implements <see cref="Component"/>.</typeparam>
|
||||||
/// <returns>A span of type <see cref="{T}"/> containing the component data for each entity in the chunk.</returns>
|
/// <returns>A span of type <see cref="{T}"/> containing the component data for each entity in the chunk.</returns>
|
||||||
/// <exception cref="InvalidOperationException">Thrown if the specified component type is not present in the archetype.</exception>
|
/// <exception cref="InvalidOperationException">Thrown if the specified component type is not present in the archetype.</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public Span<T> GetComponentData<T>()
|
public Span<T> GetComponentData<T>()
|
||||||
where T : unmanaged, IComponent
|
where T : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
@@ -144,6 +185,7 @@ public readonly unsafe ref struct ChunkView
|
|||||||
/// <typeparam name="T">The component type for which to retrieve enablement bits. Must be unmanaged and implement <see cref="IEnableableComponent"/>.</typeparam>
|
/// <typeparam name="T">The component type for which to retrieve enablement bits. Must be unmanaged and implement <see cref="IEnableableComponent"/>.</typeparam>
|
||||||
/// <returns>A <see cref="SpanBitSet"/> that provides access to the enablement bits for all instances of the specified component type in the chunk.</returns>
|
/// <returns>A <see cref="SpanBitSet"/> that provides access to the enablement bits for all instances of the specified component type in the chunk.</returns>
|
||||||
/// <exception cref="InvalidOperationException">Thrown if the specified component type does not support enablement.</exception>
|
/// <exception cref="InvalidOperationException">Thrown if the specified component type does not support enablement.</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public SpanBitSet GetEnableBits<T>()
|
public SpanBitSet GetEnableBits<T>()
|
||||||
where T : unmanaged, IEnableableComponent
|
where T : unmanaged, IEnableableComponent
|
||||||
{
|
{
|
||||||
@@ -164,6 +206,7 @@ public readonly unsafe ref struct ChunkView
|
|||||||
/// <param name="index">The zero-based index of the component instance to check within the chunk.</param>
|
/// <param name="index">The zero-based index of the component instance to check within the chunk.</param>
|
||||||
/// <returns>true if the component at the specified index is enabled; otherwise, false.</returns>
|
/// <returns>true if the component at the specified index is enabled; otherwise, false.</returns>
|
||||||
/// <exception cref="InvalidOperationException">Thrown if the specified component type <typeparamref name="T"/> does not support enable/disable functionality.</exception>
|
/// <exception cref="InvalidOperationException">Thrown if the specified component type <typeparamref name="T"/> does not support enable/disable functionality.</exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool IsComponentEnabled<T>(int index)
|
public bool IsComponentEnabled<T>(int index)
|
||||||
where T : unmanaged, IEnableableComponent
|
where T : unmanaged, IEnableableComponent
|
||||||
{
|
{
|
||||||
@@ -373,6 +416,8 @@ public ref partial struct QueryBuilder
|
|||||||
private UnsafeList<Identifier<IComponent>> _disabled;
|
private UnsafeList<Identifier<IComponent>> _disabled;
|
||||||
private UnsafeList<Identifier<IComponent>> _present;
|
private UnsafeList<Identifier<IComponent>> _present;
|
||||||
|
|
||||||
|
private UnsafeList<Identifier<IComponent>> _rw;
|
||||||
|
|
||||||
public QueryBuilder()
|
public QueryBuilder()
|
||||||
{
|
{
|
||||||
_scope = AllocationManager.CreateStackScope();
|
_scope = AllocationManager.CreateStackScope();
|
||||||
@@ -383,6 +428,8 @@ public ref partial struct QueryBuilder
|
|||||||
_none = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
_none = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
||||||
_disabled = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
_disabled = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
||||||
_present = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
_present = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
||||||
|
|
||||||
|
_rw = new UnsafeList<Identifier<IComponent>>(4, _scope.AllocationHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -394,7 +441,7 @@ public ref partial struct QueryBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier<EntityQuery> Build(World world)
|
public Identifier<EntityQuery> Build(World world, Allocator allocator = Allocator.Persistent)
|
||||||
{
|
{
|
||||||
// 1. Calculate max component ID to size the BitSets
|
// 1. Calculate max component ID to size the BitSets
|
||||||
var maxID = 0;
|
var maxID = 0;
|
||||||
@@ -408,12 +455,14 @@ public ref partial struct QueryBuilder
|
|||||||
// 2. Create the Mask
|
// 2. Create the Mask
|
||||||
var mask = new EntityQueryMask
|
var mask = new EntityQueryMask
|
||||||
{
|
{
|
||||||
structuralAll = new UnsafeBitSet(maxID + 1, Allocator.Persistent, AllocationOption.Clear),
|
structuralAll = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
structuralAny = new UnsafeBitSet(maxID + 1, Allocator.Persistent, AllocationOption.Clear),
|
structuralAny = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
structuralAbsent = new UnsafeBitSet(maxID + 1, Allocator.Persistent, AllocationOption.Clear),
|
structuralAbsent = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
requireEnabled = new UnsafeBitSet(maxID + 1, Allocator.Persistent, AllocationOption.Clear),
|
requireEnabled = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
requireDisabled = new UnsafeBitSet(maxID + 1, Allocator.Persistent, AllocationOption.Clear),
|
requireDisabled = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
rejectIfEnabled = new UnsafeBitSet(maxID + 1, Allocator.Persistent, AllocationOption.Clear),
|
rejectIfEnabled = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
|
|
||||||
|
writeAccess = new UnsafeBitSet(maxID + 1, allocator, AllocationOption.Clear),
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3. Fill BitSets
|
// 3. Fill BitSets
|
||||||
@@ -456,6 +505,11 @@ public ref partial struct QueryBuilder
|
|||||||
mask.structuralAny.SetBit(id);
|
mask.structuralAny.SetBit(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var id in _rw)
|
||||||
|
{
|
||||||
|
mask.writeAccess.SetBit(id);
|
||||||
|
}
|
||||||
|
|
||||||
// 4. Ask World for the Query (Cached)
|
// 4. Ask World for the Query (Cached)
|
||||||
var maskHash = mask.GetHashCode();
|
var maskHash = mask.GetHashCode();
|
||||||
var queryID = world.GetEntityQueryIDByMaskHash(maskHash);
|
var queryID = world.GetEntityQueryIDByMaskHash(maskHash);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
@@ -7,12 +8,37 @@ public unsafe partial struct EntityQuery
|
|||||||
public readonly void ForEach<T0>(ForEach<T0> action)
|
public readonly void ForEach<T0>(ForEach<T0> action)
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[1];
|
||||||
var offsets = stackalloc int[1];
|
var offsets = stackalloc int[1];
|
||||||
var basePtrs = stackalloc byte*[1];
|
var basePtrs = stackalloc byte*[1];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 1; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -39,6 +65,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 1; index++)
|
for (var index = 0; index < 1; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -63,12 +94,39 @@ public unsafe partial struct EntityQuery
|
|||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[2];
|
||||||
var offsets = stackalloc int[2];
|
var offsets = stackalloc int[2];
|
||||||
var basePtrs = stackalloc byte*[2];
|
var basePtrs = stackalloc byte*[2];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 2; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -95,6 +153,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 2; index++)
|
for (var index = 0; index < 2; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -121,12 +184,41 @@ public unsafe partial struct EntityQuery
|
|||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[3];
|
||||||
var offsets = stackalloc int[3];
|
var offsets = stackalloc int[3];
|
||||||
var basePtrs = stackalloc byte*[3];
|
var basePtrs = stackalloc byte*[3];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -153,6 +245,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 3; index++)
|
for (var index = 0; index < 3; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -181,12 +278,43 @@ public unsafe partial struct EntityQuery
|
|||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
where T3 : unmanaged, IComponent
|
where T3 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[4];
|
||||||
var offsets = stackalloc int[4];
|
var offsets = stackalloc int[4];
|
||||||
var basePtrs = stackalloc byte*[4];
|
var basePtrs = stackalloc byte*[4];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -213,6 +341,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 4; index++)
|
for (var index = 0; index < 4; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -243,12 +376,45 @@ public unsafe partial struct EntityQuery
|
|||||||
where T3 : unmanaged, IComponent
|
where T3 : unmanaged, IComponent
|
||||||
where T4 : unmanaged, IComponent
|
where T4 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[5];
|
||||||
var offsets = stackalloc int[5];
|
var offsets = stackalloc int[5];
|
||||||
var basePtrs = stackalloc byte*[5];
|
var basePtrs = stackalloc byte*[5];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -275,6 +441,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 5; index++)
|
for (var index = 0; index < 5; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -307,12 +478,47 @@ public unsafe partial struct EntityQuery
|
|||||||
where T4 : unmanaged, IComponent
|
where T4 : unmanaged, IComponent
|
||||||
where T5 : unmanaged, IComponent
|
where T5 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
var comp5TypeID = ComponentTypeID<T5>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
comp5TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[6];
|
||||||
var offsets = stackalloc int[6];
|
var offsets = stackalloc int[6];
|
||||||
var basePtrs = stackalloc byte*[6];
|
var basePtrs = stackalloc byte*[6];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -339,6 +545,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 6; index++)
|
for (var index = 0; index < 6; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -373,12 +584,49 @@ public unsafe partial struct EntityQuery
|
|||||||
where T5 : unmanaged, IComponent
|
where T5 : unmanaged, IComponent
|
||||||
where T6 : unmanaged, IComponent
|
where T6 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
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 comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
var comp5TypeID = ComponentTypeID<T5>.value;
|
||||||
|
var comp6TypeID = ComponentTypeID<T6>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
comp5TypeID.value,
|
||||||
|
comp6TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[7];
|
||||||
var offsets = stackalloc int[7];
|
var offsets = stackalloc int[7];
|
||||||
var basePtrs = stackalloc byte*[7];
|
var basePtrs = stackalloc byte*[7];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 7; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -405,6 +653,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 7; index++)
|
for (var index = 0; index < 7; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -441,12 +694,51 @@ public unsafe partial struct EntityQuery
|
|||||||
where T6 : unmanaged, IComponent
|
where T6 : unmanaged, IComponent
|
||||||
where T7 : unmanaged, IComponent
|
where T7 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
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 comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
var comp5TypeID = ComponentTypeID<T5>.value;
|
||||||
|
var comp6TypeID = ComponentTypeID<T6>.value;
|
||||||
|
var comp7TypeID = ComponentTypeID<T7>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
comp5TypeID.value,
|
||||||
|
comp6TypeID.value,
|
||||||
|
comp7TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[8];
|
||||||
var offsets = stackalloc int[8];
|
var offsets = stackalloc int[8];
|
||||||
var basePtrs = stackalloc byte*[8];
|
var basePtrs = stackalloc byte*[8];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -473,6 +765,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 8; index++)
|
for (var index = 0; index < 8; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -503,12 +800,37 @@ public unsafe partial struct EntityQuery
|
|||||||
public readonly void ForEach<T0>(ForEachWithEntity<T0> action)
|
public readonly void ForEach<T0>(ForEachWithEntity<T0> action)
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[1];
|
||||||
var offsets = stackalloc int[1];
|
var offsets = stackalloc int[1];
|
||||||
var basePtrs = stackalloc byte*[1];
|
var basePtrs = stackalloc byte*[1];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 1; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -535,6 +857,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 1; index++)
|
for (var index = 0; index < 1; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -560,12 +887,39 @@ public unsafe partial struct EntityQuery
|
|||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[2];
|
||||||
var offsets = stackalloc int[2];
|
var offsets = stackalloc int[2];
|
||||||
var basePtrs = stackalloc byte*[2];
|
var basePtrs = stackalloc byte*[2];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 2; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -592,6 +946,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 2; index++)
|
for (var index = 0; index < 2; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -619,12 +978,41 @@ public unsafe partial struct EntityQuery
|
|||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[3];
|
||||||
var offsets = stackalloc int[3];
|
var offsets = stackalloc int[3];
|
||||||
var basePtrs = stackalloc byte*[3];
|
var basePtrs = stackalloc byte*[3];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -651,6 +1039,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 3; index++)
|
for (var index = 0; index < 3; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -680,12 +1073,43 @@ public unsafe partial struct EntityQuery
|
|||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
where T3 : unmanaged, IComponent
|
where T3 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[4];
|
||||||
var offsets = stackalloc int[4];
|
var offsets = stackalloc int[4];
|
||||||
var basePtrs = stackalloc byte*[4];
|
var basePtrs = stackalloc byte*[4];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -712,6 +1136,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 4; index++)
|
for (var index = 0; index < 4; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -743,12 +1172,45 @@ public unsafe partial struct EntityQuery
|
|||||||
where T3 : unmanaged, IComponent
|
where T3 : unmanaged, IComponent
|
||||||
where T4 : unmanaged, IComponent
|
where T4 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[5];
|
||||||
var offsets = stackalloc int[5];
|
var offsets = stackalloc int[5];
|
||||||
var basePtrs = stackalloc byte*[5];
|
var basePtrs = stackalloc byte*[5];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 5; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -775,6 +1237,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 5; index++)
|
for (var index = 0; index < 5; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -808,12 +1275,47 @@ public unsafe partial struct EntityQuery
|
|||||||
where T4 : unmanaged, IComponent
|
where T4 : unmanaged, IComponent
|
||||||
where T5 : unmanaged, IComponent
|
where T5 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { ComponentTypeID<T0>.value, ComponentTypeID<T1>.value, ComponentTypeID<T2>.value, ComponentTypeID<T3>.value, ComponentTypeID<T4>.value, ComponentTypeID<T5>.value };
|
var comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
var comp5TypeID = ComponentTypeID<T5>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
comp5TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[6];
|
||||||
var offsets = stackalloc int[6];
|
var offsets = stackalloc int[6];
|
||||||
var basePtrs = stackalloc byte*[6];
|
var basePtrs = stackalloc byte*[6];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -840,6 +1342,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 6; index++)
|
for (var index = 0; index < 6; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -875,12 +1382,49 @@ public unsafe partial struct EntityQuery
|
|||||||
where T5 : unmanaged, IComponent
|
where T5 : unmanaged, IComponent
|
||||||
where T6 : unmanaged, IComponent
|
where T6 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
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 comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
var comp5TypeID = ComponentTypeID<T5>.value;
|
||||||
|
var comp6TypeID = ComponentTypeID<T6>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
comp5TypeID.value,
|
||||||
|
comp6TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[7];
|
||||||
var offsets = stackalloc int[7];
|
var offsets = stackalloc int[7];
|
||||||
var basePtrs = stackalloc byte*[7];
|
var basePtrs = stackalloc byte*[7];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 7; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -907,6 +1451,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 7; index++)
|
for (var index = 0; index < 7; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
@@ -944,12 +1493,51 @@ public unsafe partial struct EntityQuery
|
|||||||
where T6 : unmanaged, IComponent
|
where T6 : unmanaged, IComponent
|
||||||
where T7 : unmanaged, IComponent
|
where T7 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
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 comp0TypeID = ComponentTypeID<T0>.value;
|
||||||
|
var comp1TypeID = ComponentTypeID<T1>.value;
|
||||||
|
var comp2TypeID = ComponentTypeID<T2>.value;
|
||||||
|
var comp3TypeID = ComponentTypeID<T3>.value;
|
||||||
|
var comp4TypeID = ComponentTypeID<T4>.value;
|
||||||
|
var comp5TypeID = ComponentTypeID<T5>.value;
|
||||||
|
var comp6TypeID = ComponentTypeID<T6>.value;
|
||||||
|
var comp7TypeID = ComponentTypeID<T7>.value;
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
comp0TypeID.value,
|
||||||
|
comp1TypeID.value,
|
||||||
|
comp2TypeID.value,
|
||||||
|
comp3TypeID.value,
|
||||||
|
comp4TypeID.value,
|
||||||
|
comp5TypeID.value,
|
||||||
|
comp6TypeID.value,
|
||||||
|
comp7TypeID.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[8];
|
||||||
var offsets = stackalloc int[8];
|
var offsets = stackalloc int[8];
|
||||||
var basePtrs = stackalloc byte*[8];
|
var basePtrs = stackalloc byte*[8];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -976,6 +1564,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < 8; index++)
|
for (var index = 0; index < 8; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
|
|||||||
@@ -24,12 +24,41 @@ public unsafe partial struct EntityQuery
|
|||||||
public readonly void ForEach<<#= generics #>>(<#= delegateTupe #><<#= generics #>> action)
|
public readonly void ForEach<<#= generics #>>(<#= delegateTupe #><<#= generics #>> action)
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
var world = World.GetWorld(_worldID).GetValueOrThrow();
|
var world = World.GetWorldUncheck(_worldID);
|
||||||
|
var globalVersion = world.Version;
|
||||||
|
|
||||||
var compTypeIDs = stackalloc int[] { <#= AppendGenerics(i, "ComponentTypeID<T{0}>.value") #> };
|
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
|
||||||
|
var comp<#= localIndex #>TypeID = ComponentTypeID<T<#= localIndex #>>.value;
|
||||||
|
<# } #>
|
||||||
|
|
||||||
|
var compTypeIDs = stackalloc int[]
|
||||||
|
{
|
||||||
|
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
|
||||||
|
comp<#= localIndex #>TypeID.value,
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
|
||||||
|
var changedCompIDs = stackalloc int[<#= i #>];
|
||||||
var offsets = stackalloc int[<#= i #>];
|
var offsets = stackalloc int[<#= i #>];
|
||||||
var basePtrs = stackalloc byte*[<#= i #>];
|
var basePtrs = stackalloc byte*[<#= i #>];
|
||||||
|
|
||||||
|
var changedCompCount = 0;
|
||||||
|
|
||||||
|
var it = _mask.writeAccess.GetIterator();
|
||||||
|
while (it.Next(out var id))
|
||||||
|
{
|
||||||
|
for (var i =0; i < <#= i #>; i++)
|
||||||
|
{
|
||||||
|
if (id == compTypeIDs[i])
|
||||||
|
{
|
||||||
|
ComponentRegister.SetComponentLastWrite(id, globalVersion);
|
||||||
|
changedCompIDs[changedCompCount] = id;
|
||||||
|
changedCompCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||||
@@ -56,6 +85,11 @@ public unsafe partial struct EntityQuery
|
|||||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||||
var pChunkData = chunk.GetUnsafePtr();
|
var pChunkData = chunk.GetUnsafePtr();
|
||||||
|
|
||||||
|
for (var j = 0; j < changedCompCount; j++)
|
||||||
|
{
|
||||||
|
chunk.MarkChanged(changedCompIDs[i], globalVersion);
|
||||||
|
}
|
||||||
|
|
||||||
for (var index = 0; index < <#= i #>; index++)
|
for (var index = 0; index < <#= i #>; index++)
|
||||||
{
|
{
|
||||||
basePtrs[index] = pChunkData + offsets[index];
|
basePtrs[index] = pChunkData + offsets[index];
|
||||||
|
|||||||
@@ -18,6 +18,20 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'All' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithAllRW<T0>()
|
||||||
|
where T0 : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
_all.Add(ComponentTypeID<T0>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T0>.value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
||||||
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
@@ -83,6 +97,20 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'Present' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithPresentRW<T0>()
|
||||||
|
where T0 : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
_present.Add(ComponentTypeID<T0>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T0>.value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified component type(s) to the 'All' filter of the query.
|
/// Adds the specified component type(s) to the 'All' filter of the query.
|
||||||
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
@@ -98,6 +126,23 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'All' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithAllRW<T0, T1>()
|
||||||
|
where T0 : unmanaged, IComponent
|
||||||
|
where T1 : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
_all.Add(ComponentTypeID<T0>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T0>.value);
|
||||||
|
_all.Add(ComponentTypeID<T1>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T1>.value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
||||||
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
@@ -173,6 +218,23 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'Present' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithPresentRW<T0, T1>()
|
||||||
|
where T0 : unmanaged, IComponent
|
||||||
|
where T1 : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
_present.Add(ComponentTypeID<T0>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T0>.value);
|
||||||
|
_present.Add(ComponentTypeID<T1>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T1>.value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified component type(s) to the 'All' filter of the query.
|
/// Adds the specified component type(s) to the 'All' filter of the query.
|
||||||
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
@@ -190,6 +252,26 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'All' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithAllRW<T0, T1, T2>()
|
||||||
|
where T0 : unmanaged, IComponent
|
||||||
|
where T1 : unmanaged, IComponent
|
||||||
|
where T2 : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
_all.Add(ComponentTypeID<T0>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T0>.value);
|
||||||
|
_all.Add(ComponentTypeID<T1>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T1>.value);
|
||||||
|
_all.Add(ComponentTypeID<T2>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T2>.value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
||||||
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
@@ -275,4 +357,24 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'Present' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithPresentRW<T0, T1, T2>()
|
||||||
|
where T0 : unmanaged, IComponent
|
||||||
|
where T1 : unmanaged, IComponent
|
||||||
|
where T2 : unmanaged, IComponent
|
||||||
|
{
|
||||||
|
_present.Add(ComponentTypeID<T0>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T0>.value);
|
||||||
|
_present.Add(ComponentTypeID<T1>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T1>.value);
|
||||||
|
_present.Add(ComponentTypeID<T2>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T2>.value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -31,6 +31,22 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'All' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithAllRW<<#= generics #>>()
|
||||||
|
<#= restrictions #>
|
||||||
|
{
|
||||||
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
|
_all.Add(ComponentTypeID<T<#= j #>>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T<#= j #>>.value);
|
||||||
|
<# } #>
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
/// Adds the specified component type(s) to the 'Any' filter of the query.
|
||||||
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
@@ -106,5 +122,21 @@ public ref partial struct QueryBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified component type(s) to the 'Present' filter of the query and requires read-write access.
|
||||||
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
|
/// </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public QueryBuilder WithPresentRW<<#= generics #>>()
|
||||||
|
<#= restrictions #>
|
||||||
|
{
|
||||||
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
|
_present.Add(ComponentTypeID<T<#= j #>>.value);
|
||||||
|
_rw.Add(ComponentTypeID<T<#= j #>>.value);
|
||||||
|
<# } #>
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
<# } #>
|
<# } #>
|
||||||
}
|
}
|
||||||
@@ -47,6 +47,12 @@ public partial class World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static World GetWorldUncheck(Identifier<World> id)
|
||||||
|
{
|
||||||
|
return s_worlds[id.value]!;
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Result<World, ErrorStatus> GetWorld(Identifier<World> id)
|
public static Result<World, ErrorStatus> GetWorld(Identifier<World> id)
|
||||||
{
|
{
|
||||||
@@ -80,6 +86,7 @@ public partial class World : IIdentifierType, IDisposable, IEquatable<World>
|
|||||||
private UnsafeHashMap<int, Identifier<Archetype>> _archetypeLookup; // Signature Hash to Archetype ID
|
private UnsafeHashMap<int, Identifier<Archetype>> _archetypeLookup; // Signature Hash to Archetype ID
|
||||||
private UnsafeHashMap<int, Identifier<EntityQuery>> _querieLookup; // Query Mask Hash to Query ID
|
private UnsafeHashMap<int, Identifier<EntityQuery>> _querieLookup; // Query Mask Hash to Query ID
|
||||||
|
|
||||||
|
private int _version;
|
||||||
private bool _disposed = false;
|
private bool _disposed = false;
|
||||||
|
|
||||||
internal int ArchetypeCount => _archetypes.Count;
|
internal int ArchetypeCount => _archetypes.Count;
|
||||||
@@ -99,6 +106,11 @@ public partial class World : IIdentifierType, IDisposable, IEquatable<World>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public EntityManager EntityManager => _entityManager;
|
public EntityManager EntityManager => _entityManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current version number of the world.
|
||||||
|
/// </summary>
|
||||||
|
public int Version => Interlocked.CompareExchange(ref _version, 0, 0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the main entity command buffer for this world.
|
/// Gets the main entity command buffer for this world.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -196,6 +208,7 @@ public partial class World : IIdentifierType, IDisposable, IEquatable<World>
|
|||||||
return Identifier<EntityQuery>.Invalid;
|
return Identifier<EntityQuery>.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal void PlaybackEntityCommandBuffers()
|
internal void PlaybackEntityCommandBuffers()
|
||||||
{
|
{
|
||||||
_entityCommandBuffer.Playback();
|
_entityCommandBuffer.Playback();
|
||||||
@@ -206,6 +219,12 @@ public partial class World : IIdentifierType, IDisposable, IEquatable<World>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal int AdvanceVersion()
|
||||||
|
{
|
||||||
|
return Interlocked.Increment(ref _version);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a reference to the entity query with the specified identifier.
|
/// Gets a reference to the entity query with the specified identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ public unsafe static class MeshBuilder
|
|||||||
public static void ComputeTangents(UnsafeList<Vertex> vertices, UnsafeList<uint> indices)
|
public static void ComputeTangents(UnsafeList<Vertex> vertices, UnsafeList<uint> indices)
|
||||||
{
|
{
|
||||||
using var scope = AllocationManager.CreateStackScope();
|
using var scope = AllocationManager.CreateStackScope();
|
||||||
using var bitangents = new UnsafeArray<float4>(vertices.Count, Allocator.Stack);
|
var bitangents = new UnsafeArray<float4>(vertices.Count, scope.AllocationHandle);
|
||||||
|
|
||||||
for (var i = 0; i < indices.Count; i += 3)
|
for (var i = 0; i < indices.Count; i += 3)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
<Project Path="Ghost.Zeux.MeshOptimizer/Ghost.Zeux.MeshOptimizer.csproj" />
|
<Project Path="Ghost.Zeux.MeshOptimizer/Ghost.Zeux.MeshOptimizer.csproj" />
|
||||||
</Folder>
|
</Folder>
|
||||||
<Folder Name="/Runtime/">
|
<Folder Name="/Runtime/">
|
||||||
<Project Path="Ghost.ArcEntities/Ghost.ArcEntities.csproj" />
|
|
||||||
<Project Path="Ghost.Core/Ghost.Core.csproj" />
|
<Project Path="Ghost.Core/Ghost.Core.csproj" />
|
||||||
<Project Path="Ghost.Engine/Ghost.Engine.csproj" />
|
<Project Path="Ghost.Engine/Ghost.Engine.csproj" />
|
||||||
<Project Path="Ghost.Entities/Ghost.Entities.csproj" />
|
<Project Path="Ghost.Entities/Ghost.Entities.csproj" />
|
||||||
|
|||||||
Reference in New Issue
Block a user