forked from Misaki/GhostEngine
Support enableable components and query enhancements
- Upgraded `Misaki.HighPerformance.LowLevel` to v1.2.8. - Added `IEquatable` to `Handle<T>` and `Identifier<T>`. - Improved `Result` extensions with `[CallerArgumentExpression]`. - Introduced `SetEnabled` in `EntityManager` to toggle components. - Refactored `Chunk` and `Archetype` for enableable components. - Added `EntityQueryMask` for filtering enabled/disabled components. - Enhanced `QueryBuilder` with new filtering methods (`WithAll`, etc.). - Improved `EntityQuery.ForEach` with entity validation.
This commit is contained in:
@@ -10,13 +10,19 @@ namespace Ghost.Entities;
|
||||
|
||||
public unsafe partial struct EntityQuery
|
||||
{
|
||||
<# for (var f = 0; f < 2; f++)
|
||||
{
|
||||
var isForEachWithEntity = f != 0;
|
||||
#>
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var compGenerics = AppendGenericRefParameters(i);
|
||||
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2);
|
||||
|
||||
var delegateTupe = isForEachWithEntity ? "ForEachWithEntity" : "ForEach";
|
||||
#>
|
||||
public readonly void ForEach<<#= generics #>>(ForEach<<#= generics #>> action)
|
||||
public readonly void ForEach<<#= generics #>>(<#= delegateTupe #><<#= generics #>> action)
|
||||
<#= restrictions #>
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
@@ -25,18 +31,20 @@ public unsafe partial struct EntityQuery
|
||||
var offsets = stackalloc int[<#= i #>];
|
||||
var basePtrs = stackalloc byte*[<#= i #>];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
var layoutResult = archetype.GetLayout(compTypeIDs[index]);
|
||||
if (layoutResult.Status != ResultStatus.Success)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
|
||||
offsets[index] = layoutResult.Value.offset;
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
@@ -47,81 +55,35 @@ public unsafe partial struct EntityQuery
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
var pChunkData = chunk.GetUnsafePtr();
|
||||
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
basePtrs[index] = pChunkData + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
for (var entityIndex = 0; entityIndex < chunk.Count; entityIndex++)
|
||||
{
|
||||
if (!IsEntityValid(pChunkData, entityIndex, in archetype, in _mask))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
|
||||
var pComp<#= localIndex #> = (T<#= localIndex #>*)(basePtrs[<#= localIndex #>] + (sizeof(T<#= localIndex #>) * entityIndex));
|
||||
<# } #>
|
||||
|
||||
action(<#= AppendRefParameters(i, "*pComp{0}") #>);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var compGenerics = AppendGenericRefParameters(i);
|
||||
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2);
|
||||
#>
|
||||
public readonly void ForEach<<#= generics #>>(ForEachWithEntity<<#= generics #>> action)
|
||||
<#= restrictions #>
|
||||
{
|
||||
var world = World.GetWorld(_worldID).GetValueOrThrow(ResultStatus.Success);
|
||||
|
||||
var compTypeIDs = stackalloc int[] { <#= AppendGenerics(i, "ComponentTypeID<T{0}>.value") #> };
|
||||
var offsets = stackalloc int[<#= i #>];
|
||||
var basePtrs = stackalloc byte*[<#= i #>];
|
||||
|
||||
foreach (var archetypeID in _matchingArchetypes)
|
||||
{
|
||||
ref var archetype = ref world.GetArchetypeReference(archetypeID);
|
||||
var hasAllComponents = true;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
offsets[index] = archetype.GetOffset(compTypeIDs[index]);
|
||||
if (offsets[index] == -1)
|
||||
{
|
||||
hasAllComponents = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAllComponents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
||||
{
|
||||
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
||||
var count = chunk.Count;
|
||||
for (var index = 0; index < <#= i #>; index++)
|
||||
{
|
||||
basePtrs[index] = chunk.GetUnsafePtr() + offsets[index];
|
||||
}
|
||||
|
||||
for (var entityIndex = 0; entityIndex < count; entityIndex++)
|
||||
{
|
||||
var pEntity = (Entity*)(chunk.GetUnsafePtr() + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
<# for (var localIndex = 0; localIndex < i; localIndex++) { #>
|
||||
var pComp<#= localIndex #> = (T<#= localIndex #>*)(basePtrs[<#= localIndex #>] + (sizeof(T<#= localIndex #>) * entityIndex));
|
||||
<# } #>
|
||||
|
||||
<# if (isForEachWithEntity) { #>
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, <#= AppendRefParameters(i, "*pComp{0}") #>);
|
||||
<# } else { #>
|
||||
action(<#= AppendRefParameters(i, "*pComp{0}") #>);
|
||||
<# } #>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
<# } #>
|
||||
}
|
||||
Reference in New Issue
Block a user