2023-02-08 17:57:06 +08:00
using System ;
2023-03-30 16:45:43 +08:00
using System.Runtime.CompilerServices ;
2023-04-01 20:45:37 +08:00
using Unity.Profiling ;
2023-02-05 19:59:45 +08:00
namespace DCFApixels.DragonECS
{
2023-04-21 03:16:05 +08:00
public abstract class EcsPoolBase
2023-04-21 01:05:06 +08:00
{
#region Properties
public abstract Type ComponentType { get ; }
public abstract EcsWorld World { get ; }
#endregion
#region Methods
public abstract bool Has ( int entityID ) ;
2023-04-21 03:16:05 +08:00
protected abstract void Init ( EcsWorld world ) ;
2023-04-21 01:05:06 +08:00
protected abstract void OnWorldResize ( int newSize ) ;
protected abstract void OnDestroy ( ) ;
#endregion
#region Internal
2023-04-21 03:16:05 +08:00
internal void InvokeInit ( EcsWorld world ) = > Init ( world ) ;
2023-04-21 01:05:06 +08:00
internal void InvokeOnWorldResize ( int newSize ) = > OnWorldResize ( newSize ) ;
internal void InvokeOnDestroy ( ) = > OnDestroy ( ) ;
#endregion
}
2023-04-06 23:40:47 +08:00
public struct NullComponent { }
2023-04-21 03:16:05 +08:00
public sealed class EcsNullPool : EcsPoolBase
2023-03-13 04:32:24 +08:00
{
2023-04-06 23:40:47 +08:00
public static EcsNullPool instance = > new EcsNullPool ( null ) ;
2023-04-20 20:03:26 +08:00
private EcsWorld _source ;
private EcsNullPool ( EcsWorld source ) = > _source = source ;
2023-04-17 22:58:52 +08:00
#region Properties
2023-04-21 01:05:06 +08:00
public sealed override Type ComponentType = > typeof ( NullComponent ) ;
public sealed override EcsWorld World = > _source ;
2023-04-17 22:58:52 +08:00
#endregion
#region Methods
2023-04-21 01:05:06 +08:00
public sealed override bool Has ( int index ) = > false ;
#endregion
2023-04-21 03:16:05 +08:00
#region Callbacks
protected override void Init ( EcsWorld world ) { }
2023-04-21 01:05:06 +08:00
protected override void OnWorldResize ( int newSize ) { }
protected override void OnDestroy ( ) { }
2023-04-17 22:58:52 +08:00
#endregion
2023-03-13 04:32:24 +08:00
}
2023-04-20 18:23:23 +08:00
2023-04-21 03:16:05 +08:00
public sealed class EcsPool < T > : EcsPoolBase
2023-04-21 14:21:24 +08:00
where T : struct , IEcsComponent
2023-02-05 19:59:45 +08:00
{
2023-04-21 03:16:05 +08:00
private EcsWorld _source ;
2023-04-01 20:45:37 +08:00
2023-04-20 11:23:54 +08:00
private int [ ] _mapping ; // index = entityID / value = itemIndex;/ value = 0 = no entityID
2023-04-01 20:45:37 +08:00
private T [ ] _items ; //dense
private int _itemsCount ;
private int [ ] _recycledItems ;
private int _recycledItemsCount ;
2023-02-05 19:59:45 +08:00
2023-03-30 16:43:22 +08:00
private IEcsComponentReset < T > _componentResetHandler ;
2023-04-20 18:23:23 +08:00
private PoolRunners _poolRunners ;
2023-04-17 22:58:52 +08:00
2023-02-07 17:11:56 +08:00
#region Properites
2023-04-21 03:16:05 +08:00
public int Count = > _itemsCount ;
public int Capacity = > _items . Length ;
2023-04-21 01:05:06 +08:00
public sealed override EcsWorld World = > _source ;
public sealed override Type ComponentType = > typeof ( T ) ;
2023-02-07 17:11:56 +08:00
#endregion
2023-04-21 03:16:05 +08:00
#region Init
protected override void Init ( EcsWorld world )
2023-02-06 01:27:32 +08:00
{
2023-04-21 03:16:05 +08:00
const int capacity = 512 ;
_source = world ;
2023-02-09 02:26:43 +08:00
2023-04-21 03:16:05 +08:00
_mapping = new int [ world . Capacity ] ;
2023-04-01 20:45:37 +08:00
_recycledItems = new int [ 128 ] ;
_recycledItemsCount = 0 ;
2023-04-01 21:16:08 +08:00
_items = new T [ capacity ] ;
2023-04-01 20:45:37 +08:00
_itemsCount = 0 ;
2023-03-30 16:43:22 +08:00
2023-04-20 18:23:23 +08:00
_componentResetHandler = EcsComponentResetHandler < T > . instance ;
2023-04-21 03:16:05 +08:00
_poolRunners = new PoolRunners ( world . Pipeline ) ;
2023-02-06 01:27:32 +08:00
}
2023-02-07 17:11:56 +08:00
#endregion
2023-02-06 01:27:32 +08:00
2023-04-01 20:45:37 +08:00
#region Write / Read / Has / Del
2023-04-09 02:52:39 +08:00
private ProfilerMarker _addMark = new ProfilerMarker ( "EcsPoo.Add" ) ;
2023-04-01 20:45:37 +08:00
private ProfilerMarker _writeMark = new ProfilerMarker ( "EcsPoo.Write" ) ;
private ProfilerMarker _readMark = new ProfilerMarker ( "EcsPoo.Read" ) ;
private ProfilerMarker _hasMark = new ProfilerMarker ( "EcsPoo.Has" ) ;
private ProfilerMarker _delMark = new ProfilerMarker ( "EcsPoo.Del" ) ;
2023-04-21 03:16:05 +08:00
public ref T Add ( int entityID )
2023-02-13 21:11:54 +08:00
{
2023-04-20 18:23:23 +08:00
// using (_addMark.Auto())
// {
ref int itemIndex = ref _mapping [ entityID ] ;
if ( itemIndex < = 0 )
{
if ( _recycledItemsCount > 0 )
2023-04-01 20:45:37 +08:00
{
2023-04-20 18:23:23 +08:00
itemIndex = _recycledItems [ - - _recycledItemsCount ] ;
_itemsCount + + ;
}
else
{
itemIndex = + + _itemsCount ;
if ( itemIndex > = _items . Length )
Array . Resize ( ref _items , _items . Length < < 1 ) ;
}
2023-04-21 16:03:50 +08:00
//_mapping[entityID] = itemIndex; TODO <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <20> <> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
2023-04-20 18:23:23 +08:00
_poolRunners . add . OnComponentAdd < T > ( entityID ) ;
2023-04-17 22:58:52 +08:00
}
2023-04-20 18:23:23 +08:00
_poolRunners . write . OnComponentWrite < T > ( entityID ) ;
return ref _items [ itemIndex ] ;
2023-04-20 10:59:55 +08:00
// }
2023-04-09 02:52:39 +08:00
}
2023-04-17 22:58:52 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-21 03:16:05 +08:00
public ref T Write ( int entityID )
2023-04-09 02:52:39 +08:00
{
2023-04-20 18:23:23 +08:00
// using (_writeMark.Auto())
_poolRunners . write . OnComponentWrite < T > ( entityID ) ;
return ref _items [ _mapping [ entityID ] ] ;
2023-04-01 20:45:37 +08:00
}
2023-02-05 19:59:45 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-21 03:16:05 +08:00
public ref readonly T Read ( int entityID )
2023-02-05 19:59:45 +08:00
{
2023-04-20 18:23:23 +08:00
// using (_readMark.Auto())
2023-04-01 21:16:08 +08:00
return ref _items [ _mapping [ entityID ] ] ;
2023-02-05 19:59:45 +08:00
}
2023-02-07 17:11:56 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-04-21 01:05:06 +08:00
public sealed override bool Has ( int entityID )
2023-04-01 20:45:37 +08:00
{
2023-04-17 22:58:52 +08:00
// using (_hasMark.Auto())
2023-04-01 21:16:08 +08:00
return _mapping [ entityID ] > 0 ;
2023-04-01 20:45:37 +08:00
}
2023-04-21 03:16:05 +08:00
public void Del ( int entityID )
2023-02-07 17:11:56 +08:00
{
2023-04-20 11:23:54 +08:00
// using (_delMark.Auto())
// {
ref int itemIndex = ref _mapping [ entityID ] ;
_componentResetHandler . Reset ( ref _items [ itemIndex ] ) ;
2023-04-01 21:16:08 +08:00
if ( _recycledItemsCount > = _recycledItems . Length )
2023-04-01 20:45:37 +08:00
Array . Resize ( ref _recycledItems , _recycledItems . Length < < 1 ) ;
2023-04-20 11:23:54 +08:00
_recycledItems [ _recycledItemsCount + + ] = itemIndex ;
itemIndex = 0 ;
2023-04-01 20:45:37 +08:00
_itemsCount - - ;
2023-04-20 18:23:23 +08:00
_poolRunners . del . OnComponentDel < T > ( entityID ) ;
// }
2023-04-20 11:23:54 +08:00
}
2023-02-07 17:11:56 +08:00
#endregion
2023-04-21 01:05:06 +08:00
#region WorldCallbacks
protected override void OnWorldResize ( int newSize )
2023-03-30 16:43:22 +08:00
{
2023-04-01 20:45:37 +08:00
Array . Resize ( ref _mapping , newSize ) ;
2023-03-30 16:43:22 +08:00
}
2023-04-21 01:05:06 +08:00
protected override void OnDestroy ( ) { }
2023-04-06 23:40:47 +08:00
#endregion
2023-03-30 16:43:22 +08:00
}
2023-04-21 03:16:05 +08:00
2023-04-21 03:46:51 +08:00
public interface IEcsComponent { }
public static class EcsPoolExt
2023-04-21 03:16:05 +08:00
{
2023-04-21 16:03:50 +08:00
public static EcsPool < TComponent > GetPool < TComponent > ( this EcsWorld self ) where TComponent : struct , IEcsComponent
2023-04-21 03:16:05 +08:00
{
return self . GetPool < TComponent , EcsPool < TComponent > > ( ) ;
2023-04-21 16:03:50 +08:00
}
public static EcsPool < TComponent > Include < TComponent > ( this EcsQueryBuilderBase self ) where TComponent : struct , IEcsComponent
{
return self . Include < TComponent , EcsPool < TComponent > > ( ) ;
}
public static EcsPool < TComponent > Exclude < TComponent > ( this EcsQueryBuilderBase self ) where TComponent : struct , IEcsComponent
{
return self . Exclude < TComponent , EcsPool < TComponent > > ( ) ;
}
public static EcsPool < TComponent > Optional < TComponent > ( this EcsQueryBuilderBase self ) where TComponent : struct , IEcsComponent
{
return self . Optional < TComponent , EcsPool < TComponent > > ( ) ;
}
2023-04-21 03:16:05 +08:00
}
2023-02-05 19:59:45 +08:00
}