add Any condition for mask

This commit is contained in:
DCFApixels 2025-05-19 20:30:18 +08:00
parent 818dafc82a
commit 813b986e45
6 changed files with 241 additions and 53 deletions

View File

@ -79,6 +79,10 @@ namespace DCFApixels.DragonECS
{
get { return EcsAspect.CurrentBuilder.Exc; }
}
public static AnyMarker Any
{
get { return EcsAspect.CurrentBuilder.Any; }
}
public static OptionalMarker Opt
{
get { return EcsAspect.CurrentBuilder.Opt; }
@ -114,6 +118,10 @@ namespace DCFApixels.DragonECS
{
get { return B.Exc; }
}
protected static AnyMarker Any
{
get { return B.Any; }
}
protected static OptionalMarker Opt
{
get { return B.Opt; }
@ -181,6 +189,10 @@ namespace DCFApixels.DragonECS
{
get { return new ExcludeMarker(this); }
}
public AnyMarker Any
{
get { return new AnyMarker(this); }
}
public OptionalMarker Opt
{
get { return new OptionalMarker(this); }
@ -281,6 +293,12 @@ namespace DCFApixels.DragonECS
SetMaskExclude(pool.ComponentType);
return pool;
}
public TPool AnyPool<TPool>() where TPool : IEcsPoolImplementation, new()
{
var pool = CachePool<TPool>();
SetMaskAny(pool.ComponentType);
return pool;
}
public TPool OptionalPool<TPool>() where TPool : IEcsPoolImplementation, new()
{
return CachePool<TPool>();
@ -305,6 +323,13 @@ namespace DCFApixels.DragonECS
_maskBuilder.Exc(type);
}
}
public void SetMaskAny(Type type)
{
if (_maskBuilder.IsNull == false)
{
_maskBuilder.Any(type);
}
}
public TOtherAspect Combine<TOtherAspect>(int order = 0) where TOtherAspect : EcsAspect, new()
{
var result = _world.GetAspect<TOtherAspect>();
@ -495,6 +520,18 @@ namespace DCFApixels.DragonECS.Core
return _builder.ExcludePool<T>();
}
}
public readonly ref struct AnyMarker
{
private readonly EcsAspect.Builder _builder;
public AnyMarker(EcsAspect.Builder builder)
{
_builder = builder;
}
public T GetInstance<T>() where T : IEcsPoolImplementation, new()
{
return _builder.AnyPool<T>();
}
}
public readonly ref struct OptionalMarker
{
private readonly EcsAspect.Builder _builder;

View File

@ -38,10 +38,13 @@ namespace DCFApixels.DragonECS
internal readonly EcsStaticMask _staticMask;
internal readonly EcsMaskChunck[] _incChunckMasks;
internal readonly EcsMaskChunck[] _excChunckMasks;
internal readonly EcsMaskChunck[] _anyChunckMasks;
/// <summary> Sorted </summary>
internal readonly int[] _incs;
/// <summary> Sorted </summary>
internal readonly int[] _excs;
/// <summary> Sorted </summary>
internal readonly int[] _anys;
private EcsMaskIterator _iterator;
@ -78,22 +81,24 @@ namespace DCFApixels.DragonECS
public static Builder New(EcsWorld world) { return new Builder(world); }
internal static EcsMask CreateEmpty(int id, short worldID)
{
return new EcsMask(EcsStaticMask.Empty, id, worldID, new int[0], new int[0]);
return new EcsMask(EcsStaticMask.Empty, id, worldID, new int[0], new int[0], new int[0]);
}
internal static EcsMask CreateBroken(int id, short worldID)
{
return new EcsMask(EcsStaticMask.Broken, id, worldID, new int[1] { 1 }, new int[1] { 1 });
return new EcsMask(EcsStaticMask.Broken, id, worldID, new int[1] { 1 }, new int[1] { 1 }, new int[0]);
}
private EcsMask(EcsStaticMask staticMask, int id, short worldID, int[] inc, int[] exc)
private EcsMask(EcsStaticMask staticMask, int id, short worldID, int[] incs, int[] excs, int[] anys)
{
_staticMask = staticMask;
ID = id;
_incs = inc;
_excs = exc;
_incs = incs;
_excs = excs;
_anys = anys;
WorldID = worldID;
_incChunckMasks = MakeMaskChuncsArray(inc);
_excChunckMasks = MakeMaskChuncsArray(exc);
_incChunckMasks = MakeMaskChuncsArray(incs);
_excChunckMasks = MakeMaskChuncsArray(excs);
_anyChunckMasks = MakeMaskChuncsArray(anys);
}
private unsafe EcsMaskChunck[] MakeMaskChuncsArray(int[] sortedArray)
@ -145,7 +150,7 @@ namespace DCFApixels.DragonECS
#region Object
public override string ToString()
{
return CreateLogString(WorldID, _incs, _excs);
return CreateLogString(WorldID, _incs, _excs, _anys);
}
public bool Equals(EcsMask mask)
{
@ -324,8 +329,9 @@ namespace DCFApixels.DragonECS
{
int[] incs = ConvertTypeCodeToComponentTypeID(staticMask.IncTypeCodes, _world);
int[] excs = ConvertTypeCodeToComponentTypeID(staticMask.ExcTypeCodes, _world);
int[] anys = ConvertTypeCodeToComponentTypeID(staticMask.AnyTypeCodes, _world);
result = new EcsMask(staticMask, _staticMasks.Count, _world.ID, incs, excs);
result = new EcsMask(staticMask, _staticMasks.Count, _world.ID, incs, excs, anys);
_staticMasks.Add(staticMask.ID, result);
}
@ -347,10 +353,13 @@ namespace DCFApixels.DragonECS
public Builder Inc<T>() { _builder.Inc<T>(); return this; }
public Builder Exc<T>() { _builder.Exc<T>(); return this; }
public Builder Any<T>() { _builder.Any<T>(); return this; }
public Builder Inc(Type type) { _builder.Inc(type); return this; }
public Builder Exc(Type type) { _builder.Exc(type); return this; }
public Builder Any(Type type) { _builder.Any(type); return this; }
public Builder Inc(EcsTypeCode typeCode) { _builder.Inc(typeCode); return this; }
public Builder Exc(EcsTypeCode typeCode) { _builder.Exc(typeCode); return this; }
public Builder Any(EcsTypeCode typeCode) { _builder.Any(typeCode); return this; }
public Builder Combine(EcsMask mask) { _builder.Combine(mask._staticMask); return this; }
public Builder Except(EcsMask mask) { _builder.Except(mask._staticMask); return this; }
@ -359,11 +368,12 @@ namespace DCFApixels.DragonECS
#endregion
#region Debug utils
private static string CreateLogString(short worldID, int[] inc, int[] exc)
//TODO доработать дебаг с учетом Any
private static string CreateLogString(short worldID, int[] incs, int[] excs, int[] anys)
{
#if DEBUG
string converter(int o) { return EcsDebugUtility.GetGenericTypeName(EcsWorld.GetWorld(worldID).AllPools[o].ComponentType, 1); }
return $"Inc({string.Join(", ", inc.Select(converter))}) Exc({string.Join(", ", exc.Select(converter))})";
return $"Inc({string.Join(", ", incs.Select(converter))}) Exc({string.Join(", ", excs.Select(converter))}) Any({string.Join(", ", anys.Select(converter))})";
#else
return $"Inc({string.Join(", ", inc)}) Exc({string.Join(", ", exc)})"; // Release optimization
#endif
@ -378,10 +388,13 @@ namespace DCFApixels.DragonECS
private readonly short _worldID;
public readonly EcsMaskChunck[] includedChunkMasks;
public readonly EcsMaskChunck[] excludedChunkMasks;
public readonly EcsMaskChunck[] anyChunkMasks;
public readonly int[] included;
public readonly int[] excluded;
public readonly int[] any;
public readonly Type[] includedTypes;
public readonly Type[] excludedTypes;
public readonly Type[] anyTypes;
public bool IsEmpty { get { return _source.IsEmpty; } }
public bool IsBroken { get { return _source.IsBroken; } }
@ -395,15 +408,18 @@ namespace DCFApixels.DragonECS
_worldID = mask.WorldID;
includedChunkMasks = mask._incChunckMasks;
excludedChunkMasks = mask._excChunckMasks;
anyChunkMasks = mask._anyChunckMasks;
included = mask._incs;
excluded = mask._excs;
any = mask._anys;
Type converter(int o) { return world.GetComponentType(o); }
includedTypes = included.Select(converter).ToArray();
excludedTypes = excluded.Select(converter).ToArray();
anyTypes = any.Select(converter).ToArray();
}
public override string ToString()
{
return CreateLogString(_worldID, included, excluded);
return CreateLogString(_worldID, included, excluded, any);
}
}
#endregion
@ -498,12 +514,12 @@ namespace DCFApixels.DragonECS
public readonly EcsMask Mask;
private readonly UnsafeArray<int> _sortIncBuffer;
/// <summary> slised _sortIncBuffer </summary>
private readonly UnsafeArray<int> _sortExcBuffer;
private readonly UnsafeArray<int> _sortAnyBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
/// <summary> slised _sortIncChunckBuffer </summary>
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortAnyChunckBuffer;
private MemoryAllocator.Handler _bufferHandler;
private MemoryAllocator.Handler _chunckBufferHandler;
@ -525,8 +541,8 @@ namespace DCFApixels.DragonECS
World = source;
Mask = mask;
int bufferLength = mask._incs.Length + mask._excs.Length;
int chunckBufferLength = mask._incChunckMasks.Length + mask._excChunckMasks.Length;
int bufferLength = mask._incs.Length + mask._excs.Length + mask._anys.Length;
int chunckBufferLength = mask._incChunckMasks.Length + mask._excChunckMasks.Length + mask._anyChunckMasks.Length;
_bufferHandler = MemoryAllocator.AllocAndInit<int>(bufferLength);
_chunckBufferHandler = MemoryAllocator.AllocAndInit<EcsMaskChunck>(chunckBufferLength);
var sortBuffer = UnsafeArray<int>.Manual(_bufferHandler.As<int>(), bufferLength);
@ -536,6 +552,8 @@ namespace DCFApixels.DragonECS
_sortIncBuffer.CopyFromArray_Unchecked(mask._incs);
_sortExcBuffer = sortBuffer.Slice(mask._incs.Length, mask._excs.Length);
_sortExcBuffer.CopyFromArray_Unchecked(mask._excs);
_sortAnyBuffer = sortBuffer.Slice(mask._incs.Length + mask._excs.Length, mask._anys.Length);
_sortAnyBuffer.CopyFromArray_Unchecked(mask._anys);
//EcsDebug.PrintError(_sortIncBuffer.ToArray());
//EcsDebug.PrintError(new Span<int>(_bufferHandler.GetPtrAs<int>(), _sortIncBuffer.Length).ToArray());
@ -544,6 +562,8 @@ namespace DCFApixels.DragonECS
_sortIncChunckBuffer.CopyFromArray_Unchecked(mask._incChunckMasks);
_sortExcChunckBuffer = sortChunckBuffer.Slice(mask._incChunckMasks.Length, mask._excChunckMasks.Length);
_sortExcChunckBuffer.CopyFromArray_Unchecked(mask._excChunckMasks);
_sortAnyChunckBuffer = sortChunckBuffer.Slice(mask._incChunckMasks.Length + mask._excChunckMasks.Length, mask._anyChunckMasks.Length);
_sortAnyChunckBuffer.CopyFromArray_Unchecked(mask._anyChunckMasks);
_isHasAnyEntityStorage = false;
var pools = source.AllPools;
@ -555,13 +575,13 @@ namespace DCFApixels.DragonECS
}
_isSingleIncPoolWithEntityStorage = Mask.Excs.Length <= 0 && Mask.Incs.Length == 1;
if (_sortExcBuffer.Length <= 0)
if (_sortIncBuffer.Length > 0 && _sortExcBuffer.Length == 0 && _sortAnyBuffer.Length == 0)
{
_maskType = mask.IsEmpty ? MaskType.Empty : MaskType.OnlyInc;
_maskType = MaskType.OnlyInc;
}
else
{
_maskType = MaskType.IncExc;
_maskType = mask.IsEmpty ? MaskType.Empty : MaskType.IncExc;
}
}
unsafe ~EcsMaskIterator()
@ -577,8 +597,6 @@ namespace DCFApixels.DragonECS
{
_bufferHandler.Dispose();
_chunckBufferHandler.Dispose();
//_sortIncBuffer.ReadonlyDispose(); // использует общую памяять с _sortExcBuffer;
//_sortIncChunckBuffer.ReadonlyDispose(); // использует общую памяять с _sortExcChunckBuffer;
}
#endregion
@ -587,9 +605,10 @@ namespace DCFApixels.DragonECS
{
UnsafeArray<int> sortIncBuffer = _sortIncBuffer;
UnsafeArray<int> sortExcBuffer = _sortExcBuffer;
UnsafeArray<int> sortAnyBuffer = _sortAnyBuffer;
EcsWorld.PoolSlot[] counts = World._poolSlots;
int maxBufferSize = sortIncBuffer.Length > sortExcBuffer.Length ? sortIncBuffer.Length : sortExcBuffer.Length;
int maxBufferSize = Math.Max(Math.Max(sortIncBuffer.Length, sortExcBuffer.Length), sortAnyBuffer.Length);
int maxEntites = int.MaxValue;
EcsMaskChunck* preSortingBuffer;
@ -625,9 +644,18 @@ namespace DCFApixels.DragonECS
UnsafeArraySortHalperX<int>.InsertionSort(sortExcBuffer.ptr, sortExcBuffer.Length, ref comparer);
ConvertToChuncks(preSortingBuffer, sortExcBuffer, _sortExcChunckBuffer);
}
// Выражение мало IncCount < (AllEntitesCount - ExcCount) вероятно будет истинным.
// Выражение IncCount < (AllEntitesCount - ExcCount) мало вероятно будет истинным.
// ExcCount = максимальное количество ентитей с исключеющим ограничением и IncCount = минимальоне количество ентитей с включающим ограничением
// Поэтому исключающее ограничение игнорируется для maxEntites.
if (_sortAnyChunckBuffer.Length > 1)
{
//TODO проверить для Any
ExcCountComparer comparer = new ExcCountComparer(counts);
UnsafeArraySortHalperX<int>.InsertionSort(sortAnyBuffer.ptr, sortAnyBuffer.Length, ref comparer);
ConvertToChuncks(preSortingBuffer, sortAnyBuffer, _sortAnyChunckBuffer);
}
return maxEntites;
}
private unsafe bool TryGetEntityStorage(out IEntityStorage storage)
@ -776,6 +804,7 @@ namespace DCFApixels.DragonECS
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortAnyChunckBuffer;
private readonly int[] _entityComponentMasks;
private readonly int _entityComponentMaskLengthBitShift;
@ -784,6 +813,7 @@ namespace DCFApixels.DragonECS
{
_sortIncChunckBuffer = iterator._sortIncChunckBuffer;
_sortExcChunckBuffer = iterator._sortExcChunckBuffer;
_sortAnyChunckBuffer = iterator._sortAnyChunckBuffer;
_entityComponentMasks = iterator.World._entityComponentMasks;
_entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift;
@ -817,6 +847,25 @@ namespace DCFApixels.DragonECS
goto skip;
}
}
//можно подумать над оптимизацией через кеширование bool значения, if с bool работает быстрее прочего
if(_sortAnyChunckBuffer.Length > 0)
{
int anyCount = 0;
for (int i = 0; i < _sortAnyChunckBuffer.Length; i++)
{
var bit = _sortAnyChunckBuffer.ptr[i];
if ((_entityComponentMasks[entityLineStartIndex + bit.chunkIndex] & bit.mask) == bit.mask)
{
anyCount++;
}
}
if (anyCount == 0)
{
goto skip;
}
}
return true;
skip: continue;
}

View File

@ -38,8 +38,8 @@ namespace DCFApixels.DragonECS
_ids[key] = result;
return result;
}
Empty = createMask(0, new Key(new EcsTypeCode[0], new EcsTypeCode[0]));
Broken = createMask(_idDIspenser.UseFree(), new Key(new EcsTypeCode[1] { (EcsTypeCode)1 }, new EcsTypeCode[1] { (EcsTypeCode)1 }));
Empty = createMask(0, new Key(new EcsTypeCode[0], new EcsTypeCode[0], new EcsTypeCode[0]));
Broken = createMask(_idDIspenser.UseFree(), new Key(new EcsTypeCode[1] { (EcsTypeCode)1 }, new EcsTypeCode[1] { (EcsTypeCode)1 }, new EcsTypeCode[0]));
}
public readonly int ID;
@ -47,6 +47,8 @@ namespace DCFApixels.DragonECS
private readonly EcsTypeCode[] _incs;
/// <summary> Sorted </summary>
private readonly EcsTypeCode[] _excs;
/// <summary> Sorted </summary>
private readonly EcsTypeCode[] _anys;
#region Properties
/// <summary> Sorted set including constraints presented as global type codes. </summary>
@ -61,6 +63,12 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _excs; }
}
/// <summary> Sorted set excluding constraints presented as global type codes. </summary>
public ReadOnlySpan<EcsTypeCode> AnyTypeCodes
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _anys; }
}
public bool IsEmpty
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -78,14 +86,18 @@ namespace DCFApixels.DragonECS
ID = id;
_incs = key.Incs;
_excs = key.Excs;
_anys = key.Anys;
}
public static Builder New() { return Builder.New(); }
public static Builder Inc<T>() { return Builder.New().Inc<T>(); }
public static Builder Exc<T>() { return Builder.New().Exc<T>(); }
public static Builder Any<T>() { return Builder.New().Any<T>(); }
public static Builder Inc(Type type) { return Builder.New().Inc(type); }
public static Builder Exc(Type type) { return Builder.New().Exc(type); }
public static Builder Any(Type type) { return Builder.New().Any(type); }
public static Builder Inc(EcsTypeCode typeCode) { return Builder.New().Inc(typeCode); }
public static Builder Exc(EcsTypeCode typeCode) { return Builder.New().Exc(typeCode); }
public static Builder Any(EcsTypeCode typeCode) { return Builder.New().Any(typeCode); }
private static EcsStaticMask CreateMask(Key key)
{
if (_ids.TryGetValue(key, out EcsStaticMask result) == false)
@ -95,7 +107,7 @@ namespace DCFApixels.DragonECS
if (_ids.TryGetValue(key, out result) == false)
{
#if DEBUG
CheckConstraints(key.Incs, key.Excs);
CheckConstraints(key.Incs, key.Excs); //TODO сделать прроверку для key.Anys
#endif
result = new EcsStaticMask(_idDIspenser.UseFree(), key);
_ids[key] = result;
@ -200,23 +212,29 @@ namespace DCFApixels.DragonECS
{
public readonly EcsTypeCode[] Incs;
public readonly EcsTypeCode[] Excs;
public readonly EcsTypeCode[] Anys;
public readonly int Hash;
#region Constructors
public Key(EcsTypeCode[] inc, EcsTypeCode[] exc)
public Key(EcsTypeCode[] incs, EcsTypeCode[] excs, EcsTypeCode[] anys)
{
this.Incs = inc;
this.Excs = exc;
this.Incs = incs;
this.Excs = excs;
this.Anys = anys;
unchecked
{
Hash = inc.Length + exc.Length;
for (int i = 0, iMax = inc.Length; i < iMax; i++)
Hash = incs.Length + excs.Length;
for (int i = 0, iMax = incs.Length; i < iMax; i++)
{
Hash = Hash * EcsConsts.MAGIC_PRIME + (int)inc[i];
Hash = Hash * EcsConsts.MAGIC_PRIME + (int)incs[i];
}
for (int i = 0, iMax = exc.Length; i < iMax; i++)
for (int i = 0, iMax = excs.Length; i < iMax; i++)
{
Hash = Hash * EcsConsts.MAGIC_PRIME - (int)exc[i];
Hash = Hash * EcsConsts.MAGIC_PRIME - (int)excs[i];
}
for (int i = 0, iMax = anys.Length; i < iMax; i++)
{
Hash = Hash * EcsConsts.MAGIC_PRIME + (int)anys[i];
}
}
}
@ -228,6 +246,7 @@ namespace DCFApixels.DragonECS
{
if (Incs.Length != other.Incs.Length) { return false; }
if (Excs.Length != other.Excs.Length) { return false; }
if (Anys.Length != other.Anys.Length) { return false; }
for (int i = 0; i < Incs.Length; i++)
{
if (Incs[i] != other.Incs[i]) { return false; }
@ -236,6 +255,10 @@ namespace DCFApixels.DragonECS
{
if (Excs[i] != other.Excs[i]) { return false; }
}
for (int i = 0; i < Anys.Length; i++)
{
if (Anys[i] != other.Anys[i]) { return false; }
}
return true;
}
public override bool Equals(object obj) { return Equals((Key)obj); }
@ -277,8 +300,10 @@ namespace DCFApixels.DragonECS
#region Inc/Exc/Combine/Except
public Builder Inc<T>() { return Inc(EcsTypeCodeManager.Get<T>()); }
public Builder Exc<T>() { return Exc(EcsTypeCodeManager.Get<T>()); }
public Builder Any<T>() { return Any(EcsTypeCodeManager.Get<T>()); }
public Builder Inc(Type type) { return Inc(EcsTypeCodeManager.Get(type)); }
public Builder Exc(Type type) { return Exc(EcsTypeCodeManager.Get(type)); }
public Builder Any(Type type) { return Any(EcsTypeCodeManager.Get(type)); }
public Builder Inc(EcsTypeCode typeCode)
{
if (_version != _builder._version) { Throw.CantReuseBuilder(); }
@ -291,6 +316,12 @@ namespace DCFApixels.DragonECS
_builder.Exc(typeCode);
return this;
}
public Builder Any(EcsTypeCode typeCode)
{
if (_version != _builder._version) { Throw.CantReuseBuilder(); }
_builder.Any(typeCode);
return this;
}
public Builder Combine(EcsStaticMask mask)
{
if (_version != _builder._version) { Throw.CantReuseBuilder(); }
@ -327,8 +358,9 @@ namespace DCFApixels.DragonECS
}
private class BuilderInstance
{
private readonly HashSet<EcsTypeCode> _inc = new HashSet<EcsTypeCode>();
private readonly HashSet<EcsTypeCode> _exc = new HashSet<EcsTypeCode>();
private readonly HashSet<EcsTypeCode> _incsSet = new HashSet<EcsTypeCode>();
private readonly HashSet<EcsTypeCode> _excsSet = new HashSet<EcsTypeCode>();
private readonly HashSet<EcsTypeCode> _anysSet = new HashSet<EcsTypeCode>();
private readonly List<Combined> _combineds = new List<Combined>();
private bool _sortedCombinedChecker = true;
private readonly List<Excepted> _excepteds = new List<Excepted>();
@ -343,20 +375,29 @@ namespace DCFApixels.DragonECS
public void Inc(EcsTypeCode typeCode)
{
#if DEBUG
if (_inc.Contains(typeCode) || _exc.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(typeCode); }
if (_incsSet.Contains(typeCode) || _excsSet.Contains(typeCode) || _anysSet.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(typeCode); }
#elif DRAGONECS_STABILITY_MODE
if (_inc.Contains(typeCode) || _exc.Contains(typeCode)) { return; }
if (_incsSet.Contains(typeCode) || _excsSet.Contains(typeCode) || _anysSet.Contains(typeCode)) { return; }
#endif
_inc.Add(typeCode);
_incsSet.Add(typeCode);
}
public void Exc(EcsTypeCode typeCode)
{
#if DEBUG
if (_inc.Contains(typeCode) || _exc.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(typeCode); }
if (_incsSet.Contains(typeCode) || _excsSet.Contains(typeCode) || _anysSet.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(typeCode); }
#elif DRAGONECS_STABILITY_MODE
if (_inc.Contains(typeCode) || _exc.Contains(typeCode)) { return; }
if (_incsSet.Contains(typeCode) || _excsSet.Contains(typeCode) || _anysSet.Contains(typeCode)) { return; }
#endif
_exc.Add(typeCode);
_excsSet.Add(typeCode);
}
public void Any(EcsTypeCode typeCode)
{
#if DEBUG
if (_incsSet.Contains(typeCode) || _excsSet.Contains(typeCode) || _anysSet.Contains(typeCode)) { Throw.ConstraintIsAlreadyContainedInMask(typeCode); }
#elif DRAGONECS_STABILITY_MODE
if (_incsSet.Contains(typeCode) || _excsSet.Contains(typeCode) || _anysSet.Contains(typeCode)) { return; }
#endif
_anysSet.Add(typeCode);
}
public void Combine(EcsStaticMask mask, int order = 0)
{
@ -376,13 +417,15 @@ namespace DCFApixels.DragonECS
#region Build
public EcsStaticMask Build()
{
HashSet<EcsTypeCode> combinedIncs = _inc;
HashSet<EcsTypeCode> combinedExcs = _exc;
HashSet<EcsTypeCode> combinedIncs = _incsSet;
HashSet<EcsTypeCode> combinedExcs = _excsSet;
HashSet<EcsTypeCode> combinedAnys = _anysSet;
if (_combineds.Count > 0)
{
combinedIncs = new HashSet<EcsTypeCode>();
combinedExcs = new HashSet<EcsTypeCode>();
//combinedAnys = new HashSet<EcsTypeCode>(); //TODO разработать комбинацию для any
if (_sortedCombinedChecker == false)
{
_combineds.Sort((a, b) => a.order - b.order);
@ -395,20 +438,22 @@ namespace DCFApixels.DragonECS
combinedIncs.UnionWith(submask._incs);
combinedExcs.UnionWith(submask._excs);
}
combinedIncs.ExceptWith(_exc);//удаляю конфликтующие ограничения
combinedExcs.ExceptWith(_inc);//удаляю конфликтующие ограничения
combinedIncs.UnionWith(_inc);
combinedExcs.UnionWith(_exc);
combinedIncs.ExceptWith(_excsSet);//удаляю конфликтующие ограничения
combinedExcs.ExceptWith(_incsSet);//удаляю конфликтующие ограничения
combinedIncs.UnionWith(_incsSet);
combinedExcs.UnionWith(_excsSet);
_combineds.Clear();
}
else
{
combinedIncs = _inc;
combinedExcs = _exc;
combinedIncs = _incsSet;
combinedExcs = _excsSet;
combinedAnys = _anysSet;
}
if (_excepteds.Count > 0)
{
//TODO разработать вычитание для any
foreach (var item in _excepteds)
{
//if (combinedIncs.Overlaps(item.mask._exc) || combinedExcs.Overlaps(item.mask._inc))
@ -426,12 +471,15 @@ namespace DCFApixels.DragonECS
Array.Sort(inc);
var exc = combinedExcs.ToArray();
Array.Sort(exc);
var any = combinedAnys.ToArray();
Array.Sort(any);
var key = new Key(inc, exc);
var key = new Key(inc, exc, any);
EcsStaticMask result = CreateMask(key);
_inc.Clear();
_exc.Clear();
_incsSet.Clear();
_excsSet.Clear();
_anysSet.Clear();
_version++;
return result;

View File

@ -556,6 +556,24 @@ namespace DCFApixels.DragonECS
return false;
}
}
//TODO оптимизировать
if (mask_._anys.Length != 0)
{
int count = 0;
for (int i = 0, iMax = mask_._anys.Length; i < iMax; i++)
{
if (_pools[mask_._anys[i]].Has(entityID_))
{
count++;
}
}
if(count == 0)
{
return false;
}
}
return true;
}
bool deepDebug = IsMatchesMaskDeepDebug(mask, entityID);
@ -563,6 +581,7 @@ namespace DCFApixels.DragonECS
var incChuncks = mask._incChunckMasks;
var excChuncks = mask._excChunckMasks;
var anyChuncks = mask._anyChunckMasks;
var componentMaskStartIndex = entityID << _entityComponentMaskLengthBitShift;
for (int i = 0; i < incChuncks.Length; i++)
@ -587,6 +606,27 @@ namespace DCFApixels.DragonECS
return false;
}
}
//TODO оптимизировать
if (anyChuncks.Length > 0)
{
int count = 0;
for (int i = 0; i < anyChuncks.Length; i++)
{
var bit = anyChuncks[i];
if ((_entityComponentMasks[componentMaskStartIndex + bit.chunkIndex] & bit.mask) == bit.mask)
{
count++;
}
}
if (count == 0)
{
#if DEBUG && DRAGONECS_DEEP_DEBUG
if (false != deepDebug) { Throw.DeepDebugException(); }
#endif
return false;
}
}
#if DEBUG && DRAGONECS_DEEP_DEBUG
if (true != deepDebug) { Throw.DeepDebugException(); }

View File

@ -392,6 +392,7 @@ namespace DCFApixels.DragonECS
#region Convertors
public static implicit operator EcsPool<T>(IncludeMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator EcsPool<T>(ExcludeMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator EcsPool<T>(AnyMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator EcsPool<T>(OptionalMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator EcsPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsPool<T>>(); }
#endregion
@ -477,6 +478,7 @@ namespace DCFApixels.DragonECS
public static implicit operator ReadonlyEcsPool<T>(EcsPool<T> a) { return new ReadonlyEcsPool<T>(a); }
public static implicit operator ReadonlyEcsPool<T>(IncludeMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator ReadonlyEcsPool<T>(ExcludeMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator ReadonlyEcsPool<T>(AnyMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator ReadonlyEcsPool<T>(OptionalMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator ReadonlyEcsPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsPool<T>>(); }
#endregion
@ -511,6 +513,11 @@ namespace DCFApixels.DragonECS
{
return self.OptionalPool<EcsPool<TComponent>>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsPool<TComponent> Any<TComponent>(this EcsAspect.Builder self) where TComponent : struct, IEcsComponent
{
return self.AnyPool<EcsPool<TComponent>>();
}
#region Obsolete
[Obsolete("Use " + nameof(EcsAspect) + "." + nameof(EcsAspect.Builder) + "." + nameof(Inc) + "<T>()")]

View File

@ -314,6 +314,7 @@ namespace DCFApixels.DragonECS
#region Convertors
public static implicit operator EcsTagPool<T>(IncludeMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator EcsTagPool<T>(ExcludeMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator EcsTagPool<T>(AnyMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator EcsTagPool<T>(OptionalMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator EcsTagPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
#endregion
@ -401,6 +402,7 @@ namespace DCFApixels.DragonECS
public static implicit operator ReadonlyEcsTagPool<T>(EcsTagPool<T> a) { return new ReadonlyEcsTagPool<T>(a); }
public static implicit operator ReadonlyEcsTagPool<T>(IncludeMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator ReadonlyEcsTagPool<T>(ExcludeMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator ReadonlyEcsTagPool<T>(AnyMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator ReadonlyEcsTagPool<T>(OptionalMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
public static implicit operator ReadonlyEcsTagPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsTagPool<T>>(); }
#endregion
@ -430,6 +432,11 @@ namespace DCFApixels.DragonECS
return self.ExcludePool<EcsTagPool<TTagComponent>>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsTagPool<TTagComponent> Any<TTagComponent>(this EcsAspect.Builder self) where TTagComponent : struct, IEcsTagComponent
{
return self.AnyPool<EcsTagPool<TTagComponent>>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsTagPool<TTagComponent> Opt<TTagComponent>(this EcsAspect.Builder self) where TTagComponent : struct, IEcsTagComponent
{
return self.OptionalPool<EcsTagPool<TTagComponent>>();