2023-07-04 00:00:25 +08:00
|
|
|
|
using DCFApixels.DragonECS.Internal;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS
|
|
|
|
|
{
|
|
|
|
|
public abstract partial class EcsWorld
|
|
|
|
|
{
|
2024-02-14 21:13:00 +08:00
|
|
|
|
private SparseArray<int> _poolTypeCode_2_CmpTypeIDs = new SparseArray<int>();
|
|
|
|
|
private SparseArray<int> _componentTypeCode_2_CmpTypeIDs = new SparseArray<int>();
|
2023-07-04 00:00:25 +08:00
|
|
|
|
private int _poolsCount;
|
|
|
|
|
internal IEcsPoolImplementation[] _pools;
|
2024-01-06 00:07:07 +08:00
|
|
|
|
internal int[] _poolComponentCounts;
|
2024-01-01 21:44:33 +08:00
|
|
|
|
|
|
|
|
|
private static EcsNullPool _nullPool = EcsNullPool.instance;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
|
|
|
|
|
#region Getters
|
|
|
|
|
|
2024-01-06 00:07:07 +08:00
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public TPool TestGetPool<TPool>() where TPool : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
|
|
|
|
return Get<PoolCache<TPool>>().instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-04 00:00:25 +08:00
|
|
|
|
#if UNITY_2020_3_OR_NEWER
|
|
|
|
|
[UnityEngine.Scripting.Preserve]
|
|
|
|
|
#endif
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public TPool GetPool<TPool>() where TPool : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
|
|
|
|
return Get<PoolCache<TPool>>().instance;
|
|
|
|
|
}
|
|
|
|
|
#if UNITY_2020_3_OR_NEWER
|
|
|
|
|
[UnityEngine.Scripting.Preserve]
|
|
|
|
|
#endif
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2023-11-21 10:41:41 +08:00
|
|
|
|
public TPool GetPoolUnchecked<TPool>() where TPool : IEcsPoolImplementation, new()
|
2023-07-04 00:00:25 +08:00
|
|
|
|
{
|
2023-12-31 13:07:53 +08:00
|
|
|
|
return GetUnchecked<PoolCache<TPool>>().instance;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
#if UNITY_2020_3_OR_NEWER
|
|
|
|
|
[UnityEngine.Scripting.Preserve]
|
|
|
|
|
#endif
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static TPool GetPool<TPool>(int worldID) where TPool : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
|
|
|
|
return Get<PoolCache<TPool>>(worldID).instance;
|
|
|
|
|
}
|
|
|
|
|
#if UNITY_2020_3_OR_NEWER
|
|
|
|
|
[UnityEngine.Scripting.Preserve]
|
|
|
|
|
#endif
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static TPool UncheckedGetPool<TPool>(int worldID) where TPool : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
2023-12-31 13:07:53 +08:00
|
|
|
|
return GetUnchecked<PoolCache<TPool>>(worldID).instance;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2024-02-14 21:13:00 +08:00
|
|
|
|
#region ComponentInfo
|
|
|
|
|
public int GetComponentTypeID<TComponent>()
|
|
|
|
|
{
|
|
|
|
|
return DeclareOrGetComponentTypeID(EcsTypeCode.Get<TComponent>());
|
|
|
|
|
}
|
|
|
|
|
public int GetComponentTypeID(Type componentType)
|
|
|
|
|
{
|
|
|
|
|
return DeclareOrGetComponentTypeID(EcsTypeCode.Get(componentType));
|
|
|
|
|
}
|
|
|
|
|
public bool IsComponentTypeDeclared<TComponent>()
|
|
|
|
|
{
|
|
|
|
|
return _componentTypeCode_2_CmpTypeIDs.Contains(EcsTypeCode.Get<TComponent>());
|
|
|
|
|
}
|
|
|
|
|
public bool IsComponentTypeDeclared(Type componentType)
|
|
|
|
|
{
|
|
|
|
|
return _componentTypeCode_2_CmpTypeIDs.Contains(EcsTypeCode.Get(componentType));
|
|
|
|
|
}
|
|
|
|
|
public bool IsComponentTypeDeclared(int componentTypeID)
|
|
|
|
|
{
|
|
|
|
|
if (componentTypeID >= 0 && componentTypeID < _pools.Length)
|
|
|
|
|
{
|
|
|
|
|
return _pools[componentTypeID] != _nullPool;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
public Type GetComponentType(int componentTypeID)
|
|
|
|
|
{
|
|
|
|
|
return _pools[componentTypeID].ComponentType;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2023-07-04 00:00:25 +08:00
|
|
|
|
#region Declare/Create
|
2024-02-14 21:13:00 +08:00
|
|
|
|
private int DeclareOrGetComponentTypeID(int componentTypeCode)
|
2023-07-04 00:00:25 +08:00
|
|
|
|
{
|
2024-02-14 21:13:00 +08:00
|
|
|
|
if (!_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int ComponentTypeID))
|
2023-07-04 00:00:25 +08:00
|
|
|
|
{
|
2024-02-14 21:13:00 +08:00
|
|
|
|
ComponentTypeID = _poolsCount++;
|
|
|
|
|
_componentTypeCode_2_CmpTypeIDs.Add(componentTypeCode, ComponentTypeID);
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
2024-02-14 21:13:00 +08:00
|
|
|
|
return ComponentTypeID;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
private TPool CreatePool<TPool>() where TPool : IEcsPoolImplementation, new()
|
|
|
|
|
{
|
2023-11-15 17:47:11 +08:00
|
|
|
|
int poolTypeCode = EcsTypeCode.Get<TPool>();
|
2024-02-14 21:13:00 +08:00
|
|
|
|
if (_poolTypeCode_2_CmpTypeIDs.Contains(poolTypeCode))
|
|
|
|
|
{
|
|
|
|
|
Throw.World_PoolAlreadyCreated();
|
|
|
|
|
}
|
2024-02-14 21:20:00 +08:00
|
|
|
|
TPool newPool = new TPool();
|
2023-07-04 00:00:25 +08:00
|
|
|
|
|
2024-02-14 21:20:00 +08:00
|
|
|
|
Type componentType = newPool.ComponentType;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
int componentTypeCode = EcsTypeCode.Get(componentType);
|
|
|
|
|
|
2024-02-14 21:13:00 +08:00
|
|
|
|
if (_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID))
|
2023-07-04 00:00:25 +08:00
|
|
|
|
{
|
2024-02-14 21:13:00 +08:00
|
|
|
|
_poolTypeCode_2_CmpTypeIDs[poolTypeCode] = componentTypeID;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-12-06 18:58:06 +08:00
|
|
|
|
componentTypeID = _poolsCount++;
|
2024-02-14 21:13:00 +08:00
|
|
|
|
_poolTypeCode_2_CmpTypeIDs[poolTypeCode] = componentTypeID;
|
|
|
|
|
_componentTypeCode_2_CmpTypeIDs[componentTypeCode] = componentTypeID;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_poolsCount >= _pools.Length)
|
|
|
|
|
{
|
|
|
|
|
int oldCapacity = _pools.Length;
|
|
|
|
|
Array.Resize(ref _pools, _pools.Length << 1);
|
2024-01-06 00:07:07 +08:00
|
|
|
|
Array.Resize(ref _poolComponentCounts, _pools.Length);
|
2023-07-04 00:00:25 +08:00
|
|
|
|
ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
2023-11-22 17:35:03 +08:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < _entitesCapacity; i++)
|
2024-02-14 21:13:00 +08:00
|
|
|
|
{
|
2023-11-22 17:35:03 +08:00
|
|
|
|
Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1);
|
2024-02-14 21:13:00 +08:00
|
|
|
|
}
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-02-14 21:20:00 +08:00
|
|
|
|
if (_pools[componentTypeID] != _nullPool)
|
2023-07-04 00:00:25 +08:00
|
|
|
|
{
|
2024-02-14 21:20:00 +08:00
|
|
|
|
Throw.UndefinedException();
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
2024-02-14 21:20:00 +08:00
|
|
|
|
|
|
|
|
|
_pools[componentTypeID] = newPool;
|
|
|
|
|
newPool.OnInit(this, _poolsMediator, componentTypeID);
|
|
|
|
|
return newPool;
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
2024-01-01 21:44:33 +08:00
|
|
|
|
|
2024-01-06 00:07:07 +08:00
|
|
|
|
|
2024-01-01 21:44:33 +08:00
|
|
|
|
#region Pools mediation
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-07 18:52:54 +08:00
|
|
|
|
private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
2024-01-01 21:44:33 +08:00
|
|
|
|
{
|
2024-01-06 00:07:07 +08:00
|
|
|
|
_poolComponentCounts[componentTypeID]++;
|
2024-01-01 21:44:33 +08:00
|
|
|
|
_componentCounts[entityID]++;
|
|
|
|
|
_entitiesComponentMasks[entityID][maskBit.chankIndex] |= maskBit.mask;
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-07 18:52:54 +08:00
|
|
|
|
private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
2024-01-01 21:44:33 +08:00
|
|
|
|
{
|
2024-02-13 21:13:46 +08:00
|
|
|
|
_poolComponentCounts[componentTypeID]--;
|
|
|
|
|
var count = --_componentCounts[entityID];
|
|
|
|
|
_entitiesComponentMasks[entityID][maskBit.chankIndex] &= ~maskBit.mask;
|
|
|
|
|
|
|
|
|
|
if (count == 0 && IsUsed(entityID))
|
|
|
|
|
{
|
|
|
|
|
DelEntity(entityID);
|
|
|
|
|
}
|
|
|
|
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
|
|
|
|
if (count < 0) Throw.World_InvalidIncrementComponentsBalance();
|
|
|
|
|
#endif
|
2024-01-01 21:44:33 +08:00
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-07 18:52:54 +08:00
|
|
|
|
private bool HasEntityComponent(int entityID, EcsMaskChunck maskBit)
|
2024-01-01 21:44:33 +08:00
|
|
|
|
{
|
|
|
|
|
return (_entitiesComponentMasks[entityID][maskBit.chankIndex] & maskBit.mask) != maskBit.mask;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region PoolsMediator
|
|
|
|
|
public readonly struct PoolsMediator
|
|
|
|
|
{
|
|
|
|
|
private readonly EcsWorld _world;
|
|
|
|
|
internal PoolsMediator(EcsWorld world)
|
|
|
|
|
{
|
|
|
|
|
if (world == null || world._poolsMediator._world != null)
|
|
|
|
|
{
|
|
|
|
|
throw new MethodAccessException();
|
|
|
|
|
}
|
|
|
|
|
_world = world;
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-07 18:52:54 +08:00
|
|
|
|
public void RegisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
2024-01-01 21:44:33 +08:00
|
|
|
|
{
|
|
|
|
|
_world.RegisterEntityComponent(entityID, componentTypeID, maskBit);
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-07 18:52:54 +08:00
|
|
|
|
public void UnregisterComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
2024-01-01 21:44:33 +08:00
|
|
|
|
{
|
|
|
|
|
_world.UnregisterEntityComponent(entityID, componentTypeID, maskBit);
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-07 18:52:54 +08:00
|
|
|
|
public bool HasComponent(int entityID, EcsMaskChunck maskBit)
|
2024-01-01 21:44:33 +08:00
|
|
|
|
{
|
|
|
|
|
return _world.HasEntityComponent(entityID, maskBit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2023-07-04 00:00:25 +08:00
|
|
|
|
}
|
|
|
|
|
}
|