diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 92d3fed..6dd4a6f 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -86,6 +86,7 @@ namespace DCFApixels.DragonECS private StructList _listeners = new StructList(2); private StructList _entityListeners = new StructList(2); + private bool _hasAnyEntityListener = false; #region Properties EcsWorld IEntityStorage.World @@ -394,7 +395,10 @@ namespace DCFApixels.DragonECS { slot.gen |= GEN_SLEEP_MASK; } - _entityListeners.InvokeOnNewEntity(entityID); + if (_hasAnyEntityListener) + { + _entityListeners.InvokeOnNewEntity(entityID); + } MoveToEmptyEntities(entityID); } @@ -436,7 +440,10 @@ namespace DCFApixels.DragonECS _delEntBuffer[_delEntBufferCount++] = entityID; _entities[entityID].isUsed = false; _entitiesCount--; - _entityListeners.InvokeOnDelEntity(entityID); + if (_hasAnyEntityListener) + { + _entityListeners.InvokeOnDelEntity(entityID); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void MoveToEmptyEntities(int entityID) @@ -1045,10 +1052,12 @@ namespace DCFApixels.DragonECS public void AddListener(IEcsEntityEventListener entityEventListener) { _entityListeners.Add(entityEventListener); + _hasAnyEntityListener = _entityListeners.Count > 0; } public void RemoveListener(IEcsEntityEventListener entityEventListener) { _entityListeners.Remove(entityEventListener); + _hasAnyEntityListener = _entityListeners.Count > 0; } #endregion @@ -1374,6 +1383,7 @@ namespace DCFApixels.DragonECS public interface IEcsEntityEventListener { void OnNewEntity(int entityID); + void OnMigrateEntity(int entityID); void OnDelEntity(int entityID); } internal static class WorldEventListExtensions @@ -1411,6 +1421,14 @@ namespace DCFApixels.DragonECS } } [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InvokeOnMigrateEntity(this ref StructList self, int entityID) + { + for (int i = 0, iMax = self.Count; i < iMax; i++) + { + self[i].OnMigrateEntity(entityID); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void InvokeOnDelEntity(this ref StructList self, int entityID) { for (int i = 0, iMax = self.Count; i < iMax; i++) diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs index 9b0d3fd..9e2c941 100644 --- a/src/EcsWorld.pools.cs +++ b/src/EcsWorld.pools.cs @@ -286,6 +286,10 @@ namespace DCFApixels.DragonECS RemoveFromEmptyEntities(entityID); } _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] |= maskBit.mask; + if (_hasAnyEntityListener) + { + _entityListeners.InvokeOnMigrateEntity(entityID); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) @@ -296,12 +300,15 @@ namespace DCFApixels.DragonECS slot.version++; var count = --_entities[entityID].componentsCount; _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] &= ~maskBit.mask; - if (count == 0 && IsUsed(entityID)) { MoveToEmptyEntities(entityID); } CheckUnregisterValid(count, entityID); + if (_hasAnyEntityListener) + { + _entityListeners.InvokeOnMigrateEntity(entityID); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool TryRegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) @@ -320,6 +327,10 @@ namespace DCFApixels.DragonECS { RemoveFromEmptyEntities(entityID); } + if (_hasAnyEntityListener) + { + _entityListeners.InvokeOnMigrateEntity(entityID); + } return true; } return false; @@ -343,6 +354,10 @@ namespace DCFApixels.DragonECS MoveToEmptyEntities(entityID); } CheckUnregisterValid(count, entityID); + if (_hasAnyEntityListener) + { + _entityListeners.InvokeOnMigrateEntity(entityID); + } return true; } return false; diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index 3b71fcd..81bdad8 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -160,6 +160,7 @@ namespace DCFApixels.DragonECS.Core.Internal SortHalper.Sort(_filteredEntities.AsSpan(_filteredEntitiesCount), comparison); return new EcsUnsafeSpan(World.ID, _filteredEntities.Ptr, _filteredEntitiesCount); } + public override EcsSpan Snapshot() { return Execute(); } #endregion } } \ No newline at end of file diff --git a/src/Executors/EcsWhereToGroupExecutor.cs b/src/Executors/EcsWhereToGroupExecutor.cs index 6b19643..0c2bfb5 100644 --- a/src/Executors/EcsWhereToGroupExecutor.cs +++ b/src/Executors/EcsWhereToGroupExecutor.cs @@ -117,6 +117,7 @@ namespace DCFApixels.DragonECS.Core.Internal ExecuteFor_Iternal(span); return _filteredGroup; } + public override EcsSpan Snapshot() { return Execute(); } #endregion } } \ No newline at end of file diff --git a/src/Executors/MaskQueryExecutor.cs b/src/Executors/MaskQueryExecutor.cs index e835c66..d697082 100644 --- a/src/Executors/MaskQueryExecutor.cs +++ b/src/Executors/MaskQueryExecutor.cs @@ -105,6 +105,7 @@ namespace DCFApixels.DragonECS.Core } protected abstract void OnInitialize(); protected abstract void OnDestroy(); + public abstract EcsSpan Snapshot(); } #if ENABLE_IL2CPP