From 6e16e2962ef3202c838d856fbe11287c89919ceb Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Wed, 6 Dec 2023 18:58:06 +0800 Subject: [PATCH] update remove "pipeline" argument from base processes add PoolsMediator update component mask --- src/Builtin/BaseProcesses.cs | 32 ++-- src/Builtin/InjectSystem.cs | 20 ++- src/Builtin/Systems.cs | 5 +- src/EcsPipeline.cs | 8 +- src/EcsWorld.cs | 50 ++++-- src/EcsWorld.pools.cs | 18 +- src/Pools/EcsHybridPool.cs | 27 +-- src/Pools/EcsPool.cs | 20 ++- src/Pools/EcsPoolBase.cs | 15 +- src/Pools/EcsTagPool.cs | 21 ++- src/Pools/EcsTestPool.cs | 332 ----------------------------------- 11 files changed, 123 insertions(+), 425 deletions(-) delete mode 100644 src/Pools/EcsTestPool.cs diff --git a/src/Builtin/BaseProcesses.cs b/src/Builtin/BaseProcesses.cs index 8f226f1..468047e 100644 --- a/src/Builtin/BaseProcesses.cs +++ b/src/Builtin/BaseProcesses.cs @@ -7,19 +7,19 @@ namespace DCFApixels.DragonECS #region Interfaces public interface IEcsPreInitProcess : IEcsProcess { - void PreInit(EcsPipeline pipeline); + void PreInit(); } public interface IEcsInitProcess : IEcsProcess { - void Init(EcsPipeline pipeline); + void Init(); } public interface IEcsRunProcess : IEcsProcess { - void Run(EcsPipeline pipeline); + void Run(); } public interface IEcsDestroyProcess : IEcsProcess { - void Destroy(EcsPipeline pipeline); + void Destroy(); } #endregion @@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS } } #endif - public void PreInit(EcsPipeline pipeline) + public void PreInit() { #if DEBUG && !DISABLE_DEBUG for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) @@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS _markers[i].Begin(); try { - targets[i].PreInit(pipeline); + targets[i].PreInit(); } catch (Exception e) { @@ -62,7 +62,7 @@ namespace DCFApixels.DragonECS #else foreach (var item in targets) { - try { item.PreInit(pipeline); } + try { item.PreInit(); } catch (Exception e) { #if DISABLE_CATH_EXCEPTIONS @@ -88,7 +88,7 @@ namespace DCFApixels.DragonECS } } #endif - public void Init(EcsPipeline pipeline) + public void Init() { #if DEBUG && !DISABLE_DEBUG for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) @@ -96,7 +96,7 @@ namespace DCFApixels.DragonECS _markers[i].Begin(); try { - targets[i].Init(pipeline); + targets[i].Init(); } catch (Exception e) { @@ -110,7 +110,7 @@ namespace DCFApixels.DragonECS #else foreach (var item in targets) { - try { item.Init(pipeline); } + try { item.Init(); } catch (Exception e) { #if DISABLE_CATH_EXCEPTIONS @@ -136,7 +136,7 @@ namespace DCFApixels.DragonECS } } #endif - public void Run(EcsPipeline pipeline) + public void Run() { #if DEBUG && !DISABLE_DEBUG for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) @@ -144,7 +144,7 @@ namespace DCFApixels.DragonECS _markers[i].Begin(); try { - targets[i].Run(pipeline); + targets[i].Run(); } catch (Exception e) { @@ -158,7 +158,7 @@ namespace DCFApixels.DragonECS #else foreach (var item in targets) { - try { item.Run(pipeline); } + try { item.Run(); } catch (Exception e) { #if DISABLE_CATH_EXCEPTIONS @@ -184,7 +184,7 @@ namespace DCFApixels.DragonECS } } #endif - public void Destroy(EcsPipeline pipeline) + public void Destroy() { #if DEBUG && !DISABLE_DEBUG for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) @@ -192,7 +192,7 @@ namespace DCFApixels.DragonECS _markers[i].Begin(); try { - targets[i].Destroy(pipeline); + targets[i].Destroy(); } catch (Exception e) { @@ -206,7 +206,7 @@ namespace DCFApixels.DragonECS #else foreach (var item in targets) { - try { item.Destroy(pipeline); } + try { item.Destroy(); } catch (Exception e) { #if DISABLE_CATH_EXCEPTIONS diff --git a/src/Builtin/InjectSystem.cs b/src/Builtin/InjectSystem.cs index 47b8b50..36d28d1 100644 --- a/src/Builtin/InjectSystem.cs +++ b/src/Builtin/InjectSystem.cs @@ -102,32 +102,36 @@ namespace DCFApixels.DragonECS } public class InjectSystemBase { } [DebugHide, DebugColor(DebugColor.Gray)] - public class InjectSystem : InjectSystemBase, IEcsPreInitProcess, IEcsInject, IEcsPreInitInjectProcess + public class InjectSystem : InjectSystemBase, IEcsInject, IEcsPreInitProcess, IEcsInject, IEcsPreInitInjectProcess { - private T _injectedData; + private EcsPipeline _pipeline; + void IEcsInject.Inject(EcsPipeline obj) => _pipeline = obj; private PreInitInjectController _injectController; void IEcsInject.Inject(PreInitInjectController obj) => _injectController = obj; + + private T _injectedData; + public InjectSystem(T injectedData) { if (injectedData == null) Throw.ArgumentNull(); _injectedData = injectedData; } - public void PreInit(EcsPipeline pipeline) + public void PreInit() { if (_injectedData == null) return; if (_injectController == null) { - _injectController = new PreInitInjectController(pipeline); - var injectMapRunner = pipeline.GetRunner>(); - pipeline.GetRunner().OnPreInitInjectionBefore(); + _injectController = new PreInitInjectController(_pipeline); + var injectMapRunner = _pipeline.GetRunner>(); + _pipeline.GetRunner().OnPreInitInjectionBefore(); injectMapRunner.Inject(_injectController); } - var injectRunnerGeneric = pipeline.GetRunner>(); + var injectRunnerGeneric = _pipeline.GetRunner>(); injectRunnerGeneric.Inject(_injectedData); if (_injectController.OnInject()) { _injectController.Destroy(); - var injectCallbacksRunner = pipeline.GetRunner(); + var injectCallbacksRunner = _pipeline.GetRunner(); injectCallbacksRunner.OnPreInitInjectionAfter(); EcsRunner.Destroy(injectCallbacksRunner); } diff --git a/src/Builtin/Systems.cs b/src/Builtin/Systems.cs index c164dcb..d8f908f 100644 --- a/src/Builtin/Systems.cs +++ b/src/Builtin/Systems.cs @@ -16,7 +16,7 @@ namespace DCFApixels.DragonECS { private readonly List _worlds = new List(); public void Inject(EcsWorld obj) => _worlds.Add(obj); - public void Run(EcsPipeline pipeline) + public void Run() { foreach (var world in _worlds) { @@ -29,6 +29,7 @@ namespace DCFApixels.DragonECS public class DeleteOneFrameComponentSystem : IEcsRunProcess, IEcsInject where TComponent : struct, IEcsComponent { + public EcsPipeline pipeline { get; set; } private sealed class Aspect : EcsAspect { public EcsPool pool; @@ -36,7 +37,7 @@ namespace DCFApixels.DragonECS } private readonly List _worlds = new List(); public void Inject(EcsWorld obj) => _worlds.Add(obj); - public void Run(EcsPipeline pipeline) + public void Run() { for (int i = 0, iMax = _worlds.Count; i < iMax; i++) { diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index a3979ec..e03478d 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -67,10 +67,10 @@ namespace DCFApixels.DragonECS ecsPipelineInjectRunner.Inject(this); EcsRunner.Destroy(ecsPipelineInjectRunner); var preInitRunner = GetRunner(); - preInitRunner.PreInit(this); + preInitRunner.PreInit(); EcsRunner.Destroy(preInitRunner); var initRunner = GetRunner(); - initRunner.Init(this); + initRunner.Init(); EcsRunner.Destroy(initRunner); _runRunnerCache = GetRunner(); @@ -85,7 +85,7 @@ namespace DCFApixels.DragonECS if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run)); if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run)); #endif - _runRunnerCache.Run(this); + _runRunnerCache.Run(); } public void Destroy() { @@ -98,7 +98,7 @@ namespace DCFApixels.DragonECS return; } _isDestoryed = true; - GetRunner().Destroy(this); + GetRunner().Destroy(); } #endregion diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 0d0051e..c031b56 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -3,6 +3,7 @@ using DCFApixels.DragonECS.Utils; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using static DCFApixels.DragonECS.EcsWorld; namespace DCFApixels.DragonECS { @@ -32,6 +33,8 @@ namespace DCFApixels.DragonECS internal int[][] _entitiesComponentMasks; + private readonly PoolsMediator _poolsMediator; + #region Properties public bool IsDestroyed => _isDestroyed; public int Count => _entitiesCount; @@ -47,6 +50,8 @@ namespace DCFApixels.DragonECS public EcsWorld() : this(true) { } internal EcsWorld(bool isIndexable) { + _poolsMediator = new PoolsMediator(this); + _entitesCapacity = 512; if (isIndexable) @@ -268,20 +273,18 @@ namespace DCFApixels.DragonECS //public void CloneEntity(int fromEntityID, EcsWorld toWorld, int toEntityID) #endregion - #region Components Increment + #region Components Register [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void IncrementEntityComponentCount(int entityID, int componentID) + private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskBit maskBit) { _componentCounts[entityID]++; - EcsMaskBit bit = EcsMaskBit.FromID(componentID); - _entitiesComponentMasks[entityID][bit.chankIndex] |= bit.mask; + _entitiesComponentMasks[entityID][maskBit.chankIndex] |= maskBit.mask; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void DecrementEntityComponentCount(int entityID, int componentID) + private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskBit maskBit) { var count = --_componentCounts[entityID]; - EcsMaskBit bit = EcsMaskBit.FromID(componentID); - _entitiesComponentMasks[entityID][bit.chankIndex] &= ~bit.mask; + _entitiesComponentMasks[entityID][maskBit.chankIndex] &= ~maskBit.mask; if (count == 0 && _allEntites.Has(entityID)) DelEntity(entityID); @@ -382,6 +385,34 @@ namespace DCFApixels.DragonECS } } #endregion + + public readonly struct PoolsMediator + { + private readonly EcsWorld _world; + public PoolsMediator(EcsWorld world) + { + if (world == null) + { + throw new ArgumentNullException(); + } + if (world._poolsMediator._world != null) + { + throw new MethodAccessException("Нельзя создавать вручную"); + } + _world = world; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void RegisterComponent(int entityID, int componentTypeID, EcsMaskBit maskBit) + { + _world.RegisterEntityComponent(entityID, componentTypeID, maskBit); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void UnregisterComponent(int entityID, int componentTypeID, EcsMaskBit maskBit) + { + _world.UnregisterEntityComponent(entityID, componentTypeID, maskBit); + } + } } #region Callbacks Interface @@ -433,9 +464,4 @@ namespace DCFApixels.DragonECS public static entlong ToEntityLong(this int self, EcsWorld world) => world.GetEntityLong(self); } #endregion - - public class PoolsController - { - - } } diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs index a68be2d..ad4dda0 100644 --- a/src/EcsWorld.pools.cs +++ b/src/EcsWorld.pools.cs @@ -77,15 +77,15 @@ namespace DCFApixels.DragonECS Type componentType = typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0]; int componentTypeCode = EcsTypeCode.Get(componentType); - if (_componentIds.TryGetValue(componentTypeCode, out int componentID)) + if (_componentIds.TryGetValue(componentTypeCode, out int componentTypeID)) { - _poolIds[poolTypeCode] = componentID; + _poolIds[poolTypeCode] = componentTypeID; } else { - componentID = _poolsCount++; - _poolIds[poolTypeCode] = componentID; - _componentIds[componentTypeCode] = componentID; + componentTypeID = _poolsCount++; + _poolIds[poolTypeCode] = componentTypeID; + _componentIds[componentTypeCode] = componentTypeID; } if (_poolsCount >= _pools.Length) @@ -98,13 +98,13 @@ namespace DCFApixels.DragonECS Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1); } - if (_pools[componentID] == _nullPool) + if (_pools[componentTypeID] == _nullPool) { var pool = new TPool(); - _pools[componentID] = pool; - pool.OnInit(this, componentID); + _pools[componentTypeID] = pool; + pool.OnInit(this, _poolsMediator, componentTypeID); } - return (TPool)_pools[componentID]; + return (TPool)_pools[componentTypeID]; } #endregion } diff --git a/src/Pools/EcsHybridPool.cs b/src/Pools/EcsHybridPool.cs index 68520b7..4f9d93f 100644 --- a/src/Pools/EcsHybridPool.cs +++ b/src/Pools/EcsHybridPool.cs @@ -20,7 +20,8 @@ namespace DCFApixels.DragonECS where T : IEcsHybridComponent { private EcsWorld _source; - private int _componentID; + private int _componentTypeID; + private EcsMaskBit _maskBit; private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private T[] _items; //dense @@ -32,10 +33,12 @@ namespace DCFApixels.DragonECS private List _listeners = new List(); + private EcsWorld.PoolsMediator _mediator; + #region Properites public int Count => _itemsCount; public int Capacity => _items.Length; - public int ComponentID => _componentID; + public int ComponentID => _componentTypeID; public Type ComponentType => typeof(T); public EcsWorld World => _source; #endregion @@ -65,7 +68,7 @@ namespace DCFApixels.DragonECS Array.Resize(ref _entities, _items.Length); } } - this.IncrementEntityComponentCount(entityID, _componentID); + _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnAdd(entityID); if(isMain) component.OnAddToPool(_source.GetEntityLong(entityID)); @@ -126,7 +129,7 @@ namespace DCFApixels.DragonECS _mapping[entityID] = 0; _entities[itemIndex] = 0; _itemsCount--; - this.DecrementEntityComponentCount(entityID, _componentID); + _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnDel(entityID); } public void Del(int entityID) @@ -167,10 +170,12 @@ namespace DCFApixels.DragonECS #endregion #region Callbacks - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) + void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { _source = world; - _componentID = componentID; + _mediator = mediator; + _componentTypeID = componentTypeID; + _maskBit = EcsMaskBit.FromID(componentTypeID); const int capacity = 512; @@ -286,16 +291,15 @@ namespace DCFApixels.DragonECS } } - public partial class EcsWorld + public abstract partial class EcsWorld { - private Dictionary _mappings = new Dictionary(); - + private Dictionary _hybridMapping = new Dictionary(); internal HybridMapping GetHybridMapping(Type type) { - if(!_mappings.TryGetValue(type, out HybridMapping mapping)) + if(!_hybridMapping.TryGetValue(type, out HybridMapping mapping)) { mapping = new HybridMapping(this, type); - _mappings.Add(type, mapping); + _hybridMapping.Add(type, mapping); } return mapping; } @@ -313,7 +317,6 @@ namespace DCFApixels.DragonECS private static Type hybridPoolType = typeof(EcsHybridPool<>); private static MethodInfo getHybridPoolMethod = typeof(EcsHybridPoolExtensions).GetMethod($"{nameof(EcsHybridPoolExtensions.GetPool)}", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); - private static HashSet _hybridComponents = new HashSet(); static HybridMapping() { diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index ba41891..73fabc8 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -11,7 +11,7 @@ namespace DCFApixels.DragonECS where T : struct, IEcsComponent { private EcsWorld _source; - private int _componentID; + private int _componentTypeID; private EcsMaskBit _maskBit; private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID @@ -25,10 +25,12 @@ namespace DCFApixels.DragonECS private List _listeners = new List(); + private EcsWorld.PoolsMediator _mediator; + #region Properites public int Count => _itemsCount; public int Capacity => _items.Length; - public int ComponentID => _componentID; + public int ComponentID => _componentTypeID; public Type ComponentType => typeof(T); public EcsWorld World => _source; #endregion @@ -51,7 +53,7 @@ namespace DCFApixels.DragonECS if (itemIndex >= _items.Length) Array.Resize(ref _items, _items.Length << 1); } - this.IncrementEntityComponentCount(entityID, _componentID); + _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnAddAndGet(entityID); return ref _items[itemIndex]; } @@ -88,7 +90,7 @@ namespace DCFApixels.DragonECS if (itemIndex >= _items.Length) Array.Resize(ref _items, _items.Length << 1); } - this.IncrementEntityComponentCount(entityID, _componentID); + _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnAdd(entityID); } _listeners.InvokeOnGet(entityID); @@ -111,7 +113,7 @@ namespace DCFApixels.DragonECS _recycledItems[_recycledItemsCount++] = itemIndex; _mapping[entityID] = 0; _itemsCount--; - this.DecrementEntityComponentCount(entityID, _componentID); + _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnDel(entityID); } public void TryDel(int entityID) @@ -135,12 +137,12 @@ namespace DCFApixels.DragonECS #endregion #region Callbacks - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) + void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { _source = world; - _componentID = componentID; - - _maskBit = EcsMaskBit.FromID(componentID); + _mediator = mediator; + _componentTypeID = componentTypeID; + _maskBit = EcsMaskBit.FromID(componentTypeID); const int capacity = 512; diff --git a/src/Pools/EcsPoolBase.cs b/src/Pools/EcsPoolBase.cs index 370dfca..4ccffad 100644 --- a/src/Pools/EcsPoolBase.cs +++ b/src/Pools/EcsPoolBase.cs @@ -49,7 +49,7 @@ namespace DCFApixels.DragonECS /// Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool. public interface IEcsPoolImplementation : IEcsPool { - void OnInit(EcsWorld world, int componentID); + void OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID); void OnWorldResize(int newSize); void OnReleaseDelEntityBuffer(ReadOnlySpan buffer); void OnWorldDestroy(); @@ -71,17 +71,6 @@ namespace DCFApixels.DragonECS } public static class IEcsPoolImplementationExtensions { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void IncrementEntityComponentCount(this IEcsPoolImplementation self, int entityID, int componentID) - { - self.World.IncrementEntityComponentCount(entityID, componentID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void DecrementEntityComponentCount(this IEcsPoolImplementation self, int entityID, int componentID) - { - self.World.DecrementEntityComponentCount(entityID, componentID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNullOrDummy(this IEcsPool self) { @@ -116,7 +105,7 @@ namespace DCFApixels.DragonECS #endregion #region Callbacks - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) { } + void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { } void IEcsPoolImplementation.OnWorldDestroy() { } void IEcsPoolImplementation.OnWorldResize(int newSize) { } void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) { } diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index c5175b3..86529de 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -10,7 +10,8 @@ namespace DCFApixels.DragonECS where T : struct, IEcsTagComponent { private EcsWorld _source; - private int _componentID; + private int _componentTypeID; + private EcsMaskBit _maskBit; private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private int _count; @@ -18,8 +19,9 @@ namespace DCFApixels.DragonECS private List _listeners = new List(); private T _fakeComponent; + private EcsWorld.PoolsMediator _mediator; - + #region Constructors private static bool _isInvalidType; static EcsTagPool() { @@ -30,11 +32,12 @@ namespace DCFApixels.DragonECS if (_isInvalidType) throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data."); } + #endregion #region Properites public int Count => _count; int IEcsPool.Capacity => -1; - public int ComponentID => _componentID; + public int ComponentID => _componentTypeID; public Type ComponentType => typeof(T); public EcsWorld World => _source; #endregion @@ -47,7 +50,7 @@ namespace DCFApixels.DragonECS #endif _count++; _mapping[entityID] = true; - this.IncrementEntityComponentCount(entityID, _componentID); + _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnAdd(entityID); } public void TryAdd(int entityID) @@ -56,7 +59,7 @@ namespace DCFApixels.DragonECS { _count++; _mapping[entityID] = true; - this.IncrementEntityComponentCount(entityID, _componentID); + _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnAdd(entityID); } } @@ -72,7 +75,7 @@ namespace DCFApixels.DragonECS #endif _mapping[entityID] = false; _count--; - this.DecrementEntityComponentCount(entityID, _componentID); + _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); _listeners.InvokeOnDel(entityID); } public void TryDel(int entityID) @@ -116,10 +119,12 @@ namespace DCFApixels.DragonECS #endregion #region Callbacks - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) + void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { _source = world; - _componentID = componentID; + _mediator = mediator; + _componentTypeID = componentTypeID; + _maskBit = EcsMaskBit.FromID(componentTypeID); _mapping = new bool[world.Capacity]; _count = 0; diff --git a/src/Pools/EcsTestPool.cs b/src/Pools/EcsTestPool.cs deleted file mode 100644 index 3bbc04f..0000000 --- a/src/Pools/EcsTestPool.cs +++ /dev/null @@ -1,332 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.Contracts; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS -{ - /// Pool for IEcsComponent components - public sealed class EcsTestPool : IEcsPoolImplementation, IEcsStructPool, IEnumerable //IEnumerable - IntelliSense hack - where T : struct, IEcsTestComponent - { - private EcsWorld _source; - private int _componentID; - - - public const int MIN_CAPACITY_BITS_OFFSET = 4; - public const int MIN_CAPACITY = 1 << MIN_CAPACITY_BITS_OFFSET; - private const int EMPTY = -1; - - private int[] _buckets = Array.Empty(); - private Entry[] _entries = Array.Empty(); - - private int _count; - - private int _freeList; - private int _freeCount; - - private int _modBitMask; - - - private IEcsComponentReset _componentResetHandler = EcsComponentResetHandler.instance; - private IEcsComponentCopy _componentCopyHandler = EcsComponentCopyHandler.instance; - - private List _listeners = new List(); - - #region Properites - public int Count => _count; - public int Capacity => _entries.Length; - public int ComponentID => _componentID; - public Type ComponentType => typeof(T); - public EcsWorld World => _source; - #endregion - - #region Methods - public void Copy(int fromEntityID, int toEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent(fromEntityID); -#endif - _componentCopyHandler.Copy(ref Get(fromEntityID), ref TryAddOrGet(toEntityID)); - } - public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(fromEntityID)) EcsPoolThrowHalper.ThrowNotHaveComponent(fromEntityID); -#endif - _componentCopyHandler.Copy(ref Get(fromEntityID), ref toWorld.GetPool().TryAddOrGet(toEntityID)); - } - #endregion - - - #region Callbacks - void IEcsPoolImplementation.OnInit(EcsWorld world, int componentID) - { - _source = world; - _componentID = componentID; - - int minCapacity = 512; - minCapacity = NormalizeCapacity(minCapacity); - _buckets = new int[minCapacity]; - for (int i = 0; i < minCapacity; i++) - _buckets[i] = EMPTY; - _entries = new Entry[minCapacity]; - _modBitMask = (minCapacity - 1) & 0x7FFFFFFF; - } - void IEcsPoolImplementation.OnWorldResize(int newSize) { } - void IEcsPoolImplementation.OnWorldDestroy() { } - void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) - { - foreach (var entityID in buffer) - TryDel(entityID); - } - #endregion - - #region Other - void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID) = (T)dataRaw; - object IEcsPool.GetRaw(int entityID) => Read(entityID); - void IEcsPool.SetRaw(int entityID, object dataRaw) => Get(entityID) = (T)dataRaw; - ref readonly T IEcsStructPool.Read(int entityID) => ref Read(entityID); - ref T IEcsStructPool.Get(int entityID) => ref Get(entityID); - #endregion - - #region Listeners - public void AddListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Add(listener); - } - public void RemoveListener(IEcsPoolEventListener listener) - { - if (listener == null) { throw new ArgumentNullException("listener is null"); } - _listeners.Remove(listener); - } - #endregion - - #region IEnumerator - IntelliSense hack - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); - #endregion - - - #region Find/Insert/Remove - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int FindEntry(long x, long y) - { - return FindEntry(x << 32 | y); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int FindEntry(long key) - { - for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next) - if (_entries[i].key == key) return i; - return -1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int entityID) => Has(entityID, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool Has(long x, long y) => Has(x << 32 | y); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool Has(long key) { - for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next) - if (_entries[i].key == key) return true; - return false; - } - - public ref T Add(int entityID) => ref Add(entityID, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ref T Add(long x, long y) => ref Add(x << 32 | y); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ref T Add(long key) - { - int entityID = unchecked((int)key); -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (Has(key: key)) EcsPoolThrowHalper.ThrowAlreadyHasComponent(entityID); -#endif - - int index; - if (_freeCount > 0) - { - index = _freeList; - _freeList = _entries[index].next; - _freeCount--; - } - else - { - if (_count == _entries.Length) - Resize(); - index = _count++; - } - int targetBucket = unchecked((int)key & _modBitMask); - - ref var entry = ref _entries[index]; - entry.next = _buckets[targetBucket]; - entry.key = key; - entry.value = default; - _buckets[targetBucket] = index; - this.IncrementEntityComponentCount(entityID, _componentID); - _listeners.InvokeOnAddAndGet(entityID); - return ref entry.value; - } - public ref T TryAddOrGet(int entityID) - { - throw new NotImplementedException(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref T Get(int entityID) => ref Get(entityID, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ref T Get(long x, long y) => ref Get(x << 32 | y); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private ref T Get(long key) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(key: key)) EcsPoolThrowHalper.ThrowNotHaveComponent(unchecked((int)key)); -#endif - _listeners.InvokeOnGet(unchecked((int)key)); - //return ref _entries[FindEntry(key)].value; - - for (int i = _buckets[unchecked((int)key & _modBitMask)]; i >= 0; i = _entries[i].next) - if (_entries[i].key == key) return ref _entries[i].value; // return i; - -#pragma warning disable CS0251 // - return ref _entries[-1].value; // . -#pragma warning restore CS0251 // - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly T Read(int entityID) => ref Read(entityID, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly T Read(long x, long y) => ref Read(x << 32 | y); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly T Read(long key) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(key: key)) EcsPoolThrowHalper.ThrowNotHaveComponent(unchecked((int)key)); -#endif - return ref _entries[FindEntry(key)].value; - } - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Del(int entityID) => Del(entityID, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Del(long keyX, long keyY) => Del(keyX + (keyY << 32)); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Del(long key) - { - int entityID = unchecked((int)key); -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(key: key)) EcsPoolThrowHalper.ThrowNotHaveComponent(entityID); -#endif - int bucket = unchecked((int)key & _modBitMask); - int last = -1; - for (int i = _buckets[bucket]; i >= 0; last = i, i = _entries[i].next) - { - if (_entries[i].key == key) - { - if (last < 0) - { - _buckets[bucket] = _entries[i].next; - } - else - { - _entries[last].next = _entries[i].next; - } - _entries[i].next = _freeList; - _entries[i].key = -1; - //_entries[i].value = default; - _componentResetHandler.Reset(ref _entries[i].value); - _freeList = i; - _freeCount++; - this.DecrementEntityComponentCount(entityID, _componentID); - _listeners.InvokeOnDel(entityID); - return; - } - } - } - public void TryDel(int entityID) - { - if (Has(entityID)) Del(entityID); - } - #endregion - - #region Resize - private void Resize() - { - int newSize = _buckets.Length << 1; - _modBitMask = (newSize - 1) & 0x7FFFFFFF; - - Contract.Assert(newSize >= _entries.Length); - int[] newBuckets = new int[newSize]; - for (int i = 0; i < newBuckets.Length; i++) - newBuckets[i] = EMPTY; - - Entry[] newEntries = new Entry[newSize]; - Array.Copy(_entries, 0, newEntries, 0, _count); - for (int i = 0; i < _count; i++) - { - if (newEntries[i].key >= 0) - { - int bucket = unchecked((int)newEntries[i].key & _modBitMask); - newEntries[i].next = newBuckets[bucket]; - newBuckets[bucket] = i; - } - } - _buckets = newBuckets; - _entries = newEntries; - } - - private int NormalizeCapacity(int capacity) - { - int result = MIN_CAPACITY; - while (result < capacity) result <<= 1; - return result; - } - #endregion - - #region Utils - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct Entry - { - public int next; // Index of next entry, -1 if last - public long key; - public T value; - } - #endregion - } - /// Standard component - public interface IEcsTestComponent { } - public static class EcsTestPoolExt - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EcsTestPool GetPool(this EcsWorld self) where TComponent : struct, IEcsTestComponent - { - return self.GetPool>(); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EcsTestPool GetPoolUnchecked(this EcsWorld self) where TComponent : struct, IEcsTestComponent - { - return self.GetPoolUnchecked>(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EcsTestPool Include(this EcsAspectBuilderBase self) where TComponent : struct, IEcsTestComponent - { - return self.Include>(); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EcsTestPool Exclude(this EcsAspectBuilderBase self) where TComponent : struct, IEcsTestComponent - { - return self.Exclude>(); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static EcsTestPool Optional(this EcsAspectBuilderBase self) where TComponent : struct, IEcsTestComponent - { - return self.Optional>(); - } - } -}