mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
stash
This commit is contained in:
parent
234fc89711
commit
1f52caf9c0
@ -18,10 +18,16 @@ namespace DCFApixels.DragonECS
|
|||||||
private EcsNullPool _nullPool = EcsNullPool.instance;
|
private EcsNullPool _nullPool = EcsNullPool.instance;
|
||||||
|
|
||||||
#region Getters
|
#region Getters
|
||||||
|
public IEcsPool GetPool(int componentTypeID)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (_pools[componentTypeID].ComponentTypeID != componentTypeID) { Throw.UndefinedException(); }
|
||||||
|
#endif
|
||||||
|
return _pools[componentTypeID];
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public IEcsPool GetPool(Type componentType)
|
public IEcsPool GetPool(Type componentType)
|
||||||
//TODO. Есть проблема, возврат виртуального пула и последующая девиртуализация сделает ссылку невалидной. Одно из решений возвращать обертку
|
|
||||||
{
|
{
|
||||||
int componentTypeID = GetComponentTypeID(componentType);
|
int componentTypeID = GetComponentTypeID(componentType);
|
||||||
ref var pool = ref _pools[componentTypeID];
|
ref var pool = ref _pools[componentTypeID];
|
||||||
@ -276,45 +282,45 @@ namespace DCFApixels.DragonECS
|
|||||||
#region PoolsMediator
|
#region PoolsMediator
|
||||||
public readonly struct PoolsMediator
|
public readonly struct PoolsMediator
|
||||||
{
|
{
|
||||||
private readonly EcsWorld _world;
|
public readonly EcsWorld World;
|
||||||
internal PoolsMediator(EcsWorld world)
|
internal PoolsMediator(EcsWorld world)
|
||||||
{
|
{
|
||||||
if (world == null || world._poolsMediator._world != null)
|
if (world == null || world._poolsMediator.World != null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
_world = world;
|
World = world;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void RegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
public void RegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||||
{
|
{
|
||||||
_world.RegisterEntityComponent(entityID, componentTypeID, maskBit);
|
World.RegisterEntityComponent(entityID, componentTypeID, maskBit);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void UnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
public void UnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||||
{
|
{
|
||||||
_world.UnregisterEntityComponent(entityID, componentTypeID, maskBit);
|
World.UnregisterEntityComponent(entityID, componentTypeID, maskBit);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool TryRegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
public bool TryRegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||||
{
|
{
|
||||||
return _world.TryRegisterEntityComponent(entityID, componentTypeID, maskBit);
|
return World.TryRegisterEntityComponent(entityID, componentTypeID, maskBit);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool TryUnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
public bool TryUnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||||
{
|
{
|
||||||
return _world.TryUnregisterEntityComponent(entityID, componentTypeID, maskBit);
|
return World.TryUnregisterEntityComponent(entityID, componentTypeID, maskBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public int GetComponentCount(int componentTypeID)
|
public int GetComponentCount(int componentTypeID)
|
||||||
{
|
{
|
||||||
return _world.GetPoolComponentCount(componentTypeID);
|
return World.GetPoolComponentCount(componentTypeID);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool HasComponent(int entityID, EcsMaskChunck maskBit)
|
public bool HasComponent(int entityID, EcsMaskChunck maskBit)
|
||||||
{
|
{
|
||||||
return _world.HasEntityComponent(entityID, maskBit);
|
return World.HasEntityComponent(entityID, maskBit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using DCFApixels.DragonECS;
|
|
||||||
using DCFApixels.DragonECS.Internal;
|
using DCFApixels.DragonECS.Internal;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
@ -8,14 +7,6 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
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>
|
/// <summary>Pool for IEcsHybridComponent components</summary>
|
||||||
public sealed class EcsHybridPool<T> : IEcsPoolImplementation<T>, IEcsHybridPool<T>, IEcsHybridPoolInternal, IEnumerable<T> //IEnumerable<T> - IntelliSense hack
|
public sealed class EcsHybridPool<T> : IEcsPoolImplementation<T>, IEcsHybridPool<T>, IEcsHybridPoolInternal, IEnumerable<T> //IEnumerable<T> - IntelliSense hack
|
||||||
where T : class, IEcsHybridComponent
|
where T : class, IEcsHybridComponent
|
||||||
@ -36,6 +27,8 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
private EcsWorld.PoolsMediator _mediator;
|
private EcsWorld.PoolsMediator _mediator;
|
||||||
|
|
||||||
|
private HybridPoolGraph _graph;
|
||||||
|
|
||||||
#region Properites
|
#region Properites
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
@ -45,7 +38,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _items.Length; }
|
get { return _items.Length; }
|
||||||
}
|
}
|
||||||
public int ComponentID
|
public int ComponentTypeID
|
||||||
{
|
{
|
||||||
get { return _componentTypeID; }
|
get { return _componentTypeID; }
|
||||||
}
|
}
|
||||||
@ -57,6 +50,10 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _source; }
|
get { return _source; }
|
||||||
}
|
}
|
||||||
|
public bool IReadOnly
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
@ -95,15 +92,20 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public void Add(int entityID, T component)
|
public void Add(int entityID, T component)
|
||||||
{
|
{
|
||||||
HybridMapping mapping = _source.GetHybridMapping(component.GetType());
|
//HybridMapping mapping = _source.GetHybridMapping(component.GetType());
|
||||||
mapping.GetTargetTypePool().AddRefInternal(entityID, component, true);
|
//mapping.GetTargetTypePool().AddRefInternal(entityID, component, true);
|
||||||
foreach (var pool in mapping.GetPools())
|
//foreach (var pool in mapping.GetPools())
|
||||||
pool.AddRefInternal(entityID, component, false);
|
//{
|
||||||
|
// pool.AddRefInternal(entityID, component, false);
|
||||||
|
//}
|
||||||
|
_graph.GetBranch(component.GetType()).Add(entityID, component);
|
||||||
}
|
}
|
||||||
public void Set(int entityID, T component)
|
public void Set(int entityID, T component)
|
||||||
{
|
{
|
||||||
if (Has(entityID))
|
if (Has(entityID))
|
||||||
|
{
|
||||||
Del(entityID);
|
Del(entityID);
|
||||||
|
}
|
||||||
Add(entityID, component);
|
Add(entityID, component);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -188,7 +190,9 @@ namespace DCFApixels.DragonECS
|
|||||||
for (int i = _itemsCount - 1; i >= 0; i--)
|
for (int i = _itemsCount - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (!_items[i].IsAlive)
|
if (!_items[i].IsAlive)
|
||||||
|
{
|
||||||
Del(_entities[i]);
|
Del(_entities[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -196,6 +200,8 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Callbacks
|
#region Callbacks
|
||||||
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
|
||||||
{
|
{
|
||||||
|
_graph = world.Get<HybridPoolGraphCmp>().Graph;
|
||||||
|
|
||||||
_source = world;
|
_source = world;
|
||||||
_mediator = mediator;
|
_mediator = mediator;
|
||||||
_componentTypeID = componentTypeID;
|
_componentTypeID = componentTypeID;
|
||||||
@ -224,7 +230,7 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID, (T)dataRaw);
|
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);
|
void IEcsPool.SetRaw(int entityID, object dataRaw) => Set(entityID, (T)dataRaw);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -245,6 +251,14 @@ namespace DCFApixels.DragonECS
|
|||||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
|
||||||
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Devirtualize
|
||||||
|
void IEcsHybridPoolInternal.Devirtualize(VirtualHybridPool virtualHybridPool)
|
||||||
|
{
|
||||||
|
_mapping = virtualHybridPool._mapping;
|
||||||
|
_itemsCount = virtualHybridPool._itemsCount;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
/// <summary>Hybrid component</summary>
|
/// <summary>Hybrid component</summary>
|
||||||
public interface IEcsHybridComponent
|
public interface IEcsHybridComponent
|
||||||
@ -403,52 +417,150 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class HybridTypeMapping
|
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Internal
|
||||||
{
|
{
|
||||||
private EcsWorld _world;
|
internal interface IEcsHybridPoolInternal
|
||||||
private Dictionary<Type, IEcsHybridPoolInternal> _declared = new Dictionary<Type, IEcsHybridPoolInternal>();
|
|
||||||
|
|
||||||
private Dictionary<Type, IEcsPool> _canInstantiatedTypes = new Dictionary<Type, IEcsPool>();
|
|
||||||
|
|
||||||
public void AddIntsanceType(object instance)
|
|
||||||
{
|
{
|
||||||
// _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);
|
||||||
}
|
}
|
||||||
|
internal readonly struct HybridPoolGraphCmp : IEcsWorldComponent<HybridPoolGraphCmp>
|
||||||
public void Declare<T>()
|
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
public class HybridPoolGraph
|
||||||
|
|
||||||
private void Init()
|
|
||||||
{
|
{
|
||||||
|
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 void InitRootTypePool(IEcsHybridPoolInternal rootTypePool)
|
||||||
//public class HybridBranch<T> : HybridBranchBase
|
{
|
||||||
// where T : IEcsHybridComponent
|
if (_isVirtualPool == false)
|
||||||
//{
|
{
|
||||||
// private EcsHybridPool<T> _targetTypePool;
|
Throw.UndefinedException();
|
||||||
// public HybridBranch(EcsWorld source)
|
}
|
||||||
// {
|
_isVirtualPool = false;
|
||||||
// source.GetHybridPool<T>();
|
rootTypePool.Devirtualize(_virtualPoolRef);
|
||||||
// }
|
_rootTypePool = rootTypePool;
|
||||||
//}
|
_virtualPoolRef = null;
|
||||||
//
|
}
|
||||||
//
|
public void InitNewPool(IEcsHybridPoolInternal pool)
|
||||||
//
|
{
|
||||||
//
|
_relatedPools.Add(pool);
|
||||||
//public abstract class HybridNodeBase { }
|
}
|
||||||
//public class HybridNode<T> : HybridNodeBase
|
|
||||||
// where T : IEcsHybridComponent
|
public void Set(int entityID, object component)
|
||||||
//{
|
{
|
||||||
// private EcsHybridPool<T> _targetTypePool;
|
throw new NotImplementedException();
|
||||||
// public HybridNode(EcsWorld source)
|
}
|
||||||
// {
|
public void Add(int entityID, object component)
|
||||||
// source.GetHybridPool<T>();
|
{
|
||||||
// }
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
127
src/Pools/EcsInterfacePool.cs
Normal file
127
src/Pools/EcsInterfacePool.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _items.Length; }
|
get { return _items.Length; }
|
||||||
}
|
}
|
||||||
public int ComponentID
|
public int ComponentTypeID
|
||||||
{
|
{
|
||||||
get { return _componentTypeID; }
|
get { return _componentTypeID; }
|
||||||
}
|
}
|
||||||
@ -50,6 +50,10 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _source; }
|
get { return _source; }
|
||||||
}
|
}
|
||||||
|
public bool IReadOnly
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
@ -194,7 +198,7 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
void IEcsPool.AddRaw(int entityID, object dataRaw) { Add(entityID) = (T)dataRaw; }
|
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; }
|
void IEcsPool.SetRaw(int entityID, object dataRaw) { Get(entityID) = (T)dataRaw; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -5,22 +5,19 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
public interface IEcsPool
|
public interface IEcsReadonlyPool
|
||||||
{
|
{
|
||||||
#region Properties
|
#region Properties
|
||||||
int ComponentID { get; }
|
int ComponentTypeID { get; }
|
||||||
Type ComponentType { get; }
|
Type ComponentType { get; }
|
||||||
EcsWorld World { get; }
|
EcsWorld World { get; }
|
||||||
int Count { get; }
|
int Count { get; }
|
||||||
int Capacity { get; } //TODO удалить. не во всех реализация нужен, проще привести к типу
|
bool IReadOnly { get; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
bool Has(int entityID);
|
bool Has(int entityID);
|
||||||
void Del(int entityID);
|
|
||||||
void AddRaw(int entityID, object dataRaw);
|
|
||||||
object GetRaw(int entityID);
|
object GetRaw(int entityID);
|
||||||
void SetRaw(int entityID, object dataRaw);
|
|
||||||
void Copy(int fromEntityID, int toEntityID);
|
void Copy(int fromEntityID, int toEntityID);
|
||||||
void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID);
|
void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID);
|
||||||
#endregion
|
#endregion
|
||||||
@ -30,6 +27,14 @@ namespace DCFApixels.DragonECS
|
|||||||
void RemoveListener(IEcsPoolEventListener listener);
|
void RemoveListener(IEcsPoolEventListener listener);
|
||||||
#endregion
|
#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>
|
/// <summary>A pool for struct components.</summary>
|
||||||
public interface IEcsStructPool<T> : IEcsPool where T: struct
|
public interface IEcsStructPool<T> : IEcsPool where T: struct
|
||||||
{
|
{
|
||||||
@ -98,21 +103,21 @@ namespace DCFApixels.DragonECS
|
|||||||
public static readonly EcsNullPool instance = new EcsNullPool();
|
public static readonly EcsNullPool instance = new EcsNullPool();
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
int IEcsPool.ComponentID => -1;
|
int IEcsReadonlyPool.ComponentTypeID => -1;
|
||||||
Type IEcsPool.ComponentType => typeof(NullComponent);
|
Type IEcsReadonlyPool.ComponentType => typeof(NullComponent);
|
||||||
EcsWorld IEcsPool.World => throw new NotImplementedException();
|
EcsWorld IEcsReadonlyPool.World => throw new NotImplementedException();
|
||||||
public int Count => -1;
|
public int Count => -1;
|
||||||
public int Capacity => -1;
|
public bool IReadOnly { get { return true; } }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
bool IEcsPool.Has(int index) => false;
|
bool IEcsReadonlyPool.Has(int index) => false;
|
||||||
void IEcsPool.Del(int entityID) => throw new NotImplementedException();
|
void IEcsPool.Del(int entityID) => throw new NotImplementedException();
|
||||||
void IEcsPool.AddRaw(int entityID, object dataRaw) => 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.SetRaw(int entity, object dataRaw) => throw new NotImplementedException();
|
||||||
void IEcsPool.Copy(int fromEntityID, int toEntityID) => throw new NotImplementedException();
|
void IEcsReadonlyPool.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, EcsWorld toWorld, int toEntityID) => throw new NotImplementedException();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
@ -123,8 +128,8 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Listeners
|
#region Listeners
|
||||||
void IEcsPool.AddListener(IEcsPoolEventListener listener) { }
|
void IEcsReadonlyPool.AddListener(IEcsPoolEventListener listener) { }
|
||||||
void IEcsPool.RemoveListener(IEcsPoolEventListener listener) { }
|
void IEcsReadonlyPool.RemoveListener(IEcsPoolEventListener listener) { }
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,11 +46,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _count; }
|
get { return _count; }
|
||||||
}
|
}
|
||||||
int IEcsPool.Capacity
|
public int ComponentTypeID
|
||||||
{
|
|
||||||
get { return -1; }
|
|
||||||
}
|
|
||||||
public int ComponentID
|
|
||||||
{
|
{
|
||||||
get { return _componentTypeID; }
|
get { return _componentTypeID; }
|
||||||
}
|
}
|
||||||
@ -62,6 +58,10 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _source; }
|
get { return _source; }
|
||||||
}
|
}
|
||||||
|
public bool IReadOnly
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Method
|
#region Method
|
||||||
@ -176,7 +176,7 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
void IEcsPool.AddRaw(int entityID, object dataRaw) { Add(entityID); }
|
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 (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
|
if (Has(entityID) == false) { EcsPoolThrowHalper.ThrowNotHaveComponent<T>(entityID); }
|
||||||
|
168
src/Pools/Utils/VirtualHybridPool.cs
Normal file
168
src/Pools/Utils/VirtualHybridPool.cs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user