mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2026-04-22 01:45:55 +08:00
update
This commit is contained in:
parent
8e3a2d68c6
commit
f1b13c94a7
@ -43,11 +43,17 @@ namespace DCFApixels.DragonECS
|
||||
private EcsMaskChunck _maskBit;
|
||||
|
||||
private HMem<int> _dense;
|
||||
private int _denseCount = 0;
|
||||
private (int ComponentPosIndex, int EntityPosIndex)[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID.
|
||||
private T[] _items; // dense; _items[0] - fake component.
|
||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID.
|
||||
private (T Cmp, int EntityID)[] _items; // dense; _items[0] - fake component.
|
||||
private int _itemsCount = 0;
|
||||
private int _recycledItemsCount;
|
||||
private int _usedBlockCount;
|
||||
|
||||
private struct Slot
|
||||
{
|
||||
public T Cmp;
|
||||
public int EntityID;
|
||||
}
|
||||
|
||||
private readonly IEcsComponentLifecycle<T> _customLifecycle = EcsComponentLifecycle<T>.CustomHandler;
|
||||
private readonly bool _isCustomLifecycle = EcsComponentLifecycle<T>.IsCustom;
|
||||
@ -103,7 +109,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
recycledCapacity = capacity / 2;
|
||||
}
|
||||
_items = new T[capacity];
|
||||
_items = new (T, int)[capacity];
|
||||
//_dense = new int[capacity];
|
||||
_dense = Alloc<int>(capacity);
|
||||
}
|
||||
@ -115,11 +121,11 @@ namespace DCFApixels.DragonECS
|
||||
_componentTypeID = componentTypeID;
|
||||
_maskBit = EcsMaskChunck.FromID(componentTypeID);
|
||||
|
||||
_mapping = new (int,int)[world.Capacity];
|
||||
_mapping = new int[world.Capacity];
|
||||
var worldConfig = world.Configs.GetWorldConfigOrDefault();
|
||||
if (_items == null)
|
||||
{
|
||||
_items = new T[ArrayUtility.CeilPow2Safe(worldConfig.PoolComponentsCapacity)];
|
||||
_items = new (T, int)[ArrayUtility.CeilPow2Safe(worldConfig.PoolComponentsCapacity)];
|
||||
//_dense = new int[ArrayUtility.CeilPow2Safe(worldConfig.PoolComponentsCapacity)];
|
||||
_dense = Alloc<int>(ArrayUtility.CeilPow2Safe(worldConfig.PoolComponentsCapacity));
|
||||
}
|
||||
@ -134,7 +140,7 @@ namespace DCFApixels.DragonECS
|
||||
#if DEBUG
|
||||
if (entityID == EcsConsts.NULL_ENTITY_ID) { EcsPoolThrowHelper.ThrowEntityIsNotAlive(_world, entityID); }
|
||||
if (_world.IsUsed(entityID) == false) { EcsPoolThrowHelper.ThrowEntityIsNotAlive(_world, entityID); }
|
||||
if (mappingSlot.ComponentPosIndex > 0) { EcsPoolThrowHelper.ThrowAlreadyHasComponent<T>(entityID); }
|
||||
if (mappingSlot > 0) { EcsPoolThrowHelper.ThrowAlreadyHasComponent<T>(entityID); }
|
||||
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
|
||||
#elif DRAGONECS_STABILITY_MODE
|
||||
if (itemIndex > 0) { return ref Get(entityID); }
|
||||
@ -142,31 +148,32 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
if (_recycledItemsCount > 0)
|
||||
{
|
||||
//mappingSlot.ComponentPosIndex = _recycledItems[--_recycledItemsCount];
|
||||
//mappingSlot.ComponentPosIndex = _dense[_dense.Length - _recycledItemsCount] & int.MaxValue;
|
||||
mappingSlot.ComponentPosIndex = _dense.Ptr[_denseCount];
|
||||
//mappingSlot = _recycledItems[--_recycledItemsCount];
|
||||
//mappingSlot = _dense[_dense.Length - _recycledItemsCount] & int.MaxValue;
|
||||
mappingSlot = _dense.Ptr[_itemsCount];
|
||||
_recycledItemsCount--;
|
||||
_itemsCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mappingSlot.ComponentPosIndex = ++_itemsCount;
|
||||
if (mappingSlot.ComponentPosIndex >= _items.Length)
|
||||
mappingSlot = _itemsCount + 1;
|
||||
if (mappingSlot >= _items.Length)
|
||||
{
|
||||
Array.Resize(ref _items, ArrayUtility.NextPow2(mappingSlot.ComponentPosIndex));
|
||||
//Array.Resize(ref _dense, ArrayUtility.NextPow2(mappingSlot.ComponentPosIndex));
|
||||
_dense = Realloc<int>(_dense, ArrayUtility.NextPow2(mappingSlot.ComponentPosIndex));
|
||||
Array.Resize(ref _items, ArrayUtility.NextPow2(mappingSlot));
|
||||
//Array.Resize(ref _dense, ArrayUtility.NextPow2(mappingSlot));
|
||||
_dense = Realloc<int>(_dense, ArrayUtility.NextPow2(mappingSlot));
|
||||
}
|
||||
_usedBlockCount++;
|
||||
}
|
||||
mappingSlot.EntityPosIndex = _denseCount;
|
||||
_dense.Ptr[_denseCount++] = entityID;
|
||||
_dense.Ptr[_itemsCount] = entityID;
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
ref T result = ref _items[mappingSlot.ComponentPosIndex];
|
||||
EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref result, _worldID, entityID);
|
||||
ref var slot = ref _items[mappingSlot];
|
||||
slot.EntityID = entityID;
|
||||
_itemsCount++;
|
||||
EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref slot.Cmp, _worldID, entityID);
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
if (_hasAnyListener) { _listeners.InvokeOnAddAndGet(entityID); }
|
||||
#endif
|
||||
return ref result;
|
||||
return ref slot.Cmp;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Get(int entityID)
|
||||
@ -177,7 +184,7 @@ namespace DCFApixels.DragonECS
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
if (_hasAnyListener) { _listeners.InvokeOnGet(entityID); }
|
||||
#endif
|
||||
return ref _items[_mapping[entityID].ComponentPosIndex];
|
||||
return ref _items[_mapping[entityID]].Cmp;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(int entityID)
|
||||
@ -185,89 +192,91 @@ namespace DCFApixels.DragonECS
|
||||
#if DEBUG // íå íóæåí STAB_MODE
|
||||
if (!Has(entityID)) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); }
|
||||
#endif
|
||||
return ref _items[_mapping[entityID].ComponentPosIndex];
|
||||
return ref _items[_mapping[entityID]].Cmp;
|
||||
}
|
||||
public ref T TryAddOrGet(int entityID)
|
||||
{
|
||||
#if DEBUG
|
||||
if (entityID == EcsConsts.NULL_ENTITY_ID) { EcsPoolThrowHelper.ThrowEntityIsNotAlive(_world, entityID); }
|
||||
#endif
|
||||
ref var mappingSlot = ref _mapping[entityID];
|
||||
if (mappingSlot.ComponentPosIndex <= 0)
|
||||
{ //Add block
|
||||
#if DEBUG
|
||||
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
|
||||
#elif DRAGONECS_STABILITY_MODE
|
||||
if (_isLocked) { return ref _items[0]; }
|
||||
#endif
|
||||
if (_recycledItemsCount > 0)
|
||||
if (Has(entityID))
|
||||
{
|
||||
//mappingSlot.ComponentPosIndex = _dense[_dense.Length - _recycledItemsCount] & int.MaxValue;
|
||||
mappingSlot.ComponentPosIndex = _dense.Ptr[_denseCount];
|
||||
_recycledItemsCount--;
|
||||
_itemsCount++;
|
||||
return ref Get(entityID);
|
||||
}
|
||||
else
|
||||
{
|
||||
mappingSlot.ComponentPosIndex = ++_itemsCount;
|
||||
if (mappingSlot.ComponentPosIndex >= _items.Length)
|
||||
{
|
||||
Array.Resize(ref _items, ArrayUtility.NextPow2(mappingSlot.ComponentPosIndex));
|
||||
//Array.Resize(ref _dense, ArrayUtility.NextPow2(mappingSlot.ComponentPosIndex));
|
||||
_dense = Realloc<int>(_dense, ArrayUtility.NextPow2(mappingSlot.ComponentPosIndex));
|
||||
}
|
||||
}
|
||||
mappingSlot.EntityPosIndex = _denseCount;
|
||||
_dense.Ptr[_denseCount++] = entityID;
|
||||
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref _items[mappingSlot.ComponentPosIndex], _worldID, entityID);
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
if (_hasAnyListener) { _listeners.InvokeOnAdd(entityID); }
|
||||
#endif
|
||||
} //Add block end
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
if (_hasAnyListener) { _listeners.InvokeOnGet(entityID); }
|
||||
#endif
|
||||
return ref _items[mappingSlot.ComponentPosIndex];
|
||||
return ref Add(entityID);
|
||||
//#if DEBUG
|
||||
// if (entityID == EcsConsts.NULL_ENTITY_ID) { EcsPoolThrowHelper.ThrowEntityIsNotAlive(_world, entityID); }
|
||||
//#endif
|
||||
// ref var mappingSlot = ref _mapping[entityID];
|
||||
// if (mappingSlot <= 0)
|
||||
// { //Add block
|
||||
//#if DEBUG
|
||||
// if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
|
||||
//#elif DRAGONECS_STABILITY_MODE
|
||||
// if (_isLocked) { return ref _items[0]; }
|
||||
//#endif
|
||||
// if (_recycledItemsCount > 0)
|
||||
// {
|
||||
// //mappingSlot = _dense[_dense.Length - _recycledItemsCount] & int.MaxValue;
|
||||
// mappingSlot = _dense.Ptr[_denseCount];
|
||||
// _recycledItemsCount--;
|
||||
// _itemsCount++;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// mappingSlot = ++_itemsCount;
|
||||
// if (mappingSlot >= _items.Length)
|
||||
// {
|
||||
// Array.Resize(ref _items, ArrayUtility.NextPow2(mappingSlot));
|
||||
// //Array.Resize(ref _dense, ArrayUtility.NextPow2(mappingSlot));
|
||||
// _dense = Realloc<int>(_dense, ArrayUtility.NextPow2(mappingSlot));
|
||||
// }
|
||||
// }
|
||||
// mappingSlot.EntityPosIndex = _denseCount;
|
||||
// _dense.Ptr[_denseCount++] = entityID;
|
||||
// _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
// EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref _items[mappingSlot], _worldID, entityID);
|
||||
//#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
// if (_hasAnyListener) { _listeners.InvokeOnAdd(entityID); }
|
||||
//#endif
|
||||
// } //Add block end
|
||||
//#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
// if (_hasAnyListener) { _listeners.InvokeOnGet(entityID); }
|
||||
//#endif
|
||||
// return ref _items[mappingSlot];
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has(int entityID)
|
||||
{
|
||||
return _mapping[entityID].ComponentPosIndex > 0;
|
||||
return _mapping[entityID] > 0;
|
||||
}
|
||||
public void Del(int entityID)
|
||||
{
|
||||
ref var mappingSlot = ref _mapping[entityID];
|
||||
var mapIndex = _mapping[entityID];
|
||||
#if DEBUG
|
||||
if (entityID == EcsConsts.NULL_ENTITY_ID) { EcsPoolThrowHelper.ThrowEntityIsNotAlive(_world, entityID); }
|
||||
if (mappingSlot.ComponentPosIndex <= 0) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); }
|
||||
if (mappingSlot <= 0) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); }
|
||||
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
|
||||
#elif DRAGONECS_STABILITY_MODE
|
||||
if (itemIndex <= 0) { return; }
|
||||
if (_isLocked) { return; }
|
||||
#endif
|
||||
EcsComponentLifecycle<T>.OnDel(_isCustomLifecycle, _customLifecycle, ref _items[mappingSlot.ComponentPosIndex], _worldID, entityID);
|
||||
EcsComponentLifecycle<T>.OnDel(_isCustomLifecycle, _customLifecycle, ref _items[mapIndex].Cmp, _worldID, entityID);
|
||||
_items[mapIndex].EntityID = 0;
|
||||
|
||||
//_dense[_sparse[entityID]] = _dense[_count];
|
||||
//_sparse[_dense[_count--]] = _sparse[entityID];
|
||||
|
||||
//_dense[_mapping[entityID].EntityPosIndex] = _dense[_denseCount];
|
||||
//_mapping[_dense[_denseCount--]].EntityPosIndex = _mapping[entityID].EntityPosIndex;
|
||||
|
||||
//_dense[mappingSlot.EntityPosIndex] = _dense[_denseCount];
|
||||
//_mapping[_dense[_denseCount--]].EntityPosIndex = mappingSlot.EntityPosIndex;
|
||||
|
||||
|
||||
_dense.Ptr[mappingSlot.EntityPosIndex] = _dense.Ptr[--_denseCount];
|
||||
_mapping[_dense.Ptr[_denseCount]].EntityPosIndex = mappingSlot.EntityPosIndex;
|
||||
|
||||
//_dense[_dense.Length - _recycledItemsCount] = mappingSlot.ComponentPosIndex | int.MinValue;
|
||||
_dense.Ptr[_denseCount] = mappingSlot.ComponentPosIndex;
|
||||
_recycledItemsCount++;
|
||||
mappingSlot.ComponentPosIndex = 0;
|
||||
_itemsCount--;
|
||||
_dense.Ptr[_itemsCount] = mapIndex;
|
||||
_mapping[entityID] = 0;
|
||||
|
||||
_recycledItemsCount++;
|
||||
_isDensified = false;
|
||||
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
|
||||
//if(_itemsCount == 0)
|
||||
//{
|
||||
// _itemsCount = 0;
|
||||
// _usedBlockCount = 0;
|
||||
// _recycledItemsCount = 0;
|
||||
// _isDensified = true;
|
||||
//}
|
||||
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
if (_hasAnyListener) { _listeners.InvokeOnDel(entityID); }
|
||||
#endif
|
||||
@ -311,16 +320,47 @@ namespace DCFApixels.DragonECS
|
||||
foreach (var entityID in span)
|
||||
{
|
||||
ref var mappingSlot = ref _mapping[entityID];
|
||||
EcsComponentLifecycle<T>.OnDel(_isCustomLifecycle, _customLifecycle, ref _items[mappingSlot.ComponentPosIndex], _worldID, entityID);
|
||||
mappingSlot.ComponentPosIndex = 0;
|
||||
ref var slot = ref _items[mappingSlot];
|
||||
EcsComponentLifecycle<T>.OnDel(_isCustomLifecycle, _customLifecycle, ref slot.Cmp, _worldID, entityID);
|
||||
slot.EntityID = 0;
|
||||
mappingSlot = 0;
|
||||
_mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit);
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
if (_hasAnyListener) { _listeners.InvokeOnDel(entityID); }
|
||||
#endif
|
||||
}
|
||||
_denseCount = 0;
|
||||
_itemsCount = 0;
|
||||
_usedBlockCount = 0;
|
||||
_recycledItemsCount = 0;
|
||||
_isDensified = true;
|
||||
}
|
||||
private bool _isDensified;
|
||||
private void Densify()
|
||||
{
|
||||
if (_isDensified) { return; }
|
||||
|
||||
var newUsedBlockCount = 0;
|
||||
|
||||
int denseIndex = 0;
|
||||
for (int i = 0; i < _usedBlockCount; i++)
|
||||
{
|
||||
ref var slot = ref _items[i + 1];
|
||||
if (slot.EntityID != 0)
|
||||
{
|
||||
_dense.Ptr[denseIndex] = slot.EntityID;
|
||||
denseIndex++;
|
||||
newUsedBlockCount = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dense.Ptr[denseIndex] = i;
|
||||
}
|
||||
}
|
||||
//if (denseIndex != _itemsCount) { Throw.DeepDebugException(); }
|
||||
|
||||
_usedBlockCount = newUsedBlockCount;
|
||||
_recycledItemsCount = newUsedBlockCount - _itemsCount;
|
||||
_isDensified = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -359,7 +399,8 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public EcsSpan ToSpan()
|
||||
{
|
||||
return new EcsSpan(_worldID, new ReadOnlySpan<int>(_dense.Ptr, _denseCount));
|
||||
Densify();
|
||||
return new EcsSpan(_worldID, new ReadOnlySpan<int>(_dense.Ptr, _itemsCount));
|
||||
}
|
||||
|
||||
#region Listeners
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
#if DISABLE_DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
#define DRAGONECS_ENABLE_POOLS_EVENTS
|
||||
#else
|
||||
#undef DRAGONECS_ENABLE_POOLS_EVENTS
|
||||
#endif
|
||||
|
||||
using DCFApixels.DragonECS.Core.Internal;
|
||||
using DCFApixels.DragonECS.PoolsCore;
|
||||
using System;
|
||||
@ -178,7 +184,7 @@ namespace DCFApixels.DragonECS.Core.Internal
|
||||
void IEcsReadonlyPool.AddListener(IEcsPoolEventListener listener) { }
|
||||
void IEcsReadonlyPool.RemoveListener(IEcsPoolEventListener listener) { }
|
||||
#endif
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
public struct NullComponent { }
|
||||
}
|
||||
@ -291,14 +297,15 @@ namespace DCFApixels.DragonECS
|
||||
/// <summary>Called after deleting an entity from the pool</summary>
|
||||
void OnDel(int entityID);
|
||||
}
|
||||
#if !DRAGONECS_DISABLE_POOLS_EVENTS
|
||||
public static class PoolEventListExtensions
|
||||
{
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InvokeOnAdd(this List<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
for (int i = 0; i < self.Count; i++) { self[i].OnAdd(entityID); }
|
||||
}
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InvokeOnAddAndGet(this List<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
@ -308,11 +315,13 @@ namespace DCFApixels.DragonECS
|
||||
self[i].OnGet(entityID);
|
||||
}
|
||||
}
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InvokeOnGet(this List<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
for (int i = 1; i < self.Count; i++) { self[i].OnGet(entityID); }
|
||||
}
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InvokeOnDel(this List<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
@ -322,11 +331,13 @@ namespace DCFApixels.DragonECS
|
||||
//
|
||||
|
||||
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void InvokeOnAdd(this StructList<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
for (int i = 0; i < self.Count; i++) { self[i].OnAdd(entityID); }
|
||||
}
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void InvokeOnAddAndGet(this StructList<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
@ -336,17 +347,18 @@ namespace DCFApixels.DragonECS
|
||||
self[i].OnGet(entityID);
|
||||
}
|
||||
}
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void InvokeOnGet(this StructList<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
for (int i = 0; i < self.Count; i++) { self[i].OnGet(entityID); }
|
||||
}
|
||||
[Conditional("DRAGONECS_ENABLE_POOLS_EVENTS")]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void InvokeOnDel(this StructList<IEcsPoolEventListener> self, int entityID)
|
||||
{
|
||||
for (int i = 0; i < self.Count; i++) { self[i].OnDel(entityID); }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user