unifying Ids and adding Relations
parent
344a0082b4
commit
545637aaf3
|
@ -7,11 +7,11 @@ internal class Archetype
|
||||||
public World World;
|
public World World;
|
||||||
public ArchetypeSignature Signature;
|
public ArchetypeSignature Signature;
|
||||||
public List<Column> ComponentColumns = new List<Column>();
|
public List<Column> ComponentColumns = new List<Column>();
|
||||||
public List<EntityId> RowToEntity = new List<EntityId>();
|
public List<Id> RowToEntity = new List<Id>();
|
||||||
|
|
||||||
public Dictionary<ComponentId, int> ComponentToColumnIndex =
|
public Dictionary<Id, int> ComponentToColumnIndex =
|
||||||
new Dictionary<ComponentId, int>();
|
new Dictionary<Id, int>();
|
||||||
public SortedDictionary<ComponentId, ArchetypeEdge> Edges = new SortedDictionary<ComponentId, ArchetypeEdge>();
|
public SortedDictionary<Id, ArchetypeEdge> Edges = new SortedDictionary<Id, ArchetypeEdge>();
|
||||||
|
|
||||||
public int Count => RowToEntity.Count;
|
public int Count => RowToEntity.Count;
|
||||||
|
|
||||||
|
|
|
@ -7,36 +7,36 @@ namespace MoonTools.ECS.Rev2
|
||||||
{
|
{
|
||||||
public static ArchetypeSignature Empty = new ArchetypeSignature(0);
|
public static ArchetypeSignature Empty = new ArchetypeSignature(0);
|
||||||
|
|
||||||
List<int> Ids;
|
List<ulong> Ids;
|
||||||
|
|
||||||
public int Count => Ids.Count;
|
public int Count => Ids.Count;
|
||||||
|
|
||||||
public ComponentId this[int i] => new ComponentId(Ids[i]);
|
public Id this[int i] => new Id(Ids[i]);
|
||||||
|
|
||||||
public ArchetypeSignature()
|
public ArchetypeSignature()
|
||||||
{
|
{
|
||||||
Ids = new List<int>();
|
Ids = new List<ulong>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArchetypeSignature(int capacity)
|
public ArchetypeSignature(int capacity)
|
||||||
{
|
{
|
||||||
Ids = new List<int>(capacity);
|
Ids = new List<ulong>(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintains sorted order
|
// Maintains sorted order
|
||||||
public void Insert(ComponentId componentId)
|
public void Insert(Id componentId)
|
||||||
{
|
{
|
||||||
var index = Ids.BinarySearch(componentId.Id);
|
var index = Ids.BinarySearch(componentId.Value);
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
Ids.Insert(~index, componentId.Id);
|
Ids.Insert(~index, componentId.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(ComponentId componentId)
|
public void Remove(Id componentId)
|
||||||
{
|
{
|
||||||
var index = Ids.BinarySearch(componentId.Id);
|
var index = Ids.BinarySearch(componentId.Value);
|
||||||
|
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MoonTools.ECS.Rev2
|
|
||||||
{
|
|
||||||
internal readonly record struct ComponentId(int Id) : IHasId, IComparable<ComponentId>
|
|
||||||
{
|
|
||||||
public int CompareTo(ComponentId other)
|
|
||||||
{
|
|
||||||
return Id.CompareTo(other.Id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
namespace MoonTools.ECS.Rev2;
|
||||||
|
|
||||||
|
public readonly record struct Entity(uint Id);
|
|
@ -1,4 +0,0 @@
|
||||||
namespace MoonTools.ECS.Rev2
|
|
||||||
{
|
|
||||||
public readonly record struct EntityId(int Id) : IHasId;
|
|
||||||
}
|
|
|
@ -7,8 +7,8 @@ namespace MoonTools.ECS.Rev2
|
||||||
public class Filter
|
public class Filter
|
||||||
{
|
{
|
||||||
private Archetype EmptyArchetype;
|
private Archetype EmptyArchetype;
|
||||||
private HashSet<ComponentId> Included;
|
private HashSet<Id> Included;
|
||||||
private HashSet<ComponentId> Excluded;
|
private HashSet<Id> Excluded;
|
||||||
|
|
||||||
public EntityEnumerator Entities => new EntityEnumerator(this);
|
public EntityEnumerator Entities => new EntityEnumerator(this);
|
||||||
internal ArchetypeEnumerator Archetypes => new ArchetypeEnumerator(this);
|
internal ArchetypeEnumerator Archetypes => new ArchetypeEnumerator(this);
|
||||||
|
@ -47,7 +47,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityId RandomEntity
|
public Id RandomEntity
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: this WILL crash if the index is out of range!
|
// WARNING: this WILL crash if the index is out of range!
|
||||||
public EntityId NthEntity(int index)
|
public Id NthEntity(int index)
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Filter(Archetype emptyArchetype, HashSet<ComponentId> included, HashSet<ComponentId> excluded)
|
internal Filter(Archetype emptyArchetype, HashSet<Id> included, HashSet<Id> excluded)
|
||||||
{
|
{
|
||||||
EmptyArchetype = emptyArchetype;
|
EmptyArchetype = emptyArchetype;
|
||||||
Included = included;
|
Included = included;
|
||||||
|
@ -165,12 +165,12 @@ namespace MoonTools.ECS.Rev2
|
||||||
|
|
||||||
public ref struct EntityEnumerator
|
public ref struct EntityEnumerator
|
||||||
{
|
{
|
||||||
private EntityId CurrentEntity;
|
private Id CurrentEntity;
|
||||||
|
|
||||||
public EntityEnumerator GetEnumerator() => this;
|
public EntityEnumerator GetEnumerator() => this;
|
||||||
|
|
||||||
// TODO: pool this
|
// TODO: pool this
|
||||||
Queue<EntityId> EntityQueue = new Queue<EntityId>();
|
Queue<Id> EntityQueue = new Queue<Id>();
|
||||||
|
|
||||||
internal EntityEnumerator(Filter filter)
|
internal EntityEnumerator(Filter filter)
|
||||||
{
|
{
|
||||||
|
@ -190,7 +190,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
return EntityQueue.TryDequeue(out CurrentEntity);
|
return EntityQueue.TryDequeue(out CurrentEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityId Current => CurrentEntity;
|
public Id Current => CurrentEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref struct RandomEntityEnumerator
|
public ref struct RandomEntityEnumerator
|
||||||
|
@ -208,7 +208,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MoveNext() => LinearCongruentialEnumerator.MoveNext();
|
public bool MoveNext() => LinearCongruentialEnumerator.MoveNext();
|
||||||
public EntityId Current => Filter.NthEntity(LinearCongruentialEnumerator.Current);
|
public Id Current => Filter.NthEntity(LinearCongruentialEnumerator.Current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,17 @@ namespace MoonTools.ECS.Rev2
|
||||||
public ref struct FilterBuilder
|
public ref struct FilterBuilder
|
||||||
{
|
{
|
||||||
World World;
|
World World;
|
||||||
HashSet<ComponentId> Included;
|
HashSet<Id> Included;
|
||||||
HashSet<ComponentId> Excluded;
|
HashSet<Id> Excluded;
|
||||||
|
|
||||||
internal FilterBuilder(World world)
|
internal FilterBuilder(World world)
|
||||||
{
|
{
|
||||||
World = world;
|
World = world;
|
||||||
Included = new HashSet<ComponentId>();
|
Included = new HashSet<Id>();
|
||||||
Excluded = new HashSet<ComponentId>();
|
Excluded = new HashSet<Id>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private FilterBuilder(World world, HashSet<ComponentId> included, HashSet<ComponentId> excluded)
|
private FilterBuilder(World world, HashSet<Id> included, HashSet<Id> excluded)
|
||||||
{
|
{
|
||||||
World = world;
|
World = world;
|
||||||
Included = included;
|
Included = included;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MoonTools.ECS.Rev2;
|
||||||
|
|
||||||
|
public readonly record struct Id : IComparable<Id>
|
||||||
|
{
|
||||||
|
public readonly ulong Value;
|
||||||
|
|
||||||
|
private const ulong HI = 0xFFFFFFFF00000000;
|
||||||
|
private const ulong LO = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
public bool IsPair => (HI & Value) != 0;
|
||||||
|
public uint Low => (uint)(LO & Value);
|
||||||
|
public uint High => (uint)((HI & Value) >>> 32);
|
||||||
|
|
||||||
|
public Id(ulong value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Id(uint relation, uint target)
|
||||||
|
{
|
||||||
|
Value = (relation << 31) | target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(Id other)
|
||||||
|
{
|
||||||
|
return Value.CompareTo(other.Value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,12 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MoonTools.ECS.Rev2
|
namespace MoonTools.ECS.Rev2
|
||||||
{
|
{
|
||||||
internal class IdAssigner<T> where T : struct, IHasId
|
internal class IdAssigner
|
||||||
{
|
{
|
||||||
int Next;
|
ulong Next;
|
||||||
Queue<int> AvailableIds = new Queue<int>();
|
Queue<ulong> AvailableIds = new Queue<ulong>();
|
||||||
|
|
||||||
public T Assign()
|
public Id Assign()
|
||||||
{
|
{
|
||||||
if (!AvailableIds.TryDequeue(out var id))
|
if (!AvailableIds.TryDequeue(out var id))
|
||||||
{
|
{
|
||||||
|
@ -15,12 +15,12 @@ namespace MoonTools.ECS.Rev2
|
||||||
Next += 1;
|
Next += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new T { Id = id };
|
return new Id(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unassign(T idHaver)
|
public void Unassign(Id id)
|
||||||
{
|
{
|
||||||
AvailableIds.Enqueue(idHaver.Id);
|
AvailableIds.Enqueue(id.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,22 +8,21 @@ namespace MoonTools.ECS.Rev2
|
||||||
public class World : IDisposable
|
public class World : IDisposable
|
||||||
{
|
{
|
||||||
// Get ComponentId from a Type
|
// Get ComponentId from a Type
|
||||||
internal static Dictionary<Type, ComponentId> TypeToComponentId = new Dictionary<Type, ComponentId>();
|
internal static Dictionary<Type, Id> TypeToComponentId = new Dictionary<Type, Id>();
|
||||||
// Get element size from a ComponentId
|
// Get element size from a ComponentId
|
||||||
internal static Dictionary<ComponentId, int> ElementSizes = new Dictionary<ComponentId, int>();
|
internal static Dictionary<Id, int> ElementSizes = new Dictionary<Id, int>();
|
||||||
|
|
||||||
// Lookup from ArchetypeSignature to Archetype
|
// Lookup from ArchetypeSignature to Archetype
|
||||||
internal Dictionary<ArchetypeSignature, Archetype> ArchetypeIndex = new Dictionary<ArchetypeSignature, Archetype>();
|
internal Dictionary<ArchetypeSignature, Archetype> ArchetypeIndex = new Dictionary<ArchetypeSignature, Archetype>();
|
||||||
|
|
||||||
// Going from EntityId to Archetype and storage row
|
// Going from EntityId to Archetype and storage row
|
||||||
Dictionary<EntityId, Record> EntityIndex = new Dictionary<EntityId, Record>();
|
Dictionary<Id, Record> EntityIndex = new Dictionary<Id, Record>();
|
||||||
|
|
||||||
// Going from ComponentId to Archetype list
|
// Going from ComponentId to Archetype list
|
||||||
Dictionary<ComponentId, List<Archetype>> ComponentIndex = new Dictionary<ComponentId, List<Archetype>>();
|
Dictionary<Id, List<Archetype>> ComponentIndex = new Dictionary<Id, List<Archetype>>();
|
||||||
|
|
||||||
// ID Management
|
// ID Management
|
||||||
IdAssigner<EntityId> EntityIdAssigner = new IdAssigner<EntityId>();
|
IdAssigner IdAssigner = new IdAssigner();
|
||||||
IdAssigner<ComponentId> ComponentIdAssigner = new IdAssigner<ComponentId>();
|
|
||||||
|
|
||||||
internal readonly Archetype EmptyArchetype;
|
internal readonly Archetype EmptyArchetype;
|
||||||
|
|
||||||
|
@ -59,9 +58,9 @@ namespace MoonTools.ECS.Rev2
|
||||||
return archetype;
|
return archetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityId CreateEntity()
|
public Id CreateEntity()
|
||||||
{
|
{
|
||||||
var entityId = EntityIdAssigner.Assign();
|
var entityId = IdAssigner.Assign();
|
||||||
EntityIndex.Add(entityId, new Record(EmptyArchetype, EmptyArchetype.Count));
|
EntityIndex.Add(entityId, new Record(EmptyArchetype, EmptyArchetype.Count));
|
||||||
EmptyArchetype.RowToEntity.Add(entityId);
|
EmptyArchetype.RowToEntity.Add(entityId);
|
||||||
return entityId;
|
return entityId;
|
||||||
|
@ -70,27 +69,41 @@ namespace MoonTools.ECS.Rev2
|
||||||
// used as a fast path by snapshot restore
|
// used as a fast path by snapshot restore
|
||||||
internal void CreateEntityOnArchetype(Archetype archetype)
|
internal void CreateEntityOnArchetype(Archetype archetype)
|
||||||
{
|
{
|
||||||
var entityId = EntityIdAssigner.Assign();
|
var entityId = IdAssigner.Assign();
|
||||||
EntityIndex.Add(entityId, new Record(archetype, archetype.Count));
|
EntityIndex.Add(entityId, new Record(archetype, archetype.Count));
|
||||||
archetype.RowToEntity.Add(entityId);
|
archetype.RowToEntity.Add(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// used as a fast path by Archetype.ClearAll and snapshot restore
|
// used as a fast path by Archetype.ClearAll and snapshot restore
|
||||||
internal void FreeEntity(EntityId entityId)
|
internal void FreeEntity(Id entityId)
|
||||||
{
|
{
|
||||||
EntityIndex.Remove(entityId);
|
EntityIndex.Remove(entityId);
|
||||||
EntityIdAssigner.Unassign(entityId);
|
IdAssigner.Unassign(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterTypeId(Id typeId, int elementSize)
|
||||||
|
{
|
||||||
|
ComponentIndex.Add(typeId, new List<Archetype>());
|
||||||
|
ElementSizes.Add(typeId, elementSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 void RegisterComponent<T>() where T : unmanaged
|
private void RegisterComponent<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
var componentId = ComponentIdAssigner.Assign();
|
var componentId = IdAssigner.Assign();
|
||||||
TypeToComponentId.Add(typeof(T), componentId);
|
TypeToComponentId.Add(typeof(T), componentId);
|
||||||
ComponentIndex.Add(componentId, new List<Archetype>());
|
ComponentIndex.Add(componentId, new List<Archetype>());
|
||||||
ElementSizes.Add(componentId, Unsafe.SizeOf<T>());
|
ElementSizes.Add(componentId, Unsafe.SizeOf<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TryRegisterTypeId(Id typeId, int elementSize)
|
||||||
|
{
|
||||||
|
if (!ComponentIndex.ContainsKey(typeId))
|
||||||
|
{
|
||||||
|
RegisterTypeId(typeId, elementSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void TryRegisterComponentId<T>() where T : unmanaged
|
private void TryRegisterComponentId<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
if (!TypeToComponentId.ContainsKey(typeof(T)))
|
if (!TypeToComponentId.ContainsKey(typeof(T)))
|
||||||
|
@ -99,22 +112,13 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-generic variant for use with Transfer
|
|
||||||
internal void AddComponentIndexEntry(ComponentId componentId)
|
|
||||||
{
|
|
||||||
if (!ComponentIndex.ContainsKey(componentId))
|
|
||||||
{
|
|
||||||
ComponentIndex.Add(componentId, new List<Archetype>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private ComponentId GetComponentId<T>() where T : unmanaged
|
private Id GetComponentId<T>() where T : unmanaged
|
||||||
{
|
{
|
||||||
return TypeToComponentId[typeof(T)];
|
return TypeToComponentId[typeof(T)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Has<T>(EntityId entityId) where T : unmanaged
|
public bool Has<T>(Id entityId) where T : unmanaged
|
||||||
{
|
{
|
||||||
var componentId = GetComponentId<T>();
|
var componentId = GetComponentId<T>();
|
||||||
var record = EntityIndex[entityId];
|
var record = EntityIndex[entityId];
|
||||||
|
@ -122,7 +126,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
|
|
||||||
// will throw if non-existent
|
// will throw if non-existent
|
||||||
public unsafe ref T Get<T>(EntityId entityId) where T : unmanaged
|
public unsafe ref T Get<T>(Id entityId) where T : unmanaged
|
||||||
{
|
{
|
||||||
var componentId = GetComponentId<T>();
|
var componentId = GetComponentId<T>();
|
||||||
|
|
||||||
|
@ -133,7 +137,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
return ref ((T*) column.Elements)[record.Row];
|
return ref ((T*) column.Elements)[record.Row];
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Set<T>(in EntityId entityId, in T component) where T : unmanaged
|
public unsafe void Set<T>(in Id entityId, in T component) where T : unmanaged
|
||||||
{
|
{
|
||||||
TryRegisterComponentId<T>();
|
TryRegisterComponentId<T>();
|
||||||
var componentId = GetComponentId<T>();
|
var componentId = GetComponentId<T>();
|
||||||
|
@ -152,7 +156,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Add<T>(EntityId entityId, in T component) where T : unmanaged
|
private void Add<T>(Id entityId, in T component) where T : unmanaged
|
||||||
{
|
{
|
||||||
Archetype? nextArchetype;
|
Archetype? nextArchetype;
|
||||||
|
|
||||||
|
@ -191,7 +195,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
column.Append(component);
|
column.Append(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove<T>(EntityId entityId) where T : unmanaged
|
public void Remove<T>(Id entityId) where T : unmanaged
|
||||||
{
|
{
|
||||||
Archetype? nextArchetype;
|
Archetype? nextArchetype;
|
||||||
|
|
||||||
|
@ -223,7 +227,105 @@ namespace MoonTools.ECS.Rev2
|
||||||
MoveEntityToLowerArchetype(entityId, row, archetype, nextArchetype, componentId);
|
MoveEntityToLowerArchetype(entityId, row, archetype, nextArchetype, componentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy(EntityId entityId)
|
private Id Pair(in Id relation, in Id target)
|
||||||
|
{
|
||||||
|
return new Id(relation.Low, target.Low);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Relate<T>(in Id entityA, in Id entityB, in T relation) where T : unmanaged
|
||||||
|
{
|
||||||
|
TryRegisterComponentId<T>();
|
||||||
|
var relationDataTypeId = GetComponentId<T>();
|
||||||
|
|
||||||
|
var typeId = Pair(relationDataTypeId, entityB);
|
||||||
|
|
||||||
|
TryRegisterTypeId(typeId, Unsafe.SizeOf<T>());
|
||||||
|
SetRelationData(entityA, typeId, relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Related<T>(in Id entityA, in Id entityB) where T : unmanaged
|
||||||
|
{
|
||||||
|
var relationDataTypeId = GetComponentId<T>();
|
||||||
|
var typeId = Pair(relationDataTypeId, entityB);
|
||||||
|
return Has(entityA, typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetRelationData<T>(in Id entityA, in Id entityB) where T : unmanaged
|
||||||
|
{
|
||||||
|
var relationDataTypeId = GetComponentId<T>();
|
||||||
|
var typeId = Pair(relationDataTypeId, entityB);
|
||||||
|
return Get<T>(entityA, typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe ref T Get<T>(Id entityId, Id typeId) where T : unmanaged
|
||||||
|
{
|
||||||
|
var record = EntityIndex[entityId];
|
||||||
|
var columnIndex = record.Archetype.ComponentToColumnIndex[typeId];
|
||||||
|
var column = record.Archetype.ComponentColumns[columnIndex];
|
||||||
|
|
||||||
|
return ref ((T*) column.Elements)[record.Row];
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Has(Id entityId, Id typeId)
|
||||||
|
{
|
||||||
|
var record = EntityIndex[entityId];
|
||||||
|
return record.Archetype.ComponentToColumnIndex.ContainsKey(typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Add<T>(Id entityId, Id typeId, in T component) where T : unmanaged
|
||||||
|
{
|
||||||
|
Archetype? nextArchetype;
|
||||||
|
|
||||||
|
// move the entity to the new archetype
|
||||||
|
var record = EntityIndex[entityId];
|
||||||
|
var archetype = record.Archetype;
|
||||||
|
|
||||||
|
if (archetype.Edges.TryGetValue(typeId, out var edge))
|
||||||
|
{
|
||||||
|
nextArchetype = edge.Add;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: pool the signatures
|
||||||
|
var nextSignature = new ArchetypeSignature(archetype.Signature.Count + 1);
|
||||||
|
archetype.Signature.CopyTo(nextSignature);
|
||||||
|
nextSignature.Insert(typeId);
|
||||||
|
|
||||||
|
if (!ArchetypeIndex.TryGetValue(nextSignature, out nextArchetype))
|
||||||
|
{
|
||||||
|
nextArchetype = CreateArchetype(nextSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
var newEdge = new ArchetypeEdge(nextArchetype, archetype);
|
||||||
|
archetype.Edges.Add(typeId, newEdge);
|
||||||
|
nextArchetype.Edges.Add(typeId, newEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveEntityToHigherArchetype(entityId, record.Row, archetype, nextArchetype);
|
||||||
|
|
||||||
|
// add the new component to the new archetype
|
||||||
|
var columnIndex = nextArchetype.ComponentToColumnIndex[typeId];
|
||||||
|
var column = nextArchetype.ComponentColumns[columnIndex];
|
||||||
|
column.Append(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void SetRelationData<T>(in Id entityId, in Id typeId, T data) where T : unmanaged
|
||||||
|
{
|
||||||
|
if (Has(entityId, typeId))
|
||||||
|
{
|
||||||
|
var record = EntityIndex[entityId];
|
||||||
|
var columnIndex = record.Archetype.ComponentToColumnIndex[typeId];
|
||||||
|
var column = record.Archetype.ComponentColumns[columnIndex];
|
||||||
|
|
||||||
|
((T*) column.Elements)[record.Row] = data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Add(entityId, typeId, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Destroy(Id entityId)
|
||||||
{
|
{
|
||||||
var record = EntityIndex[entityId];
|
var record = EntityIndex[entityId];
|
||||||
var archetype = record.Archetype;
|
var archetype = record.Archetype;
|
||||||
|
@ -244,10 +346,10 @@ namespace MoonTools.ECS.Rev2
|
||||||
|
|
||||||
archetype.RowToEntity.RemoveAt(archetype.Count - 1);
|
archetype.RowToEntity.RemoveAt(archetype.Count - 1);
|
||||||
EntityIndex.Remove(entityId);
|
EntityIndex.Remove(entityId);
|
||||||
EntityIdAssigner.Unassign(entityId);
|
IdAssigner.Unassign(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoveEntityToHigherArchetype(EntityId entityId, int row, Archetype from, Archetype to)
|
private void MoveEntityToHigherArchetype(Id entityId, int row, Archetype from, Archetype to)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < from.ComponentColumns.Count; i += 1)
|
for (int i = 0; i < from.ComponentColumns.Count; i += 1)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +378,7 @@ namespace MoonTools.ECS.Rev2
|
||||||
to.RowToEntity.Add(entityId);
|
to.RowToEntity.Add(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoveEntityToLowerArchetype(EntityId entityId, int row, Archetype from, Archetype to, ComponentId removed)
|
private void MoveEntityToLowerArchetype(Id entityId, int row, Archetype from, Archetype to, Id removed)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < from.ComponentColumns.Count; i += 1)
|
for (int i = 0; i < from.ComponentColumns.Count; i += 1)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue