This commit is contained in:
Mikhail 2024-02-25 00:55:30 +08:00
parent 234fc89711
commit 1f52caf9c0
8 changed files with 510 additions and 402 deletions

View File

@ -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

View File

@ -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);
}
}
/// <summary>Pool for IEcsHybridComponent components</summary>
public sealed class EcsHybridPool<T> : IEcsPoolImplementation<T>, IEcsHybridPool<T>, IEcsHybridPoolInternal, IEnumerable<T> //IEnumerable<T> - 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<HybridPoolGraphCmp>().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<T> IEnumerable<T>.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
}
/// <summary>Hybrid component</summary>
public interface IEcsHybridComponent
@ -403,52 +417,150 @@ namespace DCFApixels.DragonECS
}
public class HybridTypeMapping
namespace DCFApixels.DragonECS.Internal
{
private EcsWorld _world;
private Dictionary<Type, IEcsHybridPoolInternal> _declared = new Dictionary<Type, IEcsHybridPoolInternal>();
private Dictionary<Type, IEcsPool> _canInstantiatedTypes = new Dictionary<Type, IEcsPool>();
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<T>()
internal readonly struct HybridPoolGraphCmp : IEcsWorldComponent<HybridPoolGraphCmp>
{
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<Type, HybridPoolBranch> _branches = new Dictionary<Type, HybridPoolBranch>();
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<IEcsHybridPoolInternal> _relatedPools = new List<IEcsHybridPoolInternal>();
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<T> : HybridBranchBase
// where T : IEcsHybridComponent
//{
// private EcsHybridPool<T> _targetTypePool;
// public HybridBranch(EcsWorld source)
// {
// source.GetHybridPool<T>();
// }
//}
//
//
//
//
//public abstract class HybridNodeBase { }
//public class HybridNode<T> : HybridNodeBase
// where T : IEcsHybridComponent
//{
// private EcsHybridPool<T> _targetTypePool;
// public HybridNode(EcsWorld source)
// {
// source.GetHybridPool<T>();
// }
//}
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);
}
}
}
}

View File

@ -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<T> : IEcsReadonlyPool where T : class
{
T Get(int entityID);
}
public interface IEcsInterfaceComponent { }
public class EcsInterfacePool<T> : IEcsPoolImplementation<T>, IEcsInterfacePool<T>, IEnumerable<T> //IEnumerable<T> - 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<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
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<T>(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<int> 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<T> IEnumerable<T>.GetEnumerator() { throw new NotImplementedException(); }
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
#endregion
}
}

View File

@ -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

View File

@ -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
}
/// <summary>A pool for struct components.</summary>
public interface IEcsStructPool<T> : 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
}
}

View File

@ -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<T>(entityID); }

View File

@ -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
}
}

View File

@ -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<IEcsPoolEventListener> _listeners = new List<IEcsPoolEventListener>();
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<int> 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<IEcsPoolEventListener>.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;
}
}