2024-04-30 16:09:57 +08:00
using DCFApixels.DragonECS.PoolsCore ;
2023-04-21 03:16:05 +08:00
using System ;
2023-05-07 00:50:02 +08:00
using System.Collections ;
using System.Collections.Generic ;
2023-04-21 03:16:05 +08:00
using System.Runtime.CompilerServices ;
2024-08-14 21:23:34 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG )
using System.Reflection ;
#endif
2024-05-01 16:32:03 +08:00
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices ;
#endif
2023-04-21 03:16:05 +08:00
namespace DCFApixels.DragonECS
{
2024-06-13 18:04:18 +08:00
/// <summary> Component without data. </summary>
[MetaColor(MetaColor.DragonRose)]
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.POOLS_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, "Tag component or component without data.")]
2024-10-12 00:08:12 +08:00
[MetaID("8D3E547C92013C6A2C2DFC8D2F1FA297")]
2024-06-05 14:39:19 +08:00
public interface IEcsTagComponent : IEcsMember { }
2024-05-01 14:29:01 +08:00
2024-06-13 18:04:18 +08:00
/// <summary> Pool for IEcsTagComponent components. </summary>
2024-04-28 19:43:10 +08:00
#if ENABLE_IL2CPP
[Il2CppSetOption (Option.NullChecks, false)]
#endif
2024-05-01 14:29:01 +08:00
[MetaColor(MetaColor.DragonRose)]
2024-06-13 18:04:18 +08:00
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.POOLS_GROUP)]
2024-06-11 02:30:00 +08:00
[MetaDescription(EcsConsts.AUTHOR, "Pool for IEcsTagComponent components. EcsTagPool is optimized for storing tag components or components without data.")]
2024-10-12 00:08:12 +08:00
[MetaID("9D80547C9201E852E4F17324EAC1E15A")]
2023-06-25 23:13:51 +08:00
public sealed class EcsTagPool < T > : IEcsPoolImplementation < T > , IEcsStructPool < T > , IEnumerable < T > //IEnumerable<T> - IntelliSense hack
2023-04-21 14:21:24 +08:00
where T : struct , IEcsTagComponent
2023-04-21 03:16:05 +08:00
{
2023-05-07 00:50:02 +08:00
private EcsWorld _source ;
2023-12-06 18:58:06 +08:00
private int _componentTypeID ;
2024-01-07 18:52:54 +08:00
private EcsMaskChunck _maskBit ;
2023-05-07 00:50:02 +08:00
2023-04-21 14:21:24 +08:00
private bool [ ] _mapping ; // index = entityID / value = itemIndex;/ value = 0 = no entityID
2024-03-07 06:46:44 +08:00
private int _count = 0 ;
2023-04-21 03:16:05 +08:00
2024-05-01 16:58:54 +08:00
#if ! DISABLE_POOLS_EVENTS
2023-06-25 23:13:51 +08:00
private List < IEcsPoolEventListener > _listeners = new List < IEcsPoolEventListener > ( ) ;
2024-04-27 19:05:05 +08:00
private int _listenersCachedCount = 0 ;
2024-05-01 16:58:54 +08:00
#endif
2024-11-04 07:36:42 +08:00
private bool _isLocked ;
2023-04-21 03:16:05 +08:00
2023-05-07 00:50:02 +08:00
private T _fakeComponent ;
2023-12-06 18:58:06 +08:00
private EcsWorld . PoolsMediator _mediator ;
2023-05-07 00:50:02 +08:00
2024-02-23 18:34:40 +08:00
#region CheckValide
2024-08-14 21:23:34 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG )
2023-11-15 17:47:11 +08:00
private static bool _isInvalidType ;
static EcsTagPool ( )
{
2024-02-23 18:34:40 +08:00
#pragma warning disable IL2090 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The generic parameter of the source method or type does not have matching annotations.
2023-11-15 17:47:11 +08:00
_isInvalidType = typeof ( T ) . GetFields ( BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic ) . Length > 0 ;
2024-02-23 18:34:40 +08:00
#pragma warning restore IL2090
2023-11-15 17:47:11 +08:00
}
public EcsTagPool ( )
{
if ( _isInvalidType )
2024-02-24 02:26:42 +08:00
{
2023-11-15 17:47:11 +08:00
throw new EcsFrameworkException ( $"{typeof(T).Name} type must not contain any data." ) ;
2024-02-24 02:26:42 +08:00
}
2023-11-15 17:47:11 +08:00
}
2024-02-23 18:34:40 +08:00
#endif
2024-05-13 19:29:36 +08:00
#endregion
2023-11-15 17:47:11 +08:00
2023-04-21 03:16:05 +08:00
#region Properites
2024-02-24 02:26:42 +08:00
public int Count
{
get { return _count ; }
}
2024-02-25 00:55:30 +08:00
public int ComponentTypeID
2024-02-24 02:26:42 +08:00
{
get { return _componentTypeID ; }
}
public Type ComponentType
{
get { return typeof ( T ) ; }
}
public EcsWorld World
{
get { return _source ; }
}
2024-02-25 17:27:08 +08:00
public bool IsReadOnly
2024-02-25 00:55:30 +08:00
{
get { return false ; }
}
2023-04-21 03:16:05 +08:00
#endregion
2023-05-07 00:50:02 +08:00
#region Method
2023-04-21 03:16:05 +08:00
public void Add ( int entityID )
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( Has ( entityID ) ) { EcsPoolThrowHelper . ThrowAlreadyHasComponent < T > ( entityID ) ; }
if ( _isLocked ) { EcsPoolThrowHelper . ThrowPoolLocked ( ) ; }
2023-05-07 00:50:02 +08:00
#endif
_count + + ;
_mapping [ entityID ] = true ;
2023-12-06 18:58:06 +08:00
_mediator . RegisterComponent ( entityID , _componentTypeID , _maskBit ) ;
2024-05-01 16:58:54 +08:00
#if ! DISABLE_POOLS_EVENTS
2024-04-27 19:05:05 +08:00
_listeners . InvokeOnAdd ( entityID , _listenersCachedCount ) ;
2024-05-01 16:58:54 +08:00
#endif
2023-05-07 00:50:02 +08:00
}
public void TryAdd ( int entityID )
{
2024-02-24 02:26:42 +08:00
if ( Has ( entityID ) = = false )
2023-04-21 03:16:05 +08:00
{
2024-02-24 02:26:42 +08:00
Add ( entityID ) ;
2023-04-21 03:16:05 +08:00
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-07 00:50:02 +08:00
public bool Has ( int entityID )
2023-04-21 03:16:05 +08:00
{
2023-04-21 14:21:24 +08:00
return _mapping [ entityID ] ;
2023-04-21 03:16:05 +08:00
}
public void Del ( int entityID )
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( ! Has ( entityID ) ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( entityID ) ; }
if ( _isLocked ) { EcsPoolThrowHelper . ThrowPoolLocked ( ) ; }
2023-05-07 00:50:02 +08:00
#endif
2023-04-21 14:21:24 +08:00
_mapping [ entityID ] = false ;
2023-04-21 03:16:05 +08:00
_count - - ;
2023-12-06 18:58:06 +08:00
_mediator . UnregisterComponent ( entityID , _componentTypeID , _maskBit ) ;
2024-05-01 16:58:54 +08:00
#if ! DISABLE_POOLS_EVENTS
2024-04-27 19:05:05 +08:00
_listeners . InvokeOnDel ( entityID , _listenersCachedCount ) ;
2024-05-01 16:58:54 +08:00
#endif
2023-05-07 00:50:02 +08:00
}
2024-04-28 18:36:24 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-07 00:50:02 +08:00
public void TryDel ( int entityID )
{
2024-02-24 02:26:42 +08:00
if ( Has ( entityID ) )
{
Del ( entityID ) ;
}
2023-05-07 00:50:02 +08:00
}
public void Copy ( int fromEntityID , int toEntityID )
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( ! Has ( fromEntityID ) ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( fromEntityID ) ; }
2023-05-07 00:50:02 +08:00
#endif
TryAdd ( toEntityID ) ;
}
2023-05-23 01:47:28 +08:00
public void Copy ( int fromEntityID , EcsWorld toWorld , int toEntityID )
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( ! Has ( fromEntityID ) ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( fromEntityID ) ; }
2023-05-23 01:47:28 +08:00
#endif
toWorld . GetPool < T > ( ) . TryAdd ( toEntityID ) ;
}
2023-05-07 00:50:02 +08:00
public void Set ( int entityID , bool isHas )
{
2024-04-28 18:36:24 +08:00
if ( isHas ! = Has ( entityID ) )
2023-05-07 00:50:02 +08:00
{
2024-04-28 18:36:24 +08:00
if ( isHas )
2024-02-24 02:26:42 +08:00
{
2023-05-07 00:50:02 +08:00
Add ( entityID ) ;
2024-02-24 02:26:42 +08:00
}
2024-04-28 18:36:24 +08:00
else
2024-02-24 02:26:42 +08:00
{
2023-05-07 00:50:02 +08:00
Del ( entityID ) ;
2024-02-24 02:26:42 +08:00
}
2023-05-07 00:50:02 +08:00
}
2023-04-21 03:16:05 +08:00
}
2023-05-23 01:47:28 +08:00
public void Toggle ( int entityID )
{
if ( Has ( entityID ) )
2024-02-24 02:26:42 +08:00
{
2023-05-23 01:47:28 +08:00
Del ( entityID ) ;
2024-02-24 02:26:42 +08:00
}
2023-05-23 01:47:28 +08:00
else
2024-02-24 02:26:42 +08:00
{
2023-05-23 01:47:28 +08:00
Add ( entityID ) ;
2024-02-24 02:26:42 +08:00
}
2023-05-23 01:47:28 +08:00
}
2024-03-13 17:41:33 +08:00
public void ClearAll ( )
{
2024-11-04 07:36:42 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( _isLocked ) { EcsPoolThrowHelper . ThrowPoolLocked ( ) ; }
2024-11-04 07:36:42 +08:00
#endif
2024-03-13 17:41:33 +08:00
var span = _source . Where ( out SingleAspect < EcsTagPool < T > > _ ) ;
_count = 0 ;
foreach ( var entityID in span )
{
_mapping [ entityID ] = false ;
_mediator . UnregisterComponent ( entityID , _componentTypeID , _maskBit ) ;
2024-05-01 16:58:54 +08:00
#if ! DISABLE_POOLS_EVENTS
2024-04-27 19:05:05 +08:00
_listeners . InvokeOnDel ( entityID , _listenersCachedCount ) ;
2024-05-01 16:58:54 +08:00
#endif
2024-03-13 17:41:33 +08:00
}
}
2023-04-21 03:16:05 +08:00
#endregion
2023-05-07 00:50:02 +08:00
#region Callbacks
2023-12-06 18:58:06 +08:00
void IEcsPoolImplementation . OnInit ( EcsWorld world , EcsWorld . PoolsMediator mediator , int componentTypeID )
2023-11-08 15:15:10 +08:00
{
_source = world ;
2023-12-06 18:58:06 +08:00
_mediator = mediator ;
_componentTypeID = componentTypeID ;
2024-01-07 18:52:54 +08:00
_maskBit = EcsMaskChunck . FromID ( componentTypeID ) ;
2023-11-08 15:15:10 +08:00
_mapping = new bool [ world . Capacity ] ;
}
2023-05-07 00:50:02 +08:00
void IEcsPoolImplementation . OnWorldResize ( int newSize )
2023-04-21 03:16:05 +08:00
{
Array . Resize ( ref _mapping , newSize ) ;
}
2023-05-07 00:50:02 +08:00
void IEcsPoolImplementation . OnWorldDestroy ( ) { }
void IEcsPoolImplementation . OnReleaseDelEntityBuffer ( ReadOnlySpan < int > buffer )
{
2024-02-25 23:05:11 +08:00
if ( _count < = 0 )
{
return ;
}
2023-05-07 00:50:02 +08:00
foreach ( var entityID in buffer )
2024-02-24 02:26:42 +08:00
{
2023-05-07 00:50:02 +08:00
TryDel ( entityID ) ;
2024-02-24 02:26:42 +08:00
}
2023-05-07 00:50:02 +08:00
}
2024-11-04 07:36:42 +08:00
void IEcsPoolImplementation . OnLockedChanged_Debug ( bool locked ) { _isLocked = locked ; }
2023-05-07 00:50:02 +08:00
#endregion
#region Other
2024-02-24 02:26:42 +08:00
void IEcsPool . AddRaw ( int entityID , object dataRaw ) { Add ( entityID ) ; }
2024-02-25 00:55:30 +08:00
object IEcsReadonlyPool . GetRaw ( int entityID )
2023-05-07 00:50:02 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( Has ( entityID ) = = false ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( entityID ) ; }
2023-05-07 00:50:02 +08:00
#endif
2024-02-24 02:26:42 +08:00
return _fakeComponent ;
2023-05-07 00:50:02 +08:00
}
2024-02-24 02:26:42 +08:00
void IEcsPool . SetRaw ( int entityID , object dataRaw )
2023-05-07 00:50:02 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( Has ( entityID ) = = false ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( entityID ) ; }
2023-05-07 00:50:02 +08:00
#endif
2024-02-24 02:26:42 +08:00
}
ref T IEcsStructPool < T > . Add ( int entityID )
{
Add ( entityID ) ;
2023-05-07 00:50:02 +08:00
return ref _fakeComponent ;
}
2024-02-24 02:26:42 +08:00
ref readonly T IEcsStructPool < T > . Read ( int entityID )
2023-05-07 00:50:02 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( Has ( entityID ) = = false ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( entityID ) ; }
2023-05-07 00:50:02 +08:00
#endif
2024-02-24 02:26:42 +08:00
return ref _fakeComponent ;
2023-05-07 00:50:02 +08:00
}
2024-02-24 02:26:42 +08:00
ref T IEcsStructPool < T > . Get ( int entityID )
2023-05-07 00:50:02 +08:00
{
2023-06-02 01:20:46 +08:00
#if ( DEBUG & & ! DISABLE_DEBUG ) | | ENABLE_DRAGONECS_ASSERT_CHEKS
2024-11-05 15:56:46 +08:00
if ( Has ( entityID ) = = false ) { EcsPoolThrowHelper . ThrowNotHaveComponent < T > ( entityID ) ; }
2023-05-07 00:50:02 +08:00
#endif
2024-02-24 02:26:42 +08:00
return ref _fakeComponent ;
2023-05-07 00:50:02 +08:00
}
#endregion
2023-05-23 15:58:31 +08:00
#region Listeners
2024-05-01 16:58:54 +08:00
#if ! DISABLE_POOLS_EVENTS
2023-05-23 15:58:31 +08:00
public void AddListener ( IEcsPoolEventListener listener )
{
2024-11-05 15:56:46 +08:00
if ( listener = = null ) { EcsPoolThrowHelper . ThrowNullListener ( ) ; }
2023-05-23 15:58:31 +08:00
_listeners . Add ( listener ) ;
2024-04-27 19:05:05 +08:00
_listenersCachedCount + + ;
2023-05-23 15:58:31 +08:00
}
public void RemoveListener ( IEcsPoolEventListener listener )
{
2024-11-05 15:56:46 +08:00
if ( listener = = null ) { EcsPoolThrowHelper . ThrowNullListener ( ) ; }
2024-04-27 19:05:05 +08:00
if ( _listeners . Remove ( listener ) )
{
_listenersCachedCount - - ;
}
2023-05-23 15:58:31 +08:00
}
2024-05-01 16:58:54 +08:00
#endif
2023-05-23 15:58:31 +08:00
#endregion
2023-05-07 00:50:02 +08:00
#region IEnumerator - IntelliSense hack
2024-09-07 17:18:35 +08:00
IEnumerator < T > IEnumerable < T > . GetEnumerator ( ) { throw new NotImplementedException ( ) ; }
IEnumerator IEnumerable . GetEnumerator ( ) { throw new NotImplementedException ( ) ; }
2023-04-21 03:16:05 +08:00
#endregion
2024-03-08 20:40:19 +08:00
#region MarkersConverter
public static implicit operator EcsTagPool < T > ( IncludeMarker a ) { return a . GetInstance < EcsTagPool < T > > ( ) ; }
public static implicit operator EcsTagPool < T > ( ExcludeMarker a ) { return a . GetInstance < EcsTagPool < T > > ( ) ; }
public static implicit operator EcsTagPool < T > ( OptionalMarker a ) { return a . GetInstance < EcsTagPool < T > > ( ) ; }
#endregion
2023-04-21 03:16:05 +08:00
}
2023-04-21 03:46:51 +08:00
public static class EcsTagPoolExt
2023-04-21 03:16:05 +08:00
{
2023-07-03 02:50:16 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-21 16:03:50 +08:00
public static EcsTagPool < TTagComponent > GetPool < TTagComponent > ( this EcsWorld self ) where TTagComponent : struct , IEcsTagComponent
2023-04-21 03:16:05 +08:00
{
2024-03-07 03:30:18 +08:00
return self . GetPoolInstance < EcsTagPool < TTagComponent > > ( ) ;
2023-04-21 16:03:50 +08:00
}
2023-07-03 02:50:16 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-11-21 10:41:41 +08:00
public static EcsTagPool < TTagComponent > GetPoolUnchecked < TTagComponent > ( this EcsWorld self ) where TTagComponent : struct , IEcsTagComponent
2023-07-03 02:50:16 +08:00
{
2024-03-07 03:30:18 +08:00
return self . GetPoolInstanceUnchecked < EcsTagPool < TTagComponent > > ( ) ;
2023-07-03 02:50:16 +08:00
}
2023-04-21 16:03:50 +08:00
2023-07-03 02:50:16 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-11 01:28:18 +08:00
public static EcsTagPool < TTagComponent > Include < TTagComponent > ( this EcsAspect . Builder self ) where TTagComponent : struct , IEcsTagComponent
2023-04-21 16:03:50 +08:00
{
2024-03-07 03:40:06 +08:00
return self . IncludePool < EcsTagPool < TTagComponent > > ( ) ;
2023-04-21 16:03:50 +08:00
}
2023-07-03 02:50:16 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-11 01:28:18 +08:00
public static EcsTagPool < TTagComponent > Exclude < TTagComponent > ( this EcsAspect . Builder self ) where TTagComponent : struct , IEcsTagComponent
2023-04-21 16:03:50 +08:00
{
2024-03-07 03:40:06 +08:00
return self . ExcludePool < EcsTagPool < TTagComponent > > ( ) ;
2023-04-21 16:03:50 +08:00
}
2023-07-03 02:50:16 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-11 01:28:18 +08:00
public static EcsTagPool < TTagComponent > Optional < TTagComponent > ( this EcsAspect . Builder self ) where TTagComponent : struct , IEcsTagComponent
2023-04-21 16:03:50 +08:00
{
2024-03-07 03:40:06 +08:00
return self . OptionalPool < EcsTagPool < TTagComponent > > ( ) ;
2023-04-21 16:03:50 +08:00
}
2023-11-21 10:41:41 +08:00
//---------------------------------------------------
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsTagPool < TTagComponent > GetTagPool < TTagComponent > ( this EcsWorld self ) where TTagComponent : struct , IEcsTagComponent
{
2024-03-07 03:30:18 +08:00
return self . GetPoolInstance < EcsTagPool < TTagComponent > > ( ) ;
2023-11-21 10:41:41 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EcsTagPool < TTagComponent > GetTagPoolUnchecked < TTagComponent > ( this EcsWorld self ) where TTagComponent : struct , IEcsTagComponent
{
2024-03-07 03:30:18 +08:00
return self . GetPoolInstanceUnchecked < EcsTagPool < TTagComponent > > ( ) ;
2023-11-21 10:41:41 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-11 01:28:18 +08:00
public static EcsTagPool < TTagComponent > IncludeTag < TTagComponent > ( this EcsAspect . Builder self ) where TTagComponent : struct , IEcsTagComponent
2023-11-21 10:41:41 +08:00
{
2024-03-07 03:40:06 +08:00
return self . IncludePool < EcsTagPool < TTagComponent > > ( ) ;
2023-11-21 10:41:41 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-11 01:28:18 +08:00
public static EcsTagPool < TTagComponent > ExcludeTag < TTagComponent > ( this EcsAspect . Builder self ) where TTagComponent : struct , IEcsTagComponent
2023-11-21 10:41:41 +08:00
{
2024-03-07 03:40:06 +08:00
return self . ExcludePool < EcsTagPool < TTagComponent > > ( ) ;
2023-11-21 10:41:41 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-11 01:28:18 +08:00
public static EcsTagPool < TTagComponent > OptionalTag < TTagComponent > ( this EcsAspect . Builder self ) where TTagComponent : struct , IEcsTagComponent
2023-11-21 10:41:41 +08:00
{
2024-03-07 03:40:06 +08:00
return self . OptionalPool < EcsTagPool < TTagComponent > > ( ) ;
2023-11-21 10:41:41 +08:00
}
2023-04-21 03:16:05 +08:00
}
}