entity iteration pattern
parent
6173b05ff6
commit
5a670fa36c
|
@ -8,7 +8,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
public ArchetypeId Id { get; private set; }
|
public ArchetypeId Id { get; private set; }
|
||||||
public List<Column> Components = new List<Column>();
|
public List<Column> Components = new List<Column>();
|
||||||
public List<EntityId> RowToEntity = new List<EntityId>();
|
public List<EntityId> RowToEntity = new List<EntityId>();
|
||||||
public Dictionary<ComponentId, ArchetypeEdge> Edges = new Dictionary<ComponentId, ArchetypeEdge>();
|
public SortedDictionary<ComponentId, ArchetypeEdge> Edges = new SortedDictionary<ComponentId, ArchetypeEdge>();
|
||||||
|
|
||||||
public int Count;
|
public int Count;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace MoonTools.ECS.Rev2
|
namespace MoonTools.ECS.Rev2
|
||||||
{
|
{
|
||||||
public readonly record struct ComponentId(int Id) : IHasId;
|
public readonly record struct ComponentId(int Id) : IHasId, IComparable<ComponentId>
|
||||||
|
{
|
||||||
|
public int CompareTo(ComponentId other)
|
||||||
|
{
|
||||||
|
return Id.CompareTo(other.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ namespace MoonTools.ECS.Rev2
|
||||||
|
|
||||||
private bool IsDisposed;
|
private bool IsDisposed;
|
||||||
|
|
||||||
|
public delegate void RefAction<T1, T2>(ref T1 arg1, ref T2 arg2);
|
||||||
|
|
||||||
public World()
|
public World()
|
||||||
{
|
{
|
||||||
// Create the Empty Archetype
|
// Create the Empty Archetype
|
||||||
|
@ -64,23 +66,31 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: would be much more efficient to do all this at load time somehow
|
// FIXME: would be much more efficient to do all this at load time somehow
|
||||||
private ComponentId RegisterComponent<T>() where T : unmanaged
|
private void RegisterComponent<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
var componentId = ComponentIdAssigner.Assign();
|
var componentId = ComponentIdAssigner.Assign();
|
||||||
TypeToComponentId.Add(typeof(T), componentId);
|
TypeToComponentId.Add(typeof(T), componentId);
|
||||||
ComponentIndex.Add(componentId, new Dictionary<ArchetypeId, ArchetypeRecord>());
|
ComponentIndex.Add(componentId, new Dictionary<ArchetypeId, ArchetypeRecord>());
|
||||||
ElementSizes.Add(componentId, Unsafe.SizeOf<T>());
|
ElementSizes.Add(componentId, Unsafe.SizeOf<T>());
|
||||||
return componentId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComponentId GetComponentId<T>() where T : unmanaged
|
private void TryRegisterComponentId<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
if (!TypeToComponentId.TryGetValue(typeof(T), out var componentId))
|
if (!TypeToComponentId.TryGetValue(typeof(T), out var componentId))
|
||||||
{
|
{
|
||||||
return RegisterComponent<T>();
|
RegisterComponent<T>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return componentId;
|
private ComponentId GetComponentId<T>() where T : unmanaged
|
||||||
|
{
|
||||||
|
return TypeToComponentId[typeof(T)];
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ArchetypeRecord GetArchetypeRecord<T>(Archetype archetype) where T : unmanaged
|
||||||
|
{
|
||||||
|
var componentId = GetComponentId<T>();
|
||||||
|
return ComponentIndex[componentId][archetype.Id];
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasComponent<T>(EntityId entityId) where T : unmanaged
|
public bool HasComponent<T>(EntityId entityId) where T : unmanaged
|
||||||
|
@ -111,7 +121,28 @@ namespace MoonTools.ECS.Rev2
|
||||||
return ((T*) column.Elements)[record.Row];
|
return ((T*) column.Elements)[record.Row];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddComponent<T>(EntityId entityId, T component) where T : unmanaged
|
public unsafe void SetComponent<T>(EntityId entityId, T component) where T : unmanaged
|
||||||
|
{
|
||||||
|
TryRegisterComponentId<T>();
|
||||||
|
var componentId = GetComponentId<T>();
|
||||||
|
|
||||||
|
if (HasComponent<T>(entityId))
|
||||||
|
{
|
||||||
|
var record = EntityIndex[entityId];
|
||||||
|
var archetype = record.Archetype;
|
||||||
|
var archetypes = ComponentIndex[componentId];
|
||||||
|
var archetypeRecord = archetypes[archetype.Id];
|
||||||
|
var column = archetype.Components[archetypeRecord.ColumnIndex];
|
||||||
|
|
||||||
|
((T*) column.Elements)[record.Row] = component;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddComponent(entityId, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddComponent<T>(EntityId entityId, T component) where T : unmanaged
|
||||||
{
|
{
|
||||||
Archetype? nextArchetype;
|
Archetype? nextArchetype;
|
||||||
|
|
||||||
|
@ -247,6 +278,54 @@ namespace MoonTools.ECS.Rev2
|
||||||
from.Count -= 1;
|
from.Count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe void ForEachEntity<T1, T2>(ArchetypeSignature signature, RefAction<T1, T2> rowAction) where T1 : unmanaged where T2 : unmanaged
|
||||||
|
{
|
||||||
|
var archetype = ArchetypeIndex[signature];
|
||||||
|
|
||||||
|
var componentIdOne = signature[0];
|
||||||
|
var columnIndexOne = ComponentIndex[componentIdOne][archetype.Id].ColumnIndex;
|
||||||
|
var columnOneElements = archetype.Components[columnIndexOne].Elements;
|
||||||
|
|
||||||
|
var componentIdTwo = signature[1];
|
||||||
|
var columnIndexTwo = ComponentIndex[componentIdTwo][archetype.Id].ColumnIndex;
|
||||||
|
var columnTwoElements = archetype.Components[columnIndexTwo].Elements;
|
||||||
|
|
||||||
|
for (int i = 0; i < archetype.Count; i += 1)
|
||||||
|
{
|
||||||
|
rowAction(ref ((T1*) columnOneElements)[i], ref ((T2*) columnTwoElements)[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var edge in archetype.Edges.Values)
|
||||||
|
{
|
||||||
|
if (edge.Add != archetype)
|
||||||
|
{
|
||||||
|
ForEachEntity(edge.Add.Signature, rowAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public void ForEachEntity(ArchetypeSignature signature, Action<Entity> rowAction)
|
||||||
|
{
|
||||||
|
var archetype = ArchetypeIndex[signature];
|
||||||
|
|
||||||
|
for (int i = 0; i < archetype.Count; i += 1)
|
||||||
|
{
|
||||||
|
var entity = new Entity(this, archetype, i, archetype.RowToEntity[i]);
|
||||||
|
rowAction(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// recursion might get too hairy here
|
||||||
|
foreach (var edge in archetype.Edges.Values)
|
||||||
|
{
|
||||||
|
if (edge.Add != archetype)
|
||||||
|
{
|
||||||
|
ForEachEntity(edge.Add.Signature, rowAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
|
|
Loading…
Reference in New Issue