diff --git a/src/FilterStorage.cs b/src/FilterStorage.cs index 9d10c2c..55c9b9b 100644 --- a/src/FilterStorage.cs +++ b/src/FilterStorage.cs @@ -20,6 +20,35 @@ namespace MoonTools.ECS ComponentTypeIndices = componentTypeIndices; } + private void CopyTypeCache(Dictionary> typeCache) + { + foreach (var type in typeCache.Keys) + { + if (!typeToFilterSignatures.ContainsKey(type)) + { + typeToFilterSignatures.Add(type, new List()); + + 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()); + } + } + + CopyTypeCache(other.typeToFilterSignatures); + } + public Filter CreateFilter(IndexableSet included, IndexableSet 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 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() { diff --git a/src/World.cs b/src/World.cs index 79fa68f..e0400e0 100644 --- a/src/World.cs +++ b/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(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); } } }