mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44: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;
|
||||
|
||||
#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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
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; }
|
||||
}
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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); }
|
||||
|
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