move EcsAspectIterator to EcsAspect.Iterator

This commit is contained in:
Mikhail 2024-02-11 01:14:54 +08:00
parent 88bc3355b7
commit 316735cf9a

View File

@ -1,5 +1,4 @@
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.Utils;
using System;
using System.Collections.Generic;
using System.Reflection;
@ -13,10 +12,10 @@ namespace DCFApixels.DragonECS
internal EcsMask _mask;
private bool _isInit;
internal UnsafeArray<int> _sortIncBuffer;
internal UnsafeArray<int> _sortExcBuffer;
internal UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
internal UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private UnsafeArray<int> _sortIncBuffer;
private UnsafeArray<int> _sortExcBuffer;
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
#region Properties
public EcsMask Mask => _mask;
@ -150,13 +149,13 @@ namespace DCFApixels.DragonECS
#endregion
#region Iterator
public EcsAspectIterator GetIterator()
public Iterator GetIterator()
{
return new EcsAspectIterator(this, _source.Entities);
return new Iterator(this, _source.Entities);
}
public EcsAspectIterator GetIteratorFor(EcsSpan span)
public Iterator GetIteratorFor(EcsSpan span)
{
return new EcsAspectIterator(this, span);
return new Iterator(this, span);
}
#endregion
@ -172,6 +171,224 @@ namespace DCFApixels.DragonECS
}
}
#endregion
#region Iterator
public ref struct Iterator
{
public readonly int worldID;
public readonly EcsAspect aspect;
private EcsSpan _span;
public Iterator(EcsAspect aspect, EcsSpan span)
{
worldID = aspect.World.id;
_span = span;
this.aspect = aspect;
}
public void CopyTo(EcsGroup group)
{
group.Clear();
var enumerator = GetEnumerator();
while (enumerator.MoveNext())
group.AddInternal(enumerator.Current);
}
public int CopyTo(ref int[] array)
{
var enumerator = GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
if (array.Length <= count)
Array.Resize(ref array, array.Length << 1);
array[count++] = enumerator.Current;
}
return count;
}
public EcsSpan CopyToSpan(ref int[] array)
{
var enumerator = GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
if (array.Length <= count)
Array.Resize(ref array, array.Length << 1);
array[count++] = enumerator.Current;
}
return new EcsSpan(worldID, array, count);
}
#region object
public override string ToString()
{
List<int> ints = new List<int>();
foreach (var e in this)
{
ints.Add(e);
}
return CollectionUtility.EntitiesToString(ints, "it");
}
#endregion
#region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() => new Enumerator(_span, aspect);
public unsafe ref struct Enumerator
{
#region CountComparers
private readonly struct IncCountComparer : IComparerX<int>
{
public readonly int[] counts;
public IncCountComparer(int[] counts)
{
this.counts = counts;
}
public int Compare(int a, int b)
{
return counts[a] - counts[b];
}
}
private readonly struct ExcCountComparer : IComparerX<int>
{
public readonly int[] counts;
public ExcCountComparer(int[] counts)
{
this.counts = counts;
}
public int Compare(int a, int b)
{
return counts[b] - counts[a];
}
}
#endregion
private ReadOnlySpan<int>.Enumerator _span;
private readonly int[][] _entitiesComponentMasks;
private static EcsMaskChunck* _preSortedIncBuffer;
private static EcsMaskChunck* _preSortedExcBuffer;
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
//private EcsAspect aspect;
public unsafe Enumerator(EcsSpan span, EcsAspect aspect)
{
//this.aspect = aspect;
_span = span.GetEnumerator();
_entitiesComponentMasks = aspect.World._entitiesComponentMasks;
_sortIncChunckBuffer = aspect._sortIncChunckBuffer;
_sortExcChunckBuffer = aspect._sortExcChunckBuffer;
#region Sort
UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer;
UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer;
int[] counts = aspect.World._poolComponentCounts;
if (_preSortedIncBuffer == null)
{
_preSortedIncBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
_preSortedExcBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
}
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 bas = _preSortedIncBuffer[i];
int chankIndexX = bas.chankIndex;
int maskX = bas.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
}
}
}
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
}
}
}
#endregion
}
public int Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _span.Current;
}
//public entlong CurrentLong
//{
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// get => aspect.World.GetEntityLong(_span.Current);
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
while (_span.MoveNext())
{
int e = _span.Current;
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
{
var bit = _sortIncChunckBuffer.ptr[i];
if ((_entitiesComponentMasks[e][bit.chankIndex] & bit.mask) != bit.mask)
goto skip;
}
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
{
var bit = _sortExcChunckBuffer.ptr[i];
if ((_entitiesComponentMasks[e][bit.chankIndex] & bit.mask) > 0)
goto skip;
}
return true;
skip: continue;
}
return false;
}
}
#endregion
}
#endregion
}
#region BuilderBase
@ -182,222 +399,4 @@ namespace DCFApixels.DragonECS
public abstract TPool Optional<TPool>() where TPool : IEcsPoolImplementation, new();
}
#endregion
#region Iterator
public ref struct EcsAspectIterator
{
public readonly int worldID;
public readonly EcsAspect aspect;
private EcsSpan _span;
public EcsAspectIterator(EcsAspect aspect, EcsSpan span)
{
worldID = aspect.World.id;
_span = span;
this.aspect = aspect;
}
public void CopyTo(EcsGroup group)
{
group.Clear();
var enumerator = GetEnumerator();
while (enumerator.MoveNext())
group.AddInternal(enumerator.Current);
}
public int CopyTo(ref int[] array)
{
var enumerator = GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
if (array.Length <= count)
Array.Resize(ref array, array.Length << 1);
array[count++] = enumerator.Current;
}
return count;
}
public EcsSpan CopyToSpan(ref int[] array)
{
var enumerator = GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
if (array.Length <= count)
Array.Resize(ref array, array.Length << 1);
array[count++] = enumerator.Current;
}
return new EcsSpan(worldID, array, count);
}
#region object
public override string ToString()
{
List<int> ints = new List<int>();
foreach (var e in this)
{
ints.Add(e);
}
return CollectionUtility.EntitiesToString(ints, "it");
}
#endregion
#region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() => new Enumerator(_span, aspect);
public unsafe ref struct Enumerator
{
#region CountComparers
private readonly struct IncCountComparer : IComparerX<int>
{
public readonly int[] counts;
public IncCountComparer(int[] counts)
{
this.counts = counts;
}
public int Compare(int a, int b)
{
return counts[a] - counts[b];
}
}
private readonly struct ExcCountComparer : IComparerX<int>
{
public readonly int[] counts;
public ExcCountComparer(int[] counts)
{
this.counts = counts;
}
public int Compare(int a, int b)
{
return counts[b] - counts[a];
}
}
#endregion
private ReadOnlySpan<int>.Enumerator _span;
private readonly int[][] _entitiesComponentMasks;
private static EcsMaskChunck* _preSortedIncBuffer;
private static EcsMaskChunck* _preSortedExcBuffer;
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
//private EcsAspect aspect;
public unsafe Enumerator(EcsSpan span, EcsAspect aspect)
{
//this.aspect = aspect;
_span = span.GetEnumerator();
_entitiesComponentMasks = aspect.World._entitiesComponentMasks;
_sortIncChunckBuffer = aspect._sortIncChunckBuffer;
_sortExcChunckBuffer = aspect._sortExcChunckBuffer;
#region Sort
UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer;
UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer;
int[] counts = aspect.World._poolComponentCounts;
if (_preSortedIncBuffer == null)
{
_preSortedIncBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
_preSortedExcBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256);
}
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 bas = _preSortedIncBuffer[i];
int chankIndexX = bas.chankIndex;
int maskX = bas.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
}
}
}
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
}
}
}
#endregion
}
public int Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _span.Current;
}
//public entlong CurrentLong
//{
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// get => aspect.World.GetEntityLong(_span.Current);
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
while (_span.MoveNext())
{
int e = _span.Current;
for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
{
var bit = _sortIncChunckBuffer.ptr[i];
if ((_entitiesComponentMasks[e][bit.chankIndex] & bit.mask) != bit.mask)
goto skip;
}
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
{
var bit = _sortExcChunckBuffer.ptr[i];
if ((_entitiesComponentMasks[e][bit.chankIndex] & bit.mask) > 0)
goto skip;
}
return true;
skip: continue;
}
return false;
}
}
#endregion
}
#endregion
}