2025-03-14 16:53:25 +08:00
#if DISABLE_DEBUG
#undef DEBUG
#endif
using DCFApixels.DragonECS.Internal ;
2024-02-23 18:34:40 +08:00
using DCFApixels.DragonECS.RunnersCore ;
2023-05-27 23:02:32 +08:00
using System ;
2023-03-11 17:11:40 +08:00
using System.Linq ;
2024-10-31 14:48:56 +08:00
using System.Runtime.CompilerServices ;
2023-05-26 04:25:09 +08:00
using static DCFApixels . DragonECS . EcsDebugUtility ;
2025-03-10 13:00:30 +08:00
#pragma warning disable CS0162 // Обнаружен недостижимый код
2023-03-11 17:11:40 +08:00
namespace DCFApixels.DragonECS
{
2024-06-13 18:04:18 +08:00
[MetaColor(MetaColor.DragonRose)]
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.OTHER_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, "...")]
[MetaTags(MetaTags.HIDDEN)]
2024-10-12 00:08:12 +08:00
[MetaID("EF8A557C9201E6F04D4A76DC670BDE19")]
2024-06-05 14:39:19 +08:00
public interface IEcsProcess : IEcsMember { }
2023-03-16 01:49:14 +08:00
2023-04-23 17:55:01 +08:00
namespace RunnersCore
2023-03-11 17:11:40 +08:00
{
2025-03-10 13:00:30 +08:00
//добавить инъекцию в раннеры
2024-02-23 18:34:40 +08:00
public abstract class EcsRunner
2023-03-11 17:11:40 +08:00
{
2024-02-23 18:34:40 +08:00
internal abstract void Init_Internal ( EcsPipeline source ) ;
2023-03-11 17:11:40 +08:00
2024-02-23 18:34:40 +08:00
#region CheckRunnerValide
public static void CheckRunnerTypeIsValide ( Type runnerType , Type processInterfaceType )
2023-12-06 21:15:35 +08:00
{
2025-01-06 10:48:39 +08:00
#if DEBUG
2024-02-23 18:34:40 +08:00
#pragma warning disable IL2070 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations.
Type targetInterface = processInterfaceType ;
if ( runnerType . IsAbstract | | runnerType . IsInterface )
2023-12-06 21:15:35 +08:00
{
2024-11-06 19:55:33 +08:00
Throw . Exception ( "The instance of a runner cannot be abstract." ) ;
2023-12-06 21:15:35 +08:00
}
2024-01-08 13:39:38 +08:00
Type GetRunnerBaseType ( Type inType )
2023-12-06 21:15:35 +08:00
{
2024-01-08 13:39:38 +08:00
if ( inType . IsGenericType & & inType . GetGenericTypeDefinition ( ) = = typeof ( EcsRunner < > ) )
2024-02-23 18:34:40 +08:00
{
2024-01-08 13:39:38 +08:00
return inType ;
2024-02-23 18:34:40 +08:00
}
2024-01-08 13:39:38 +08:00
if ( inType . BaseType ! = null )
2024-02-23 18:34:40 +08:00
{
2024-01-08 13:39:38 +08:00
return GetRunnerBaseType ( inType . BaseType ) ;
2024-02-23 18:34:40 +08:00
}
2023-12-06 21:15:35 +08:00
return null ;
}
2024-02-23 18:34:40 +08:00
Type baseType = GetRunnerBaseType ( runnerType ) ;
2023-12-06 21:15:35 +08:00
Type baseTypeArgument = baseType . GenericTypeArguments [ 0 ] ;
if ( baseTypeArgument ! = targetInterface )
{
2024-02-23 18:34:40 +08:00
Throw . UndefinedException ( ) ;
2023-12-06 21:15:35 +08:00
}
2024-02-23 18:34:40 +08:00
if ( ! runnerType . GetInterfaces ( ) . Any ( o = > o = = targetInterface ) )
2023-12-06 20:34:33 +08:00
{
2025-03-14 21:57:52 +08:00
throw new ImplementationException ( $"Runner {GetGenericTypeFullName(runnerType, 1)} does not implement interface {GetGenericTypeFullName(baseTypeArgument, 1)}." ) ;
2023-12-06 20:34:33 +08:00
}
2024-02-23 18:34:40 +08:00
#pragma warning restore IL2070 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations.
2025-01-06 10:48:39 +08:00
#endif
2023-04-23 17:55:01 +08:00
}
#endregion
2025-03-10 13:00:30 +08:00
public delegate void ActionWithData < in TProcess , T > ( TProcess process , ref T Data ) ;
2024-02-23 18:34:40 +08:00
}
2024-06-13 18:04:18 +08:00
[MetaColor(MetaColor.DragonRose)]
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.OTHER_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, "...")]
[MetaTags(MetaTags.HIDDEN)]
2024-10-12 00:08:12 +08:00
[MetaID("E49B557C92010E46DF1602972BC988BC")]
2024-02-23 18:34:40 +08:00
public interface IEcsRunner : IEcsProcess
{
EcsPipeline Pipeline { get ; }
Type Interface { get ; }
EcsProcessRaw ProcessRaw { get ; }
bool IsEmpty { get ; }
}
2025-03-13 13:55:19 +08:00
//TODO инъекция в раннеры
2024-10-31 14:48:56 +08:00
//TODO добавить функцию фильтрации систем по string, за счет создания отдельных ранеров для отдельных string
2024-06-13 18:04:18 +08:00
[MetaColor(MetaColor.DragonRose)]
[MetaGroup(EcsConsts.PACK_GROUP, EcsConsts.OTHER_GROUP)]
[MetaDescription(EcsConsts.AUTHOR, "...")]
[MetaTags(MetaTags.HIDDEN)]
2024-10-12 00:08:12 +08:00
[MetaID("7DB3557C9201F85E0E1C17D7B19D9CEE")]
2024-02-23 18:34:40 +08:00
public abstract class EcsRunner < TProcess > : EcsRunner , IEcsRunner , IEcsProcess
where TProcess : IEcsProcess
{
2023-04-23 17:55:01 +08:00
private EcsPipeline _source ;
2024-02-22 15:39:37 +08:00
private EcsProcess < TProcess > _process ;
2024-02-23 18:34:40 +08:00
private bool _isInit = false ;
2023-03-26 11:19:03 +08:00
2023-04-23 17:55:01 +08:00
#region Properties
2024-02-22 15:39:37 +08:00
public EcsPipeline Pipeline
{
get { return _source ; }
}
public Type Interface
{
get { return typeof ( TProcess ) ; }
}
public EcsProcessRaw ProcessRaw
{
get { return _process ; }
}
public EcsProcess < TProcess > Process
{
get { return _process ; }
}
public bool IsEmpty
{
2024-02-22 23:48:10 +08:00
get { return _process . IsNullOrEmpty ; }
2024-02-22 15:39:37 +08:00
}
2023-04-23 17:55:01 +08:00
#endregion
2023-03-27 17:34:12 +08:00
2024-02-23 18:34:40 +08:00
#region Constructor Init OnSetup
public EcsRunner ( ) { }
internal override sealed void Init_Internal ( EcsPipeline source )
2023-04-23 17:55:01 +08:00
{
2024-02-23 18:34:40 +08:00
if ( _isInit )
{
2024-04-22 17:49:24 +08:00
Throw . Exception ( "Reinitialization." ) ;
2024-02-23 18:34:40 +08:00
}
_isInit = true ;
2023-04-23 17:55:01 +08:00
_source = source ;
2024-02-23 18:34:40 +08:00
_process = source . GetProcess < TProcess > ( ) ;
2023-04-23 17:55:01 +08:00
OnSetup ( ) ;
}
2024-02-23 18:34:40 +08:00
protected virtual void OnSetup ( ) { }
#endregion
2024-10-31 14:48:56 +08:00
2025-01-06 10:48:39 +08:00
#region RunHelper
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
public
#else
public readonly
#endif
struct RunHelper
2024-10-31 14:48:56 +08:00
{
private readonly EcsProcess < TProcess > _process ;
2025-03-14 16:53:25 +08:00
#if DEBUG
2024-10-31 14:48:56 +08:00
private Delegate _cacheCheck ;
private bool _cacheCheckInit ;
private readonly EcsProfilerMarker [ ] _markers ;
#endif
#region Constructors
2024-11-06 20:17:07 +08:00
public RunHelper ( EcsRunner < TProcess > runner ) : this ( runner ,
2025-03-14 16:53:25 +08:00
#if DEBUG
2024-11-06 20:17:07 +08:00
typeof ( TProcess ) . ToMeta ( ) . Name )
#else
2024-11-06 20:33:44 +08:00
string . Empty )
2024-11-06 20:17:07 +08:00
#endif
{ }
2024-11-06 20:33:44 +08:00
2024-10-31 15:27:53 +08:00
public RunHelper ( EcsRunner < TProcess > runner , string methodName )
2024-10-31 14:48:56 +08:00
{
_process = runner . Process ;
2025-03-14 16:53:25 +08:00
#if DEBUG
2024-10-31 14:48:56 +08:00
_cacheCheck = null ;
_cacheCheckInit = false ;
_markers = new EcsProfilerMarker [ _process . Length ] ;
for ( int i = 0 ; i < _process . Length ; i + + )
{
_markers [ i ] = new EcsProfilerMarker ( $"{_process[i].GetMeta().Name}.{methodName}" ) ;
}
#endif
}
#endregion
2024-10-31 14:53:08 +08:00
#region Utils
2025-03-14 16:53:25 +08:00
#if DEBUG
2024-10-31 14:48:56 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckCache ( Delegate d )
{
if ( _cacheCheckInit = = false )
{
if ( _cacheCheck = = null )
{
_cacheCheck = d ;
}
else
{
if ( ReferenceEquals ( _cacheCheck , d ) = = false )
{
EcsDebug . PrintWarning ( "The delegate is not cached" ) ;
}
_cacheCheckInit = true ;
}
}
}
2024-10-31 15:27:53 +08:00
#endif
2024-10-31 14:48:56 +08:00
#endregion
#region Do
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-10-31 14:53:08 +08:00
public void Run ( Action < TProcess > translationCallback )
2024-10-31 14:48:56 +08:00
{
2025-03-14 16:53:25 +08:00
#if DEBUG
2024-10-31 15:27:53 +08:00
CheckCache ( translationCallback ) ;
2024-10-31 14:48:56 +08:00
for ( int i = 0 , n = _process . Length < _markers . Length ? _process . Length : _markers . Length ; i < n ; i + + )
{
_markers [ i ] . Begin ( ) ;
try
{
translationCallback ( _process [ i ] ) ;
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
_markers [ i ] . End ( ) ;
}
#else
foreach ( var item in _process )
{
2024-11-06 20:33:44 +08:00
try
2024-10-31 14:48:56 +08:00
{
translationCallback ( item ) ;
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
}
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2025-03-10 13:00:30 +08:00
public void Run < TData > ( ActionWithData < TProcess , TData > translationCallback , ref TData data )
2024-10-31 14:48:56 +08:00
{
2025-03-14 16:53:25 +08:00
#if DEBUG
2024-10-31 15:27:53 +08:00
CheckCache ( translationCallback ) ;
2024-10-31 14:48:56 +08:00
for ( int i = 0 , n = _process . Length < _markers . Length ? _process . Length : _markers . Length ; i < n ; i + + )
{
_markers [ i ] . Begin ( ) ;
try
{
2025-03-10 13:00:30 +08:00
translationCallback ( _process [ i ] , ref data ) ;
2024-10-31 14:48:56 +08:00
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
_markers [ i ] . End ( ) ;
}
#else
foreach ( var item in _process )
{
2024-11-06 20:33:44 +08:00
try
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
translationCallback ( item , ref data ) ;
2024-10-31 14:48:56 +08:00
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
}
#endif
}
2025-03-10 13:00:30 +08:00
#endregion
}
#endregion
2024-10-31 14:48:56 +08:00
2025-03-10 13:00:30 +08:00
#region RunHelperWithFinally
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
public
#else
public readonly
#endif
struct RunHelperWithFinally < TProcessFinally > where TProcessFinally : class , IEcsProcess
{
private readonly Pair [ ] _pairs ;
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
private Delegate _cacheCheck ;
private Delegate _cacheCheckF ;
private bool _cacheCheckInit ;
private readonly EcsProfilerMarker [ ] _markers ;
#endif
#region Constructors
public RunHelperWithFinally ( EcsRunner < TProcess > runner ) : this ( runner ,
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
typeof ( TProcess ) . ToMeta ( ) . Name )
#else
string . Empty )
#endif
{ }
public RunHelperWithFinally ( EcsRunner < TProcess > runner , string methodName )
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
_pairs = new Pair [ runner . Process . Length ] ;
for ( int i = 0 ; i < runner . Process . Length ; i + + )
{
_pairs [ i ] = new Pair ( runner . Process [ i ] ) ;
}
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
_cacheCheck = null ;
_cacheCheckF = null ;
_cacheCheckInit = false ;
_markers = new EcsProfilerMarker [ _pairs . Length ] ;
for ( int i = 0 ; i < _pairs . Length ; i + + )
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
_markers [ i ] = new EcsProfilerMarker ( $"{_pairs[i].run.GetMeta().Name}.{methodName}" ) ;
}
2024-10-31 14:48:56 +08:00
#endif
2025-03-10 13:00:30 +08:00
}
#endregion
#region Utils
private readonly struct Pair
{
public readonly TProcess run ;
public readonly TProcessFinally runFinally ;
public Pair ( TProcess run )
{
this . run = run ;
runFinally = run as TProcessFinally ;
2024-10-31 14:48:56 +08:00
}
2025-03-10 13:00:30 +08:00
}
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckCache ( Delegate d , Delegate df )
{
if ( _cacheCheckInit = = false )
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
if ( _cacheCheck = = null )
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
_cacheCheck = d ;
_cacheCheckF = df ;
2024-10-31 14:48:56 +08:00
}
2025-03-10 13:00:30 +08:00
else
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
if ( ReferenceEquals ( _cacheCheck , d ) = = false | | ReferenceEquals ( _cacheCheckF , df ) = = false )
{
EcsDebug . PrintWarning ( "The delegate is not cached" ) ;
}
_cacheCheckInit = true ;
2024-10-31 14:48:56 +08:00
}
}
}
2025-03-10 13:00:30 +08:00
#endif
#endregion
2024-10-31 14:48:56 +08:00
2025-03-10 13:00:30 +08:00
#region Do
2024-10-31 14:48:56 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2025-03-10 13:00:30 +08:00
public void Run (
Action < TProcess > translationCallback ,
Action < TProcessFinally > translationFinnalyCallback )
2024-10-31 14:48:56 +08:00
{
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
CheckCache ( translationCallback , translationFinnalyCallback ) ;
for ( int i = 0 , n = _pairs . Length < _markers . Length ? _pairs . Length : _markers . Length ; i < n ; i + + )
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
var pair = _pairs [ i ] ;
2024-10-31 14:48:56 +08:00
_markers [ i ] . Begin ( ) ;
try
{
2025-03-10 13:00:30 +08:00
translationCallback ( pair . run ) ;
2024-10-31 14:48:56 +08:00
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
2025-03-10 13:00:30 +08:00
finally
{
2025-03-10 22:55:34 +08:00
if ( pair . runFinally ! = null )
2025-03-10 13:00:30 +08:00
{
translationFinnalyCallback ( pair . runFinally ) ;
}
}
2024-10-31 14:48:56 +08:00
_markers [ i ] . End ( ) ;
}
#else
2025-03-10 13:00:30 +08:00
foreach ( var item in _pairs )
2024-10-31 14:48:56 +08:00
{
2024-11-06 20:33:44 +08:00
try
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
translationCallback ( item . run ) ;
2024-10-31 14:48:56 +08:00
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
2025-03-10 13:00:30 +08:00
finally
{
translationFinnalyCallback ( item . runFinally ) ;
}
2024-10-31 14:48:56 +08:00
}
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2025-03-10 13:00:30 +08:00
public void Run < TData > (
ActionWithData < TProcess , TData > translationCallback ,
ActionWithData < TProcessFinally , TData > translationFinnalyCallback ,
ref TData data )
2024-10-31 14:48:56 +08:00
{
2025-03-14 16:53:25 +08:00
#if DEBUG
2025-03-10 13:00:30 +08:00
CheckCache ( translationCallback , translationFinnalyCallback ) ;
for ( int i = 0 , n = _pairs . Length < _markers . Length ? _pairs . Length : _markers . Length ; i < n ; i + + )
2024-10-31 14:48:56 +08:00
{
2025-03-10 13:00:30 +08:00
var pair = _pairs [ i ] ;
2024-10-31 14:48:56 +08:00
_markers [ i ] . Begin ( ) ;
try
{
2025-03-10 13:00:30 +08:00
translationCallback ( pair . run , ref data ) ;
2024-10-31 14:48:56 +08:00
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
2025-03-10 13:00:30 +08:00
finally
{
if ( pair . runFinally ! = null )
{
translationFinnalyCallback ( pair . runFinally , ref data ) ;
}
}
2024-10-31 14:48:56 +08:00
_markers [ i ] . End ( ) ;
}
#else
2025-03-10 13:00:30 +08:00
foreach ( var pair in _pairs )
2024-10-31 14:48:56 +08:00
{
2024-11-06 20:33:44 +08:00
try
2024-10-31 14:48:56 +08:00
{
2025-03-12 19:32:38 +08:00
translationCallback ( pair . run , ref data ) ;
2024-10-31 14:48:56 +08:00
}
catch ( Exception e )
{
2025-03-15 15:00:07 +08:00
#if DRAGONECS_DISABLE_CATH_EXCEPTIONS
2024-10-31 14:48:56 +08:00
throw ;
#endif
EcsDebug . PrintError ( e ) ;
}
2025-03-10 13:00:30 +08:00
finally
{
if ( pair . runFinally ! = null )
{
2025-03-12 19:32:38 +08:00
translationFinnalyCallback ( pair . runFinally , ref data ) ;
2025-03-10 13:00:30 +08:00
}
}
2024-10-31 14:48:56 +08:00
}
#endif
}
#endregion
}
#endregion
2025-03-10 13:00:30 +08:00
//----
2023-04-23 17:55:01 +08:00
}
2023-03-11 17:11:40 +08:00
}
2023-05-26 04:25:09 +08:00
2023-03-30 01:57:10 +08:00
#region Extensions
2024-02-23 18:34:40 +08:00
public static class IEcsProcessExtensions
2023-03-30 01:57:10 +08:00
{
2024-02-22 22:16:03 +08:00
public static bool IsRunner ( this IEcsProcess self )
2023-03-30 01:57:10 +08:00
{
return self is IEcsRunner ;
}
}
#endregion
2024-10-31 14:48:56 +08:00
}