Major ECS API overhaul: added ComponentSet, refactored ComponentRegistry, and updated all entity/component creation methods. Introduced robust custom serialization infrastructure and per-component source generators for registration and (de)serialization. Updated editor, engine, and test code to use new APIs. Improved code quality, naming, and performance throughout. Removed obsolete code and updated dependencies.
120 lines
3.8 KiB
Plaintext
120 lines
3.8 KiB
Plaintext
<#@ template language="C#" #>
|
|
<#@ output extension="gen.cs" #>
|
|
<#@ assembly name="System.Core" #>
|
|
<#@ import namespace="System.Linq" #>
|
|
<#@ import namespace="System.Text" #>
|
|
<#@ include file="Helpers.ttinclude" #>
|
|
namespace Ghost.Entities;
|
|
|
|
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 = AppendParameters(i, "T{0}");
|
|
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2);
|
|
|
|
var delegateTupe = isForEachWithEntity ? "ForEachWithEntity" : "ForEach";
|
|
#>
|
|
public readonly void ForEach<<#= generics #>>(<#= delegateTupe #><<#= generics #>> action)
|
|
<#= restrictions #>
|
|
{
|
|
var world = World.GetWorldUncheck(_worldID);
|
|
var globalVersion = world.Version;
|
|
|
|
<# 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 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])
|
|
{
|
|
changedCompIDs[changedCompCount] = id;
|
|
changedCompCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
|
{
|
|
ref var archetype = ref world.GetArchetypeReference(_matchingArchetypes[i]);
|
|
var hasAllComponents = true;
|
|
for (var index = 0; index < <#= i #>; index++)
|
|
{
|
|
var layoutResult = archetype.GetLayout(compTypeIDs[index]);
|
|
if (!layoutResult)
|
|
{
|
|
hasAllComponents = false;
|
|
break;
|
|
}
|
|
|
|
offsets[index] = layoutResult.Value.offset;
|
|
}
|
|
|
|
if (!hasAllComponents)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (var chunkIndex = 0; chunkIndex < archetype.ChunkCount; chunkIndex++)
|
|
{
|
|
ref var chunk = ref archetype.GetChunkReference(chunkIndex);
|
|
var pChunkData = chunk.GetUnsafePtr();
|
|
|
|
for (var j = 0; j < changedCompCount; j++)
|
|
{
|
|
archetype.MarkChanged(chunkIndex, changedCompIDs[j], globalVersion);
|
|
}
|
|
|
|
for (var index = 0; index < <#= i #>; index++)
|
|
{
|
|
basePtrs[index] = pChunkData + offsets[index];
|
|
}
|
|
|
|
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));
|
|
<# } #>
|
|
|
|
<# if (isForEachWithEntity) { #>
|
|
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
|
action(*pEntity, <#= AppendParameters(i, "ref *pComp{0}") #>);
|
|
<# } else { #>
|
|
action(<#= AppendParameters(i, "ref *pComp{0}") #>);
|
|
<# } #>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
<# } #>
|
|
<# } #>
|
|
}
|