mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-17 09:24:37 +08:00
add Any condition for mask
This commit is contained in:
parent
818dafc82a
commit
813b986e45
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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(); }
|
||||
|
@ -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>()")]
|
||||
|
@ -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>>();
|
||||
|
Loading…
Reference in New Issue
Block a user