add EcsMask.Builder.Except

This commit is contained in:
Mikhail 2024-04-18 22:14:50 +08:00
parent 02fcd5f821
commit f2238cd33a
2 changed files with 95 additions and 20 deletions

View File

@ -168,7 +168,7 @@ namespace DCFApixels.DragonECS
return (TAspect)newAspect; return (TAspect)newAspect;
} }
#region Include/Exclude/Optional/Combine #region Include/Exclude/Optional/Combine/Except
public TPool IncludePool<TPool>() where TPool : IEcsPoolImplementation, new() public TPool IncludePool<TPool>() where TPool : IEcsPoolImplementation, new()
{ {
var pool = _world.GetPoolInstance<TPool>(); var pool = _world.GetPoolInstance<TPool>();
@ -199,6 +199,12 @@ namespace DCFApixels.DragonECS
_maskBuilder.Combine(result.Mask); _maskBuilder.Combine(result.Mask);
return result; return result;
} }
public TOtherAspect Except<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect
{
var result = _world.GetAspect<TOtherAspect>();
_maskBuilder.Except(result.Mask);
return result;
}
#endregion #endregion
private void Build(out EcsMask mask) private void Build(out EcsMask mask)
@ -364,9 +370,14 @@ namespace DCFApixels.DragonECS
_sortIncChunckBuffer = aspect._sortIncChunckBuffer; _sortIncChunckBuffer = aspect._sortIncChunckBuffer;
_sortExcChunckBuffer = aspect._sortExcChunckBuffer; _sortExcChunckBuffer = aspect._sortExcChunckBuffer;
//_entityComponentMaskBitShift = BitsUtility.GetHighBitNumber(aspect.World._entityComponentMaskLength);
_entityComponentMaskLengthBitShift = aspect.World._entityComponentMaskLengthBitShift; _entityComponentMaskLengthBitShift = aspect.World._entityComponentMaskLengthBitShift;
if (aspect.Mask.IsBroken)
{
_span = span.Slice(0, 0).GetEnumerator();
return;
}
#region Sort #region Sort
UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer; UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer;
UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer; UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer;
@ -388,9 +399,9 @@ namespace DCFApixels.DragonECS
} }
for (int i = 0, ii = 0; ii < _sortIncChunckBuffer.Length; ii++) for (int i = 0, ii = 0; ii < _sortIncChunckBuffer.Length; ii++)
{ {
EcsMaskChunck bas = _preSortedIncBuffer[i]; EcsMaskChunck chunkX = _preSortedIncBuffer[i];
int chankIndexX = bas.chankIndex; int chankIndexX = chunkX.chankIndex;
int maskX = bas.mask; int maskX = chunkX.mask;
for (int j = i + 1; j < _sortIncBuffer.Length; j++) for (int j = i + 1; j < _sortIncBuffer.Length; j++)
{ {

View File

@ -44,6 +44,10 @@ namespace DCFApixels.DragonECS
{ {
get { return inc.Length == 0 && exc.Length == 0; } get { return inc.Length == 0 && exc.Length == 0; }
} }
public bool IsBroken
{
get { return (inc.Length & exc.Length) == 1 && inc[0] == exc[0]; }
}
#endregion #endregion
#region Constructors #region Constructors
@ -51,11 +55,24 @@ namespace DCFApixels.DragonECS
{ {
return new Builder(world); return new Builder(world);
} }
internal EcsMask(int id, short worldID, int[] inc, int[] exc)
internal static EcsMask New(int id, short worldID, int[] inc, int[] exc)
{ {
#if DEBUG #if DEBUG
CheckConstraints(inc, exc); CheckConstraints(inc, exc);
#endif #endif
return new EcsMask(id, worldID, inc, exc);
}
internal static EcsMask NewEmpty(int id, short worldID)
{
return new EcsMask(id, worldID, new int[0], new int[0]);
}
internal static EcsMask NewBroken(int id, short worldID)
{
return new EcsMask(id, worldID, new int[1] { 1 }, new int[1] { 1 });
}
private EcsMask(int id, short worldID, int[] inc, int[] exc)
{
this.id = id; this.id = id;
this.inc = inc; this.inc = inc;
this.exc = exc; this.exc = exc;
@ -198,7 +215,7 @@ namespace DCFApixels.DragonECS
#region Debug utils #region Debug utils
#if DEBUG #if DEBUG
private static HashSet<int> _dummyHashSet = new HashSet<int>(); private static HashSet<int> _dummyHashSet = new HashSet<int>();
private void CheckConstraints(int[] inc, int[] exc) private static void CheckConstraints(int[] inc, int[] exc)
{ {
lock (_dummyHashSet) lock (_dummyHashSet)
{ {
@ -209,7 +226,7 @@ namespace DCFApixels.DragonECS
if (_dummyHashSet.Overlaps(exc)) { throw new EcsFrameworkException("Conflicting Include and Exclude constraints."); } if (_dummyHashSet.Overlaps(exc)) { throw new EcsFrameworkException("Conflicting Include and Exclude constraints."); }
} }
} }
private bool CheckRepeats(int[] array) private static bool CheckRepeats(int[] array)
{ {
_dummyHashSet.Clear(); _dummyHashSet.Clear();
foreach (var item in array) foreach (var item in array)
@ -235,6 +252,8 @@ namespace DCFApixels.DragonECS
internal class DebuggerProxy internal class DebuggerProxy
{ {
private EcsMask _source;
public readonly int ID; public readonly int ID;
public readonly EcsWorld world; public readonly EcsWorld world;
private readonly short _worldID; private readonly short _worldID;
@ -245,8 +264,13 @@ namespace DCFApixels.DragonECS
public readonly Type[] includedTypes; public readonly Type[] includedTypes;
public readonly Type[] excludedTypes; public readonly Type[] excludedTypes;
public bool IsEmpty { get { return _source.IsEmpty; } }
public bool IsBroken { get { return _source.IsBroken; } }
public DebuggerProxy(EcsMask mask) public DebuggerProxy(EcsMask mask)
{ {
_source = mask;
ID = mask.id; ID = mask.id;
world = EcsWorld.GetWorld(mask.worldID); world = EcsWorld.GetWorld(mask.worldID);
_worldID = mask.worldID; _worldID = mask.worldID;
@ -308,16 +332,26 @@ namespace DCFApixels.DragonECS
private readonly Dictionary<Key, EcsMask> _masks; private readonly Dictionary<Key, EcsMask> _masks;
private readonly Dictionary<OpMaskKey, EcsMask> _opMasks; private readonly Dictionary<OpMaskKey, EcsMask> _opMasks;
public readonly EcsMask EmptyMask;
public readonly EcsMask BrokenMask;
#region Constructor/Destructor #region Constructor/Destructor
public WorldMaskComponent(EcsWorld world, Dictionary<Key, EcsMask> masks, Dictionary<OpMaskKey, EcsMask> opMasks) public WorldMaskComponent(EcsWorld world, Dictionary<Key, EcsMask> masks, Dictionary<OpMaskKey, EcsMask> opMasks, EcsMask emptyMask, EcsMask brokenMask)
{ {
_world = world; _world = world;
_masks = masks; _masks = masks;
_opMasks = opMasks; _opMasks = opMasks;
EmptyMask = emptyMask;
BrokenMask = brokenMask;
} }
public void Init(ref WorldMaskComponent component, EcsWorld world) public void Init(ref WorldMaskComponent component, EcsWorld world)
{ {
component = new WorldMaskComponent(world, new Dictionary<Key, EcsMask>(256), new Dictionary<OpMaskKey, EcsMask>(256)); var masks = new Dictionary<Key, EcsMask>(256);
EcsMask emptyMask = NewEmpty(0, world.id);
EcsMask brokenMask = NewBroken(1, world.id);
masks.Add(new Key(emptyMask.inc, emptyMask.exc), emptyMask);
masks.Add(new Key(brokenMask.inc, brokenMask.exc), brokenMask);
component = new WorldMaskComponent(world, masks, new Dictionary<OpMaskKey, EcsMask>(256), emptyMask, brokenMask);
} }
public void OnDestroy(ref WorldMaskComponent component, EcsWorld world) public void OnDestroy(ref WorldMaskComponent component, EcsWorld world)
{ {
@ -336,7 +370,7 @@ namespace DCFApixels.DragonECS
var builder = New(a.World); var builder = New(a.World);
if (a.IsConflictWith(b)) if (a.IsConflictWith(b))
{ {
return a.World.GetAspect<EmptyAspect>().Mask; return a.World.Get<WorldMaskComponent>().BrokenMask;
} }
ExceptMaskConstraint(builder, a.inc, b.inc, true); ExceptMaskConstraint(builder, a.inc, b.inc, true);
ExceptMaskConstraint(builder, a.exc, b.exc, false); ExceptMaskConstraint(builder, a.exc, b.exc, false);
@ -376,7 +410,7 @@ namespace DCFApixels.DragonECS
{ {
if (!_masks.TryGetValue(maskKey, out EcsMask result)) if (!_masks.TryGetValue(maskKey, out EcsMask result))
{ {
result = new EcsMask(_masks.Count, _world.id, maskKey.inc, maskKey.exc); result = EcsMask.New(_masks.Count, _world.id, maskKey.inc, maskKey.exc);
_masks.Add(maskKey, result); _masks.Add(maskKey, result);
} }
return result; return result;
@ -447,7 +481,8 @@ namespace DCFApixels.DragonECS
private readonly EcsWorld _world; private readonly EcsWorld _world;
private readonly HashSet<int> _inc = new HashSet<int>(); private readonly HashSet<int> _inc = new HashSet<int>();
private readonly HashSet<int> _exc = new HashSet<int>(); private readonly HashSet<int> _exc = new HashSet<int>();
private readonly List<Combined> _combined = new List<Combined>(); private readonly List<Combined> _combineds = new List<Combined>();
private readonly List<Excepted> _excepteds = new List<Excepted>();
#region Constrcutors #region Constrcutors
internal Builder(EcsWorld world) internal Builder(EcsWorld world)
@ -493,7 +528,13 @@ namespace DCFApixels.DragonECS
public Builder Combine(EcsMask mask, int order = 0) public Builder Combine(EcsMask mask, int order = 0)
{ {
_combined.Add(new Combined(mask, order)); _combineds.Add(new Combined(mask, order));
return this;
}
public Builder Except(EcsMask mask, int order = 0)
{
_excepteds.Add(new Excepted(mask, order));
return this; return this;
} }
#endregion #endregion
@ -503,12 +544,12 @@ namespace DCFApixels.DragonECS
{ {
HashSet<int> combinedInc; HashSet<int> combinedInc;
HashSet<int> combinedExc; HashSet<int> combinedExc;
if (_combined.Count > 0) if (_combineds.Count > 0)
{ {
combinedInc = new HashSet<int>(); combinedInc = new HashSet<int>();
combinedExc = new HashSet<int>(); combinedExc = new HashSet<int>();
_combined.Sort((a, b) => a.order - b.order); _combineds.Sort((a, b) => a.order - b.order);
foreach (var item in _combined) foreach (var item in _combineds)
{ {
EcsMask submask = item.mask; EcsMask submask = item.mask;
combinedInc.ExceptWith(submask.exc);//удаляю конфликтующие ограничения combinedInc.ExceptWith(submask.exc);//удаляю конфликтующие ограничения
@ -526,15 +567,28 @@ namespace DCFApixels.DragonECS
combinedInc = _inc; combinedInc = _inc;
combinedExc = _exc; combinedExc = _exc;
} }
if (_excepteds.Count > 0)
{
foreach (var item in _excepteds)
{
if(combinedInc.Overlaps(item.mask.exc) || combinedExc.Overlaps(item.mask.inc))
{
_combineds.Clear();
_excepteds.Clear();
return _world.Get<WorldMaskComponent>().BrokenMask;
}
combinedInc.ExceptWith(item.mask.inc);
combinedExc.ExceptWith(item.mask.exc);
}
}
var inc = combinedInc.ToArray(); var inc = combinedInc.ToArray();
Array.Sort(inc); Array.Sort(inc);
_inc.Clear();
var exc = combinedExc.ToArray(); var exc = combinedExc.ToArray();
Array.Sort(exc); Array.Sort(exc);
_exc.Clear();
_combined.Clear(); _combineds.Clear();
_excepteds.Clear();
return _world.Get<WorldMaskComponent>().GetMask(new Key(inc, exc)); return _world.Get<WorldMaskComponent>().GetMask(new Key(inc, exc));
} }
@ -551,6 +605,16 @@ namespace DCFApixels.DragonECS
this.order = order; this.order = order;
} }
} }
private readonly struct Excepted
{
public readonly EcsMask mask;
public readonly int order;
public Excepted(EcsMask mask, int order)
{
this.mask = mask;
this.order = order;
}
}
#endregion #endregion
} }