2023-02-13 21:11:54 +08:00
using System ;
using System.Runtime.CompilerServices ;
2023-03-30 20:47:39 +08:00
using System.Runtime.InteropServices ;
2023-04-10 22:22:17 +08:00
using Unity.Profiling ;
2023-04-17 22:58:52 +08:00
using UnityEngine ;
2023-03-30 10:46:57 +08:00
using delayedOp = System . Int32 ;
2023-02-13 21:11:54 +08:00
namespace DCFApixels.DragonECS
{
2023-03-30 20:47:39 +08:00
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
public readonly ref struct EcsReadonlyGroup
2023-02-14 03:26:34 +08:00
{
2023-03-30 20:47:39 +08:00
private readonly EcsGroup _source ;
2023-04-01 22:29:34 +08:00
#region Constructors
2023-03-30 20:47:39 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsReadonlyGroup ( EcsGroup source ) = > _source = source ;
2023-04-01 22:29:34 +08:00
#endregion
#region Properties
2023-04-09 02:52:39 +08:00
public IEcsWorld World
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get = > _source . World ;
}
2023-03-30 20:47:39 +08:00
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)]
get = > _source . IsReleazed ;
}
2023-04-01 22:29:34 +08:00
#endregion
#region Methods
2023-03-30 20:47:39 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains ( int entityID ) = > _source . Contains ( 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 ( ) ;
2023-04-01 22:29:34 +08:00
#endregion
2023-04-08 23:01:10 +08:00
#region Object
public override string ToString ( )
{
if ( _source ! = null )
return _source . ToString ( ) ;
return "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-02-14 03:26:34 +08:00
}
2023-04-17 22:58:52 +08:00
// индексация начинается с 1
2023-03-30 10:46:57 +08:00
// _delayedOps это int[] для отложенных операций, хранятся отложенные операции в виде int значения, если старший бит = 0 то это опреация добавленияб если = 1 то это операция вычитания
2023-04-15 00:23:46 +08:00
public unsafe class EcsGroup : IDisposable , IEquatable < EcsGroup >
2023-02-13 21:11:54 +08:00
{
2023-04-09 02:52:39 +08:00
private const int DEALAYED_ADD = 0 ;
private const int DEALAYED_REMOVE = int . MinValue ;
2023-03-30 10:46:57 +08:00
2023-03-02 14:42:44 +08:00
private IEcsWorld _source ;
2023-02-13 21:11:54 +08:00
2023-03-30 10:46:57 +08:00
private int [ ] _dense ;
private int [ ] _sparse ;
private int _count ;
private delayedOp [ ] _delayedOps ;
2023-02-13 21:11:54 +08:00
private int _delayedOpsCount ;
private int _lockCount ;
2023-04-15 00:23:46 +08:00
private bool _isReleazed = true ;
2023-02-13 21:11:54 +08:00
#region Properties
2023-03-02 14:42:44 +08:00
public IEcsWorld 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 ;
}
2023-03-30 20:47:39 +08:00
public EcsReadonlyGroup Readonly
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get = > new EcsReadonlyGroup ( this ) ;
}
2023-04-15 00:23:46 +08:00
public bool IsReleazed
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get = > _isReleazed ;
}
2023-02-13 21:11:54 +08:00
#endregion
2023-04-17 22:58:52 +08:00
#region Constrcutors / Finalizer
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-15 00:23:46 +08:00
public static EcsGroup New ( IEcsWorld 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-04-15 00:23:46 +08:00
internal EcsGroup ( IEcsWorld world , int denseCapacity = 64 , int delayedOpsCapacity = 128 )
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 ] ;
_sparse = new int [ world . EntitesCapacity ] ;
2023-04-08 21:29:18 +08:00
_delayedOps = new delayedOp [ delayedOpsCapacity ] ;
2023-03-30 10:46:57 +08:00
2023-04-08 21:29:18 +08:00
_lockCount = 0 ;
_delayedOpsCount = 0 ;
2023-03-30 10:46:57 +08:00
_count = 0 ;
2023-02-13 21:11:54 +08:00
}
2023-04-17 22:58:52 +08:00
//защита от криворукости
//перед сборкой мусора снова создает сильную ссылку и возвращает в пул
//TODO переделат ьиил удалить, так как сборщик мусора просыпается только после 12к и более экземпляров, только тогда и вызывается финализатор, слишком жирно
~ EcsGroup ( )
{
Release ( ) ;
}
2023-02-13 21:11:54 +08:00
#endregion
2023-03-30 10:46:57 +08:00
#region Contains
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains ( int entityID )
{
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 ) ;
2023-02-13 21:11:54 +08:00
public void Add ( int entityID )
{
2023-04-01 20:45:37 +08:00
if ( Contains ( entityID ) ) return ;
2023-04-01 22:18:40 +08:00
AddInternal ( entityID ) ;
2023-04-01 20:45:37 +08:00
}
2023-04-01 22:18:40 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void AddInternal ( int entityID )
2023-04-01 20:45:37 +08:00
{
2023-04-10 22:22:17 +08:00
//if (_lockCount > 0)
//{
// AddDelayedOp(entityID, DEALAYED_ADD);
// return;
//}
2023-04-08 21:29:18 +08:00
AggressiveAdd ( entityID ) ;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void AggressiveAdd ( int entityID )
{
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-02-13 21:11:54 +08:00
}
2023-04-01 20:45:37 +08:00
public void UncheckedRemove ( int entityID ) = > RemoveInternal ( entityID ) ;
2023-02-13 21:11:54 +08:00
public void Remove ( int entityID )
2023-04-01 20:45:37 +08:00
{
if ( ! Contains ( entityID ) ) return ;
RemoveInternal ( entityID ) ;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-01 22:18:40 +08:00
internal void RemoveInternal ( int entityID )
2023-02-13 21:11:54 +08:00
{
2023-04-10 22:22:17 +08:00
//if (_lockCount > 0)
//{
// AddDelayedOp(entityID, DEALAYED_REMOVE);
// return;
//}
2023-04-08 21:29:18 +08:00
AggressiveRemove ( entityID ) ;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void AggressiveRemove ( int entityID )
{
2023-03-30 10:46:57 +08:00
_dense [ _sparse [ entityID ] ] = _dense [ _count ] ;
_sparse [ _dense [ _count - - ] ] = _sparse [ entityID ] ;
_sparse [ entityID ] = 0 ;
2023-02-13 21:11:54 +08:00
}
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void AddDelayedOp ( int entityID , int isAddBitFlag )
2023-02-13 21:11:54 +08:00
{
if ( _delayedOpsCount > = _delayedOps . Length )
{
Array . Resize ( ref _delayedOps , _delayedOps . Length < < 1 ) ;
}
2023-03-30 10:46:57 +08:00
_delayedOps [ _delayedOpsCount + + ] = entityID | isAddBitFlag ; // delayedOp = entityID add isAddBitFlag
2023-02-13 21:11:54 +08:00
}
#endregion
2023-04-15 00:23:46 +08:00
#region Sort / Clear
2023-04-07 03:12:56 +08:00
public void Sort ( )
{
int increment = 1 ;
for ( int i = 0 ; i < _dense . Length ; i + + )
{
if ( _sparse [ i ] > 0 )
{
_sparse [ i ] = increment ;
_dense [ increment + + ] = i ;
}
}
}
2023-04-15 00:23:46 +08:00
public void Clear ( )
{
_count = 0 ;
2023-04-17 22:58:52 +08:00
//массив _dense нет смысла очищать, испольщуется только область от 1 до _count
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
2023-04-09 02:52:39 +08:00
if ( group . World ! = _source ) throw new ArgumentException ( "groupFilter.World != World" ) ;
#endif
2023-04-17 22:58:52 +08:00
if ( _count > 0 )
Clear ( ) ;
2023-04-09 02:52:39 +08:00
foreach ( var item in group )
AggressiveAdd ( item . id ) ;
}
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
if ( _source ! = group . World ) throw new ArgumentException ( "World != groupFilter.World" ) ;
2023-04-08 23:01:10 +08:00
#endif
foreach ( var item in group )
if ( ! Contains ( item . id ) )
AggressiveAdd ( item . id ) ;
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
2023-04-09 02:52:39 +08:00
if ( _source ! = group . World ) throw new ArgumentException ( "World != groupFilter.World" ) ;
#endif
2023-04-10 22:22:17 +08:00
foreach ( var item in this )
if ( group . Contains ( item . id ) )
2023-04-09 02:52:39 +08:00
AggressiveRemove ( item . id ) ;
}
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
if ( World ! = group . World ) throw new ArgumentException ( "World != groupFilter.World" ) ;
2023-04-08 21:29:18 +08:00
#endif
2023-04-08 23:01:10 +08:00
foreach ( var item in this )
2023-04-09 02:52:39 +08:00
if ( ! group . Contains ( item . id ) )
2023-04-08 23:01:10 +08:00
AggressiveRemove ( item . id ) ;
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
if ( _source ! = group . World ) throw new ArgumentException ( "World != groupFilter.World" ) ;
2023-04-08 21:29:18 +08:00
#endif
2023-04-08 23:01:10 +08:00
foreach ( var item in group )
if ( Contains ( item . id ) )
AggressiveRemove ( item . id ) ;
else
AggressiveAdd ( item . id ) ;
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
if ( a . _source ! = b . _source ) throw new ArgumentException ( "a.World != b.World" ) ;
#endif
EcsGroup result = a . _source . GetGroupFromPool ( ) ;
foreach ( var item in a )
if ( ! b . Contains ( item . id ) )
result . AggressiveAdd ( item . id ) ;
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
if ( a . _source ! = b . _source ) throw new ArgumentException ( "a.World != b.World" ) ;
#endif
EcsGroup result = a . _source . GetGroupFromPool ( ) ;
foreach ( var item in a )
if ( b . Contains ( item . id ) )
result . AggressiveAdd ( item . id ) ;
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 ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
if ( a . _source ! = b . _source ) throw new ArgumentException ( "a.World != b.World" ) ;
#endif
EcsGroup result = a . _source . GetGroupFromPool ( ) ;
foreach ( var item in a )
result . AggressiveAdd ( item . id ) ;
foreach ( var item in a )
result . Add ( item . id ) ;
return result ;
2023-04-10 22:22:17 +08:00
}
#endregion
2023-02-13 21:11:54 +08:00
#region GetEnumerator
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-02-13 21:11:54 +08:00
private void Unlock ( )
{
2023-04-01 20:45:37 +08:00
#if ( DEBUG & & ! DISABLE_DRAGONECS_DEBUG ) | | ! DRAGONECS_NO_SANITIZE_CHECKS
2023-02-13 21:11:54 +08:00
if ( _lockCount < = 0 )
{
2023-03-30 10:46:57 +08:00
throw new Exception ( $"Invalid lock-unlock balance for {nameof(EcsGroup)}." ) ;
2023-02-13 21:11:54 +08:00
}
#endif
if ( - - _lockCount < = 0 )
{
for ( int i = 0 ; i < _delayedOpsCount ; i + + )
{
2023-03-30 10:46:57 +08:00
delayedOp op = _delayedOps [ i ] ;
if ( op > = 0 ) //delayedOp.IsAdded
2023-04-09 02:52:39 +08:00
AggressiveAdd ( op & int . MaxValue ) ; //delayedOp.EcsEntity
2023-02-13 21:11:54 +08:00
else
2023-04-09 02:52:39 +08:00
AggressiveRemove ( op & int . MaxValue ) ; //delayedOp.EcsEntity
2023-02-13 21:11:54 +08:00
}
}
}
2023-04-10 22:22:17 +08:00
private ProfilerMarker _getEnumeratorReturn = new ProfilerMarker ( "EcsGroup.GetEnumerator" ) ;
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-02-13 21:11:54 +08:00
public Enumerator GetEnumerator ( )
{
2023-04-10 22:22:17 +08:00
// _lockCount++;
2023-02-13 21:11:54 +08:00
return new Enumerator ( this ) ;
}
#endregion
2023-03-30 20:47:39 +08:00
#region Enumerator
2023-04-10 22:22:17 +08:00
public ref struct Enumerator // : IDisposable
2023-02-13 21:11:54 +08:00
{
2023-04-17 22:58:52 +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)]
2023-02-13 21:11:54 +08:00
public Enumerator ( EcsGroup group )
{
2023-04-17 22:58:52 +08:00
// source = group;
2023-04-01 21:16:08 +08:00
_dense = group . _dense ;
_count = group . Count ;
2023-04-06 23:40:47 +08:00
_index = 0 ;
2023-02-13 21:11:54 +08:00
}
2023-03-26 11:19:03 +08:00
public ent Current
2023-02-13 21:11:54 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-10 22:22:17 +08:00
get = > ( ent ) _dense [ _index ] ;
2023-02-13 21:11:54 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-08 00:47:35 +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();
2023-02-13 21:11:54 +08:00
}
#endregion
2023-04-08 23:01:10 +08:00
2023-04-09 02:52:39 +08:00
#region Object
2023-04-08 23:01:10 +08:00
public override string ToString ( )
{
return 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 ( other . Count ! = Count )
return false ;
foreach ( var item in other )
if ( ! Contains ( item . id ) )
return false ;
return true ;
}
public override int GetHashCode ( )
{
int hash = 0 ;
foreach ( var item in this )
hash ^ = 1 < < ( item . id % 32 ) ; //реализация от балды, так как не нужен, но фишка в том что хеш не учитывает порядок сущьностей, что явлется правильным поведением.
return hash ;
}
#endregion
#region operators
public static bool operator = = ( EcsGroup a , EcsGroup b ) = > a . Equals ( b ) ;
public static bool operator = = ( EcsGroup a , EcsReadonlyGroup b ) = > a . Equals ( b ) ;
public static bool operator ! = ( EcsGroup a , EcsGroup b ) = > ! a . Equals ( b ) ;
public static bool operator ! = ( EcsGroup a , EcsReadonlyGroup b ) = > ! a . Equals ( b ) ;
#endregion
#region OnWorldResize
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void OnWorldResize ( int newSize )
{
Array . Resize ( ref _sparse , newSize ) ;
}
#endregion
#region IDisposable / Release
public void Dispose ( )
{
Release ( ) ;
}
public void Release ( )
{
_isReleazed = true ;
_source . ReleaseGroup ( this ) ;
}
2023-04-08 23:01:10 +08:00
#endregion
2023-02-13 21:11:54 +08:00
}
2023-04-01 20:45:37 +08:00
public static class EcsGroupExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Normalize < T > ( this EcsGroup self , ref T [ ] array )
{
if ( array . Length < self . CapacityDense ) Array . Resize ( ref array , self . CapacityDense ) ;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Normalize < T > ( this EcsReadonlyGroup self , ref T [ ] array )
{
if ( array . Length < self . CapacityDense ) Array . Resize ( ref array , self . CapacityDense ) ;
}
}
2023-02-13 21:11:54 +08:00
}