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

View File

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

View File

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

View File

@ -556,6 +556,24 @@ namespace DCFApixels.DragonECS
return false; 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; return true;
} }
bool deepDebug = IsMatchesMaskDeepDebug(mask, entityID); bool deepDebug = IsMatchesMaskDeepDebug(mask, entityID);
@ -563,6 +581,7 @@ namespace DCFApixels.DragonECS
var incChuncks = mask._incChunckMasks; var incChuncks = mask._incChunckMasks;
var excChuncks = mask._excChunckMasks; var excChuncks = mask._excChunckMasks;
var anyChuncks = mask._anyChunckMasks;
var componentMaskStartIndex = entityID << _entityComponentMaskLengthBitShift; var componentMaskStartIndex = entityID << _entityComponentMaskLengthBitShift;
for (int i = 0; i < incChuncks.Length; i++) for (int i = 0; i < incChuncks.Length; i++)
@ -587,6 +606,27 @@ namespace DCFApixels.DragonECS
return false; 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 DEBUG && DRAGONECS_DEEP_DEBUG
if (true != deepDebug) { Throw.DeepDebugException(); } if (true != deepDebug) { Throw.DeepDebugException(); }

View File

@ -392,6 +392,7 @@ namespace DCFApixels.DragonECS
#region Convertors #region Convertors
public static implicit operator EcsPool<T>(IncludeMarker a) { return a.GetInstance<EcsPool<T>>(); } 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>(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>(OptionalMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator EcsPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsPool<T>>(); } public static implicit operator EcsPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsPool<T>>(); }
#endregion #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>(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>(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>(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>(OptionalMarker a) { return a.GetInstance<EcsPool<T>>(); }
public static implicit operator ReadonlyEcsPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsPool<T>>(); } public static implicit operator ReadonlyEcsPool<T>(EcsWorld.GetPoolInstanceMarker a) { return a.GetInstance<EcsPool<T>>(); }
#endregion #endregion
@ -511,6 +513,11 @@ namespace DCFApixels.DragonECS
{ {
return self.OptionalPool<EcsPool<TComponent>>(); 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 #region Obsolete
[Obsolete("Use " + nameof(EcsAspect) + "." + nameof(EcsAspect.Builder) + "." + nameof(Inc) + "<T>()")] [Obsolete("Use " + nameof(EcsAspect) + "." + nameof(EcsAspect.Builder) + "." + nameof(Inc) + "<T>()")]

View File

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