mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
update mask iterator
This commit is contained in:
parent
7544d18d1e
commit
57b0ba225a
@ -260,7 +260,8 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public EcsSpan CopyToSpan(ref int[] array)
|
||||
{
|
||||
return iterator.CopyToSpan(ref array);
|
||||
int count = CopyTo(ref array);
|
||||
return new EcsSpan(worldID, array, count);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
473
src/EcsMask.cs
473
src/EcsMask.cs
@ -11,6 +11,7 @@ using Unity.IL2CPP.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
using static EcsMaskIteratorUtility;
|
||||
public interface IEcsComponentMask
|
||||
{
|
||||
EcsMask ToMask(EcsWorld world);
|
||||
@ -283,7 +284,7 @@ namespace DCFApixels.DragonECS
|
||||
do
|
||||
{
|
||||
EcsMaskChunck bitJ = EcsMaskChunck.FromID(sortedArray[i]);
|
||||
if (bitJ.chankIndex != chankIndexX)
|
||||
if (bitJ.chunkIndex != chankIndexX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -554,7 +555,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#endregion
|
||||
|
||||
#region AbstractMask
|
||||
#region StaticMask
|
||||
public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask)
|
||||
{
|
||||
return world.Get<WorldMaskComponent>().ConvertFromAbstract(abstractMask);
|
||||
@ -849,11 +850,11 @@ namespace DCFApixels.DragonECS
|
||||
internal const int DIV_SHIFT = 5;
|
||||
internal const int MOD_MASK = BITS - 1;
|
||||
|
||||
public readonly int chankIndex;
|
||||
public readonly int chunkIndex;
|
||||
public readonly int mask;
|
||||
public EcsMaskChunck(int chankIndex, int mask)
|
||||
{
|
||||
this.chankIndex = chankIndex;
|
||||
this.chunkIndex = chankIndex;
|
||||
this.mask = mask;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -863,7 +864,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return $"mask({chankIndex}, {mask}, {BitsUtility.CountBits(mask)})";
|
||||
return $"mask({chunkIndex}, {mask}, {BitsUtility.CountBits(mask)})";
|
||||
}
|
||||
internal class DebuggerProxy
|
||||
{
|
||||
@ -873,7 +874,7 @@ namespace DCFApixels.DragonECS
|
||||
public string bits;
|
||||
public DebuggerProxy(EcsMaskChunck maskbits)
|
||||
{
|
||||
chunk = maskbits.chankIndex;
|
||||
chunk = maskbits.chunkIndex;
|
||||
mask = (uint)maskbits.mask;
|
||||
BitsUtility.GetBitNumbersNoAlloc(mask, ref values);
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
@ -893,103 +894,75 @@ namespace DCFApixels.DragonECS
|
||||
#endif
|
||||
public class EcsMaskIterator
|
||||
{
|
||||
#region CountStructComparers
|
||||
private readonly struct IncCountComparer : IStructComparer<int>
|
||||
{
|
||||
public readonly EcsWorld.PoolSlot[] counts;
|
||||
public IncCountComparer(EcsWorld.PoolSlot[] counts)
|
||||
{
|
||||
this.counts = counts;
|
||||
}
|
||||
public int Compare(int a, int b)
|
||||
{
|
||||
return counts[a].count - counts[b].count;
|
||||
}
|
||||
}
|
||||
private readonly struct ExcCountComparer : IStructComparer<int>
|
||||
{
|
||||
public readonly EcsWorld.PoolSlot[] counts;
|
||||
public ExcCountComparer(EcsWorld.PoolSlot[] counts)
|
||||
{
|
||||
this.counts = counts;
|
||||
}
|
||||
public int Compare(int a, int b)
|
||||
{
|
||||
return counts[b].count - counts[a].count;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
public readonly EcsWorld World;
|
||||
public readonly EcsMask Mask;
|
||||
|
||||
internal EcsWorld _source;
|
||||
internal EcsMask _mask;
|
||||
private readonly UnsafeArray<int> _sortIncBuffer;
|
||||
private readonly UnsafeArray<int> _sortExcBuffer;
|
||||
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
|
||||
private UnsafeArray<int> _sortIncBuffer;
|
||||
private UnsafeArray<int> _sortExcBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
private readonly bool _isOnlyInc;
|
||||
|
||||
#region Constructors
|
||||
#region Constructors/Finalizator
|
||||
public unsafe EcsMaskIterator(EcsWorld source, EcsMask mask)
|
||||
{
|
||||
_source = source;
|
||||
_mask = mask;
|
||||
|
||||
_sortIncBuffer = new UnsafeArray<int>(_mask._inc.Length);
|
||||
_sortExcBuffer = new UnsafeArray<int>(_mask._exc.Length);
|
||||
_sortIncChunckBuffer = new UnsafeArray<EcsMaskChunck>(_mask._incChunckMasks.Length);
|
||||
_sortExcChunckBuffer = new UnsafeArray<EcsMaskChunck>(_mask._excChunckMasks.Length);
|
||||
|
||||
for (int i = 0; i < _sortIncBuffer.Length; i++)
|
||||
{
|
||||
_sortIncBuffer.ptr[i] = _mask._inc[i];
|
||||
World = source;
|
||||
Mask = mask;
|
||||
_sortIncBuffer = UnsafeArray<int>.FromArray(mask._inc);
|
||||
_sortExcBuffer = UnsafeArray<int>.FromArray(mask._exc);
|
||||
_sortIncChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._incChunckMasks);
|
||||
_sortExcChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._excChunckMasks);
|
||||
_isOnlyInc = _sortExcBuffer.Length <= 0;
|
||||
}
|
||||
for (int i = 0; i < _sortExcBuffer.Length; i++)
|
||||
{
|
||||
_sortExcBuffer.ptr[i] = _mask._exc[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
|
||||
{
|
||||
_sortIncChunckBuffer.ptr[i] = _mask._incChunckMasks[i];
|
||||
}
|
||||
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
|
||||
{
|
||||
_sortExcChunckBuffer.ptr[i] = _mask._excChunckMasks[i];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Finalizator
|
||||
unsafe ~EcsMaskIterator()
|
||||
{
|
||||
_sortIncBuffer.Dispose();
|
||||
_sortExcBuffer.Dispose();
|
||||
_sortIncChunckBuffer.Dispose();
|
||||
_sortExcChunckBuffer.Dispose();
|
||||
_sortIncBuffer.ReadonlyDispose();
|
||||
_sortExcBuffer.ReadonlyDispose();
|
||||
_sortIncChunckBuffer.ReadonlyDispose();
|
||||
_sortExcChunckBuffer.ReadonlyDispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public EcsWorld World
|
||||
|
||||
#region IterateTo
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void IterateTo(EcsSpan source, EcsGroup group)
|
||||
{
|
||||
get { return _source; }
|
||||
if (_isOnlyInc)
|
||||
{
|
||||
IterateOnlyInc(source).CopyTo(group);
|
||||
}
|
||||
public EcsMask Mask
|
||||
else
|
||||
{
|
||||
get { return _mask; }
|
||||
Iterate(source).CopyTo(group);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IterateTo(EcsSpan source, ref int[] array)
|
||||
{
|
||||
if (_isOnlyInc)
|
||||
{
|
||||
return IterateOnlyInc(source).CopyTo(ref array);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Iterate(source).CopyTo(ref array);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Enumerable
|
||||
public Enumerable Iterate(EcsSpan span)
|
||||
{
|
||||
return new Enumerable(this, span);
|
||||
}
|
||||
#region Iterate/Enumerable
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Enumerable Iterate(EcsSpan span) { return new Enumerable(this, span); }
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
public readonly ref struct Enumerable
|
||||
{
|
||||
private readonly EcsMaskIterator _iterator;
|
||||
private readonly EcsSpan _span;
|
||||
|
||||
public Enumerable(EcsMaskIterator iterator, EcsSpan span)
|
||||
{
|
||||
_iterator = iterator;
|
||||
@ -997,6 +970,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
#region CopyTo
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void CopyTo(EcsGroup group)
|
||||
{
|
||||
group.Clear();
|
||||
@ -1006,6 +980,7 @@ namespace DCFApixels.DragonECS
|
||||
group.AddUnchecked(enumerator.Current);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CopyTo(ref int[] array)
|
||||
{
|
||||
int count = 0;
|
||||
@ -1020,50 +995,41 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public EcsSpan CopyToSpan(ref int[] array)
|
||||
{
|
||||
int count = CopyTo(ref array);
|
||||
return new EcsSpan(_iterator.World.id, array, count);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
public override string ToString()
|
||||
public List<int> ToList()
|
||||
{
|
||||
List<int> ints = new List<int>();
|
||||
foreach (var e in this)
|
||||
{
|
||||
ints.Add(e);
|
||||
}
|
||||
return CollectionUtility.EntitiesToString(ints, "it");
|
||||
foreach (var e in this) { ints.Add(e); }
|
||||
return ints;
|
||||
}
|
||||
public override string ToString() { return CollectionUtility.EntitiesToString(ToList(), "it"); }
|
||||
#endregion
|
||||
|
||||
#region Enumerator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); }
|
||||
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
public unsafe ref struct Enumerator
|
||||
{
|
||||
private ReadOnlySpan<int>.Enumerator _span;
|
||||
|
||||
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
|
||||
private readonly int[] _entityComponentMasks;
|
||||
|
||||
[ThreadStatic]
|
||||
private static EcsMaskChunck* _preSortedIncBuffer;
|
||||
[ThreadStatic]
|
||||
private static EcsMaskChunck* _preSortedExcBuffer;
|
||||
|
||||
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
|
||||
private readonly int _entityComponentMaskLengthBitShift;
|
||||
|
||||
public unsafe Enumerator(EcsSpan span, EcsMaskIterator iterator)
|
||||
{
|
||||
_entityComponentMasks = iterator.World._entityComponentMasks;
|
||||
_sortIncChunckBuffer = iterator._sortIncChunckBuffer;
|
||||
_sortExcChunckBuffer = iterator._sortExcChunckBuffer;
|
||||
|
||||
_entityComponentMasks = iterator.World._entityComponentMasks;
|
||||
_entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift;
|
||||
|
||||
if (iterator.Mask.IsBroken)
|
||||
@ -1076,74 +1042,36 @@ namespace DCFApixels.DragonECS
|
||||
UnsafeArray<int> _sortIncBuffer = iterator._sortIncBuffer;
|
||||
UnsafeArray<int> _sortExcBuffer = iterator._sortExcBuffer;
|
||||
EcsWorld.PoolSlot[] counts = iterator.World._poolSlots;
|
||||
int max = _sortIncBuffer.Length > _sortExcBuffer.Length ? _sortIncBuffer.Length : _sortExcBuffer.Length;
|
||||
|
||||
if (_preSortedIncBuffer == null)
|
||||
EcsMaskChunck* preSortingBuffer;
|
||||
if (max > STACK_BUFFER_THRESHOLD)
|
||||
{
|
||||
_preSortedIncBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
|
||||
_preSortedExcBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
|
||||
preSortingBuffer = TempBuffer<EcsMaskChunck>.Get(max);
|
||||
}
|
||||
else
|
||||
{
|
||||
EcsMaskChunck* ptr = stackalloc EcsMaskChunck[max];
|
||||
preSortingBuffer = ptr;
|
||||
}
|
||||
|
||||
if (_sortIncChunckBuffer.Length > 1)
|
||||
{
|
||||
IncCountComparer incComparer = new IncCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref incComparer);
|
||||
for (int i = 0; i < _sortIncBuffer.Length; i++)
|
||||
{
|
||||
_preSortedIncBuffer[i] = EcsMaskChunck.FromID(_sortIncBuffer.ptr[i]);
|
||||
}
|
||||
for (int i = 0, ii = 0; ii < _sortIncChunckBuffer.Length; ii++)
|
||||
{
|
||||
EcsMaskChunck chunkX = _preSortedIncBuffer[i];
|
||||
int chankIndexX = chunkX.chankIndex;
|
||||
int maskX = chunkX.mask;
|
||||
|
||||
for (int j = i + 1; j < _sortIncBuffer.Length; j++)
|
||||
{
|
||||
if (_preSortedIncBuffer[j].chankIndex == chankIndexX)
|
||||
{
|
||||
maskX |= _preSortedIncBuffer[j].mask;
|
||||
}
|
||||
}
|
||||
_sortIncChunckBuffer.ptr[ii] = new EcsMaskChunck(chankIndexX, maskX);
|
||||
while (++i < _sortIncBuffer.Length && _preSortedIncBuffer[i].chankIndex == chankIndexX)
|
||||
{
|
||||
// skip
|
||||
}
|
||||
}
|
||||
var comparer = new IncCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref comparer);
|
||||
ConvertToChuncks(preSortingBuffer, _sortIncBuffer, _sortIncChunckBuffer);
|
||||
}
|
||||
if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]].count <= 0)
|
||||
{
|
||||
_span = span.Slice(0, 0).GetEnumerator();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_sortExcChunckBuffer.Length > 1)
|
||||
{
|
||||
ExcCountComparer excComparer = new ExcCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref excComparer);
|
||||
for (int i = 0; i < _sortExcBuffer.Length; i++)
|
||||
{
|
||||
_preSortedExcBuffer[i] = EcsMaskChunck.FromID(_sortExcBuffer.ptr[i]);
|
||||
}
|
||||
|
||||
for (int i = 0, ii = 0; ii < _sortExcChunckBuffer.Length; ii++)
|
||||
{
|
||||
EcsMaskChunck bas = _preSortedExcBuffer[i];
|
||||
int chankIndexX = bas.chankIndex;
|
||||
int maskX = bas.mask;
|
||||
|
||||
for (int j = i + 1; j < _sortExcBuffer.Length; j++)
|
||||
{
|
||||
if (_preSortedExcBuffer[j].chankIndex == chankIndexX)
|
||||
{
|
||||
maskX |= _preSortedExcBuffer[j].mask;
|
||||
}
|
||||
}
|
||||
_sortExcChunckBuffer.ptr[ii] = new EcsMaskChunck(chankIndexX, maskX);
|
||||
while (++i < _sortExcBuffer.Length && _preSortedExcBuffer[i].chankIndex == chankIndexX)
|
||||
{
|
||||
// skip
|
||||
}
|
||||
}
|
||||
ExcCountComparer comparer = new ExcCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref comparer);
|
||||
ConvertToChuncks(preSortingBuffer, _sortExcBuffer, _sortExcChunckBuffer);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -1163,7 +1091,7 @@ namespace DCFApixels.DragonECS
|
||||
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
|
||||
{
|
||||
var bit = _sortIncChunckBuffer.ptr[i];
|
||||
if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != bit.mask)
|
||||
if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != bit.mask)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
@ -1171,7 +1099,152 @@ namespace DCFApixels.DragonECS
|
||||
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
|
||||
{
|
||||
var bit = _sortExcChunckBuffer.ptr[i];
|
||||
if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != 0)
|
||||
if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != 0)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
skip: continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Iterate/Enumerable OnlyInc
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public OnlyIncEnumerable IterateOnlyInc(EcsSpan span) { return new OnlyIncEnumerable(this, span); }
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
public readonly ref struct OnlyIncEnumerable
|
||||
{
|
||||
private readonly EcsMaskIterator _iterator;
|
||||
private readonly EcsSpan _span;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public OnlyIncEnumerable(EcsMaskIterator iterator, EcsSpan span)
|
||||
{
|
||||
_iterator = iterator;
|
||||
_span = span;
|
||||
}
|
||||
|
||||
#region CopyTo
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void CopyTo(EcsGroup group)
|
||||
{
|
||||
group.Clear();
|
||||
var enumerator = GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
group.AddUnchecked(enumerator.Current);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CopyTo(ref int[] array)
|
||||
{
|
||||
int count = 0;
|
||||
var enumerator = GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
if (array.Length <= count)
|
||||
{
|
||||
Array.Resize(ref array, array.Length << 1);
|
||||
}
|
||||
array[count++] = enumerator.Current;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
public List<int> ToList()
|
||||
{
|
||||
List<int> ints = new List<int>();
|
||||
foreach (var e in this) { ints.Add(e); }
|
||||
return ints;
|
||||
}
|
||||
public override string ToString() { return CollectionUtility.EntitiesToString(ToList(), "inc_it"); }
|
||||
#endregion
|
||||
|
||||
#region Enumerator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); }
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
public unsafe ref struct Enumerator
|
||||
{
|
||||
private ReadOnlySpan<int>.Enumerator _span;
|
||||
|
||||
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
|
||||
private readonly int[] _entityComponentMasks;
|
||||
private readonly int _entityComponentMaskLengthBitShift;
|
||||
|
||||
public unsafe Enumerator(EcsSpan span, EcsMaskIterator iterator)
|
||||
{
|
||||
_sortIncChunckBuffer = iterator._sortIncChunckBuffer;
|
||||
|
||||
_entityComponentMasks = iterator.World._entityComponentMasks;
|
||||
_entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift;
|
||||
|
||||
if (iterator.Mask.IsBroken)
|
||||
{
|
||||
_span = span.Slice(0, 0).GetEnumerator();
|
||||
return;
|
||||
}
|
||||
|
||||
#region Sort
|
||||
UnsafeArray<int> _sortIncBuffer = iterator._sortIncBuffer;
|
||||
EcsWorld.PoolSlot[] counts = iterator.World._poolSlots;
|
||||
int max = _sortIncBuffer.Length;
|
||||
|
||||
EcsMaskChunck* preSortingBuffer;
|
||||
if (max > STACK_BUFFER_THRESHOLD)
|
||||
{
|
||||
preSortingBuffer = TempBuffer<EcsMaskChunck>.Get(max);
|
||||
}
|
||||
else
|
||||
{
|
||||
EcsMaskChunck* ptr = stackalloc EcsMaskChunck[max];
|
||||
preSortingBuffer = ptr;
|
||||
}
|
||||
|
||||
if (_sortIncChunckBuffer.Length > 1)
|
||||
{
|
||||
var comparer = new IncCountComparer(counts);
|
||||
UnsafeArraySortHalperX<int>.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref comparer);
|
||||
ConvertToChuncks(preSortingBuffer, _sortIncBuffer, _sortIncChunckBuffer);
|
||||
}
|
||||
if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]].count <= 0)
|
||||
{
|
||||
_span = span.Slice(0, 0).GetEnumerator();
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
|
||||
_span = span.GetEnumerator();
|
||||
}
|
||||
public int Current
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _span.Current; }
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool MoveNext()
|
||||
{
|
||||
while (_span.MoveNext())
|
||||
{
|
||||
int chunck = _span.Current << _entityComponentMaskLengthBitShift;
|
||||
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
|
||||
{
|
||||
var bit = _sortIncChunckBuffer.ptr[i];
|
||||
if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != bit.mask)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
@ -1188,3 +1261,83 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
#region EcsMaskIteratorUtility
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
internal unsafe class EcsMaskIteratorUtility
|
||||
{
|
||||
internal const int STACK_BUFFER_THRESHOLD = 256;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void ConvertToChuncks(EcsMaskChunck* ptr, UnsafeArray<int> input, UnsafeArray<EcsMaskChunck> output)
|
||||
{
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
ptr[i] = EcsMaskChunck.FromID(input.ptr[i]);
|
||||
}
|
||||
|
||||
for (int inputI = 0, outputI = 0; outputI < output.Length; inputI++, ptr++)
|
||||
{
|
||||
int maskX = ptr->mask;
|
||||
if (maskX == 0) { continue; }
|
||||
int chunkIndexX = ptr->chunkIndex;
|
||||
|
||||
EcsMaskChunck* subptr = ptr;
|
||||
for (int j = 1; j < input.Length - inputI; j++, subptr++)
|
||||
{
|
||||
if (subptr->chunkIndex == chunkIndexX)
|
||||
{
|
||||
maskX |= subptr->mask;
|
||||
*subptr = default;
|
||||
}
|
||||
}
|
||||
output.ptr[outputI] = new EcsMaskChunck(chunkIndexX, maskX);
|
||||
outputI++;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
internal readonly struct IncCountComparer : IStructComparer<int>
|
||||
{
|
||||
public readonly EcsWorld.PoolSlot[] counts;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public IncCountComparer(EcsWorld.PoolSlot[] counts)
|
||||
{
|
||||
this.counts = counts;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Compare(int a, int b)
|
||||
{
|
||||
return counts[a].count - counts[b].count;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
internal readonly struct ExcCountComparer : IStructComparer<int>
|
||||
{
|
||||
public readonly EcsWorld.PoolSlot[] counts;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ExcCountComparer(EcsWorld.PoolSlot[] counts)
|
||||
{
|
||||
this.counts = counts;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Compare(int a, int b)
|
||||
{
|
||||
return counts[b].count - counts[a].count;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
@ -238,7 +238,7 @@ namespace DCFApixels.DragonECS
|
||||
slot.count++;
|
||||
slot.version++;
|
||||
_entities[entityID].componentsCount++;
|
||||
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] |= maskBit.mask;
|
||||
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] |= maskBit.mask;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||
@ -248,7 +248,7 @@ namespace DCFApixels.DragonECS
|
||||
slot.count--;
|
||||
slot.version++;
|
||||
var count = --_entities[entityID].componentsCount;
|
||||
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] &= ~maskBit.mask;
|
||||
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] &= ~maskBit.mask;
|
||||
|
||||
if (count == 0 && IsUsed(entityID))
|
||||
{
|
||||
@ -263,7 +263,7 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool TryRegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||
{
|
||||
ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex];
|
||||
ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex];
|
||||
int newChunk = chunk | maskBit.mask;
|
||||
if (chunk != newChunk)
|
||||
{
|
||||
@ -280,7 +280,7 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool TryUnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||
{
|
||||
ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex];
|
||||
ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex];
|
||||
int newChunk = chunk & ~maskBit.mask;
|
||||
if (chunk != newChunk)
|
||||
{
|
||||
@ -316,7 +316,7 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool HasEntityComponent(int entityID, EcsMaskChunck maskBit)
|
||||
{
|
||||
return (_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] & maskBit.mask) == maskBit.mask;
|
||||
return (_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] & maskBit.mask) == maskBit.mask;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false)
|
||||
{
|
||||
_version++;
|
||||
_filteredAllEntitiesCount = _iterator.Iterate(World.Entities).CopyTo(ref _filteredAllEntities);
|
||||
_filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities);
|
||||
}
|
||||
_lastWorldVersion = World.Version;
|
||||
}
|
||||
@ -63,7 +63,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
_filteredEntities = new int[32];
|
||||
}
|
||||
_filteredEntitiesCount = _iterator.Iterate(span).CopyTo(ref _filteredEntities);
|
||||
_filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
@ -49,7 +49,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false)
|
||||
{
|
||||
_version++;
|
||||
_iterator.Iterate(World.Entities).CopyTo(_filteredAllGroup);
|
||||
_iterator.IterateTo(World.Entities, _filteredAllGroup);
|
||||
}
|
||||
_lastWorldVersion = World.Version;
|
||||
}
|
||||
@ -64,7 +64,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
_filteredGroup = EcsGroup.New(World);
|
||||
}
|
||||
_iterator.Iterate(span).CopyTo(_filteredGroup);
|
||||
_iterator.IterateTo(span, _filteredGroup);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
@ -4,11 +4,45 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
#if ENABLE_IL2CPP
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
#endif
|
||||
|
||||
namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
#if ENABLE_IL2CPP
|
||||
using Unity.IL2CPP.CompilerServices;
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
public static unsafe class TempBuffer<T> where T : unmanaged
|
||||
{
|
||||
[ThreadStatic] private static T* _ptr;
|
||||
[ThreadStatic] private static int _size;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T* Get(int size)
|
||||
{
|
||||
if (_size < size)
|
||||
{
|
||||
if (_ptr != null)
|
||||
{
|
||||
UnmanagedArrayUtility.Free(_ptr);
|
||||
}
|
||||
_ptr = UnmanagedArrayUtility.New<T>(size);
|
||||
_size = size;
|
||||
}
|
||||
return _ptr;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Clear()
|
||||
{
|
||||
for (int i = 0; i < _size; i++)
|
||||
{
|
||||
_ptr[i] = default;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ENABLE_IL2CPP
|
||||
[Il2CppSetOption (Option.NullChecks, false)]
|
||||
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
|
||||
#endif
|
||||
@ -19,6 +53,16 @@ namespace DCFApixels.DragonECS.Internal
|
||||
internal T* ptr;
|
||||
internal int Length;
|
||||
|
||||
public static UnsafeArray<T> FromArray(T[] array)
|
||||
{
|
||||
UnsafeArray<T> result = new UnsafeArray<T>(array.Length);
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
result.ptr[i] = array[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public UnsafeArray(int length)
|
||||
{
|
||||
@ -49,6 +93,11 @@ namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
UnmanagedArrayUtility.Free(ref ptr, ref Length);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ReadonlyDispose()
|
||||
{
|
||||
UnmanagedArrayUtility.Free(ptr);
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
T* ptr = this.ptr;
|
||||
|
Loading…
Reference in New Issue
Block a user