DragonECS/src/EcsGroup.cs

499 lines
18 KiB
C#
Raw Normal View History

using System;
2023-05-28 06:29:04 +08:00
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-05-26 04:25:09 +08:00
using static DCFApixels.DragonECS.EcsGroup.ThrowHalper;
#endif
2023-05-26 04:25:09 +08:00
namespace DCFApixels.DragonECS
{
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
2023-05-28 06:29:04 +08:00
[DebuggerTypeProxy(typeof(DebuggerProxy))]
public readonly ref struct EcsReadonlyGroup
2023-02-14 03:26:34 +08:00
{
private readonly EcsGroup _source;
2023-04-24 00:19:07 +08:00
2023-04-01 22:29:34 +08:00
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup(EcsGroup source) => _source = source;
2023-04-01 22:29:34 +08:00
#endregion
#region Properties
public bool IsNull => _source == null;
2023-04-24 00:31:03 +08:00
public EcsWorld World
2023-04-09 02:52:39 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.World;
}
public int Count
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.Count;
}
2023-04-01 20:45:37 +08:00
public int CapacityDense
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.CapacityDense;
}
public int CapacitySparce
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.CapacitySparce;
}
2023-04-15 00:23:46 +08:00
public bool IsReleazed
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-26 00:24:38 +08:00
get => _source.IsReleased;
2023-04-15 00:23:46 +08:00
}
public int this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source[index];
}
2023-04-01 22:29:34 +08:00
#endregion
#region Methods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID) => _source.Has(entityID);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsGroup.Enumerator GetEnumerator() => _source.GetEnumerator();
2023-04-15 00:23:46 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-17 22:58:52 +08:00
public EcsGroup Clone() => _source.Clone();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int First() => _source.First();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Last() => _source.Last();
2023-04-01 22:29:34 +08:00
#endregion
2023-04-08 23:01:10 +08:00
#region Object
2023-05-28 06:29:04 +08:00
public override string ToString() => _source != null ? _source.ToString() : "NULL";
2023-04-15 00:23:46 +08:00
public override int GetHashCode() => _source.GetHashCode();
public override bool Equals(object obj) => obj is EcsGroup group && group == this;
public bool Equals(EcsReadonlyGroup other) => _source == other._source;
2023-04-08 23:01:10 +08:00
#endregion
#region Internal
2023-04-09 02:52:39 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-08 23:01:10 +08:00
internal EcsGroup GetGroupInternal() => _source;
#endregion
2023-04-15 00:23:46 +08:00
#region operators
public static bool operator ==(EcsReadonlyGroup a, EcsReadonlyGroup b) => a.Equals(b);
public static bool operator ==(EcsReadonlyGroup a, EcsGroup b) => a.Equals(b);
public static bool operator !=(EcsReadonlyGroup a, EcsReadonlyGroup b) => !a.Equals(b);
public static bool operator !=(EcsReadonlyGroup a, EcsGroup b) => !a.Equals(b);
#endregion
2023-05-28 06:29:04 +08:00
#region DebuggerProxy
internal class DebuggerProxy : EcsGroup.DebuggerProxy
{
public DebuggerProxy(EcsReadonlyGroup group) : base(group._source) { }
}
#endregion
2023-02-14 03:26:34 +08:00
}
2023-05-28 06:29:04 +08:00
[DebuggerTypeProxy(typeof(DebuggerProxy))]
2023-04-15 00:23:46 +08:00
public unsafe class EcsGroup : IDisposable, IEquatable<EcsGroup>
{
private EcsWorld _source;
2023-03-30 10:46:57 +08:00
private int[] _dense;
private int[] _sparse;
private int _count;
2023-05-28 06:29:04 +08:00
internal bool _isReleased = true;
2023-04-15 00:23:46 +08:00
#region Properties
public EcsWorld World => _source;
2023-03-30 10:46:57 +08:00
public int Count
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _count;
}
2023-04-01 20:45:37 +08:00
public int CapacityDense
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _dense.Length;
}
public int CapacitySparce
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _sparse.Length;
}
public EcsReadonlyGroup Readonly
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new EcsReadonlyGroup(this);
}
2023-05-26 00:24:38 +08:00
public bool IsReleased
2023-04-15 00:23:46 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-26 00:24:38 +08:00
get => _isReleased;
2023-04-15 00:23:46 +08:00
}
public int this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (index < 0 || index >= Count) ThrowArgumentOutOfRange();
#endif
return _dense[index];
}
}
#endregion
2023-04-17 22:58:52 +08:00
#region Constrcutors/Finalizer
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsGroup New(EcsWorld world)
2023-04-01 20:45:37 +08:00
{
2023-04-15 00:23:46 +08:00
return world.GetGroupFromPool();
2023-04-08 21:29:18 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-26 00:24:38 +08:00
internal EcsGroup(EcsWorld world, int denseCapacity = 64)
2023-04-08 21:29:18 +08:00
{
2023-04-15 00:23:46 +08:00
_source = world;
2023-04-08 21:29:18 +08:00
_source.RegisterGroup(this);
2023-04-15 00:23:46 +08:00
_dense = new int[denseCapacity];
2023-04-18 19:35:42 +08:00
_sparse = new int[world.Capacity];
2023-04-08 21:29:18 +08:00
2023-03-30 10:46:57 +08:00
_count = 0;
}
#endregion
2023-04-24 16:48:18 +08:00
#region Has
//TODO переименовать в Has
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-24 16:48:18 +08:00
public bool Has(int entityID)
2023-03-30 10:46:57 +08:00
{
2023-04-15 00:23:46 +08:00
return _sparse[entityID] > 0;
2023-04-01 20:45:37 +08:00
}
#endregion
#region IndexOf
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int IndexOf(int entityID)
{
return _sparse[entityID];
2023-03-30 10:46:57 +08:00
}
#endregion
2023-04-08 21:29:18 +08:00
#region Add/Remove
2023-04-01 20:45:37 +08:00
public void UncheckedAdd(int entityID) => AddInternal(entityID);
public void Add(int entityID)
{
2023-04-24 16:48:18 +08:00
if (Has(entityID)) return;
AddInternal(entityID);
2023-04-01 20:45:37 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void AddInternal(int entityID)
2023-04-01 20:45:37 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (Has(entityID)) ThrowAlreadyContains(entityID);
#endif
2023-04-01 20:45:37 +08:00
if (++_count >= _dense.Length)
2023-03-30 10:46:57 +08:00
Array.Resize(ref _dense, _dense.Length << 1);
_dense[_count] = entityID;
_sparse[entityID] = _count;
}
2023-04-01 20:45:37 +08:00
public void UncheckedRemove(int entityID) => RemoveInternal(entityID);
public void Remove(int entityID)
2023-04-01 20:45:37 +08:00
{
2023-04-24 16:48:18 +08:00
if (!Has(entityID)) return;
2023-04-01 20:45:37 +08:00
RemoveInternal(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void RemoveInternal(int entityID)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
if (!Has(entityID)) ThrowDoesNotContain(entityID);
#endif
2023-03-30 10:46:57 +08:00
_dense[_sparse[entityID]] = _dense[_count];
_sparse[_dense[_count--]] = _sparse[entityID];
_sparse[entityID] = 0;
}
2023-04-24 16:48:18 +08:00
public void RemoveUnusedEntityIDs()
{
foreach (var e in this)
{
if (!_source.IsUsed(e))
2023-05-26 00:24:38 +08:00
RemoveInternal(e);
2023-04-24 16:48:18 +08:00
}
}
#endregion
2023-05-27 15:59:46 +08:00
#region Clear
2023-04-15 00:23:46 +08:00
public void Clear()
{
_count = 0;
2023-05-27 15:59:46 +08:00
//массив _dense нет смысла очищать
2023-04-15 00:23:46 +08:00
for (int i = 0; i < _sparse.Length; i++)
_sparse[i] = 0;
}
#endregion
#region CopyFrom/Clone
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyFrom(EcsReadonlyGroup group) => CopyFrom(group.GetGroupInternal());
2023-04-08 23:01:10 +08:00
public void CopyFrom(EcsGroup group)
2023-04-08 21:29:18 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (group.World != _source) throw new ArgumentException("groupFilter.WorldIndex != WorldIndex");
2023-04-09 02:52:39 +08:00
#endif
2023-05-30 18:30:10 +08:00
if (_count > 0)
2023-04-17 22:58:52 +08:00
Clear();
2023-04-09 02:52:39 +08:00
foreach (var item in group)
2023-05-26 00:24:38 +08:00
AddInternal(item);
2023-04-09 02:52:39 +08:00
}
2023-04-15 00:23:46 +08:00
public EcsGroup Clone()
2023-04-09 02:52:39 +08:00
{
2023-04-15 00:23:46 +08:00
EcsGroup result = _source.GetGroupFromPool();
result.CopyFrom(this);
return result;
2023-04-08 23:01:10 +08:00
}
2023-04-15 00:23:46 +08:00
#endregion
2023-04-01 21:16:08 +08:00
2023-04-08 23:01:10 +08:00
#region Set operations
/// <summary>as Union sets</summary>
2023-04-15 00:23:46 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UnionWith(EcsReadonlyGroup group) => UnionWith(group.GetGroupInternal());
2023-04-09 02:52:39 +08:00
/// <summary>as Union sets</summary>
2023-04-15 00:23:46 +08:00
public void UnionWith(EcsGroup group)
2023-04-09 02:52:39 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
2023-04-08 23:01:10 +08:00
#endif
foreach (var item in group)
2023-04-24 16:48:18 +08:00
if (!Has(item))
2023-05-26 00:24:38 +08:00
AddInternal(item);
2023-04-08 21:29:18 +08:00
}
2023-04-15 00:23:46 +08:00
2023-04-08 23:01:10 +08:00
/// <summary>as Except sets</summary>
2023-04-15 00:23:46 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ExceptWith(EcsReadonlyGroup group) => ExceptWith(group.GetGroupInternal());
/// <summary>as Except sets</summary>
public void ExceptWith(EcsGroup group)
2023-04-08 21:29:18 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
2023-04-09 02:52:39 +08:00
#endif
2023-04-10 22:22:17 +08:00
foreach (var item in this)
2023-04-24 16:48:18 +08:00
if (group.Has(item))
2023-05-26 00:24:38 +08:00
RemoveInternal(item);
2023-04-09 02:52:39 +08:00
}
2023-04-15 00:23:46 +08:00
2023-04-08 23:01:10 +08:00
/// <summary>as Intersect sets</summary>
2023-04-15 00:23:46 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AndWith(EcsReadonlyGroup group) => AndWith(group.GetGroupInternal());
2023-04-09 02:52:39 +08:00
/// <summary>as Intersect sets</summary>
2023-04-15 00:23:46 +08:00
public void AndWith(EcsGroup group)
2023-04-09 02:52:39 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (World != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
2023-04-08 21:29:18 +08:00
#endif
2023-04-08 23:01:10 +08:00
foreach (var item in this)
2023-04-24 16:48:18 +08:00
if (!group.Has(item))
2023-05-26 00:24:38 +08:00
RemoveInternal(item);
2023-04-08 21:29:18 +08:00
}
2023-04-15 00:23:46 +08:00
2023-04-08 23:01:10 +08:00
/// <summary>as Symmetric Except sets</summary>
2023-04-15 00:23:46 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void XorWith(EcsReadonlyGroup group) => XorWith(group.GetGroupInternal());
2023-04-09 02:52:39 +08:00
/// <summary>as Symmetric Except sets</summary>
2023-04-15 00:23:46 +08:00
public void XorWith(EcsGroup group)
2023-04-09 02:52:39 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (_source != group.World) throw new ArgumentException("WorldIndex != groupFilter.WorldIndex");
2023-04-08 21:29:18 +08:00
#endif
2023-04-08 23:01:10 +08:00
foreach (var item in group)
2023-04-24 16:48:18 +08:00
if (Has(item))
2023-05-26 00:24:38 +08:00
RemoveInternal(item);
2023-04-08 23:01:10 +08:00
else
2023-05-26 00:24:38 +08:00
AddInternal(item);
2023-04-08 21:29:18 +08:00
}
2023-02-14 03:26:34 +08:00
#endregion
2023-04-10 22:22:17 +08:00
#region Static Set operations
/// <summary>as Except sets</summary>
2023-04-15 00:23:46 +08:00
/// <returns>new group from pool</returns>
public static EcsGroup Except(EcsGroup a, EcsGroup b)
2023-04-10 22:22:17 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex");
2023-04-10 22:22:17 +08:00
#endif
EcsGroup result = a._source.GetGroupFromPool();
foreach (var item in a)
2023-04-24 16:48:18 +08:00
if (!b.Has(item))
2023-05-26 00:24:38 +08:00
result.AddInternal(item);
2023-04-10 22:22:17 +08:00
a._source.ReleaseGroup(a);
2023-04-15 00:23:46 +08:00
return result;
2023-04-10 22:22:17 +08:00
}
/// <summary>as Intersect sets</summary>
2023-04-15 00:23:46 +08:00
/// <returns>new group from pool</returns>
public static EcsGroup And(EcsGroup a, EcsGroup b)
2023-04-10 22:22:17 +08:00
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex");
2023-04-10 22:22:17 +08:00
#endif
EcsGroup result = a._source.GetGroupFromPool();
foreach (var item in a)
2023-04-24 16:48:18 +08:00
if (b.Has(item))
2023-05-26 00:24:38 +08:00
result.AddInternal(item);
2023-04-10 22:22:17 +08:00
a._source.ReleaseGroup(a);
2023-04-15 00:23:46 +08:00
return result;
}
/// <summary>as Intersect sets</summary>
/// <returns>new group from pool</returns>
public static EcsGroup Union(EcsGroup a, EcsGroup b)
{
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
2023-04-20 18:23:23 +08:00
if (a._source != b._source) throw new ArgumentException("a.WorldIndex != b.WorldIndex");
2023-04-15 00:23:46 +08:00
#endif
EcsGroup result = a._source.GetGroupFromPool();
foreach (var item in a)
2023-05-26 00:24:38 +08:00
result.AddInternal(item);
2023-04-15 00:23:46 +08:00
foreach (var item in a)
2023-04-23 15:57:35 +08:00
result.Add(item);
2023-04-15 00:23:46 +08:00
return result;
2023-04-10 22:22:17 +08:00
}
#endregion
#region GetEnumerator
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
#endregion
#region Enumerator
2023-04-10 22:22:17 +08:00
public ref struct Enumerator// : IDisposable
{
2023-05-30 18:30:10 +08:00
// private readonly EcsGroup source;
2023-04-01 21:16:08 +08:00
private readonly int[] _dense;
private readonly int _count;
2023-04-06 23:40:47 +08:00
private int _index;
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(EcsGroup group)
{
2023-05-30 18:30:10 +08:00
// source = group;
2023-04-01 21:16:08 +08:00
_dense = group._dense;
2023-04-23 22:55:13 +08:00
_count = group._count;
2023-04-06 23:40:47 +08:00
_index = 0;
}
2023-04-23 15:57:35 +08:00
public int Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-23 15:57:35 +08:00
get => _dense[_index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-30 18:30:10 +08:00
public bool MoveNext() => ++_index <= _count && _count < _dense.Length; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны
2023-04-10 22:22:17 +08:00
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-17 22:58:52 +08:00
//public void Dispose() => source.Unlock();
}
#endregion
2023-04-08 23:01:10 +08:00
2023-04-09 02:52:39 +08:00
#region Object
2023-05-28 06:29:04 +08:00
public override string ToString() => string.Join(", ", _dense.AsSpan(1, _count).ToArray());
2023-04-15 00:23:46 +08:00
public override bool Equals(object obj) => obj is EcsGroup group && Equals(group);
public bool Equals(EcsReadonlyGroup other) => Equals(other.GetGroupInternal());
public bool Equals(EcsGroup other)
{
if (ReferenceEquals(other, null))
return false;
2023-04-15 00:23:46 +08:00
if (other.Count != Count)
return false;
foreach (var item in other)
2023-04-24 16:48:18 +08:00
if (!Has(item))
2023-04-15 00:23:46 +08:00
return false;
return true;
}
2023-05-30 18:30:10 +08:00
public override int GetHashCode()
2023-04-15 00:23:46 +08:00
{
int hash = 0;
foreach (var item in this)
2023-04-23 15:57:35 +08:00
hash ^= 1 << (item % 32); //реализация от балды, так как не нужен, но фишка в том что хеш не учитывает порядок сущьностей, что явлется правильным поведением.
2023-04-15 00:23:46 +08:00
return hash;
}
#endregion
#region OtherMethods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int First() => this[0];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Last() => this[_count - 1];
#endregion
2023-04-15 00:23:46 +08:00
#region operators
private static bool StaticEquals(EcsGroup a, EcsReadonlyGroup b) => StaticEquals(a, b.GetGroupInternal());
private static bool StaticEquals(EcsGroup a, EcsGroup b)
{
if (ReferenceEquals(a, null))
return false;
return a.Equals(b);
}
public static bool operator ==(EcsGroup a, EcsGroup b) => StaticEquals(a, b);
public static bool operator ==(EcsGroup a, EcsReadonlyGroup b) => StaticEquals(a, b);
public static bool operator !=(EcsGroup a, EcsGroup b) => !StaticEquals(a, b);
public static bool operator !=(EcsGroup a, EcsReadonlyGroup b) => !StaticEquals(a, b);
2023-04-15 00:23:46 +08:00
#endregion
#region OnWorldResize
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void OnWorldResize(int newSize)
{
Array.Resize(ref _sparse, newSize);
}
#endregion
#region IDisposable/Release
2023-05-28 06:29:04 +08:00
public void Dispose() => Release();
2023-04-15 00:23:46 +08:00
public void Release()
{
_source.ReleaseGroup(this);
}
2023-04-08 23:01:10 +08:00
#endregion
#region ThrowHalper
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
internal static class ThrowHalper
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowAlreadyContains(int entityID) => throw new EcsFrameworkException($"This group already contains entity {entityID}.");
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowArgumentOutOfRange() => throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count.");
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowDoesNotContain(int entityID) => throw new EcsFrameworkException($"This group does not contain entity {entityID}.");
}
#endif
#endregion
2023-04-01 20:45:37 +08:00
2023-05-28 06:29:04 +08:00
#region DebuggerProxy
internal class DebuggerProxy
2023-04-01 20:45:37 +08:00
{
2023-05-28 06:29:04 +08:00
private EcsGroup _group;
public EcsWorld World => _group.World;
public bool IsReleased => _group.IsReleased;
public entlong[] Entities
{
get
{
entlong[] result = new entlong[_group.Count];
int i = 0;
foreach (var e in _group)
result[i++] = _group.World.GetEntityLong(e);
return result;
}
}
public int Count => _group.Count;
public int CapacityDense => _group.CapacityDense;
public int CapacitySparce => _group.CapacitySparce;
public DebuggerProxy(EcsGroup group) => _group = group;
2023-04-01 20:45:37 +08:00
}
2023-05-28 06:29:04 +08:00
#endregion
2023-04-01 20:45:37 +08:00
}
2023-05-28 06:29:04 +08:00
}