mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-17 17:34:36 +08:00
move EcsAspectIterator to EcsAspect.Iterator
This commit is contained in:
parent
88bc3355b7
commit
316735cf9a
453
src/EcsAspect.cs
453
src/EcsAspect.cs
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user