fix filter results being out of order on world transfer
parent
a2a81bf477
commit
3cba3e047c
|
@ -20,6 +20,35 @@ namespace MoonTools.ECS
|
|||
ComponentTypeIndices = componentTypeIndices;
|
||||
}
|
||||
|
||||
private void CopyTypeCache(Dictionary<int, List<FilterSignature>> typeCache)
|
||||
{
|
||||
foreach (var type in typeCache.Keys)
|
||||
{
|
||||
if (!typeToFilterSignatures.ContainsKey(type))
|
||||
{
|
||||
typeToFilterSignatures.Add(type, new List<FilterSignature>());
|
||||
|
||||
foreach (var signature in typeCache[type])
|
||||
{
|
||||
typeToFilterSignatures[type].Add(signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateMissingStorages(FilterStorage other)
|
||||
{
|
||||
foreach (var filterSignature in other.filterSignatureToEntityIDs.Keys)
|
||||
{
|
||||
if (!filterSignatureToEntityIDs.ContainsKey(filterSignature))
|
||||
{
|
||||
filterSignatureToEntityIDs.Add(filterSignature, new IndexableSet<Entity>());
|
||||
}
|
||||
}
|
||||
|
||||
CopyTypeCache(other.typeToFilterSignatures);
|
||||
}
|
||||
|
||||
public Filter CreateFilter(IndexableSet<int> included, IndexableSet<int> excluded)
|
||||
{
|
||||
var filterSignature = new FilterSignature(included, excluded);
|
||||
|
@ -174,6 +203,32 @@ namespace MoonTools.ECS
|
|||
}
|
||||
}
|
||||
|
||||
// Used by TransferEntity
|
||||
public void AddEntity(FilterSignature signature, int entityID)
|
||||
{
|
||||
filterSignatureToEntityIDs[signature].Add(entityID);
|
||||
}
|
||||
|
||||
public void TransferStorage(Dictionary<int, int> worldToTransferID, FilterStorage other)
|
||||
{
|
||||
foreach (var (filterSignature, entityIDs) in filterSignatureToEntityIDs)
|
||||
{
|
||||
foreach (var entity in entityIDs)
|
||||
{
|
||||
if (worldToTransferID.ContainsKey(entity))
|
||||
{
|
||||
var otherEntityID = worldToTransferID[entity];
|
||||
other.AddEntity(filterSignature, otherEntityID);
|
||||
|
||||
if (other.addCallbacks.TryGetValue(filterSignature, out var addCallback))
|
||||
{
|
||||
addCallback(otherEntityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// used by World.Clear, ignores callbacks
|
||||
public void Clear()
|
||||
{
|
||||
|
|
14
src/World.cs
14
src/World.cs
|
@ -54,14 +54,11 @@ namespace MoonTools.ECS
|
|||
}
|
||||
|
||||
// untyped version for Transfer
|
||||
// no filter check because filter state is copied directly
|
||||
internal unsafe void Set(Entity entity, int componentTypeIndex, void* component)
|
||||
{
|
||||
ComponentDepot.Set(entity.ID, componentTypeIndex, component);
|
||||
|
||||
if (EntityStorage.SetComponent(entity.ID, componentTypeIndex))
|
||||
{
|
||||
FilterStorage.Check(entity.ID, componentTypeIndex);
|
||||
}
|
||||
EntityStorage.SetComponent(entity.ID, componentTypeIndex);
|
||||
}
|
||||
|
||||
public void Remove<TComponent>(in Entity entity) where TComponent : unmanaged
|
||||
|
@ -163,6 +160,10 @@ namespace MoonTools.ECS
|
|||
other.ComponentDepot.CreateMissingStorages(ComponentDepot);
|
||||
other.RelationDepot.CreateMissingStorages(RelationDepot);
|
||||
|
||||
// FIXME: we could just do this once on startup
|
||||
// Could have a PrepareTransfer method or something
|
||||
other.FilterStorage.CreateMissingStorages(FilterStorage);
|
||||
|
||||
// destroy all entities matching the filter
|
||||
foreach (var entity in otherFilter.Entities)
|
||||
{
|
||||
|
@ -176,6 +177,7 @@ namespace MoonTools.ECS
|
|||
WorldToTransferID.Add(entity.ID, otherWorldEntity.ID);
|
||||
}
|
||||
|
||||
// FIXME: make sure this preserves relation order, should probably do something similar to filter storage
|
||||
// set relations before components so filters don't freak out
|
||||
foreach (var entity in filter.Entities)
|
||||
{
|
||||
|
@ -211,6 +213,8 @@ namespace MoonTools.ECS
|
|||
other.Set(otherWorldEntity, componentTypeIndex, ComponentDepot.UntypedGet(entity.ID, componentTypeIndex));
|
||||
}
|
||||
}
|
||||
|
||||
FilterStorage.TransferStorage(WorldToTransferID, other.FilterStorage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue