2023-02-13 21:11:54 +08:00
using System ;
2023-06-12 21:59:27 +08:00
using System.Linq ;
2023-06-01 19:13:04 +08:00
using System.Collections ;
using System.Collections.Generic ;
2023-05-28 06:29:04 +08:00
using System.Diagnostics ;
2023-02-13 21:11:54 +08:00
using System.Runtime.CompilerServices ;
2023-03-30 20:47:39 +08:00
using System.Runtime.InteropServices ;
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
using static DCFApixels . DragonECS . EcsThrowHalper ;
2023-05-07 00:50:02 +08:00
#endif
2023-05-26 04:25:09 +08:00
namespace DCFApixels.DragonECS
{
2023-03-30 20:47:39 +08:00
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
2023-05-28 06:29:04 +08:00
[DebuggerTypeProxy(typeof(DebuggerProxy))]
2023-03-30 20:47:39 +08:00
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-24 00:19:07 +08:00
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-05-07 00:50:02 +08:00
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 ;
}
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)]
2023-05-26 00:24:38 +08:00
get = > _source . IsReleased ;
2023-04-15 00:23:46 +08:00
}
2023-05-07 00:50:02 +08:00
public int this [ int index ]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get = > _source [ index ] ;
}
2023-04-01 22:29:34 +08:00
#endregion
#region Methods
2023-03-30 20:47:39 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-07 00:50:02 +08:00
public bool Has ( int entityID ) = > _source . Has ( entityID ) ;
2023-03-30 20:47:39 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-06-01 19:13:04 +08:00
public int IndexOf ( int entityID ) = > _source . IndexOf ( entityID ) ;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-03-30 20:47:39 +08:00
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-06-01 19:13:04 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int [ ] Bake ( ) = > _source . Bake ( ) ;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Bake ( ref int [ ] entities ) = > _source . Bake ( ref entities ) ;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Bake ( List < int > entities ) = > _source . Bake ( entities ) ;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-06-05 00:23:18 +08:00
public ReadOnlySpan < int > ToSpan ( ) = > _source . ToSpan ( ) ;
public ReadOnlySpan < int > ToSpan ( int start , int length ) = > _source . ToSpan ( start , length ) ;
2023-06-01 19:13:04 +08:00
2023-05-07 00:50:02 +08:00
[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-06-01 19:13:04 +08:00
public unsafe class EcsGroup : IDisposable , IEquatable < EcsGroup > , IEnumerable < int >
2023-02-13 21:11:54 +08:00
{
2023-04-20 20:03:26 +08:00
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
2023-02-13 21:11:54 +08:00
#region Properties
2023-04-20 20:03:26 +08:00
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 ;
}
2023-03-30 20:47:39 +08:00
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
}
2023-05-07 00:50:02 +08:00
public int this [ int index ]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( index < 0 | | index > = Count ) Throw . ArgumentOutOfRange ( ) ;
2023-05-07 00:50:02 +08:00
#endif
2023-06-12 12:49:41 +08:00
return _dense [ + + index ] ;
2023-05-07 00:50:02 +08:00
}
}
2023-02-13 21:11:54 +08:00
#endregion
2023-06-10 00:55:00 +08:00
#region Constrcutors / Dispose
2023-04-17 22:58:52 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-20 20:03:26 +08:00
public static EcsGroup New ( EcsWorld world )
2023-04-01 20:45:37 +08:00
{
2023-06-01 20:14:34 +08:00
return world . GetFreeGroup ( ) ;
2023-04-08 21:29:18 +08:00
}
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 ;
2023-02-13 21:11:54 +08:00
}
2023-06-10 00:55:00 +08:00
public void Dispose ( ) = > _source . ReleaseGroup ( this ) ;
2023-02-13 21:11:54 +08:00
#endregion
2023-06-01 19:13:04 +08:00
#region Has / IndexOf
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
}
[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-24 16:48:18 +08:00
if ( Has ( 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-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( Has ( entityID ) ) Throw . Group_AlreadyContains ( entityID ) ;
2023-05-07 00:50:02 +08:00
#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-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
{
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)]
2023-04-01 22:18:40 +08:00
internal void RemoveInternal ( int entityID )
2023-02-13 21:11:54 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( ! Has ( entityID ) ) Throw . Group_DoesNotContain ( entityID ) ;
2023-05-07 00:50:02 +08:00
#endif
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-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
}
}
2023-02-13 21:11:54 +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
2023-06-01 19:13:04 +08:00
#region CopyFrom / Clone / Bake / ToSpan
2023-04-15 00:23:46 +08:00
[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
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_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-06-01 20:14:34 +08:00
EcsGroup result = _source . GetFreeGroup ( ) ;
2023-04-15 00:23:46 +08:00
result . CopyFrom ( this ) ;
return result ;
2023-04-08 23:01:10 +08:00
}
2023-06-01 19:13:04 +08:00
public int [ ] Bake ( )
{
int [ ] result = new int [ _count ] ;
2023-06-12 00:59:22 +08:00
Array . Copy ( _dense , 1 , result , 0 , _count ) ;
2023-06-01 19:13:04 +08:00
return result ;
}
public int Bake ( ref int [ ] entities )
{
2023-06-22 14:39:12 +08:00
if ( entities . Length < _count )
2023-06-01 19:13:04 +08:00
entities = new int [ _count ] ;
2023-06-12 00:59:22 +08:00
Array . Copy ( _dense , 1 , entities , 0 , _count ) ;
2023-06-01 19:13:04 +08:00
return _count ;
}
public void Bake ( List < int > entities )
{
entities . Clear ( ) ;
foreach ( var e in this )
entities . Add ( e ) ;
}
2023-06-05 00:23:18 +08:00
public ReadOnlySpan < int > ToSpan ( ) = > new ReadOnlySpan < int > ( _dense , 0 , _count ) ;
public ReadOnlySpan < int > ToSpan ( int start , int length )
2023-06-01 19:13:04 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( start + length > _count ) Throw . ArgumentOutOfRange ( ) ;
2023-06-01 19:13:04 +08:00
#endif
2023-06-05 00:23:18 +08:00
return new ReadOnlySpan < int > ( _dense , start , length ) ;
2023-06-01 19:13:04 +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
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( _source ! = group . World ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
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
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( _source ! = group . World ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
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)]
2023-06-05 00:23:18 +08:00
public void IntersectWith ( EcsReadonlyGroup group ) = > IntersectWith ( group . GetGroupInternal ( ) ) ;
2023-04-09 02:52:39 +08:00
/// <summary>as Intersect sets</summary>
2023-06-05 00:23:18 +08:00
public void IntersectWith ( EcsGroup group )
2023-04-09 02:52:39 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( World ! = group . World ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
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)]
2023-06-05 00:23:18 +08:00
public void SymmetricExceptWith ( EcsReadonlyGroup group ) = > SymmetricExceptWith ( group . GetGroupInternal ( ) ) ;
2023-04-09 02:52:39 +08:00
/// <summary>as Symmetric Except sets</summary>
2023-06-05 00:23:18 +08:00
public void SymmetricExceptWith ( EcsGroup group )
2023-04-09 02:52:39 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( _source ! = group . World ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
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-06-01 20:14:34 +08:00
public void Inverse ( )
{
foreach ( var item in _source . Entities )
if ( Has ( item ) )
RemoveInternal ( item ) ;
else
AddInternal ( item ) ;
}
2023-02-14 03:26:34 +08:00
#endregion
2023-04-10 22:22:17 +08:00
#region Static Set operations
2023-06-01 19:13:04 +08:00
/// <summary>as Intersect sets</summary>
/// <returns>new group from pool</returns>
public static EcsGroup Union ( EcsGroup a , EcsGroup b )
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( a . _source ! = b . _source ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
2023-06-01 19:13:04 +08:00
#endif
2023-06-01 20:14:34 +08:00
EcsGroup result = a . _source . GetFreeGroup ( ) ;
2023-06-01 19:13:04 +08:00
foreach ( var item in a )
result . AddInternal ( item ) ;
foreach ( var item in b )
result . Add ( item ) ;
return result ;
}
2023-04-10 22:22:17 +08:00
/// <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
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( a . _source ! = b . _source ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
2023-04-10 22:22:17 +08:00
#endif
2023-06-01 20:14:34 +08:00
EcsGroup result = a . _source . GetFreeGroup ( ) ;
2023-04-10 22:22:17 +08:00
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-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>
2023-06-05 00:23:18 +08:00
public static EcsGroup Intersect ( EcsGroup a , EcsGroup b )
2023-04-10 22:22:17 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( a . _source ! = b . _source ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
2023-04-10 22:22:17 +08:00
#endif
2023-06-01 20:14:34 +08:00
EcsGroup result = a . _source . GetFreeGroup ( ) ;
2023-04-10 22:22:17 +08:00
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-15 00:23:46 +08:00
return result ;
}
2023-06-01 19:13:04 +08:00
/// <summary>as Symmetric Except sets</summary>
2023-04-15 00:23:46 +08:00
/// <returns>new group from pool</returns>
2023-06-05 00:23:18 +08:00
public static EcsGroup SymmetricExcept ( EcsGroup a , EcsGroup b )
2023-04-15 00:23:46 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2023-06-26 01:57:50 +08:00
if ( a . _source ! = b . _source ) Throw . Group_ArgumentDifferentWorldsException ( ) ;
2023-04-15 00:23:46 +08:00
#endif
2023-06-01 20:14:34 +08:00
EcsGroup result = a . _source . GetFreeGroup ( ) ;
2023-04-15 00:23:46 +08:00
foreach ( var item in a )
2023-06-01 19:13:04 +08:00
if ( ! b . Has ( item ) )
result . AddInternal ( item ) ;
foreach ( var item in b )
if ( ! a . Has ( item ) )
result . AddInternal ( item ) ;
2023-04-15 00:23:46 +08:00
return result ;
2023-04-10 22:22:17 +08:00
}
2023-06-01 20:14:34 +08:00
public static EcsGroup Inverse ( EcsGroup a )
{
EcsGroup result = a . _source . GetFreeGroup ( ) ;
foreach ( var item in a . _source . Entities )
if ( ! a . Has ( item ) )
result . AddInternal ( item ) ;
return result ;
}
2023-04-10 22:22:17 +08:00
#endregion
2023-06-01 19:13:04 +08:00
#region Enumerator
2023-03-30 10:46:57 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-02-13 21:11:54 +08:00
public Enumerator GetEnumerator ( )
{
return new Enumerator ( this ) ;
}
2023-06-01 19:13:04 +08:00
IEnumerator IEnumerable . GetEnumerator ( )
{
for ( int i = 0 ; i < _count ; i + + )
yield return _dense [ i ] ;
}
IEnumerator < int > IEnumerable < int > . GetEnumerator ( )
{
for ( int i = 0 ; i < _count ; i + + )
yield return _dense [ i ] ;
}
public ref struct Enumerator
2023-02-13 21:11:54 +08:00
{
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-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-02-13 21:11:54 +08:00
}
2023-04-23 15:57:35 +08:00
public int Current
2023-02-13 21:11:54 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-23 15:57:35 +08:00
get = > _dense [ _index ] ;
2023-02-13 21:11:54 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-30 18:30:10 +08:00
public bool MoveNext ( ) = > + + _index < = _count & & _count < _dense . Length ; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны
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-06-12 21:59:27 +08:00
public override string ToString ( ) = > string . Join ( ", " , _dense . Cast < string > ( ) , 0 , _count ) ;
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 )
{
2023-06-01 19:13:04 +08:00
if ( other is null | | other . Count ! = Count )
2023-04-26 16:45:37 +08:00
return false ;
2023-06-01 19:13:04 +08:00
foreach ( var e in other )
if ( ! Has ( e ) )
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
2023-05-07 00:50:02 +08:00
#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
2023-04-26 16:45:37 +08:00
private static bool StaticEquals ( EcsGroup a , EcsReadonlyGroup b ) = > StaticEquals ( a , b . GetGroupInternal ( ) ) ;
private static bool StaticEquals ( EcsGroup a , EcsGroup b )
{
2023-06-01 19:13:04 +08:00
if ( a is null ) return false ;
2023-04-26 16:45:37 +08:00
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
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 ;
2023-06-01 20:14:34 +08:00
public override string ToString ( ) = > _group . ToString ( ) ;
2023-05-28 06:29:04 +08:00
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
}