2023-05-23 01:47:28 +08:00
using DCFApixels.DragonECS.Internal ;
using System ;
2023-05-23 15:58:31 +08:00
using System.Collections.Generic ;
2023-04-26 16:45:37 +08:00
using System.Runtime.CompilerServices ;
namespace DCFApixels.DragonECS
{
2023-05-07 00:50:02 +08:00
public interface IEcsPool
2023-04-26 16:45:37 +08:00
{
2023-05-07 00:50:02 +08:00
#region Properties
2023-06-12 20:46:51 +08:00
int ComponentID { get ; }
Type ComponentType { get ; }
EcsWorld World { get ; }
int Count { get ; }
2024-02-24 02:26:42 +08:00
int Capacity { get ; } //TODO удалить. не во всех реализация нужен, проще привести к типу
2023-05-07 00:50:02 +08:00
#endregion
#region Methods
bool Has ( int entityID ) ;
void Del ( int entityID ) ;
void AddRaw ( int entityID , object dataRaw ) ;
object GetRaw ( int entityID ) ;
void SetRaw ( int entityID , object dataRaw ) ;
void Copy ( int fromEntityID , int toEntityID ) ;
2023-05-23 01:47:28 +08:00
void Copy ( int fromEntityID , EcsWorld toWorld , int toEntityID ) ;
2023-05-07 00:50:02 +08:00
#endregion
2023-05-23 15:58:31 +08:00
#region Add / Remove Listeners
void AddListener ( IEcsPoolEventListener listener ) ;
void RemoveListener ( IEcsPoolEventListener listener ) ;
#endregion
}
2024-02-24 02:26:42 +08:00
/// <summary>A pool for struct components.</summary>
public interface IEcsStructPool < T > : IEcsPool where T : struct
2023-05-07 00:50:02 +08:00
{
ref T Add ( int entityID ) ;
ref readonly T Read ( int entityID ) ;
2023-05-30 16:01:16 +08:00
ref T Get ( int entityID ) ;
2023-05-07 00:50:02 +08:00
}
2024-02-24 02:26:42 +08:00
/// <summary>A pool for reference components of type T that instantiates components itself.</summary>
public interface IEcsClassPool < T > : IEcsPool where T : class
2023-06-25 23:13:51 +08:00
{
T Add ( int entityID ) ;
T Get ( int entityID ) ;
}
2024-02-24 02:26:42 +08:00
/// <summary>A pool for reference components of type T, which does not instantiate components itself but receives components from external sources..</summary>
public interface IEcsHybridPool < T > : IEcsPool where T : class
2023-06-29 23:53:26 +08:00
{
void Add ( int entityID , T component ) ;
T Get ( int entityID ) ;
}
2023-05-07 00:50:02 +08:00
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
public interface IEcsPoolImplementation : IEcsPool
{
2023-12-06 18:58:06 +08:00
void OnInit ( EcsWorld world , EcsWorld . PoolsMediator mediator , int componentTypeID ) ;
2024-02-24 03:02:41 +08:00
void OnDevirtualize ( EcsVirtualPool . Data data ) ;
2023-05-07 00:50:02 +08:00
void OnWorldResize ( int newSize ) ;
void OnReleaseDelEntityBuffer ( ReadOnlySpan < int > buffer ) ;
void OnWorldDestroy ( ) ;
}
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
/// <typeparam name="T">Component type</typeparam>
2023-06-20 23:34:51 +08:00
public interface IEcsPoolImplementation < T > : IEcsPoolImplementation { }
2023-05-23 15:58:31 +08:00
2023-05-07 00:50:02 +08:00
public static class EcsPoolThrowHalper
{
public static void ThrowAlreadyHasComponent < T > ( int entityID )
2023-04-26 16:45:37 +08:00
{
2023-06-26 02:53:55 +08:00
throw new EcsFrameworkException ( $"Entity({entityID}) already has component {EcsDebugUtility.GetGenericTypeName<T>()}." ) ;
2023-04-26 16:45:37 +08:00
}
2023-05-07 00:50:02 +08:00
public static void ThrowNotHaveComponent < T > ( int entityID )
{
2023-06-26 02:53:55 +08:00
throw new EcsFrameworkException ( $"Entity({entityID}) has no component {EcsDebugUtility.GetGenericTypeName<T>()}." ) ;
2023-05-07 00:50:02 +08:00
}
2024-02-24 02:26:42 +08:00
public static void ThrowAlreadyHasComponent ( Type type , int entityID )
{
throw new EcsFrameworkException ( $"Entity({entityID}) already has component {EcsDebugUtility.GetGenericTypeName(type)}." ) ;
}
public static void ThrowNotHaveComponent ( Type type , int entityID )
{
throw new EcsFrameworkException ( $"Entity({entityID}) has no component {EcsDebugUtility.GetGenericTypeName(type)}." ) ;
}
2023-05-07 00:50:02 +08:00
}
public static class IEcsPoolImplementationExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNullOrDummy ( this IEcsPool self )
{
2023-05-23 01:47:28 +08:00
return self = = null | | self = = EcsNullPool . instance ;
2023-05-07 00:50:02 +08:00
}
}
2023-04-26 16:45:37 +08:00
2023-05-28 05:53:08 +08:00
#region Dummy EcsNullPool
2023-05-07 00:50:02 +08:00
namespace Internal
{
public struct NullComponent { }
public sealed class EcsNullPool : IEcsPoolImplementation < NullComponent >
{
2024-01-01 21:44:33 +08:00
public static readonly EcsNullPool instance = new EcsNullPool ( ) ;
2023-04-26 16:45:37 +08:00
2023-05-07 00:50:02 +08:00
#region Properties
2023-05-23 01:47:28 +08:00
int IEcsPool . ComponentID = > - 1 ;
2023-05-07 00:50:02 +08:00
Type IEcsPool . ComponentType = > typeof ( NullComponent ) ;
EcsWorld IEcsPool . World = > throw new NotImplementedException ( ) ;
2023-05-23 01:47:28 +08:00
public int Count = > - 1 ;
public int Capacity = > - 1 ;
2023-05-07 00:50:02 +08:00
#endregion
2023-04-26 16:45:37 +08:00
2023-05-07 00:50:02 +08:00
#region Methods
bool IEcsPool . Has ( int index ) = > false ;
void IEcsPool . Del ( int entityID ) = > throw new NotImplementedException ( ) ;
void IEcsPool . AddRaw ( int entityID , object dataRaw ) = > throw new NotImplementedException ( ) ;
object IEcsPool . GetRaw ( int entityID ) = > throw new NotImplementedException ( ) ;
void IEcsPool . SetRaw ( int entity , object dataRaw ) = > throw new NotImplementedException ( ) ;
void IEcsPool . Copy ( int fromEntityID , int toEntityID ) = > throw new NotImplementedException ( ) ;
2023-05-23 01:47:28 +08:00
void IEcsPool . Copy ( int fromEntityID , EcsWorld toWorld , int toEntityID ) = > throw new NotImplementedException ( ) ;
2024-02-24 03:02:41 +08:00
void IEcsPoolImplementation . OnDevirtualize ( EcsVirtualPool . Data virtualPoolData )
{
Throw . UndefinedException ( ) ;
}
2023-05-07 00:50:02 +08:00
#endregion
#region Callbacks
2023-12-06 18:58:06 +08:00
void IEcsPoolImplementation . OnInit ( EcsWorld world , EcsWorld . PoolsMediator mediator , int componentTypeID ) { }
2023-05-07 00:50:02 +08:00
void IEcsPoolImplementation . OnWorldDestroy ( ) { }
void IEcsPoolImplementation . OnWorldResize ( int newSize ) { }
void IEcsPoolImplementation . OnReleaseDelEntityBuffer ( ReadOnlySpan < int > buffer ) { }
#endregion
2023-05-23 15:58:31 +08:00
#region Listeners
2023-06-20 23:34:51 +08:00
void IEcsPool . AddListener ( IEcsPoolEventListener listener ) { }
void IEcsPool . RemoveListener ( IEcsPoolEventListener listener ) { }
2023-05-23 15:58:31 +08:00
#endregion
2023-05-07 00:50:02 +08:00
}
2023-04-26 16:45:37 +08:00
}
2023-05-07 00:50:02 +08:00
#endregion
2023-05-28 05:53:08 +08:00
#region Callbacks Interface
public interface IEcsPoolEventListener
{
2023-05-30 16:07:45 +08:00
/// <summary>Called after adding an entity to the pool, but before changing values</summary>
2023-05-28 05:53:08 +08:00
void OnAdd ( int entityID ) ;
2023-05-30 16:07:45 +08:00
/// <summary>Is called when EcsPool.Get or EcsPool.Add is called, but before changing values</summary>
2023-05-30 16:01:16 +08:00
void OnGet ( int entityID ) ;
2023-05-28 05:53:08 +08:00
/// <summary>Called after deleting an entity from the pool</summary>
void OnDel ( int entityID ) ;
}
2023-05-23 15:58:31 +08:00
public static class PoolEventListExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnAdd ( this List < IEcsPoolEventListener > self , int entityID )
{
for ( int i = 0 , iMax = self . Count ; i < iMax ; i + + ) self [ i ] . OnAdd ( entityID ) ;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-30 16:01:16 +08:00
public static void InvokeOnAddAndGet ( this List < IEcsPoolEventListener > self , int entityID )
2023-05-23 15:58:31 +08:00
{
for ( int i = 0 , iMax = self . Count ; i < iMax ; i + + )
{
self [ i ] . OnAdd ( entityID ) ;
2023-05-30 16:01:16 +08:00
self [ i ] . OnGet ( entityID ) ;
2023-05-23 15:58:31 +08:00
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-30 16:01:16 +08:00
public static void InvokeOnGet ( this List < IEcsPoolEventListener > self , int entityID )
2023-05-23 15:58:31 +08:00
{
2023-05-30 16:01:16 +08:00
for ( int i = 0 , iMax = self . Count ; i < iMax ; i + + ) self [ i ] . OnGet ( entityID ) ;
2023-05-23 15:58:31 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnDel ( this List < IEcsPoolEventListener > self , int entityID )
{
for ( int i = 0 , iMax = self . Count ; i < iMax ; i + + ) self [ i ] . OnDel ( entityID ) ;
}
}
#endregion
2023-04-26 16:45:37 +08:00
}