mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
rework EcsMask
This commit is contained in:
parent
12f166a01a
commit
5edd55df88
@ -123,10 +123,10 @@ namespace DCFApixels.DragonECS
|
||||
foreach (var item in _combined)
|
||||
{
|
||||
EcsMask submask = item.aspect.mask;
|
||||
maskInc.ExceptWith(submask.exc);//удаляю конфликтующие ограничения
|
||||
maskExc.ExceptWith(submask.inc);//удаляю конфликтующие ограничения
|
||||
maskInc.UnionWith(submask.inc);
|
||||
maskExc.UnionWith(submask.exc);
|
||||
maskInc.ExceptWith(submask.excChunckMasks);//удаляю конфликтующие ограничения
|
||||
maskExc.ExceptWith(submask.incChunckMasks);//удаляю конфликтующие ограничения
|
||||
maskInc.UnionWith(submask.incChunckMasks);
|
||||
maskExc.UnionWith(submask.excChunckMasks);
|
||||
}
|
||||
maskInc.ExceptWith(_exc);//удаляю конфликтующие ограничения
|
||||
maskExc.ExceptWith(_inc);//удаляю конфликтующие ограничения
|
||||
@ -139,12 +139,29 @@ namespace DCFApixels.DragonECS
|
||||
maskExc = _exc;
|
||||
}
|
||||
|
||||
var inc = maskInc.ToArray();
|
||||
Array.Sort(inc);
|
||||
var exc = maskExc.ToArray();
|
||||
Array.Sort(exc);
|
||||
int[] inc = new int[0];
|
||||
int[] exc = new int[0];
|
||||
foreach (var v in maskInc)
|
||||
{
|
||||
var bit = EcsMaskBit.FromPoolID(v);
|
||||
if (inc.Length <= bit.chankIndex)
|
||||
Array.Resize(ref inc, bit.chankIndex + 1);
|
||||
inc[bit.chankIndex] |= bit.mask;
|
||||
}
|
||||
foreach (var v in maskExc)
|
||||
{
|
||||
var bit = EcsMaskBit.FromPoolID(v);
|
||||
if (exc.Length <= bit.chankIndex)
|
||||
Array.Resize(ref exc, bit.chankIndex + 1);
|
||||
exc[bit.chankIndex] |= bit.mask;
|
||||
}
|
||||
|
||||
mask = new EcsMask(_world.id, inc, exc);
|
||||
//var inc = maskInc.ToArray();
|
||||
//Array.Sort(inc);
|
||||
//var exc = maskExc.ToArray();
|
||||
//Array.Sort(exc);
|
||||
|
||||
mask = new EcsMask(_world.id, inc.ToArray(), exc.ToArray());
|
||||
_world = null;
|
||||
_inc = null;
|
||||
_exc = null;
|
||||
@ -203,25 +220,25 @@ namespace DCFApixels.DragonECS
|
||||
public sealed class EcsMask
|
||||
{
|
||||
internal readonly int worldID;
|
||||
internal readonly int[] inc;
|
||||
internal readonly int[] exc;
|
||||
internal readonly int[] incChunckMasks;
|
||||
internal readonly int[] excChunckMasks;
|
||||
public int WorldID => worldID;
|
||||
/// <summary>Including constraints</summary>
|
||||
public ReadOnlySpan<int> Inc => inc;
|
||||
public ReadOnlySpan<int> Inc => incChunckMasks;
|
||||
/// <summary>Excluding constraints</summary>
|
||||
public ReadOnlySpan<int> Exc => exc;
|
||||
public ReadOnlySpan<int> Exc => excChunckMasks;
|
||||
internal EcsMask(int worldID, int[] inc, int[] exc)
|
||||
{
|
||||
#if DEBUG
|
||||
CheckConstraints(inc, exc);
|
||||
//CheckConstraints(inc, exc);
|
||||
#endif
|
||||
this.worldID = worldID;
|
||||
this.inc = inc;
|
||||
this.exc = exc;
|
||||
this.incChunckMasks = inc;
|
||||
this.excChunckMasks = exc;
|
||||
}
|
||||
|
||||
#region Object
|
||||
public override string ToString() => CreateLogString(worldID, inc, exc);
|
||||
public override string ToString() => CreateLogString(worldID, incChunckMasks, excChunckMasks);
|
||||
#endregion
|
||||
|
||||
#region Debug utils
|
||||
@ -264,17 +281,17 @@ namespace DCFApixels.DragonECS
|
||||
public readonly int worldID;
|
||||
public readonly int[] included;
|
||||
public readonly int[] excluded;
|
||||
public readonly Type[] includedTypes;
|
||||
public readonly Type[] excludedTypes;
|
||||
//public readonly Type[] includedTypes;
|
||||
//public readonly Type[] excludedTypes;
|
||||
public DebuggerProxy(EcsMask mask)
|
||||
{
|
||||
world = EcsWorld.GetWorld(mask.worldID);
|
||||
worldID = mask.worldID;
|
||||
included = mask.inc;
|
||||
excluded = mask.exc;
|
||||
Type converter(int o) => world.GetComponentType(o);
|
||||
includedTypes = included.Select(converter).ToArray();
|
||||
excludedTypes = excluded.Select(converter).ToArray();
|
||||
included = mask.incChunckMasks;
|
||||
excluded = mask.excChunckMasks;
|
||||
//Type converter(int o) => world.GetComponentType(o);
|
||||
//includedTypes = included.Select(converter).ToArray();
|
||||
//excludedTypes = excluded.Select(converter).ToArray();
|
||||
}
|
||||
public override string ToString() => CreateLogString(worldID, included, excluded);
|
||||
}
|
||||
@ -335,31 +352,36 @@ namespace DCFApixels.DragonECS
|
||||
private EcsGroup.Enumerator _sourceGroup;
|
||||
private readonly int[] _inc;
|
||||
private readonly int[] _exc;
|
||||
private readonly IEcsPoolImplementation[] _pools;
|
||||
private readonly int[][] _entitiesComponentMasks;
|
||||
|
||||
public Enumerator(EcsReadonlyGroup sourceGroup, EcsMask mask)
|
||||
{
|
||||
_sourceGroup = sourceGroup.GetEnumerator();
|
||||
_inc = mask.inc;
|
||||
_exc = mask.exc;
|
||||
_pools = sourceGroup.World._pools;
|
||||
_inc = mask.incChunckMasks;
|
||||
_exc = mask.excChunckMasks;
|
||||
_entitiesComponentMasks = sourceGroup.World._entitiesComponentMasks;
|
||||
}
|
||||
public int Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _sourceGroup.Current;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
while (_sourceGroup.MoveNext())
|
||||
{
|
||||
int e = _sourceGroup.Current;
|
||||
for (int i = 0, iMax = _inc.Length; i < iMax; i++)
|
||||
if (!_pools[_inc[i]].Has(e)) goto next;
|
||||
{
|
||||
if (_inc[i] > 0 && (_entitiesComponentMasks[e][i] & _inc[i]) == 0) goto skip;
|
||||
}
|
||||
for (int i = 0, iMax = _exc.Length; i < iMax; i++)
|
||||
if (_pools[_exc[i]].Has(e)) goto next;
|
||||
{
|
||||
if (_exc[i] > 0 && (_entitiesComponentMasks[e][i] & _exc[i]) != 0) goto skip;
|
||||
}
|
||||
return true;
|
||||
next: continue;
|
||||
skip: continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ namespace DCFApixels.DragonECS
|
||||
private List<IEcsWorldEventListener> _listeners = new List<IEcsWorldEventListener>();
|
||||
private List<IEcsEntityEventListener> _entityListeners = new List<IEcsEntityEventListener>();
|
||||
|
||||
internal int[][] _entitiesComponentMasks;
|
||||
|
||||
#region Properties
|
||||
public bool IsDestroyed => _isDestroyed;
|
||||
public int Count => _entitiesCount;
|
||||
@ -66,6 +68,10 @@ namespace DCFApixels.DragonECS
|
||||
_delEntBufferCount = 0;
|
||||
//_delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET];
|
||||
_delEntBuffer = new int[_entitesCapacity];
|
||||
_entitiesComponentMasks = new int[_entitesCapacity][];
|
||||
for (int i = 0; i < _entitesCapacity; i++)
|
||||
_entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1];
|
||||
|
||||
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
|
||||
|
||||
_allEntites = GetFreeGroup();
|
||||
@ -148,6 +154,10 @@ namespace DCFApixels.DragonECS
|
||||
Array.Resize(ref _gens, _gens.Length << 1);
|
||||
Array.Resize(ref _componentCounts, _gens.Length);
|
||||
Array.Resize(ref _delEntBuffer, _gens.Length);
|
||||
Array.Resize(ref _entitiesComponentMasks, _gens.Length);
|
||||
for (int i = _entitesCapacity; i < _gens.Length; i++)
|
||||
_entitiesComponentMasks[i] = new int[_pools.Length / 32 + 1];
|
||||
|
||||
_delEntBufferMinCount = Math.Max(_delEntBuffer.Length >> DEL_ENT_BUFFER_SIZE_OFFSET, DEL_ENT_BUFFER_MIN_SIZE);
|
||||
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity);
|
||||
_entitesCapacity = _gens.Length;
|
||||
@ -212,14 +222,14 @@ namespace DCFApixels.DragonECS
|
||||
if (mask.worldID != id)
|
||||
throw new EcsFrameworkException("The types of the target world of the mask and this world are different.");
|
||||
#endif
|
||||
for (int i = 0, iMax = mask.inc.Length; i < iMax; i++)
|
||||
for (int i = 0, iMax = mask.incChunckMasks.Length; i < iMax; i++)
|
||||
{
|
||||
if (!_pools[mask.inc[i]].Has(entityID))
|
||||
if (!_pools[mask.incChunckMasks[i]].Has(entityID))
|
||||
return false;
|
||||
}
|
||||
for (int i = 0, iMax = mask.exc.Length; i < iMax; i++)
|
||||
for (int i = 0, iMax = mask.excChunckMasks.Length; i < iMax; i++)
|
||||
{
|
||||
if (_pools[mask.exc[i]].Has(entityID))
|
||||
if (_pools[mask.excChunckMasks[i]].Has(entityID))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -288,13 +298,22 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Components Increment
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void IncrementEntityComponentCount(int entityID) => _componentCounts[entityID]++;
|
||||
internal void IncrementEntityComponentCount(int entityID, int componentID)
|
||||
{
|
||||
_componentCounts[entityID]++;
|
||||
EcsMaskBit bit = EcsMaskBit.FromPoolID(componentID);
|
||||
_entitiesComponentMasks[entityID][bit.chankIndex] |= bit.mask;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void DecrementEntityComponentCount(int entityID)
|
||||
internal void DecrementEntityComponentCount(int entityID, int componentID)
|
||||
{
|
||||
var count = --_componentCounts[entityID];
|
||||
if (count == 0 && _allEntites.Has(entityID)) DelEntity(entityID);
|
||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||
EcsMaskBit bit = EcsMaskBit.FromPoolID(componentID);
|
||||
_entitiesComponentMasks[entityID][bit.chankIndex] &= ~bit.mask;
|
||||
|
||||
if (count == 0 && _allEntites.Has(entityID))
|
||||
DelEntity(entityID);
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (count < 0) Throw.World_InvalidIncrementComponentsBalance();
|
||||
#endif
|
||||
}
|
||||
|
@ -93,6 +93,9 @@ namespace DCFApixels.DragonECS
|
||||
int oldCapacity = _pools.Length;
|
||||
Array.Resize(ref _pools, _pools.Length << 1);
|
||||
ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
||||
|
||||
for (int i = 0; i < _entitesCapacity; i++)
|
||||
Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1);
|
||||
}
|
||||
|
||||
if (_pools[componentID] == _nullPool)
|
||||
|
@ -65,7 +65,7 @@ namespace DCFApixels.DragonECS
|
||||
Array.Resize(ref _entities, _items.Length);
|
||||
}
|
||||
}
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
if(isMain)
|
||||
component.OnAddToPool(_source.GetEntityLong(entityID));
|
||||
@ -126,7 +126,7 @@ namespace DCFApixels.DragonECS
|
||||
_mapping[entityID] = 0;
|
||||
_entities[itemIndex] = 0;
|
||||
_itemsCount--;
|
||||
this.DecrementEntityComponentCount(entityID);
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void Del(int entityID)
|
||||
|
@ -12,6 +12,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
private EcsWorld _source;
|
||||
private int _componentID;
|
||||
private EcsMaskBit _maskBit;
|
||||
|
||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
private T[] _items; //dense
|
||||
@ -50,7 +51,7 @@ namespace DCFApixels.DragonECS
|
||||
if (itemIndex >= _items.Length)
|
||||
Array.Resize(ref _items, _items.Length << 1);
|
||||
}
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAddAndGet(entityID);
|
||||
return ref _items[itemIndex];
|
||||
}
|
||||
@ -87,7 +88,7 @@ namespace DCFApixels.DragonECS
|
||||
if (itemIndex >= _items.Length)
|
||||
Array.Resize(ref _items, _items.Length << 1);
|
||||
}
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
}
|
||||
_listeners.InvokeOnGet(entityID);
|
||||
@ -110,7 +111,7 @@ namespace DCFApixels.DragonECS
|
||||
_recycledItems[_recycledItemsCount++] = itemIndex;
|
||||
_mapping[entityID] = 0;
|
||||
_itemsCount--;
|
||||
this.DecrementEntityComponentCount(entityID);
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void TryDel(int entityID)
|
||||
@ -139,6 +140,8 @@ namespace DCFApixels.DragonECS
|
||||
_source = world;
|
||||
_componentID = componentID;
|
||||
|
||||
_maskBit = EcsMaskBit.FromPoolID(componentID);
|
||||
|
||||
const int capacity = 512;
|
||||
|
||||
_mapping = new int[world.Capacity];
|
||||
|
@ -72,14 +72,14 @@ namespace DCFApixels.DragonECS
|
||||
public static class IEcsPoolImplementationExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void IncrementEntityComponentCount<T>(this IEcsPoolImplementation<T> self, int entityID)
|
||||
public static void IncrementEntityComponentCount<T>(this IEcsPoolImplementation<T> self, int entityID, int componentID)
|
||||
{
|
||||
self.World.IncrementEntityComponentCount(entityID);
|
||||
self.World.IncrementEntityComponentCount(entityID, componentID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void DecrementEntityComponentCount<T>(this IEcsPoolImplementation<T> self, int entityID)
|
||||
public static void DecrementEntityComponentCount<T>(this IEcsPoolImplementation<T> self, int entityID, int componentID)
|
||||
{
|
||||
self.World.DecrementEntityComponentCount(entityID);
|
||||
self.World.DecrementEntityComponentCount(entityID, componentID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
@ -47,7 +47,7 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
_count++;
|
||||
_mapping[entityID] = true;
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
}
|
||||
public void TryAdd(int entityID)
|
||||
@ -56,7 +56,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_count++;
|
||||
_mapping[entityID] = true;
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAdd(entityID);
|
||||
}
|
||||
}
|
||||
@ -72,7 +72,7 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
_mapping[entityID] = false;
|
||||
_count--;
|
||||
this.DecrementEntityComponentCount(entityID);
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
}
|
||||
public void TryDel(int entityID)
|
||||
|
@ -167,7 +167,7 @@ namespace DCFApixels.DragonECS
|
||||
entry.key = key;
|
||||
entry.value = default;
|
||||
_buckets[targetBucket] = index;
|
||||
this.IncrementEntityComponentCount(entityID);
|
||||
this.IncrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnAddAndGet(entityID);
|
||||
return ref entry.value;
|
||||
}
|
||||
@ -235,7 +235,7 @@ namespace DCFApixels.DragonECS
|
||||
_componentResetHandler.Reset(ref _entries[i].value);
|
||||
_freeList = i;
|
||||
_freeCount++;
|
||||
this.DecrementEntityComponentCount(entityID);
|
||||
this.DecrementEntityComponentCount(entityID, _componentID);
|
||||
_listeners.InvokeOnDel(entityID);
|
||||
return;
|
||||
}
|
||||
|
17
src/Utils/EcsMaskBit.cs
Normal file
17
src/Utils/EcsMaskBit.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public readonly struct EcsMaskBit
|
||||
{
|
||||
public readonly int chankIndex;
|
||||
public readonly int mask;
|
||||
public EcsMaskBit(int chankIndex, int mask)
|
||||
{
|
||||
this.chankIndex = chankIndex;
|
||||
this.mask = mask;
|
||||
}
|
||||
public static EcsMaskBit FromPoolID(int id)
|
||||
{
|
||||
return new EcsMaskBit(id / 32, 1 << (id % 32));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user