diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs
index b082e5a..1db9584 100644
--- a/src/EcsAspect.cs
+++ b/src/EcsAspect.cs
@@ -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;
/// Including constraints
- public ReadOnlySpan Inc => inc;
+ public ReadOnlySpan Inc => incChunckMasks;
/// Excluding constraints
- public ReadOnlySpan Exc => exc;
+ public ReadOnlySpan 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;
}
diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs
index d4ca88b..43ac5a2 100644
--- a/src/EcsWorld.cs
+++ b/src/EcsWorld.cs
@@ -30,6 +30,8 @@ namespace DCFApixels.DragonECS
private List _listeners = new List();
private List _entityListeners = new List();
+ 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
}
diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs
index f6a9040..a68be2d 100644
--- a/src/EcsWorld.pools.cs
+++ b/src/EcsWorld.pools.cs
@@ -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)
diff --git a/src/Pools/EcsHybridPool.cs b/src/Pools/EcsHybridPool.cs
index 85f9383..68520b7 100644
--- a/src/Pools/EcsHybridPool.cs
+++ b/src/Pools/EcsHybridPool.cs
@@ -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)
diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs
index 7fdcfc7..cd7d1aa 100644
--- a/src/Pools/EcsPool.cs
+++ b/src/Pools/EcsPool.cs
@@ -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];
diff --git a/src/Pools/EcsPoolBase.cs b/src/Pools/EcsPoolBase.cs
index bcd8b90..370dfca 100644
--- a/src/Pools/EcsPoolBase.cs
+++ b/src/Pools/EcsPoolBase.cs
@@ -72,14 +72,14 @@ namespace DCFApixels.DragonECS
public static class IEcsPoolImplementationExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void IncrementEntityComponentCount(this IEcsPoolImplementation self, int entityID)
+ public static void IncrementEntityComponentCount(this IEcsPoolImplementation self, int entityID, int componentID)
{
- self.World.IncrementEntityComponentCount(entityID);
+ self.World.IncrementEntityComponentCount(entityID, componentID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void DecrementEntityComponentCount(this IEcsPoolImplementation self, int entityID)
+ public static void DecrementEntityComponentCount(this IEcsPoolImplementation self, int entityID, int componentID)
{
- self.World.DecrementEntityComponentCount(entityID);
+ self.World.DecrementEntityComponentCount(entityID, componentID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs
index 30d7d61..c5175b3 100644
--- a/src/Pools/EcsTagPool.cs
+++ b/src/Pools/EcsTagPool.cs
@@ -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)
diff --git a/src/Pools/EcsTestPool.cs b/src/Pools/EcsTestPool.cs
index b7abf99..7eaff35 100644
--- a/src/Pools/EcsTestPool.cs
+++ b/src/Pools/EcsTestPool.cs
@@ -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;
}
diff --git a/src/Utils/EcsMaskBit.cs b/src/Utils/EcsMaskBit.cs
new file mode 100644
index 0000000..7050222
--- /dev/null
+++ b/src/Utils/EcsMaskBit.cs
@@ -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));
+ }
+ }
+}