transfer relations in order
parent
3cba3e047c
commit
2aa8fc87e7
|
@ -6,11 +6,13 @@ namespace MoonTools.ECS
|
||||||
{
|
{
|
||||||
internal class RelationDepot
|
internal class RelationDepot
|
||||||
{
|
{
|
||||||
|
private EntityStorage EntityStorage;
|
||||||
private TypeIndices RelationTypeIndices;
|
private TypeIndices RelationTypeIndices;
|
||||||
private RelationStorage[] storages = new RelationStorage[256];
|
private RelationStorage[] storages = new RelationStorage[256];
|
||||||
|
|
||||||
public RelationDepot(TypeIndices relationTypeIndices)
|
public RelationDepot(EntityStorage entityStorage, TypeIndices relationTypeIndices)
|
||||||
{
|
{
|
||||||
|
EntityStorage = entityStorage;
|
||||||
RelationTypeIndices = relationTypeIndices;
|
RelationTypeIndices = relationTypeIndices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,26 +125,11 @@ namespace MoonTools.ECS
|
||||||
storages[relationTypeIndex].Set(entityA, entityB, relationData);
|
storages[relationTypeIndex].Set(entityA, entityB, relationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetStorageIndex(int relationTypeIndex, int entityA, int entityB)
|
|
||||||
{
|
|
||||||
return storages[relationTypeIndex].GetStorageIndex(entityA, entityB);
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe void* Get(int relationTypeIndex, int relationStorageIndex)
|
|
||||||
{
|
|
||||||
return storages[relationTypeIndex].Get(relationStorageIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnrelateAll(int entityID, int relationTypeIndex)
|
public void UnrelateAll(int entityID, int relationTypeIndex)
|
||||||
{
|
{
|
||||||
storages[relationTypeIndex].UnrelateAll(entityID);
|
storages[relationTypeIndex].UnrelateAll(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReverseSpanEnumerator<Entity> OutRelations(int entityID, int relationTypeIndex)
|
|
||||||
{
|
|
||||||
return storages[relationTypeIndex].OutRelations(entityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < storages.Length; i += 1)
|
for (var i = 0; i < storages.Length; i += 1)
|
||||||
|
@ -174,5 +161,33 @@ namespace MoonTools.ECS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe void TransferStorage(Dictionary<int, int> worldToTransferID, RelationDepot other)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < storages.Length; i += 1)
|
||||||
|
{
|
||||||
|
if (storages[i] != null)
|
||||||
|
{
|
||||||
|
foreach (var (a, b) in storages[i].All())
|
||||||
|
{
|
||||||
|
if (worldToTransferID.TryGetValue(a, out var otherA))
|
||||||
|
{
|
||||||
|
if (worldToTransferID.TryGetValue(b, out var otherB))
|
||||||
|
{
|
||||||
|
var storageIndex = storages[i].GetStorageIndex(a, b);
|
||||||
|
var relationData = storages[i].Get(storageIndex);
|
||||||
|
other.Set(otherA, otherB, i, relationData);
|
||||||
|
other.EntityStorage.AddRelationKind(otherA, i);
|
||||||
|
other.EntityStorage.AddRelationKind(otherB, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Missing transfer entity! {EntityStorage.Tag(a.ID)} related to {EntityStorage.Tag(b.ID)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace MoonTools.ECS
|
||||||
public abstract int GetStorageIndex(int entityA, int entityB);
|
public abstract int GetStorageIndex(int entityA, int entityB);
|
||||||
public abstract unsafe void* Get(int relationStorageIndex);
|
public abstract unsafe void* Get(int relationStorageIndex);
|
||||||
public abstract void UnrelateAll(int entityID);
|
public abstract void UnrelateAll(int entityID);
|
||||||
public abstract ReverseSpanEnumerator<Entity> OutRelations(int entityID);
|
public abstract ReverseSpanEnumerator<(Entity, Entity)> All();
|
||||||
public abstract RelationStorage CreateStorage();
|
public abstract RelationStorage CreateStorage();
|
||||||
public abstract void Clear();
|
public abstract void Clear();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ namespace MoonTools.ECS
|
||||||
relationDatas = (TRelation*) NativeMemory.Alloc((nuint) (capacity * Unsafe.SizeOf<TRelation>()));
|
relationDatas = (TRelation*) NativeMemory.Alloc((nuint) (capacity * Unsafe.SizeOf<TRelation>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReverseSpanEnumerator<(Entity, Entity)> All()
|
public override ReverseSpanEnumerator<(Entity, Entity)> All()
|
||||||
{
|
{
|
||||||
return new ReverseSpanEnumerator<(Entity, Entity)>(new Span<(Entity, Entity)>(relations, count));
|
return new ReverseSpanEnumerator<(Entity, Entity)>(new Span<(Entity, Entity)>(relations, count));
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ namespace MoonTools.ECS
|
||||||
return indices.ContainsKey(relation);
|
return indices.ContainsKey(relation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ReverseSpanEnumerator<Entity> OutRelations(int entityID)
|
public ReverseSpanEnumerator<Entity> OutRelations(int entityID)
|
||||||
{
|
{
|
||||||
if (outRelations.TryGetValue(entityID, out var entityOutRelations))
|
if (outRelations.TryGetValue(entityID, out var entityOutRelations))
|
||||||
{
|
{
|
||||||
|
|
38
src/World.cs
38
src/World.cs
|
@ -17,7 +17,7 @@ namespace MoonTools.ECS
|
||||||
public World()
|
public World()
|
||||||
{
|
{
|
||||||
ComponentDepot = new ComponentDepot(ComponentTypeIndices);
|
ComponentDepot = new ComponentDepot(ComponentTypeIndices);
|
||||||
RelationDepot = new RelationDepot(RelationTypeIndices);
|
RelationDepot = new RelationDepot(EntityStorage, RelationTypeIndices);
|
||||||
FilterStorage = new FilterStorage(EntityStorage, ComponentTypeIndices);
|
FilterStorage = new FilterStorage(EntityStorage, ComponentTypeIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,14 +79,6 @@ namespace MoonTools.ECS
|
||||||
EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex);
|
EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// untyped version for Transfer
|
|
||||||
internal unsafe void Relate(Entity entityA, Entity entityB, int relationTypeIndex, void* relationData)
|
|
||||||
{
|
|
||||||
RelationDepot.Set(entityA, entityB, relationTypeIndex, relationData);
|
|
||||||
EntityStorage.AddRelationKind(entityA.ID, relationTypeIndex);
|
|
||||||
EntityStorage.AddRelationKind(entityB.ID, relationTypeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged
|
public void Unrelate<TRelationKind>(in Entity entityA, in Entity entityB) where TRelationKind : unmanaged
|
||||||
{
|
{
|
||||||
var (aEmpty, bEmpty) = RelationDepot.Remove<TRelationKind>(entityA, entityB);
|
var (aEmpty, bEmpty) = RelationDepot.Remove<TRelationKind>(entityA, entityB);
|
||||||
|
@ -177,31 +169,8 @@ namespace MoonTools.ECS
|
||||||
WorldToTransferID.Add(entity.ID, otherWorldEntity.ID);
|
WorldToTransferID.Add(entity.ID, otherWorldEntity.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: make sure this preserves relation order, should probably do something similar to filter storage
|
// transfer relations
|
||||||
// set relations before components so filters don't freak out
|
RelationDepot.TransferStorage(WorldToTransferID, other.RelationDepot);
|
||||||
foreach (var entity in filter.Entities)
|
|
||||||
{
|
|
||||||
var otherWorldEntityA = WorldToTransferID[entity.ID];
|
|
||||||
|
|
||||||
foreach (var relationTypeIndex in EntityStorage.RelationTypeIndices(entity.ID))
|
|
||||||
{
|
|
||||||
foreach (var entityB in RelationDepot.OutRelations(entity.ID, relationTypeIndex))
|
|
||||||
{
|
|
||||||
var storageIndex = RelationDepot.GetStorageIndex(relationTypeIndex, entity.ID, entityB);
|
|
||||||
|
|
||||||
int otherWorldEntityB;
|
|
||||||
if (WorldToTransferID.TryGetValue(entityB, out otherWorldEntityB))
|
|
||||||
{
|
|
||||||
other.Relate(otherWorldEntityA, otherWorldEntityB, relationTypeIndex, RelationDepot.Get(relationTypeIndex, storageIndex));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// related entity is not in the filter
|
|
||||||
throw new Exception($"Missing transfer entity! {EntityStorage.Tag(entity.ID)} related to {EntityStorage.Tag(entityB.ID)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set components
|
// set components
|
||||||
foreach (var entity in filter.Entities)
|
foreach (var entity in filter.Entities)
|
||||||
|
@ -214,6 +183,7 @@ namespace MoonTools.ECS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transfer filters last so callbacks trigger correctly
|
||||||
FilterStorage.TransferStorage(WorldToTransferID, other.FilterStorage);
|
FilterStorage.TransferStorage(WorldToTransferID, other.FilterStorage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue