From 1f52caf9c0303c3d4c6700d0068bca23121788f0 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Sun, 25 Feb 2024 00:55:30 +0800 Subject: [PATCH] stash --- src/EcsWorld.pools.cs | 26 ++- src/Pools/EcsHybridPool.cs | 220 ++++++++++++++----- src/Pools/EcsInterfacePool.cs | 127 +++++++++++ src/Pools/EcsPool.cs | 8 +- src/Pools/EcsPoolBase.cs | 37 ++-- src/Pools/EcsTagPool.cs | 12 +- src/Pools/Utils/VirtualHybridPool.cs | 168 ++++++++++++++ src/Pools/VirtualPool.cs | 314 --------------------------- 8 files changed, 510 insertions(+), 402 deletions(-) create mode 100644 src/Pools/EcsInterfacePool.cs create mode 100644 src/Pools/Utils/VirtualHybridPool.cs delete mode 100644 src/Pools/VirtualPool.cs diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs index c1e71bf..5f07ede 100644 --- a/src/EcsWorld.pools.cs +++ b/src/EcsWorld.pools.cs @@ -18,10 +18,16 @@ namespace DCFApixels.DragonECS private EcsNullPool _nullPool = EcsNullPool.instance; #region Getters + public IEcsPool GetPool(int componentTypeID) + { +#if DEBUG + if (_pools[componentTypeID].ComponentTypeID != componentTypeID) { Throw.UndefinedException(); } +#endif + return _pools[componentTypeID]; + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public IEcsPool GetPool(Type componentType) - //TODO. Есть проблема, возврат виртуального пула и последующая девиртуализация сделает ссылку невалидной. Одно из решений возвращать обертку { int componentTypeID = GetComponentTypeID(componentType); ref var pool = ref _pools[componentTypeID]; @@ -276,45 +282,45 @@ namespace DCFApixels.DragonECS #region PoolsMediator public readonly struct PoolsMediator { - private readonly EcsWorld _world; + public readonly EcsWorld World; internal PoolsMediator(EcsWorld world) { - if (world == null || world._poolsMediator._world != null) + if (world == null || world._poolsMediator.World != null) { throw new InvalidOperationException(); } - _world = world; + World = world; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) { - _world.RegisterEntityComponent(entityID, componentTypeID, maskBit); + World.RegisterEntityComponent(entityID, componentTypeID, maskBit); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void UnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) { - _world.UnregisterEntityComponent(entityID, componentTypeID, maskBit); + World.UnregisterEntityComponent(entityID, componentTypeID, maskBit); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryRegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) { - return _world.TryRegisterEntityComponent(entityID, componentTypeID, maskBit); + return World.TryRegisterEntityComponent(entityID, componentTypeID, maskBit); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryUnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) { - return _world.TryUnregisterEntityComponent(entityID, componentTypeID, maskBit); + return World.TryUnregisterEntityComponent(entityID, componentTypeID, maskBit); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetComponentCount(int componentTypeID) { - return _world.GetPoolComponentCount(componentTypeID); + return World.GetPoolComponentCount(componentTypeID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool HasComponent(int entityID, EcsMaskChunck maskBit) { - return _world.HasEntityComponent(entityID, maskBit); + return World.HasEntityComponent(entityID, maskBit); } } #endregion diff --git a/src/Pools/EcsHybridPool.cs b/src/Pools/EcsHybridPool.cs index 26e40e8..ca3013e 100644 --- a/src/Pools/EcsHybridPool.cs +++ b/src/Pools/EcsHybridPool.cs @@ -1,4 +1,3 @@ -using DCFApixels.DragonECS; using DCFApixels.DragonECS.Internal; using System; using System.Collections; @@ -8,14 +7,6 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { - namespace Internal - { - public interface IEcsHybridPoolInternal : IEcsPool - { - void AddRefInternal(int entityID, object component, bool isAppend); - void DelInternal(int entityID, bool isAppend); - } - } /// Pool for IEcsHybridComponent components public sealed class EcsHybridPool : IEcsPoolImplementation, IEcsHybridPool, IEcsHybridPoolInternal, IEnumerable //IEnumerable - IntelliSense hack where T : class, IEcsHybridComponent @@ -36,6 +27,8 @@ namespace DCFApixels.DragonECS private EcsWorld.PoolsMediator _mediator; + private HybridPoolGraph _graph; + #region Properites public int Count { @@ -45,7 +38,7 @@ namespace DCFApixels.DragonECS { get { return _items.Length; } } - public int ComponentID + public int ComponentTypeID { get { return _componentTypeID; } } @@ -57,6 +50,10 @@ namespace DCFApixels.DragonECS { get { return _source; } } + public bool IReadOnly + { + get { return false; } + } #endregion #region Methods @@ -95,15 +92,20 @@ namespace DCFApixels.DragonECS } public void Add(int entityID, T component) { - HybridMapping mapping = _source.GetHybridMapping(component.GetType()); - mapping.GetTargetTypePool().AddRefInternal(entityID, component, true); - foreach (var pool in mapping.GetPools()) - pool.AddRefInternal(entityID, component, false); + //HybridMapping mapping = _source.GetHybridMapping(component.GetType()); + //mapping.GetTargetTypePool().AddRefInternal(entityID, component, true); + //foreach (var pool in mapping.GetPools()) + //{ + // pool.AddRefInternal(entityID, component, false); + //} + _graph.GetBranch(component.GetType()).Add(entityID, component); } public void Set(int entityID, T component) { if (Has(entityID)) + { Del(entityID); + } Add(entityID, component); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -188,7 +190,9 @@ namespace DCFApixels.DragonECS for (int i = _itemsCount - 1; i >= 0; i--) { if (!_items[i].IsAlive) + { Del(_entities[i]); + } } } #endregion @@ -196,6 +200,8 @@ namespace DCFApixels.DragonECS #region Callbacks void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) { + _graph = world.Get().Graph; + _source = world; _mediator = mediator; _componentTypeID = componentTypeID; @@ -224,7 +230,7 @@ namespace DCFApixels.DragonECS #region Other void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID, (T)dataRaw); - object IEcsPool.GetRaw(int entityID) => Read(entityID); + object IEcsReadonlyPool.GetRaw(int entityID) => Read(entityID); void IEcsPool.SetRaw(int entityID, object dataRaw) => Set(entityID, (T)dataRaw); #endregion @@ -245,6 +251,14 @@ namespace DCFApixels.DragonECS IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); #endregion + + #region Devirtualize + void IEcsHybridPoolInternal.Devirtualize(VirtualHybridPool virtualHybridPool) + { + _mapping = virtualHybridPool._mapping; + _itemsCount = virtualHybridPool._itemsCount; + } + #endregion } /// Hybrid component public interface IEcsHybridComponent @@ -403,52 +417,150 @@ namespace DCFApixels.DragonECS } -public class HybridTypeMapping + + +namespace DCFApixels.DragonECS.Internal { - private EcsWorld _world; - private Dictionary _declared = new Dictionary(); - - private Dictionary _canInstantiatedTypes = new Dictionary(); - - public void AddIntsanceType(object instance) + internal interface IEcsHybridPoolInternal { - // _canInstantiatedTypes.Add(instance.GetType()); + Type ComponentType { get; } + void AddRefInternal(int entityID, object component, bool isMain); + void DelInternal(int entityID, bool isMain); + void Devirtualize(VirtualHybridPool virtualHybridPool); } - - public void Declare() + internal readonly struct HybridPoolGraphCmp : IEcsWorldComponent { - + public readonly HybridPoolGraph Graph; + private HybridPoolGraphCmp(EcsWorld world) + { + Graph = new HybridPoolGraph(world); + } + public void Init(ref HybridPoolGraphCmp component, EcsWorld world) + { + component = new HybridPoolGraphCmp(world); + } + public void OnDestroy(ref HybridPoolGraphCmp component, EcsWorld world) + { + component = default; + } } - - - private void Init() + public class HybridPoolGraph { + private EcsWorld _world; + private Dictionary _branches = new Dictionary(); + public HybridPoolGraph(EcsWorld world) + { + _world = world; + } + + public bool IsInstantiable(Type type) + { + return _branches.ContainsKey(type); + } + public bool TryGetBranch(Type type, out HybridPoolBranch branch) + { + return _branches.TryGetValue(type, out branch); + } + public void InitNewPool(IEcsHybridPoolInternal pool) + { + foreach (var pair in _branches) + { + var type = pair.Key; + var branch = pair.Value; + if (type.IsAssignableFrom(pool.ComponentType)) + { + if (type == pool.ComponentType) + { + branch.InitRootTypePool(pool); + } + else + { + branch.InitNewPool(pool); + } + } + } + } + + public HybridPoolBranch GetBranch(Type targetType) + { + if (_branches.TryGetValue(targetType, out HybridPoolBranch branch) == false) + { + branch = new HybridPoolBranch(_world, targetType, null); + _branches.Add(targetType, branch); + } + return branch; + } } -} + public class HybridPoolBranch + { + private EcsWorld _world; + + private Type _rootComponentType; + private int _rootComponentTypeID; + private IEcsHybridPoolInternal _rootTypePool; + private List _relatedPools = new List(); + + private VirtualHybridPool _virtualPoolRef; + private bool _isVirtualPool = false; + + public bool IsVirtualPool + { + get { return _isVirtualPool; } + } + + public HybridPoolBranch(EcsWorld world, Type rootComponentType, IEcsHybridPoolInternal rootTypePool) + { + _world = world; + + _rootComponentType = rootComponentType; + _rootComponentTypeID = world.GetComponentTypeID(rootComponentType); + + if (rootTypePool == null) + { + _virtualPoolRef = new VirtualHybridPool(world, rootComponentType); + rootTypePool = _virtualPoolRef; + _isVirtualPool = true; + } + _rootTypePool = rootTypePool; + } -//public abstract class HybridBranchBase { } -//public class HybridBranch : HybridBranchBase -// where T : IEcsHybridComponent -//{ -// private EcsHybridPool _targetTypePool; -// public HybridBranch(EcsWorld source) -// { -// source.GetHybridPool(); -// } -//} -// -// -// -// -//public abstract class HybridNodeBase { } -//public class HybridNode : HybridNodeBase -// where T : IEcsHybridComponent -//{ -// private EcsHybridPool _targetTypePool; -// public HybridNode(EcsWorld source) -// { -// source.GetHybridPool(); -// } -//} + public void InitRootTypePool(IEcsHybridPoolInternal rootTypePool) + { + if (_isVirtualPool == false) + { + Throw.UndefinedException(); + } + _isVirtualPool = false; + rootTypePool.Devirtualize(_virtualPoolRef); + _rootTypePool = rootTypePool; + _virtualPoolRef = null; + } + public void InitNewPool(IEcsHybridPoolInternal pool) + { + _relatedPools.Add(pool); + } + + public void Set(int entityID, object component) + { + throw new NotImplementedException(); + } + public void Add(int entityID, object component) + { + _rootTypePool.AddRefInternal(entityID, component, true); + foreach (var pool in _relatedPools) + { + pool.AddRefInternal(entityID, component, false); + } + } + public void Del(int entityID) + { + _rootTypePool.DelInternal(entityID, true); + foreach (var pool in _relatedPools) + { + pool.DelInternal(entityID, false); + } + } + } +} \ No newline at end of file diff --git a/src/Pools/EcsInterfacePool.cs b/src/Pools/EcsInterfacePool.cs new file mode 100644 index 0000000..8455a7e --- /dev/null +++ b/src/Pools/EcsInterfacePool.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DCFApixels.DragonECS +{ + public interface IEcsInterfacePool : IEcsReadonlyPool where T : class + { + T Get(int entityID); + } + public interface IEcsInterfaceComponent { } + public class EcsInterfacePool : IEcsPoolImplementation, IEcsInterfacePool, IEnumerable //IEnumerable - IntelliSense hack + where T : class, IEcsInterfaceComponent + { + private EcsWorld _source; + private int _componentTypeID; + + private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID + private T[] _items; //dense + private int _itemsCount; + private int[] _recycledItems; + private int _recycledItemsCount; + + private List _listeners = new List(); + + private EcsWorld.PoolsMediator _mediator; + + #region Properties + public int ComponentTypeID + { + get { return _componentTypeID; } + } + public Type ComponentType + { + get { return typeof(T); } + } + public EcsWorld World + { + get { return _source; } + } + public int Count + { + get { return _itemsCount; } + } + public bool IReadOnly + { + get { return true; } + } + #endregion + + #region Methdos + public T Get(int entityID) + { +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent(entityID); } +#endif + _listeners.InvokeOnGet(entityID); + return _items[_mapping[entityID]]; + } + public bool Has(int entityID) + { + return _mapping[entityID] > 0; + } + #endregion + + #region Other + object IEcsReadonlyPool.GetRaw(int entityID) + { + return Get(entityID); + } + public void Copy(int fromEntityID, int toEntityID) { } + public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) { } + void IEcsPool.AddRaw(int entityID, object dataRaw) + { + EcsDebug.PrintWarning("Is read only!"); + } + void IEcsPool.SetRaw(int entityID, object dataRaw) + { + EcsDebug.PrintWarning("Is read only!"); + } + void IEcsPool.Del(int entityID) + { + EcsDebug.PrintWarning("Is read only!"); + } + #endregion + + #region Callbacks + void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) + { + throw new NotImplementedException(); + } + void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) + { + throw new NotImplementedException(); + } + void IEcsPoolImplementation.OnWorldResize(int newSize) + { + throw new NotImplementedException(); + } + void IEcsPoolImplementation.OnWorldDestroy() + { + throw new NotImplementedException(); + } + #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 + } +} diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index e8f019c..a0b918e 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -38,7 +38,7 @@ namespace DCFApixels.DragonECS { get { return _items.Length; } } - public int ComponentID + public int ComponentTypeID { get { return _componentTypeID; } } @@ -50,6 +50,10 @@ namespace DCFApixels.DragonECS { get { return _source; } } + public bool IReadOnly + { + get { return false; } + } #endregion #region Methods @@ -194,7 +198,7 @@ namespace DCFApixels.DragonECS #region Other void IEcsPool.AddRaw(int entityID, object dataRaw) { Add(entityID) = (T)dataRaw; } - object IEcsPool.GetRaw(int entityID) { return Get(entityID); } + object IEcsReadonlyPool.GetRaw(int entityID) { return Get(entityID); } void IEcsPool.SetRaw(int entityID, object dataRaw) { Get(entityID) = (T)dataRaw; } #endregion diff --git a/src/Pools/EcsPoolBase.cs b/src/Pools/EcsPoolBase.cs index 97ca510..3329275 100644 --- a/src/Pools/EcsPoolBase.cs +++ b/src/Pools/EcsPoolBase.cs @@ -5,22 +5,19 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { - public interface IEcsPool + public interface IEcsReadonlyPool { #region Properties - int ComponentID { get; } + int ComponentTypeID { get; } Type ComponentType { get; } EcsWorld World { get; } int Count { get; } - int Capacity { get; } //TODO удалить. не во всех реализация нужен, проще привести к типу + bool IReadOnly { get; } #endregion #region Methods bool Has(int entityID); - void Del(int entityID); - void AddRaw(int entityID, object dataRaw); object GetRaw(int entityID); - void SetRaw(int entityID, object dataRaw); void Copy(int fromEntityID, int toEntityID); void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID); #endregion @@ -30,6 +27,14 @@ namespace DCFApixels.DragonECS void RemoveListener(IEcsPoolEventListener listener); #endregion } + public interface IEcsPool : IEcsReadonlyPool + { + #region Methods + void AddRaw(int entityID, object dataRaw); + void SetRaw(int entityID, object dataRaw); + void Del(int entityID); + #endregion + } /// A pool for struct components. public interface IEcsStructPool : IEcsPool where T: struct { @@ -98,21 +103,21 @@ namespace DCFApixels.DragonECS public static readonly EcsNullPool instance = new EcsNullPool(); #region Properties - int IEcsPool.ComponentID => -1; - Type IEcsPool.ComponentType => typeof(NullComponent); - EcsWorld IEcsPool.World => throw new NotImplementedException(); + int IEcsReadonlyPool.ComponentTypeID => -1; + Type IEcsReadonlyPool.ComponentType => typeof(NullComponent); + EcsWorld IEcsReadonlyPool.World => throw new NotImplementedException(); public int Count => -1; - public int Capacity => -1; + public bool IReadOnly { get { return true; } } #endregion #region Methods - bool IEcsPool.Has(int index) => false; + bool IEcsReadonlyPool.Has(int index) => false; void IEcsPool.Del(int entityID) => throw new NotImplementedException(); void IEcsPool.AddRaw(int entityID, object dataRaw) => throw new NotImplementedException(); - object IEcsPool.GetRaw(int entityID) => throw new NotImplementedException(); + object IEcsReadonlyPool.GetRaw(int entityID) => throw new NotImplementedException(); void IEcsPool.SetRaw(int entity, object dataRaw) => throw new NotImplementedException(); - void IEcsPool.Copy(int fromEntityID, int toEntityID) => throw new NotImplementedException(); - void IEcsPool.Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) => throw new NotImplementedException(); + void IEcsReadonlyPool.Copy(int fromEntityID, int toEntityID) => throw new NotImplementedException(); + void IEcsReadonlyPool.Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) => throw new NotImplementedException(); #endregion #region Callbacks @@ -123,8 +128,8 @@ namespace DCFApixels.DragonECS #endregion #region Listeners - void IEcsPool.AddListener(IEcsPoolEventListener listener) { } - void IEcsPool.RemoveListener(IEcsPoolEventListener listener) { } + void IEcsReadonlyPool.AddListener(IEcsPoolEventListener listener) { } + void IEcsReadonlyPool.RemoveListener(IEcsPoolEventListener listener) { } #endregion } } diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 775ceca..cdf9f33 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -46,11 +46,7 @@ namespace DCFApixels.DragonECS { get { return _count; } } - int IEcsPool.Capacity - { - get { return -1; } - } - public int ComponentID + public int ComponentTypeID { get { return _componentTypeID; } } @@ -62,6 +58,10 @@ namespace DCFApixels.DragonECS { get { return _source; } } + public bool IReadOnly + { + get { return false; } + } #endregion #region Method @@ -176,7 +176,7 @@ namespace DCFApixels.DragonECS #region Other void IEcsPool.AddRaw(int entityID, object dataRaw) { Add(entityID); } - object IEcsPool.GetRaw(int entityID) + object IEcsReadonlyPool.GetRaw(int entityID) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent(entityID); } diff --git a/src/Pools/Utils/VirtualHybridPool.cs b/src/Pools/Utils/VirtualHybridPool.cs new file mode 100644 index 0000000..ede8fce --- /dev/null +++ b/src/Pools/Utils/VirtualHybridPool.cs @@ -0,0 +1,168 @@ +using System; +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS.Internal +{ + internal class VirtualHybridPool : IEcsHybridPoolInternal + { + private EcsWorld _source; + private Type _componentType; + + internal int[] _mapping; + internal object[] _items; + private int[] _entities; + internal int _itemsCount = 0; + + internal int[] _recycledItems; + internal int _recycledItemsCount; + + private bool _isDevirtualized = false; + + #region Properties + public Type ComponentType + { + get { return _componentType; } + } + public EcsWorld World + { + get { return _source; } + } + public int Count + { + get { return _itemsCount; } + } + public int Capacity + { + get { return _mapping.Length; } + } + public bool IsDevirtualized + { + get { return _isDevirtualized; } + } + #endregion + + #region Constructors + public VirtualHybridPool(EcsWorld world, Type componentType) + { + _source = world; + _componentType = componentType; + + _mapping = new int[world.Capacity]; + _recycledItems = new int[world.Config.Get_PoolRecycledComponentsCapacity()]; + _recycledItemsCount = 0; + _items = new object[ArrayUtility.NormalizeSizeToPowerOfTwo(world.Config.Get_PoolComponentsCapacity())]; + _itemsCount = 0; + } + #endregion + + #region Callbacks + public void OnWorldResize(int newSize) + { + Array.Resize(ref _mapping, newSize); + } + #endregion + + #region Methods + public void AddRaw(int entityID, object dataRaw) + { + ref int itemIndex = ref _mapping[entityID]; +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (itemIndex > 0) { EcsPoolThrowHalper.ThrowAlreadyHasComponent(_componentType, entityID); } +#endif + if (_recycledItemsCount > 0) + { + itemIndex = _recycledItems[--_recycledItemsCount]; + _itemsCount++; + } + else + { + itemIndex = ++_itemsCount; + if (_itemsCount >= _items.Length) + { + Array.Resize(ref _items, _items.Length << 1); + } + } + _items[itemIndex] = dataRaw; + } + public bool TryAddRaw(int entityID, object dataRaw) + { + if (Has(entityID)) + { + return false; + } + AddRaw(entityID, dataRaw); + return true; + } + public void SetRaw(int entityID, object dataRaw) + { +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent(_componentType, entityID); } +#endif + _items[_mapping[entityID]] = dataRaw; + } + public object GetRaw(int entityID) + { +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent(_componentType, entityID); } +#endif + return _items[_mapping[entityID]]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Has(int entityID) + { + return _mapping[entityID] > 0; + } + public void Del(int entityID) + { + ref int itemIndex = ref _mapping[entityID]; +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (itemIndex <= 0) EcsPoolThrowHalper.ThrowNotHaveComponent(_componentType, entityID); +#endif + _items[itemIndex] = null; + if (_recycledItemsCount >= _recycledItems.Length) + { + Array.Resize(ref _recycledItems, _recycledItems.Length << 1); + } + _recycledItems[_recycledItemsCount++] = itemIndex; + itemIndex = 0; + _itemsCount--; + } + public bool TryDel(int entityID) + { + if (Has(entityID)) + { + Del(entityID); + return true; + } + return false; + } + + public void Copy(int fromEntityID, int toEntityID) + { + throw new NotImplementedException(); + } + public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) + { + Throw.Exception("Copying data to another world is not supported for virtual pools, devirtualize the pool first."); + } + #endregion + + #region IEcsHybridPoolInternal + public void AddRefInternal(int entityID, object component, bool isMain) + { + AddRaw(entityID, component); + } + public void DelInternal(int entityID, bool isMain) + { + Del(entityID); + } + #endregion + + #region Devirtualize + void IEcsHybridPoolInternal.Devirtualize(VirtualHybridPool virtualHybridPool) + { + Throw.UndefinedException(); + } + #endregion + } +} \ No newline at end of file diff --git a/src/Pools/VirtualPool.cs b/src/Pools/VirtualPool.cs deleted file mode 100644 index cda8df3..0000000 --- a/src/Pools/VirtualPool.cs +++ /dev/null @@ -1,314 +0,0 @@ -using DCFApixels.DragonECS; -using DCFApixels.DragonECS.Internal; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - - -internal class VirtualPool : IEcsPoolImplementation, IEnumerable -{ - private EcsWorld _source; - private Type _componentType; - private int _componentTypeID; - private EcsMaskChunck _maskBit; - - private int[] _mapping; - private object[] _items; - private int _itemsCount = 0; - private int[] _recycledItems; - private int _recycledItemsCount; - - private List _listeners = new List(); - - private EcsWorld.PoolsMediator _mediator; - - private bool _isDevirtualized = false; - - #region Properties - public int ComponentID - { - get { return _componentTypeID; } - } - public Type ComponentType - { - get { return _componentType; } - } - public EcsWorld World - { - get { return _source; } - } - public int Count - { - get { return _itemsCount; } - } - public int Capacity - { - get { return _mapping.Length; } - } - public bool IsDevirtualized - { - get { return _isDevirtualized; } - } - #endregion - - #region Callbacks - void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) - { - _componentType = world.GetComponentType(componentTypeID); - - _source = world; - _mediator = mediator; - _componentTypeID = componentTypeID; - _maskBit = EcsMaskChunck.FromID(componentTypeID); - - _mapping = new int[world.Capacity]; - _recycledItems = new int[world.Config.Get_PoolRecycledComponentsCapacity()]; - _recycledItemsCount = 0; - _items = new object[ArrayUtility.NormalizeSizeToPowerOfTwo(world.Config.Get_PoolComponentsCapacity())]; - _itemsCount = 0; - } - void IEcsPoolImplementation.OnDevirtualize(Data data) - { - Throw.UndefinedException(); - } - void IEcsPoolImplementation.OnWorldResize(int newSize) - { - Array.Resize(ref _mapping, newSize); - } - void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) - { - foreach (var entityID in buffer) - { - TryDel(entityID); - } - } - void IEcsPoolImplementation.OnWorldDestroy() { } - #endregion - - #region Methods - public void AddRaw(int entityID, object dataRaw) - { - ref int itemIndex = ref _mapping[entityID]; -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (itemIndex > 0) { EcsPoolThrowHalper.ThrowAlreadyHasComponent(_componentType, entityID); } -#endif - if (_recycledItemsCount > 0) - { - itemIndex = _recycledItems[--_recycledItemsCount]; - _itemsCount++; - } - else - { - itemIndex = ++_itemsCount; - if (_itemsCount >= _items.Length) - { - Array.Resize(ref _items, _items.Length << 1); - } - } - _items[itemIndex] = dataRaw; - _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); - _listeners.InvokeOnAddAndGet(entityID); - } - public bool TryAddRaw(int entityID, object dataRaw) - { - if (Has(entityID)) - { - return false; - } - AddRaw(entityID, dataRaw); - return true; - } - public void SetRaw(int entityID, object dataRaw) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent(_componentType, entityID); } -#endif - _items[_mapping[entityID]] = dataRaw; - } - public object GetRaw(int entityID) - { -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) { EcsPoolThrowHalper.ThrowNotHaveComponent(_componentType, entityID); } -#endif - _listeners.InvokeOnGet(entityID); - return _items[_mapping[entityID]]; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int entityID) - { - return _mapping[entityID] > 0; - } - public void Del(int entityID) - { - ref int itemIndex = ref _mapping[entityID]; -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (itemIndex <= 0) EcsPoolThrowHalper.ThrowNotHaveComponent(_componentType, entityID); -#endif - _items[itemIndex] = null; - if (_recycledItemsCount >= _recycledItems.Length) - { - Array.Resize(ref _recycledItems, _recycledItems.Length << 1); - } - _recycledItems[_recycledItemsCount++] = itemIndex; - itemIndex = 0; - _itemsCount--; - _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); - _listeners.InvokeOnDel(entityID); - } - public bool TryDel(int entityID) - { - if (Has(entityID)) - { - Del(entityID); - return true; - } - return false; - } - - public void Copy(int fromEntityID, int toEntityID) - { - throw new NotImplementedException(); - } - public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) - { - Throw.Exception("Copying data to another world is not supported for virtual pools, devirtualize the pool first."); - } - #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(); - #endregion - - #region Devirtualization - public Data GetDevirtualizationData() - { - return new Data(this); - } - public readonly ref struct Data - { - private readonly VirtualPool _target; - - public int ComponentsCount - { - get { return _target.Count; } - } - public RawDataIterator RawComponents - { - get { return new RawDataIterator(_target); } - } - public ListenersIterator Listeners - { - get { return new ListenersIterator(_target); } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Data(VirtualPool target) - { - _target = target; - } - - public readonly ref struct ListenersIterator - { - private readonly VirtualPool _target; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ListenersIterator(VirtualPool target) - { - _target = target; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public List.Enumerator GetEnumerator() { return _target._listeners.GetEnumerator(); } - } - - public readonly ref struct RawDataIterator - { - private readonly VirtualPool _target; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RawDataIterator(VirtualPool target) - { - _target = target; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() { return new Enumerator(this); } - public ref struct Enumerator - { - private readonly int[] _mapping; - private readonly object[] _items; - private readonly int _entitesCount; - private int _entityID; - private int _itemIndex; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator(RawDataIterator devirtualizator) - { - _mapping = devirtualizator._target._mapping; - _items = devirtualizator._target._items; - _entitesCount = devirtualizator._target.World.Count + 1; - if (_entitesCount > _mapping.Length) - { - _entitesCount = _mapping.Length; - } - _entityID = 0; - } - public EntityRawDataPair Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return new EntityRawDataPair(_entityID, _items[_itemIndex]); } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - while (_entityID++ < _entitesCount) - { - _itemIndex = _mapping[_entityID]; - if (_itemIndex != 0) - { - return true; - } - } - return false; - } - } - } - } - public readonly struct EntityRawDataPair - { - public readonly int EntityID; - public readonly object RawData; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public EntityRawDataPair(int entityID, object rawData) - { - EntityID = entityID; - RawData = rawData; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Deconstruct(out int entityID, out object rawData) - { - entityID = EntityID; - rawData = RawData; - } - } - #endregion -} - - - -public static class VirtualPoolExtensions -{ - public static bool IsVirtual(this IEcsPool self) - { - return self is VirtualPool; - } -} \ No newline at end of file