mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
update queries stash
This commit is contained in:
parent
3a22a914d5
commit
9c033e6330
@ -242,6 +242,9 @@ namespace DCFApixels.DragonECS
|
||||
#region Add/Remove
|
||||
public void AddUnchecked(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (Has(entityID)) { Throw.Group_AlreadyContains(entityID); }
|
||||
#endif
|
||||
Add_Internal(entityID);
|
||||
}
|
||||
public bool Add(int entityID)
|
||||
@ -254,11 +257,8 @@ namespace DCFApixels.DragonECS
|
||||
return true;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void Add_Internal(int entityID)
|
||||
private void Add_Internal(int entityID)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (Has(entityID)) { Throw.Group_AlreadyContains(entityID); }
|
||||
#endif
|
||||
if (++_count >= _dense.Length)
|
||||
{
|
||||
Array.Resize(ref _dense, _dense.Length << 1);
|
||||
@ -340,9 +340,9 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
foreach (var item in group)
|
||||
foreach (var entityID in group)
|
||||
{
|
||||
Add_Internal(item);
|
||||
Add_Internal(entityID);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -786,11 +786,11 @@ namespace DCFApixels.DragonECS
|
||||
public static EcsGroup Inverse(EcsGroup a)
|
||||
{
|
||||
EcsGroup result = a._source.GetFreeGroup();
|
||||
foreach (var item in a._source.Entities)
|
||||
foreach (var entityID in a._source.Entities)
|
||||
{
|
||||
if (a.Has(item) == false)
|
||||
if (a.Has(entityID) == false)
|
||||
{
|
||||
result.Add_Internal(item);
|
||||
result.Add_Internal(entityID);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
238
src/EcsAspect.cs
238
src/EcsAspect.cs
@ -8,10 +8,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
public abstract class EcsAspect : ITemplateNode
|
||||
{
|
||||
internal EcsWorld _source;
|
||||
internal EcsMask _mask;
|
||||
private bool _isBuilt = false;
|
||||
|
||||
#region Initialization Halpers
|
||||
[ThreadStatic]
|
||||
private static Stack<Builder> _constructorBuildersStack = null;
|
||||
private static Stack<Builder> GetBuildersStack()
|
||||
@ -70,11 +67,11 @@ namespace DCFApixels.DragonECS
|
||||
return buildersStack.Peek().Opt;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private UnsafeArray<int> _sortIncBuffer;
|
||||
private UnsafeArray<int> _sortExcBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
internal EcsWorld _source;
|
||||
internal EcsMask _mask;
|
||||
private bool _isBuilt = false;
|
||||
|
||||
#region Properties
|
||||
public EcsMask Mask
|
||||
@ -274,219 +271,6 @@ namespace DCFApixels.DragonECS
|
||||
_span = span;
|
||||
this.aspect = aspect;
|
||||
}
|
||||
|
||||
#region CopyTo
|
||||
public void CopyTo(EcsGroup group)
|
||||
{
|
||||
group.Clear();
|
||||
var enumerator = GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
group.Add_Internal(enumerator.Current);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
public EcsSpan CopyToSpan(ref int[] array)
|
||||
{
|
||||
int count = CopyTo(ref array);
|
||||
return new EcsSpan(worldID, array, count);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
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() { return 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[] _entityComponentMasks;
|
||||
|
||||
private static EcsMaskChunck* _preSortedIncBuffer;
|
||||
private static EcsMaskChunck* _preSortedExcBuffer;
|
||||
|
||||
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
|
||||
private readonly int _entityComponentMaskLengthBitShift;
|
||||
|
||||
public unsafe Enumerator(EcsSpan span, EcsAspect aspect)
|
||||
{
|
||||
_entityComponentMasks = aspect.World._entityComponentMasks;
|
||||
_sortIncChunckBuffer = aspect._sortIncChunckBuffer;
|
||||
_sortExcChunckBuffer = aspect._sortExcChunckBuffer;
|
||||
|
||||
_entityComponentMaskLengthBitShift = aspect.World._entityComponentMaskLengthBitShift;
|
||||
|
||||
if (aspect.Mask.IsBroken)
|
||||
{
|
||||
_span = span.Slice(0, 0).GetEnumerator();
|
||||
return;
|
||||
}
|
||||
|
||||
#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 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
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]] <= 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
|
||||
}
|
||||
}
|
||||
}
|
||||
#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.chankIndex] & bit.mask) != bit.mask)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
|
||||
{
|
||||
var bit = _sortExcChunckBuffer.ptr[i];
|
||||
if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != 0)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
skip: continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -522,6 +306,8 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Constraint Markers
|
||||
public readonly ref struct IncludeMarker
|
||||
{
|
||||
private readonly EcsAspect.Builder _builder;
|
||||
@ -529,8 +315,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_builder = builder;
|
||||
}
|
||||
public T GetInstance<T>()
|
||||
where T : IEcsPoolImplementation, new()
|
||||
public T GetInstance<T>() where T : IEcsPoolImplementation, new()
|
||||
{
|
||||
return _builder.IncludePool<T>();
|
||||
}
|
||||
@ -542,8 +327,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_builder = builder;
|
||||
}
|
||||
public T GetInstance<T>()
|
||||
where T : IEcsPoolImplementation, new()
|
||||
public T GetInstance<T>() where T : IEcsPoolImplementation, new()
|
||||
{
|
||||
return _builder.ExcludePool<T>();
|
||||
}
|
||||
@ -555,10 +339,10 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_builder = builder;
|
||||
}
|
||||
public T GetInstance<T>()
|
||||
where T : IEcsPoolImplementation, new()
|
||||
public T GetInstance<T>() where T : IEcsPoolImplementation, new()
|
||||
{
|
||||
return _builder.OptionalPool<T>();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
318
src/EcsMask.cs
318
src/EcsMask.cs
@ -22,6 +22,8 @@ namespace DCFApixels.DragonECS
|
||||
internal readonly int[] _inc; //Sorted
|
||||
internal readonly int[] _exc; //Sorted
|
||||
|
||||
private EcsMaskIterator _iterator;
|
||||
|
||||
#region Properties
|
||||
public int ID
|
||||
{
|
||||
@ -217,6 +219,17 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other
|
||||
public EcsMaskIterator GetIterator()
|
||||
{
|
||||
if(_iterator == null)
|
||||
{
|
||||
_iterator = new EcsMaskIterator(EcsWorld.GetWorld(_worldID), this);
|
||||
}
|
||||
return _iterator;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Debug utils
|
||||
#if DEBUG
|
||||
private static HashSet<int> _dummyHashSet = new HashSet<int>();
|
||||
@ -381,50 +394,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//internal EcsMask ExceptMask(EcsMask a, EcsMask b)
|
||||
//{
|
||||
// int operation = OpMaskKey.EXCEPT_OP;
|
||||
// if (_opMasks.TryGetValue(new OpMaskKey(a.id, b.id, operation), out EcsMask result) == false)
|
||||
// {
|
||||
// var builder = New(a.World);
|
||||
// if (a.IsConflictWith(b))
|
||||
// {
|
||||
// return a.World.Get<WorldMaskComponent>().BrokenMask;
|
||||
// }
|
||||
// ExceptMaskConstraint(builder, a.inc, b.inc, true);
|
||||
// ExceptMaskConstraint(builder, a.exc, b.exc, false);
|
||||
// result = builder.Build();
|
||||
// _opMasks.Add(new OpMaskKey(a.id, b.id, operation), result);
|
||||
// }
|
||||
// return result;
|
||||
//}
|
||||
//private void ExceptMaskConstraint(Builder b, int[] acnstrs, int[] bcnstrs, bool isInc)
|
||||
//{
|
||||
// for (int i = 0, ii = 0; i < acnstrs.Length; i++)
|
||||
// {
|
||||
// int acnst = acnstrs[i];
|
||||
// while (ii < bcnstrs.Length && acnst > bcnstrs[ii])
|
||||
// {
|
||||
// ii++;
|
||||
// }
|
||||
// if (ii >= bcnstrs.Length)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// int binc = bcnstrs[ii];
|
||||
// if (acnst == binc)
|
||||
// {
|
||||
// if (isInc)
|
||||
// {
|
||||
// b.Include(acnst);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// b.Exclude(acnst);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
internal EcsMask GetMask(Key maskKey)
|
||||
{
|
||||
if (!_masks.TryGetValue(maskKey, out EcsMask result))
|
||||
@ -681,4 +650,265 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
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
|
||||
|
||||
internal EcsWorld _source;
|
||||
internal EcsMask _mask;
|
||||
|
||||
private UnsafeArray<int> _sortIncBuffer;
|
||||
private UnsafeArray<int> _sortExcBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
|
||||
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
|
||||
|
||||
#region Constructors
|
||||
public EcsMaskIterator(EcsWorld source, EcsMask mask)
|
||||
{
|
||||
_source = source;
|
||||
_mask = mask;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public EcsWorld World
|
||||
{
|
||||
get { return _source; }
|
||||
}
|
||||
public EcsMask Mask
|
||||
{
|
||||
get { return _mask; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Enumerable
|
||||
public Enumerable Iterate(EcsSpan span)
|
||||
{
|
||||
return new Enumerable();
|
||||
}
|
||||
public readonly ref struct Enumerable
|
||||
{
|
||||
private readonly EcsMaskIterator _iterator;
|
||||
private readonly EcsSpan _span;
|
||||
|
||||
public Enumerable(EcsMaskIterator iterator, EcsSpan span)
|
||||
{
|
||||
_iterator = iterator;
|
||||
_span = span;
|
||||
}
|
||||
|
||||
#region CopyTo
|
||||
public void CopyTo(EcsGroup group)
|
||||
{
|
||||
group.Clear();
|
||||
var enumerator = GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
group.AddUnchecked(enumerator.Current);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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()
|
||||
{
|
||||
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() { return new Enumerator(_span, _iterator); }
|
||||
|
||||
public unsafe ref struct Enumerator
|
||||
{
|
||||
private ReadOnlySpan<int>.Enumerator _span;
|
||||
private readonly int[] _entityComponentMasks;
|
||||
|
||||
private static EcsMaskChunck* _preSortedIncBuffer;
|
||||
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;
|
||||
|
||||
_entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift;
|
||||
|
||||
if (iterator.Mask.IsBroken)
|
||||
{
|
||||
_span = span.Slice(0, 0).GetEnumerator();
|
||||
return;
|
||||
}
|
||||
|
||||
#region Sort
|
||||
UnsafeArray<int> _sortIncBuffer = iterator._sortIncBuffer;
|
||||
UnsafeArray<int> _sortExcBuffer = iterator._sortExcBuffer;
|
||||
EcsWorld.PoolSlot[] counts = iterator.World._poolSlots;
|
||||
|
||||
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 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
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
#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.chankIndex] & bit.mask) != bit.mask)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
|
||||
{
|
||||
var bit = _sortExcChunckBuffer.ptr[i];
|
||||
if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != 0)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
skip: continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
int poolsCapacity = ArrayUtility.NormalizeSizeToPowerOfTwo(config.PoolsCapacity);
|
||||
_pools = new IEcsPoolImplementation[poolsCapacity];
|
||||
_poolComponentCounts = new int[poolsCapacity];
|
||||
_poolSlots = new int[poolsCapacity];
|
||||
ArrayUtility.Fill(_pools, _nullPool);
|
||||
|
||||
int entitiesCapacity = ArrayUtility.NormalizeSizeToPowerOfTwo(config.EntitiesCapacity);
|
||||
@ -816,10 +816,19 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public static class EcsWorldExtenssions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNullOrDetroyed(this EcsWorld self)
|
||||
{
|
||||
return self == null || self.IsDestroyed;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ReleaseDelEntityBufferAllAuto(this EcsWorld self)
|
||||
{
|
||||
if (self.IsEnableReleaseDelEntBuffer)
|
||||
{
|
||||
self.ReleaseDelEntityBufferAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Callbacks Interface
|
||||
|
@ -12,11 +12,11 @@ namespace DCFApixels.DragonECS
|
||||
private SparseArray<int> _cmpTypeCode_2_CmpTypeIDs = new SparseArray<int>();
|
||||
private int _poolsCount;
|
||||
internal IEcsPoolImplementation[] _pools;
|
||||
internal int[] _poolComponentCounts;
|
||||
internal PoolSlot[] _poolSlots;
|
||||
|
||||
private readonly PoolsMediator _poolsMediator;
|
||||
|
||||
private readonly EcsNullPool _nullPool = EcsNullPool.instance;
|
||||
private EcsNullPool _nullPool = EcsNullPool.instance;
|
||||
|
||||
#region FindPoolInstance
|
||||
[Obsolete("The GetPoolInstance(int componentTypeID) method will be removed in future updates, use FindPoolInstance(Type componentType)")]
|
||||
@ -146,7 +146,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Create
|
||||
#region CreatePool
|
||||
private TPool CreatePool<TPool>() where TPool : IEcsPoolImplementation, new()
|
||||
{
|
||||
int poolTypeCode = EcsTypeCode.Get<TPool>();
|
||||
@ -184,7 +184,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
int oldCapacity = _pools.Length;
|
||||
Array.Resize(ref _pools, _pools.Length << 1);
|
||||
Array.Resize(ref _poolComponentCounts, _pools.Length);
|
||||
Array.Resize(ref _poolSlots, _pools.Length);
|
||||
ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
||||
|
||||
int newEntityComponentMaskLength = CalcEntityComponentMaskLength(); //_pools.Length / COMPONENT_MASK_CHUNK_SIZE + 1;
|
||||
@ -231,7 +231,9 @@ namespace DCFApixels.DragonECS
|
||||
private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||
{
|
||||
UpVersion();
|
||||
_poolComponentCounts[componentTypeID]++;
|
||||
ref PoolSlot slot = ref _poolSlots[componentTypeID];
|
||||
slot.count++;
|
||||
slot.version++;
|
||||
_entities[entityID].componentsCount++;
|
||||
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] |= maskBit.mask;
|
||||
}
|
||||
@ -239,7 +241,9 @@ namespace DCFApixels.DragonECS
|
||||
private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
|
||||
{
|
||||
UpVersion();
|
||||
_poolComponentCounts[componentTypeID]--;
|
||||
ref PoolSlot slot = ref _poolSlots[componentTypeID];
|
||||
slot.count--;
|
||||
slot.version++;
|
||||
var count = --_entities[entityID].componentsCount;
|
||||
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] &= ~maskBit.mask;
|
||||
|
||||
@ -262,7 +266,9 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
UpVersion();
|
||||
chunk = newChunk;
|
||||
_poolComponentCounts[componentTypeID]++;
|
||||
ref PoolSlot slot = ref _poolSlots[componentTypeID];
|
||||
slot.count++;
|
||||
slot.version++;
|
||||
_entities[entityID].componentsCount++;
|
||||
return true;
|
||||
}
|
||||
@ -276,7 +282,9 @@ namespace DCFApixels.DragonECS
|
||||
if (chunk != newChunk)
|
||||
{
|
||||
UpVersion();
|
||||
_poolComponentCounts[componentTypeID]--;
|
||||
ref PoolSlot slot = ref _poolSlots[componentTypeID];
|
||||
slot.count--;
|
||||
slot.version++;
|
||||
var count = --_entities[entityID].componentsCount;
|
||||
chunk = newChunk;
|
||||
|
||||
@ -295,7 +303,12 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int GetPoolComponentCount(int componentTypeID)
|
||||
{
|
||||
return _poolComponentCounts[componentTypeID];
|
||||
return _poolSlots[componentTypeID].count;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private long GetPoolVersion(int componentTypeID)
|
||||
{
|
||||
return _poolSlots[componentTypeID].version;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool HasEntityComponent(int entityID, EcsMaskChunck maskBit)
|
||||
@ -343,11 +356,24 @@ namespace DCFApixels.DragonECS
|
||||
return World.GetPoolComponentCount(componentTypeID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public long GetVersion(int componentTypeID)
|
||||
{
|
||||
return World.GetPoolVersion(componentTypeID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool HasComponent(int entityID, EcsMaskChunck maskBit)
|
||||
{
|
||||
return World.HasEntityComponent(entityID, maskBit);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PoolSlot
|
||||
internal struct PoolSlot
|
||||
{
|
||||
public int count;
|
||||
public long version;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -29,4 +29,38 @@ namespace DCFApixels.DragonECS
|
||||
protected abstract void OnInitialize();
|
||||
protected abstract void OnDestroy();
|
||||
}
|
||||
|
||||
public readonly struct PoolVersionsChecker
|
||||
{
|
||||
private readonly EcsMask _mask;
|
||||
private readonly long[] _versions;
|
||||
|
||||
public PoolVersionsChecker(EcsMask mask) : this()
|
||||
{
|
||||
_mask = mask;
|
||||
_versions = new long[mask._inc.Length + mask._exc.Length];
|
||||
}
|
||||
|
||||
public bool NextEquals()
|
||||
{
|
||||
var slots = _mask.World._poolSlots;
|
||||
bool result = true;
|
||||
int index = 0;
|
||||
foreach (var i in _mask._inc)
|
||||
{
|
||||
if (slots[i].version != _versions[index++])
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
foreach (var i in _mask._exc)
|
||||
{
|
||||
if (slots[i].version != _versions[index++])
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,10 +15,7 @@ namespace DCFApixels.DragonECS
|
||||
private int _filteredEntitiesCount;
|
||||
|
||||
private long _lastWorldVersion;
|
||||
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
//private readonly EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Where");
|
||||
#endif
|
||||
private PoolVersionsChecker _versionsChecker;
|
||||
|
||||
#region Properties
|
||||
public TAspect Aspect
|
||||
@ -38,11 +35,39 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_aspect = World.GetAspect<TAspect>();
|
||||
_filteredEntities = new int[32];
|
||||
_versionsChecker = new PoolVersionsChecker(_aspect._mask);
|
||||
}
|
||||
protected sealed override void OnDestroy() { }
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Filter(EcsSpan span)
|
||||
{
|
||||
_filteredEntitiesCount = _aspect.GetIteratorFor(span).CopyTo(ref _filteredEntities);
|
||||
_lastWorldVersion = World.Version;
|
||||
}
|
||||
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public EcsSpan Execute(Comparison<int> comparison)
|
||||
// {
|
||||
// return ExecuteFor(_aspect.World.Entities, comparison);
|
||||
// }
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public EcsSpan ExecuteFor(EcsSpan span, Comparison<int> comparison)
|
||||
// {
|
||||
//#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
// if (span.IsNull) { Throw.ArgumentNull(nameof(span)); }
|
||||
// if (span.WorldID != WorldID) { Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
//#endif
|
||||
// World.ReleaseDelEntityBufferAllAuto();
|
||||
// if (_lastWorldVersion != World.Version)
|
||||
// {
|
||||
// Filter(span);
|
||||
// }
|
||||
// Array.Sort<int>(_filteredEntities, 0, _filteredEntitiesCount, comparison);
|
||||
// }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsSpan Execute()
|
||||
{
|
||||
@ -52,29 +77,15 @@ namespace DCFApixels.DragonECS
|
||||
public EcsSpan ExecuteFor(EcsSpan span)
|
||||
{
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
//_executeMarker.Begin();
|
||||
if (span.IsNull) { Throw.ArgumentNull(nameof(span)); }
|
||||
if (span.WorldID != WorldID) { Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
#endif
|
||||
if (World.IsEnableReleaseDelEntBuffer)
|
||||
World.ReleaseDelEntityBufferAllAuto();
|
||||
if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false)
|
||||
{
|
||||
World.ReleaseDelEntityBufferAll();
|
||||
Filter(span);
|
||||
}
|
||||
EcsSpan result;
|
||||
if (_lastWorldVersion != World.Version)
|
||||
{
|
||||
result = _aspect.GetIteratorFor(span).CopyToSpan(ref _filteredEntities);
|
||||
_filteredEntitiesCount = result.Count;
|
||||
_lastWorldVersion = World.Version;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new EcsSpan(WorldID, _filteredEntities, _filteredEntitiesCount);
|
||||
}
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
//_executeMarker.End();
|
||||
#endif
|
||||
return result;
|
||||
return new EcsSpan(WorldID, _filteredEntities, _filteredEntitiesCount);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace DCFApixels.DragonECS
|
||||
private EcsGroup _filteredGroup;
|
||||
|
||||
private long _lastWorldVersion;
|
||||
private PoolVersionsChecker _versionsChecker;
|
||||
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
private readonly EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Where");
|
||||
@ -37,6 +38,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_aspect = World.GetAspect<TAspect>();
|
||||
_filteredGroup = EcsGroup.New(World);
|
||||
_versionsChecker = new PoolVersionsChecker(_aspect._mask);
|
||||
}
|
||||
protected sealed override void OnDestroy()
|
||||
{
|
||||
@ -46,6 +48,12 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Methods
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Filter(EcsSpan span)
|
||||
{
|
||||
_aspect.GetIteratorFor(span).CopyTo(_filteredGroup);
|
||||
_lastWorldVersion = World.Version;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsReadonlyGroup Execute()
|
||||
{
|
||||
return ExecuteFor(_aspect.World.Entities);
|
||||
@ -58,14 +66,10 @@ namespace DCFApixels.DragonECS
|
||||
if (span.IsNull) { Throw.ArgumentNull(nameof(span)); }
|
||||
if (span.WorldID != WorldID) { Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
#endif
|
||||
if (World.IsEnableReleaseDelEntBuffer)
|
||||
World.ReleaseDelEntityBufferAllAuto();
|
||||
if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false)
|
||||
{
|
||||
World.ReleaseDelEntityBufferAll();
|
||||
}
|
||||
if (_lastWorldVersion != World.Version)
|
||||
{
|
||||
_aspect.GetIteratorFor(span).CopyTo(_filteredGroup);
|
||||
_lastWorldVersion = World.Version;
|
||||
Filter(span);
|
||||
}
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
_executeMarker.End();
|
||||
|
@ -4,7 +4,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DCFApixels.DragonECS.Internal
|
||||
{
|
||||
internal interface IComparerX<T>
|
||||
internal interface IStructComparer<T>
|
||||
{
|
||||
// a > b = return > 0
|
||||
int Compare(T a, T b);
|
||||
@ -14,7 +14,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
private const int IntrosortSizeThreshold = 16;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SwapIfGreater<TComparer>(T[] items, ref TComparer comparer, int i, int j) where TComparer : IComparerX<T>
|
||||
public static void SwapIfGreater<TComparer>(T[] items, ref TComparer comparer, int i, int j) where TComparer : IStructComparer<T>
|
||||
{
|
||||
if (comparer.Compare(items[i], items[j]) > 0)
|
||||
{
|
||||
@ -24,7 +24,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InsertionSort<TComparer>(T[] items, ref TComparer comparer) where TComparer : IComparerX<T>
|
||||
public static void InsertionSort<TComparer>(T[] items, ref TComparer comparer) where TComparer : IStructComparer<T>
|
||||
{
|
||||
for (int i = 0; i < items.Length - 1; i++)
|
||||
{
|
||||
@ -41,7 +41,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Sort<TComparer>(T[] items, ref TComparer comparer) where TComparer : IComparerX<T>
|
||||
public static void Sort<TComparer>(T[] items, ref TComparer comparer) where TComparer : IStructComparer<T>
|
||||
{
|
||||
int length = items.Length;
|
||||
if (length == 1)
|
||||
@ -69,7 +69,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
InsertionSort(items, ref comparer);
|
||||
return;
|
||||
}
|
||||
IComparerX<T> packed = comparer;
|
||||
IStructComparer<T> packed = comparer;
|
||||
Array.Sort(items, comparer.Compare);
|
||||
comparer = (TComparer)packed;
|
||||
}
|
||||
@ -80,7 +80,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
private const int IntrosortSizeThreshold = 16;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SwapIfGreater<TComparer>(T* items, ref TComparer comparer, int i, int j) where TComparer : IComparerX<T>
|
||||
public static void SwapIfGreater<TComparer>(T* items, ref TComparer comparer, int i, int j) where TComparer : IStructComparer<T>
|
||||
{
|
||||
if (comparer.Compare(items[i], items[j]) > 0)
|
||||
{
|
||||
@ -90,7 +90,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InsertionSort_Unchecked<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IComparerX<T>
|
||||
public static void InsertionSort_Unchecked<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IStructComparer<T>
|
||||
{
|
||||
for (int i = 0; i < length - 1; i++)
|
||||
{
|
||||
@ -127,7 +127,7 @@ namespace DCFApixels.DragonECS.Internal
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
public static void InsertionSort<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IComparerX<T>
|
||||
public static void InsertionSort<TComparer>(T* items, int length, ref TComparer comparer) where TComparer : IStructComparer<T>
|
||||
{
|
||||
if (length == 1)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user