From 2fff79439e41525308c99ba306e69bc8b210a28a Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 12 Mar 2025 13:08:16 +0800 Subject: [PATCH 01/10] impl IEntityStorage in EcsPool --- src/Pools/EcsPool.cs | 146 +++++++++++++++++++++++++++------------- src/Pools/EcsTagPool.cs | 2 +- 2 files changed, 101 insertions(+), 47 deletions(-) diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 49e34a6..7dfeb19 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -1,3 +1,6 @@ +#if DISABLE_DEBUG +#undef DEBUG +#endif using DCFApixels.DragonECS.Core; using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.PoolsCore; @@ -28,8 +31,8 @@ namespace DCFApixels.DragonECS [MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.POOLS_GROUP)] [MetaDescription(EcsConsts.AUTHOR, "Pool for IEcsComponent components.")] [MetaID("C501547C9201A4B03FC25632E4FAAFD7")] - [DebuggerDisplay("{ComponentType}: {Count}")] - public sealed class EcsPool : IEcsPoolImplementation, IEcsStructPool, IEnumerable //IEnumerable - IntelliSense hack + [DebuggerDisplay("Count: {Count} Type: {ComponentType}")] + public sealed class EcsPool : IEcsPoolImplementation, IEcsStructPool, IEntityStorage, IEnumerable //IEnumerable - IntelliSense hack where T : struct, IEcsComponent { private EcsWorld _source; @@ -39,13 +42,17 @@ namespace DCFApixels.DragonECS private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private T[] _items; //dense private int _itemsCount = 0; - private int[] _recycledItems; - private int _recycledItemsCount = 0; + private int _capacity = 0; - private IEcsComponentLifecycle _componentLifecycleHandler = EcsComponentResetHandler.instance; - private bool _isHasComponentLifecycleHandler = EcsComponentResetHandler.isHasHandler; - private IEcsComponentCopy _componentCopyHandler = EcsComponentCopyHandler.instance; - private bool _isHasComponentCopyHandler = EcsComponentCopyHandler.isHasHandler; + private int[] _sparseEntities; + private int[] _denseEntitiesDelayed; + private int _denseEntitiesDelayedCount = 0; + private bool _isDenseEntitiesDelayedValid = false; + + private readonly IEcsComponentLifecycle _componentLifecycleHandler = EcsComponentResetHandler.instance; + private readonly bool _isHasComponentLifecycleHandler = EcsComponentResetHandler.isHasHandler; + private readonly IEcsComponentCopy _componentCopyHandler = EcsComponentCopyHandler.instance; + private readonly bool _isHasComponentCopyHandler = EcsComponentCopyHandler.isHasHandler; #if !DISABLE_POOLS_EVENTS private readonly StructList _listeners = new StructList(2); @@ -90,21 +97,10 @@ namespace DCFApixels.DragonECS if (itemIndex > 0) { EcsPoolThrowHelper.ThrowAlreadyHasComponent(entityID); } if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } #endif - if (_recycledItemsCount > 0) - { - itemIndex = _recycledItems[--_recycledItemsCount]; - _itemsCount++; - } - else - { - itemIndex = ++_itemsCount; - if (itemIndex >= _items.Length) - { - Array.Resize(ref _items, _items.Length << 1); - } - } + itemIndex = GetFreeItemIndex(entityID); _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); ref T result = ref _items[itemIndex]; + _sparseEntities[itemIndex] = entityID; EnableComponent(ref result); #if !DISABLE_POOLS_EVENTS _listeners.InvokeOnAddAndGet(entityID, _listenersCachedCount); @@ -132,26 +128,15 @@ namespace DCFApixels.DragonECS } public ref T TryAddOrGet(int entityID) { +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } +#endif ref int itemIndex = ref _mapping[entityID]; if (itemIndex <= 0) { //Add block -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } -#endif - if (_recycledItemsCount > 0) - { - itemIndex = _recycledItems[--_recycledItemsCount]; - _itemsCount++; - } - else - { - itemIndex = ++_itemsCount; - if (itemIndex >= _items.Length) - { - Array.Resize(ref _items, _items.Length << 1); - } - } + itemIndex = GetFreeItemIndex(entityID); _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); + _sparseEntities[itemIndex] = entityID; EnableComponent(ref _items[itemIndex]); #if !DISABLE_POOLS_EVENTS _listeners.InvokeOnAdd(entityID, _listenersCachedCount); @@ -177,14 +162,11 @@ namespace DCFApixels.DragonECS if (itemIndex <= 0) { EcsPoolThrowHelper.ThrowNotHaveComponent(entityID); } #endif DisableComponent(ref _items[itemIndex]); - if (_recycledItemsCount >= _recycledItems.Length) - { - Array.Resize(ref _recycledItems, _recycledItems.Length << 1); - } - _recycledItems[_recycledItemsCount++] = itemIndex; + _sparseEntities[itemIndex] = 0; itemIndex = 0; _itemsCount--; _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); + _isDenseEntitiesDelayedValid = false; #if !DISABLE_POOLS_EVENTS _listeners.InvokeOnDel(entityID, _listenersCachedCount); #endif @@ -216,7 +198,6 @@ namespace DCFApixels.DragonECS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } #endif - _recycledItemsCount = 0; // спереди потому чтобы обнулялось, так как Del не обнуляет if (_itemsCount <= 0) { return; } _itemsCount = 0; var span = _source.Where(out SingleAspect _); @@ -246,8 +227,15 @@ namespace DCFApixels.DragonECS _maskBit = EcsMaskChunck.FromID(componentTypeID); _mapping = new int[world.Capacity]; - _items = new T[ArrayUtility.NormalizeSizeToPowerOfTwo(world.Configs.GetWorldConfigOrDefault().PoolComponentsCapacity)]; - _recycledItems = new int[world.Configs.GetWorldConfigOrDefault().PoolRecycledComponentsCapacity]; + Resize(ArrayUtility.NormalizeSizeToPowerOfTwo(world.Configs.GetWorldConfigOrDefault().PoolComponentsCapacity)); + //_capacity = ArrayUtility.NormalizeSizeToPowerOfTwo(world.Configs.GetWorldConfigOrDefault().PoolComponentsCapacity); + //_items = new T[_capacity]; + //_sparseEntities = new int[_capacity]; + //_denseEntitiesDelayed = new int[_capacity]; + //for (int i = 0; i < _capacity; i++) + //{// можно оптимизировать тем чтобы вместо заполнения, в методе выдачи free index-а если _denseEntitiesDelayed возвращает 0, то free index определять через инкремент + // _denseEntitiesDelayed[i] = i; + //} } void IEcsPoolImplementation.OnWorldResize(int newSize) { @@ -279,6 +267,72 @@ namespace DCFApixels.DragonECS { Get(entityID) = dataRaw == null ? default : (T)dataRaw; } + + + public EcsSpan ToSpan() + { + UpdateDenseEntities(); + return new EcsSpan(_source.ID, _denseEntitiesDelayed, 1, _itemsCount); + } + private bool IsDenseEntitiesDelayedValid() + { + return _isDenseEntitiesDelayedValid;//_itemsCount == _denseEntitiesDelayedCount; + } + private void UpdateDenseEntities() + { + //if (IsDenseEntitiesDelayedValid()) { return; } + _denseEntitiesDelayedCount = 0; + for (int i = 0, jRight = _itemsCount + 1; i < _capacity; i++) + { + if (_sparseEntities[i] == 0 && i != 0) + { + _denseEntitiesDelayed[jRight] = i; + jRight++; + } + else + { + _denseEntitiesDelayed[_denseEntitiesDelayedCount++] = _sparseEntities[i]; + } + } + _isDenseEntitiesDelayedValid = true; + } + private int GetFreeItemIndex(int entityID) + { + //if (_denseEntitiesDelayedCount >= _capacity - 1) + { + UpdateDenseEntities(); + } + + if (_itemsCount >= _capacity - 1) + { + Resize(_items.Length << 1); + } + + int result = _denseEntitiesDelayed[_denseEntitiesDelayedCount]; + _denseEntitiesDelayed[_denseEntitiesDelayedCount] = entityID; + _itemsCount++; + _denseEntitiesDelayedCount++; + if(result == 0) + { + + } + return result; + } + private void CheckOrUpsize() + { + if (_itemsCount < _capacity) { return; } + Resize(_items.Length << 1); + } + private void Resize(int newSize) + { + if (newSize <= _capacity) { return; } + ArrayUtility.ResizeOrCreate(ref _sparseEntities, newSize); + ArrayUtility.ResizeOrCreate(ref _items, newSize); + _denseEntitiesDelayed = new int[newSize]; + _denseEntitiesDelayedCount = 0; + _capacity = newSize; + UpdateDenseEntities(); + } #endregion #region Listeners @@ -298,7 +352,7 @@ namespace DCFApixels.DragonECS } } #endif - #endregion +#endregion #region Enable/Disable/Copy [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index b3f8d29..e4b25af 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -31,7 +31,7 @@ namespace DCFApixels.DragonECS [MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.POOLS_GROUP)] [MetaDescription(EcsConsts.AUTHOR, "Pool for IEcsTagComponent components. EcsTagPool is optimized for storing tag components or components without data.")] [MetaID("9D80547C9201E852E4F17324EAC1E15A")] - [DebuggerDisplay("Count: {Count}")] + [DebuggerDisplay("Count: {Count} Type: {ComponentType}")] public sealed class EcsTagPool : IEcsPoolImplementation, IEcsStructPool, IEnumerable //IEnumerable - IntelliSense hack where T : struct, IEcsTagComponent { From ab444859d3deef8ceff8e0cea11f3ac3e302d177 Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 12 Mar 2025 15:29:16 +0800 Subject: [PATCH 02/10] fix --- src/Consts.cs | 6 ++ src/EcsMask.cs | 2 +- src/EcsWorld.cs | 8 +-- src/Internal/ArrayUtility.cs | 2 +- src/Pools/EcsPool.cs | 128 ++++++++++++++++++++++++++++------- 5 files changed, 115 insertions(+), 31 deletions(-) diff --git a/src/Consts.cs b/src/Consts.cs index ee13215..ee34699 100644 --- a/src/Consts.cs +++ b/src/Consts.cs @@ -93,6 +93,12 @@ true; #else false; +#endif + public const bool DRAGONECS_DEEP_DEBUG = +#if DRAGONECS_DEV_MODE + true; +#else + false; #endif } } diff --git a/src/EcsMask.cs b/src/EcsMask.cs index 91149c4..de29a8c 100644 --- a/src/EcsMask.cs +++ b/src/EcsMask.cs @@ -869,7 +869,7 @@ namespace DCFApixels.DragonECS { return new Enumerator(_span.Slice(0, 0), _iterator); } - if (_iterator.TryGetEntityStorage(out IEntityStorage storage)) + if (_span.IsSourceEntities && _iterator.TryGetEntityStorage(out IEntityStorage storage)) { return new Enumerator(storage.ToSpan(), _iterator); } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 6639c98..5860d73 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -127,11 +127,7 @@ namespace DCFApixels.DragonECS public EcsSpan Entities { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - ReleaseDelEntityBufferAll(); - return GetCurrentEntities_Internal(); - } + get { return ToSpan(); } } public int PoolsCount { @@ -397,7 +393,7 @@ namespace DCFApixels.DragonECS { ReleaseDelEntityBufferAll(); } - return _entityDispenser.UsedToEcsSpan(ID); + return GetCurrentEntities_Internal(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe entlong GetEntityLong(int entityID) diff --git a/src/Internal/ArrayUtility.cs b/src/Internal/ArrayUtility.cs index 9a13bd2..e95d43f 100644 --- a/src/Internal/ArrayUtility.cs +++ b/src/Internal/ArrayUtility.cs @@ -69,7 +69,7 @@ namespace DCFApixels.DragonECS.Internal //TODO потестить public static void ResizeOrCreate(ref T[] array, int newSize) { - if(array == null) + if (array == null) { array = new T[newSize]; } diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 7dfeb19..61fced4 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -4,6 +4,7 @@ using DCFApixels.DragonECS.Core; using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.PoolsCore; +using DCFApixels.DragonECS.UncheckedCore; using System; using System.Collections; using System.Collections.Generic; @@ -105,6 +106,14 @@ namespace DCFApixels.DragonECS #if !DISABLE_POOLS_EVENTS _listeners.InvokeOnAddAndGet(entityID, _listenersCachedCount); #endif + + +#if DRAGONECS_DEEP_DEBUG + if (_mediator.GetComponentCount(_componentTypeID) != _itemsCount) + { + Throw.UndefinedException(); + } +#endif return ref result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -128,24 +137,43 @@ namespace DCFApixels.DragonECS } public ref T TryAddOrGet(int entityID) { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } -#endif - ref int itemIndex = ref _mapping[entityID]; - if (itemIndex <= 0) - { //Add block - itemIndex = GetFreeItemIndex(entityID); - _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); - _sparseEntities[itemIndex] = entityID; - EnableComponent(ref _items[itemIndex]); -#if !DISABLE_POOLS_EVENTS - _listeners.InvokeOnAdd(entityID, _listenersCachedCount); -#endif - } //Add block end -#if !DISABLE_POOLS_EVENTS - _listeners.InvokeOnGet(entityID, _listenersCachedCount); -#endif - return ref _items[itemIndex]; + if (Has(entityID)) + { + return ref Get(entityID); + } + else + { + return ref Add(entityID); + } + + + + //#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + // if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } + //#endif + // ref int itemIndex = ref _mapping[entityID]; + // if (itemIndex <= 0) + // { //Add block + // itemIndex = GetFreeItemIndex(entityID); + // _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); + // _sparseEntities[itemIndex] = entityID; + // EnableComponent(ref _items[itemIndex]); + //#if !DISABLE_POOLS_EVENTS + // _listeners.InvokeOnAdd(entityID, _listenersCachedCount); + //#endif + // } //Add block end + //#if !DISABLE_POOLS_EVENTS + // _listeners.InvokeOnGet(entityID, _listenersCachedCount); + //#endif + // + // + //#if DRAGONECS_DEEP_DEBUG + // if (_mediator.GetComponentCount(_componentTypeID) != _itemsCount) + // { + // Throw.UndefinedException(); + // } + //#endif + // return ref _items[itemIndex]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Has(int entityID) @@ -170,6 +198,13 @@ namespace DCFApixels.DragonECS #if !DISABLE_POOLS_EVENTS _listeners.InvokeOnDel(entityID, _listenersCachedCount); #endif + +#if DRAGONECS_DEEP_DEBUG + if (_mediator.GetComponentCount(_componentTypeID) != _itemsCount) + { + Throw.UndefinedException(); + } +#endif } public void TryDel(int entityID) { @@ -268,11 +303,22 @@ namespace DCFApixels.DragonECS Get(entityID) = dataRaw == null ? default : (T)dataRaw; } - + private bool _lockToSpan = false; public EcsSpan ToSpan() { + if (_lockToSpan) + { + return _source.Entities; + } UpdateDenseEntities(); - return new EcsSpan(_source.ID, _denseEntitiesDelayed, 1, _itemsCount); + var span = new EcsSpan(_source.ID, _denseEntitiesDelayed, 1, _itemsCount); +#if DRAGONECS_DEEP_DEBUG + if (UncheckedCoreUtility.CheckSpanValideDebug(span) == false) + { + Throw.UndefinedException(); + } +#endif + return span; } private bool IsDenseEntitiesDelayedValid() { @@ -294,6 +340,40 @@ namespace DCFApixels.DragonECS _denseEntitiesDelayed[_denseEntitiesDelayedCount++] = _sparseEntities[i]; } } +#if DRAGONECS_DEEP_DEBUG + _lockToSpan = true; + if (_denseEntitiesDelayed[0] != 0) + { + Throw.UndefinedException(); + } + if (_denseEntitiesDelayedCount != _itemsCount + 1) + { + Throw.UndefinedException(); + } + int coreCount = _mediator.GetComponentCount(_componentTypeID); + if (coreCount != _itemsCount) + { + Throw.UndefinedException(); + } + using (_source.DisableAutoReleaseDelEntBuffer()) using (var group = EcsGroup.New(_source)) + { + EcsStaticMask.Inc().Build().ToMask(_source).GetIterator().IterateTo(World.Entities, group); + var span = new EcsSpan(_source.ID, _denseEntitiesDelayed, 1, _itemsCount); + if (group.SetEquals(span) == false) + { + Throw.UndefinedException(); + } + } + _lockToSpan = false; + for (int i = _denseEntitiesDelayedCount; i < _capacity; i++) + { + var index = _denseEntitiesDelayed[i]; + if (_sparseEntities[index] != 0) + { + Throw.UndefinedException(); + } + } +#endif _isDenseEntitiesDelayedValid = true; } private int GetFreeItemIndex(int entityID) @@ -312,10 +392,12 @@ namespace DCFApixels.DragonECS _denseEntitiesDelayed[_denseEntitiesDelayedCount] = entityID; _itemsCount++; _denseEntitiesDelayedCount++; - if(result == 0) +#if DRAGONECS_DEEP_DEBUG + if (result == 0) { - + Throw.UndefinedException(); } +#endif return result; } private void CheckOrUpsize() @@ -352,7 +434,7 @@ namespace DCFApixels.DragonECS } } #endif -#endregion + #endregion #region Enable/Disable/Copy [MethodImpl(MethodImplOptions.AggressiveInlining)] From 50691b33097d78a26e5a418be6a0a8ccf346ed0b Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 12 Mar 2025 17:18:46 +0800 Subject: [PATCH 03/10] stash --- src/EcsRunner.cs | 4 ++-- src/Pools/EcsPool.cs | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index 67ad62a..c288b28 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -443,7 +443,7 @@ namespace DCFApixels.DragonECS { try { - translationCallback(pair.run, t0); + translationCallback(pair.run, ref data); } catch (Exception e) { @@ -456,7 +456,7 @@ namespace DCFApixels.DragonECS { if (pair.runFinally != null) { - translationFinnalyCallback(pair.runFinally, t0); + translationFinnalyCallback(pair.runFinally, ref data); } } } diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 61fced4..c301bd5 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -303,13 +303,17 @@ namespace DCFApixels.DragonECS Get(entityID) = dataRaw == null ? default : (T)dataRaw; } +#if DRAGONECS_DEEP_DEBUG private bool _lockToSpan = false; +#endif public EcsSpan ToSpan() { +#if DRAGONECS_DEEP_DEBUG if (_lockToSpan) { return _source.Entities; } +#endif UpdateDenseEntities(); var span = new EcsSpan(_source.ID, _denseEntitiesDelayed, 1, _itemsCount); #if DRAGONECS_DEEP_DEBUG @@ -326,7 +330,7 @@ namespace DCFApixels.DragonECS } private void UpdateDenseEntities() { - //if (IsDenseEntitiesDelayedValid()) { return; } + if (IsDenseEntitiesDelayedValid()) { return; } _denseEntitiesDelayedCount = 0; for (int i = 0, jRight = _itemsCount + 1; i < _capacity; i++) { @@ -378,7 +382,7 @@ namespace DCFApixels.DragonECS } private int GetFreeItemIndex(int entityID) { - //if (_denseEntitiesDelayedCount >= _capacity - 1) + if (_denseEntitiesDelayedCount >= _capacity - 1) { UpdateDenseEntities(); } @@ -413,9 +417,10 @@ namespace DCFApixels.DragonECS _denseEntitiesDelayed = new int[newSize]; _denseEntitiesDelayedCount = 0; _capacity = newSize; + _isDenseEntitiesDelayedValid = false; UpdateDenseEntities(); } - #endregion +#endregion #region Listeners #if !DISABLE_POOLS_EVENTS @@ -434,7 +439,7 @@ namespace DCFApixels.DragonECS } } #endif - #endregion +#endregion #region Enable/Disable/Copy [MethodImpl(MethodImplOptions.AggressiveInlining)] From 2d9499cd9e9d4ec62e935fa8e5ffa966fdf968ff Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 12 Mar 2025 17:56:12 +0800 Subject: [PATCH 04/10] fix --- src/Executors/MaskQueryExecutor.cs | 2 +- src/Pools/EcsPool.cs | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Executors/MaskQueryExecutor.cs b/src/Executors/MaskQueryExecutor.cs index 96e786a..46e70f3 100644 --- a/src/Executors/MaskQueryExecutor.cs +++ b/src/Executors/MaskQueryExecutor.cs @@ -176,7 +176,7 @@ namespace DCFApixels.DragonECS.Core long* ptr = _versions; var slots = _world._poolSlots; - bool result = _maskInc.Length > 0 || _maskExc.Length > 0; + bool result = _maskInc.Length != 0 | _maskExc.Length != 0; //тут РІРѕР·РјРѕР¶РЅРѕ РЅСѓР¶РЅРѕ оптимизировать foreach (var slotIndex in _maskInc) { ptr++; diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index c301bd5..40eb2cc 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -324,17 +324,14 @@ namespace DCFApixels.DragonECS #endif return span; } - private bool IsDenseEntitiesDelayedValid() - { - return _isDenseEntitiesDelayedValid;//_itemsCount == _denseEntitiesDelayedCount; - } private void UpdateDenseEntities() { - if (IsDenseEntitiesDelayedValid()) { return; } - _denseEntitiesDelayedCount = 0; - for (int i = 0, jRight = _itemsCount + 1; i < _capacity; i++) + if (_isDenseEntitiesDelayedValid) { return; } + _denseEntitiesDelayedCount = 1; + _denseEntitiesDelayed[0] = 0; + for (int i = 1, jRight = _itemsCount + 1; i < _capacity; i++) { - if (_sparseEntities[i] == 0 && i != 0) + if (_sparseEntities[i] == 0) { _denseEntitiesDelayed[jRight] = i; jRight++; From c715ddd3b17ca53c8fed9b6f2e836a680471700a Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 12 Mar 2025 23:24:48 +0800 Subject: [PATCH 05/10] Update EcsPool.cs --- src/Pools/EcsPool.cs | 94 ++++++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 40eb2cc..fc3a1e1 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -49,6 +49,7 @@ namespace DCFApixels.DragonECS private int[] _denseEntitiesDelayed; private int _denseEntitiesDelayedCount = 0; private bool _isDenseEntitiesDelayedValid = false; + private int _recycledCount = 0; private readonly IEcsComponentLifecycle _componentLifecycleHandler = EcsComponentResetHandler.instance; private readonly bool _isHasComponentLifecycleHandler = EcsComponentResetHandler.isHasHandler; @@ -56,7 +57,7 @@ namespace DCFApixels.DragonECS private readonly bool _isHasComponentCopyHandler = EcsComponentCopyHandler.isHasHandler; #if !DISABLE_POOLS_EVENTS - private readonly StructList _listeners = new StructList(2); + private StructList _listeners = new StructList(2); private int _listenersCachedCount = 0; #endif private bool _isLocked; @@ -137,43 +138,43 @@ namespace DCFApixels.DragonECS } public ref T TryAddOrGet(int entityID) { - if (Has(entityID)) - { - return ref Get(entityID); - } - else - { - return ref Add(entityID); - } + //if (Has(entityID)) + //{ + // return ref Get(entityID); + //} + //else + //{ + // return ref Add(entityID); + //} - //#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - // if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } - //#endif - // ref int itemIndex = ref _mapping[entityID]; - // if (itemIndex <= 0) - // { //Add block - // itemIndex = GetFreeItemIndex(entityID); - // _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); - // _sparseEntities[itemIndex] = entityID; - // EnableComponent(ref _items[itemIndex]); - //#if !DISABLE_POOLS_EVENTS - // _listeners.InvokeOnAdd(entityID, _listenersCachedCount); - //#endif - // } //Add block end - //#if !DISABLE_POOLS_EVENTS - // _listeners.InvokeOnGet(entityID, _listenersCachedCount); - //#endif - // - // - //#if DRAGONECS_DEEP_DEBUG - // if (_mediator.GetComponentCount(_componentTypeID) != _itemsCount) - // { - // Throw.UndefinedException(); - // } - //#endif - // return ref _items[itemIndex]; +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); } +#endif + ref int itemIndex = ref _mapping[entityID]; + if (itemIndex <= 0) + { //Add block + itemIndex = GetFreeItemIndex(entityID); + _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); + _sparseEntities[itemIndex] = entityID; + EnableComponent(ref _items[itemIndex]); +#if !DISABLE_POOLS_EVENTS + _listeners.InvokeOnAdd(entityID, _listenersCachedCount); +#endif + } //Add block end +#if !DISABLE_POOLS_EVENTS + _listeners.InvokeOnGet(entityID, _listenersCachedCount); +#endif + + +#if DRAGONECS_DEEP_DEBUG + if (_mediator.GetComponentCount(_componentTypeID) != _itemsCount) + { + Throw.UndefinedException(); + } +#endif + return ref _items[itemIndex]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Has(int entityID) @@ -329,12 +330,14 @@ namespace DCFApixels.DragonECS if (_isDenseEntitiesDelayedValid) { return; } _denseEntitiesDelayedCount = 1; _denseEntitiesDelayed[0] = 0; - for (int i = 1, jRight = _itemsCount + 1; i < _capacity; i++) + _recycledCount = 0; + for (int i = 1, jRight = _itemsCount + 1; _denseEntitiesDelayedCount <= _itemsCount; i++) { if (_sparseEntities[i] == 0) { _denseEntitiesDelayed[jRight] = i; jRight++; + _recycledCount++; } else { @@ -366,7 +369,7 @@ namespace DCFApixels.DragonECS } } _lockToSpan = false; - for (int i = _denseEntitiesDelayedCount; i < _capacity; i++) + for (int i = _denseEntitiesDelayedCount; i < _denseEntitiesDelayedCount + _recycledCount; i++) { var index = _denseEntitiesDelayed[i]; if (_sparseEntities[index] != 0) @@ -388,12 +391,25 @@ namespace DCFApixels.DragonECS { Resize(_items.Length << 1); } - - int result = _denseEntitiesDelayed[_denseEntitiesDelayedCount]; + int result = 0; + if(_recycledCount > 0) + { + _recycledCount--; + result = _denseEntitiesDelayed[_denseEntitiesDelayedCount]; + } + else + { + result = _denseEntitiesDelayedCount; + } _denseEntitiesDelayed[_denseEntitiesDelayedCount] = entityID; _itemsCount++; _denseEntitiesDelayedCount++; + #if DRAGONECS_DEEP_DEBUG + if (_sparseEntities[result] != 0) + { + Throw.UndefinedException(); + } if (result == 0) { Throw.UndefinedException(); From 1d94ad41191abef311a8ed9d0307fce681daf99e Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:16:09 +0800 Subject: [PATCH 06/10] add IOnInitInjectionComplete.OnBeforeInitInjection --- src/Injections/Injector.cs | 8 +++++++- src/Injections/Utils/Interfaces.cs | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Injections/Injector.cs b/src/Injections/Injector.cs index cf82f7d..3efe4bf 100644 --- a/src/Injections/Injector.cs +++ b/src/Injections/Injector.cs @@ -230,12 +230,18 @@ namespace DCFApixels.DragonECS monoWorldSystem.World = _monoWorld; } + + var initInjectionCallbacks = pipeline.GetProcess(); + foreach (var system in initInjectionCallbacks) + { + system.OnBeforeInitInjection(); + } _instance.Init(pipeline); foreach (var item in _initInjections) { item.InjectTo(_instance); } - foreach (var system in pipeline.GetProcess()) + foreach (var system in initInjectionCallbacks) { system.OnInitInjectionComplete(); } diff --git a/src/Injections/Utils/Interfaces.cs b/src/Injections/Utils/Interfaces.cs index 7ecd48f..e7bc9ad 100644 --- a/src/Injections/Utils/Interfaces.cs +++ b/src/Injections/Utils/Interfaces.cs @@ -20,6 +20,7 @@ [MetaID("05C3537C920155AFC044C900E4F17D90")] public interface IOnInitInjectionComplete : IEcsProcess { + void OnBeforeInitInjection(); void OnInitInjectionComplete(); } public interface IInjector From 8b28069338740860b87baf15d906b2d68855716c Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:18:45 +0800 Subject: [PATCH 07/10] add EcsMask.ToStatic --- src/EcsMask.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/EcsMask.cs b/src/EcsMask.cs index de29a8c..fef1042 100644 --- a/src/EcsMask.cs +++ b/src/EcsMask.cs @@ -163,6 +163,10 @@ namespace DCFApixels.DragonECS { return world.Get().ConvertFromStatic(abstractMask); } + public EcsStaticMask ToStatic() + { + return _staticMask; + } EcsMask IComponentMask.ToMask(EcsWorld world) { return this; } public EcsMaskIterator GetIterator() { From bf99b9f483b3b6a895f0251366f1ef9469a1eee4 Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:19:02 +0800 Subject: [PATCH 08/10] add EcsAspect events --- src/EcsAspect.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs index 7d1a87c..8a76f7c 100644 --- a/src/EcsAspect.cs +++ b/src/EcsAspect.cs @@ -127,7 +127,6 @@ namespace DCFApixels.DragonECS internal EcsWorld _source; internal EcsMask _mask; private bool _isBuilt = false; - //private IEcsPool[] _pools; #region Properties public EcsMask Mask @@ -232,6 +231,7 @@ namespace DCFApixels.DragonECS builtinAspect._source = world; builtinAspect.Init(builder); } + OnInit(newAspect, builder); //Build Mask if (staticMask == null) @@ -253,6 +253,9 @@ namespace DCFApixels.DragonECS } _constructorBuildersStackIndex--; + + OnAfterInit(newAspect, mask); + return (newAspect, mask); } #endregion @@ -430,6 +433,14 @@ namespace DCFApixels.DragonECS } } #endregion + + #region Events + public delegate void OnInitApectHandler(object aspect, Builder builder); + public static event OnInitApectHandler OnInit = delegate { }; + + public delegate void OnBuildApectHandler(object aspect, EcsMask mask); + public static event OnBuildApectHandler OnAfterInit = delegate { }; + #endregion } #region EcsAspect.Builder.Extensions From ca0f80aaaf214321c220293ab8090c7c64efd56c Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 14 Mar 2025 21:27:51 +0800 Subject: [PATCH 09/10] fix --- src/Pools/EcsTagPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 09789e8..31db87c 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS #endif private bool _isLocked; - private readonly T _fakeComponent = default; + private T _fakeComponent = default; private EcsWorld.PoolsMediator _mediator; #region CheckValide From e95a6225a7407a96d1f8f86862d333c8e74031fe Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Sun, 16 Mar 2025 14:12:23 +0800 Subject: [PATCH 10/10] Update EcsPool.cs --- src/Pools/EcsPool.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 648af29..92ab48b 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -396,14 +396,15 @@ namespace DCFApixels.DragonECS #endif _isDenseEntitiesDelayedValid = true; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private int GetFreeItemIndex(int entityID) { - if (_denseEntitiesDelayedCount >= _capacity - 1) + if (_denseEntitiesDelayedCount >= _capacity) { UpdateDenseEntities(); } - if (_itemsCount >= _capacity - 1) + if (_itemsCount + 1 >= _capacity) { Resize(_items.Length << 1); }