diff --git a/src/Collections/EcsSpan.cs b/src/Collections/EcsSpan.cs index f45d97c..a2f5b75 100644 --- a/src/Collections/EcsSpan.cs +++ b/src/Collections/EcsSpan.cs @@ -1,4 +1,4 @@ -using DCFApixels.DragonECS.Utils; +using DCFApixels.DragonECS.Internal; using System; using System.Collections.Generic; using System.ComponentModel; diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 572c208..895c876 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -3,7 +3,6 @@ using DCFApixels.DragonECS.Utils; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; -using static Leopotam.EcsLite.EcsWorld; namespace DCFApixels.DragonECS { @@ -114,12 +113,12 @@ namespace DCFApixels.DragonECS _poolsMediator = new PoolsMediator(this); _entityDispenser = new IntDispenser(0); - int poolsCapacity = config.Get_PoolsCapacity(); + int poolsCapacity = ArrayUtility.NormalizeSizeToPowerOfTwo(config.Get_PoolsCapacity()); _pools = new IEcsPoolImplementation[poolsCapacity]; _poolComponentCounts = new int[poolsCapacity]; ArrayUtility.Fill(_pools, _nullPool); - _entitesCapacity = config.Get_EntitiesCapacity(); + _entitesCapacity = ArrayUtility.NormalizeSizeToPowerOfTwo(config.Get_EntitiesCapacity()); _gens = new short[_entitesCapacity]; _componentCounts = new short[_entitesCapacity]; @@ -267,22 +266,20 @@ namespace DCFApixels.DragonECS #endregion #region Entity + [MethodImpl(MethodImplOptions.AggressiveInlining)] public int NewEntity() { - //if (_isEnableReleaseDelEntBuffer && _freeSpace <= 1 && _delEntBufferCount > _delEntBufferMinCount) - // ReleaseDelEntityBufferAll(); - int entityID = _entityDispenser.GetFree(); _freeSpace--; _entitiesCount++; if (_gens.Length <= entityID) { - Upsize(_gens.Length << 1); + Upsize_Internal(_gens.Length << 1); } _gens[entityID] &= GEN_BITS; - _allEntites.Add(entityID); + _allEntites.AddUnchecked(entityID); _entityListeners.InvokeOnNewEntity(entityID); return entityID; } @@ -291,8 +288,23 @@ namespace DCFApixels.DragonECS int e = NewEntity(); return GetEntityLong(e); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void TryDelEntity(int entityID) + { + if (IsUsed(entityID)) + { + DelEntity(entityID); + } + } public void DelEntity(int entityID) { +#if DEBUG + if(IsUsed(entityID) == false) + { + Throw.UndefinedException(); + } +#endif _allEntites.Remove(entityID); _delEntBuffer[_delEntBufferCount++] = entityID; _gens[entityID] |= DEATH_GEN_BIT; @@ -446,16 +458,13 @@ namespace DCFApixels.DragonECS #endregion #region Upsize - [MethodImpl(MethodImplOptions.NoInlining)] public void Upsize(int minSize) { - if (minSize < Capacity) - { - return; - } - - int newSize = 1 << (BitsUtility.GetHighBitNumber(minSize - 1) + 1); - + Upsize_Internal(ArrayUtility.NormalizeSizeToPowerOfTwo(minSize)); + } + [MethodImpl(MethodImplOptions.NoInlining)] + private void Upsize_Internal(int newSize) + { Array.Resize(ref _gens, newSize); Array.Resize(ref _componentCounts, newSize); Array.Resize(ref _delEntBuffer, newSize); diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 07a5a26..0110348 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -1,3 +1,4 @@ +using DCFApixels.DragonECS.Internal; using System; using System.Collections; using System.Collections.Generic; @@ -54,6 +55,7 @@ namespace DCFApixels.DragonECS } _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnAddAndGet(entityID); + _componentResetHandler.Reset(ref _items[itemIndex]); return ref _items[itemIndex]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -93,6 +95,7 @@ namespace DCFApixels.DragonECS _listeners.InvokeOnAdd(entityID); } _listeners.InvokeOnGet(entityID); + _componentResetHandler.Reset(ref _items[itemIndex]); return ref _items[itemIndex]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -146,7 +149,7 @@ namespace DCFApixels.DragonECS _mapping = new int[world.Capacity]; _recycledItems = new int[world.Config.Get_PoolRecycledComponentsCapacity()]; _recycledItemsCount = 0; - _items = new T[world.Config.Get_PoolComponentsCapacity()]; + _items = new T[ArrayUtility.NormalizeSizeToPowerOfTwo(world.Config.Get_PoolComponentsCapacity())]; _itemsCount = 0; } void IEcsPoolImplementation.OnWorldResize(int newSize) @@ -157,7 +160,9 @@ namespace DCFApixels.DragonECS void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) { foreach (var entityID in buffer) + { TryDel(entityID); + } } #endregion diff --git a/src/Utils/ArrayUtility.cs b/src/Utils/ArrayUtility.cs index 1a80faa..52c7a70 100644 --- a/src/Utils/ArrayUtility.cs +++ b/src/Utils/ArrayUtility.cs @@ -5,18 +5,61 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -namespace DCFApixels.DragonECS.Utils +namespace DCFApixels.DragonECS.Internal { internal static class ArrayUtility { + private static int GetHighBitNumber(uint bits) + { + if (bits == 0) + { + return -1; + } + int bit = 0; + if ((bits & 0xFFFF0000) != 0) + { + bits >>= 16; + bit |= 16; + } + if ((bits & 0xFF00) != 0) + { + bits >>= 8; + bit |= 8; + } + if ((bits & 0xF0) != 0) + { + bits >>= 4; + bit |= 4; + } + if ((bits & 0xC) != 0) + { + bits >>= 2; + bit |= 2; + } + if ((bits & 0x2) != 0) + { + bit |= 1; + } + return bit; + } + public static int NormalizeSizeToPowerOfTwo(int minSize) + { + return 1 << (GetHighBitNumber((uint)minSize - 1u) + 1); + } public static void Fill(T[] array, T value, int startIndex = 0, int length = -1) { if (length < 0) + { length = array.Length; + } else + { length = startIndex + length; + } for (int i = startIndex; i < length; i++) + { array[i] = value; + } } } internal readonly struct EnumerableInt : IEnumerable @@ -113,7 +156,9 @@ namespace DCFApixels.DragonECS.Utils { T* clone = New(length); for (int i = 0; i < length; i++) + { clone[i] = sourcePtr[i]; + } return clone; }