mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-19 02:24:37 +08:00
remove Reflection except inside EcsHybridPool
This commit is contained in:
parent
c14a513172
commit
4888ad82e4
@ -1,5 +1,4 @@
|
|||||||
#pragma warning disable CS0162 // Обнаружен недостижимый код
|
#pragma warning disable CS0162 // Обнаружен недостижимый код
|
||||||
using DCFApixels.DragonECS.Internal;
|
|
||||||
using DCFApixels.DragonECS.RunnersCore;
|
using DCFApixels.DragonECS.RunnersCore;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
@ -7,28 +6,24 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
[MetaName(nameof(PreInit))]
|
[MetaName(nameof(PreInit))]
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
[BindWithEcsRunner(typeof(EcsPreInitRunner))]
|
|
||||||
public interface IEcsPreInit : IEcsProcess
|
public interface IEcsPreInit : IEcsProcess
|
||||||
{
|
{
|
||||||
void PreInit();
|
void PreInit();
|
||||||
}
|
}
|
||||||
[MetaName(nameof(Init))]
|
[MetaName(nameof(Init))]
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
[BindWithEcsRunner(typeof(EcsInitRunner))]
|
|
||||||
public interface IEcsInit : IEcsProcess
|
public interface IEcsInit : IEcsProcess
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
}
|
}
|
||||||
[MetaName(nameof(Run))]
|
[MetaName(nameof(Run))]
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
[BindWithEcsRunner(typeof(EcsRunRunner))]
|
|
||||||
public interface IEcsRun : IEcsProcess
|
public interface IEcsRun : IEcsProcess
|
||||||
{
|
{
|
||||||
void Run();
|
void Run();
|
||||||
}
|
}
|
||||||
[MetaName(nameof(Destroy))]
|
[MetaName(nameof(Destroy))]
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
[BindWithEcsRunner(typeof(EcsDestroyRunner))]
|
|
||||||
public interface IEcsDestroy : IEcsProcess
|
public interface IEcsDestroy : IEcsProcess
|
||||||
{
|
{
|
||||||
void Destroy();
|
void Destroy();
|
||||||
@ -38,7 +33,7 @@ namespace DCFApixels.DragonECS
|
|||||||
namespace DCFApixels.DragonECS.Internal
|
namespace DCFApixels.DragonECS.Internal
|
||||||
{
|
{
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInit>, IEcsPreInit
|
internal sealed class EcsPreInitRunner : EcsRunner<IEcsPreInit>, IEcsPreInit
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
private EcsProfilerMarker[] _markers;
|
private EcsProfilerMarker[] _markers;
|
||||||
@ -73,7 +68,10 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
#else
|
#else
|
||||||
foreach (var item in Process)
|
foreach (var item in Process)
|
||||||
{
|
{
|
||||||
try { item.PreInit(); }
|
try
|
||||||
|
{
|
||||||
|
item.PreInit();
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
#if DISABLE_CATH_EXCEPTIONS
|
#if DISABLE_CATH_EXCEPTIONS
|
||||||
@ -86,7 +84,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
public sealed class EcsInitRunner : EcsRunner<IEcsInit>, IEcsInit
|
internal sealed class EcsInitRunner : EcsRunner<IEcsInit>, IEcsInit
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
private EcsProfilerMarker[] _markers;
|
private EcsProfilerMarker[] _markers;
|
||||||
@ -134,7 +132,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
public sealed class EcsRunRunner : EcsRunner<IEcsRun>, IEcsRun
|
internal sealed class EcsRunRunner : EcsRunner<IEcsRun>, IEcsRun
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
private EcsProfilerMarker[] _markers;
|
private EcsProfilerMarker[] _markers;
|
||||||
@ -182,7 +180,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
[MetaColor(MetaColor.Orange)]
|
[MetaColor(MetaColor.Orange)]
|
||||||
public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroy>, IEcsDestroy
|
internal sealed class EcsDestroyRunner : EcsRunner<IEcsDestroy>, IEcsDestroy
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
private EcsProfilerMarker[] _markers;
|
private EcsProfilerMarker[] _markers;
|
||||||
@ -195,7 +193,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
void IEcsDestroy.Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
|
for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
|
||||||
|
@ -44,6 +44,15 @@
|
|||||||
true;
|
true;
|
||||||
#else
|
#else
|
||||||
false;
|
false;
|
||||||
|
#endif
|
||||||
|
public const bool DISABLE_CATH_EXCEPTIONS =
|
||||||
|
#if DISABLE_CATH_EXCEPTIONS
|
||||||
|
true;
|
||||||
|
#else
|
||||||
|
false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//#if UNITY_2020_3_OR_NEWER
|
||||||
|
// [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve]
|
||||||
|
//#endif
|
||||||
|
@ -49,8 +49,11 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
private static string AutoToString(object target, Type type, bool isWriteName)
|
private static string AutoToString(object target, Type type, bool isWriteName)
|
||||||
{
|
{
|
||||||
|
#if !REFLECTION_DISABLED
|
||||||
//TODO сделать специальный вывод в виде названий констант для Enum-ов
|
//TODO сделать специальный вывод в виде названий констант для Enum-ов
|
||||||
|
#pragma warning disable IL2070 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations.
|
||||||
var fields = type.GetFields(RFL_FLAGS);
|
var fields = type.GetFields(RFL_FLAGS);
|
||||||
|
#pragma warning restore IL2070
|
||||||
string[] values = new string[fields.Length];
|
string[] values = new string[fields.Length];
|
||||||
for (int i = 0; i < fields.Length; i++)
|
for (int i = 0; i < fields.Length; i++)
|
||||||
values[i] = (fields[i].GetValue(target) ?? "NULL").ToString();
|
values[i] = (fields[i].GetValue(target) ?? "NULL").ToString();
|
||||||
@ -58,6 +61,9 @@ namespace DCFApixels.DragonECS
|
|||||||
return $"{type.Name}({string.Join(", ", values)})";
|
return $"{type.Name}({string.Join(", ", values)})";
|
||||||
else
|
else
|
||||||
return $"({string.Join(", ", values)})";
|
return $"({string.Join(", ", values)})";
|
||||||
|
#endif
|
||||||
|
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(AutoToString)} method does not work.");
|
||||||
|
return string.Empty;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -48,15 +48,20 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
Builder builder = new Builder(world);
|
Builder builder = new Builder(world);
|
||||||
Type aspectType = typeof(TAspect);
|
Type aspectType = typeof(TAspect);
|
||||||
ConstructorInfo constructorInfo = aspectType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null);
|
|
||||||
EcsAspect newAspect;
|
EcsAspect newAspect;
|
||||||
|
//TODO добавить оповещение что инициализация через конструктор не работает
|
||||||
|
#if !REFLECTION_DISABLED
|
||||||
|
ConstructorInfo constructorInfo = aspectType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null);
|
||||||
if (constructorInfo != null)
|
if (constructorInfo != null)
|
||||||
{
|
{
|
||||||
newAspect = (EcsAspect)constructorInfo.Invoke(new object[] { builder });
|
newAspect = (EcsAspect)constructorInfo.Invoke(new object[] { builder });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
newAspect = (EcsAspect)Activator.CreateInstance(typeof(TAspect));
|
#pragma warning disable IL2091 // Target generic argument does not satisfy 'DynamicallyAccessedMembersAttribute' in target method or type. The generic parameter of the source method or type does not have matching annotations.
|
||||||
|
newAspect = Activator.CreateInstance<TAspect>();
|
||||||
|
#pragma warning restore IL2091
|
||||||
newAspect.Init(builder);
|
newAspect.Init(builder);
|
||||||
}
|
}
|
||||||
newAspect._source = world;
|
newAspect._source = world;
|
||||||
@ -92,13 +97,15 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Include/Exclude/Optional/Combine
|
#region Include/Exclude/Optional/Combine
|
||||||
public TPool Include<TPool>() where TPool : IEcsPoolImplementation, new()
|
public TPool Include<TPool>() where TPool : IEcsPoolImplementation, new()
|
||||||
{
|
{
|
||||||
IncludeImplicit(typeof(TPool).GetGenericArguments()[0]);
|
var pool = _world.GetPool<TPool>();
|
||||||
return _world.GetPool<TPool>();
|
IncludeImplicit(pool.ComponentType);
|
||||||
|
return pool;
|
||||||
}
|
}
|
||||||
public TPool Exclude<TPool>() where TPool : IEcsPoolImplementation, new()
|
public TPool Exclude<TPool>() where TPool : IEcsPoolImplementation, new()
|
||||||
{
|
{
|
||||||
ExcludeImplicit(typeof(TPool).GetGenericArguments()[0]);
|
var pool = _world.GetPool<TPool>();
|
||||||
return _world.GetPool<TPool>();
|
ExcludeImplicit(pool.ComponentType);
|
||||||
|
return pool;
|
||||||
}
|
}
|
||||||
public TPool Optional<TPool>() where TPool : IEcsPoolImplementation, new()
|
public TPool Optional<TPool>() where TPool : IEcsPoolImplementation, new()
|
||||||
{
|
{
|
||||||
|
@ -21,12 +21,14 @@ namespace DCFApixels.DragonECS
|
|||||||
private IEcsProcess[] _allSystems;
|
private IEcsProcess[] _allSystems;
|
||||||
private Dictionary<Type, Array> _processes = new Dictionary<Type, Array>();
|
private Dictionary<Type, Array> _processes = new Dictionary<Type, Array>();
|
||||||
private Dictionary<Type, IEcsRunner> _runners = new Dictionary<Type, IEcsRunner>();
|
private Dictionary<Type, IEcsRunner> _runners = new Dictionary<Type, IEcsRunner>();
|
||||||
private IEcsRun _runRunnerCache;
|
private EcsRunRunner _runRunnerCache;
|
||||||
|
|
||||||
private bool _isInit = false;
|
private bool _isInit = false;
|
||||||
private bool _isDestoryed = false;
|
private bool _isDestoryed = false;
|
||||||
|
|
||||||
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
private EcsProfilerMarker _initBarker = new EcsProfilerMarker("EcsPipeline.Init");
|
private EcsProfilerMarker _initBarker = new EcsProfilerMarker("EcsPipeline.Init");
|
||||||
|
#endif
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public IEcsPipelineConfig Config
|
public IEcsPipelineConfig Config
|
||||||
@ -64,7 +66,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Get Process/Runner
|
#region Get Process
|
||||||
public EcsProcess<T> GetProcess<T>() where T : IEcsProcess
|
public EcsProcess<T> GetProcess<T>() where T : IEcsProcess
|
||||||
{
|
{
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
@ -80,31 +82,43 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
return new EcsProcess<T>(result);
|
return new EcsProcess<T>(result);
|
||||||
}
|
}
|
||||||
#if !REFLECTION_DISABLED
|
#endregion
|
||||||
|
|
||||||
|
#region Declare/Get Runner
|
||||||
|
public TRunner DeclareRunner<TRunner>() where TRunner : EcsRunner, IEcsRunner, new()
|
||||||
|
{
|
||||||
|
Type runnerType = typeof(TRunner);
|
||||||
|
if (_runners.TryGetValue(runnerType, out IEcsRunner result))
|
||||||
|
{
|
||||||
|
return (TRunner)result;
|
||||||
|
}
|
||||||
|
TRunner instance = new TRunner();
|
||||||
|
#if DEBUG
|
||||||
|
EcsRunner.CheckRunnerTypeIsValide(runnerType, instance.Interface);
|
||||||
|
#endif
|
||||||
|
instance.Init_Internal(this);
|
||||||
|
_runners.Add(runnerType, instance);
|
||||||
|
_runners.Add(instance.Interface, instance);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
public T GetRunner<T>() where T : IEcsProcess
|
public T GetRunner<T>() where T : IEcsProcess
|
||||||
{
|
{
|
||||||
Type interfaceType = typeof(T);
|
if (_runners.TryGetValue(typeof(T), out IEcsRunner result))
|
||||||
if (_runners.TryGetValue(interfaceType, out IEcsRunner result) == false)
|
|
||||||
{
|
{
|
||||||
result = (IEcsRunner)EcsRunner<T>.Instantiate(this);
|
|
||||||
_runners.Add(result.GetType(), result);
|
|
||||||
_runners.Add(interfaceType, result);
|
|
||||||
}
|
|
||||||
return (T)result;
|
return (T)result;
|
||||||
}
|
}
|
||||||
#endif
|
Throw.UndefinedException();
|
||||||
public T GetRunnerInstance<T>() where T : IEcsRunner, new()
|
return default;
|
||||||
{
|
|
||||||
Type runnerType = typeof(T);
|
|
||||||
if (_runners.TryGetValue(runnerType, out IEcsRunner result) == false)
|
|
||||||
{
|
|
||||||
result = new T();
|
|
||||||
_runners.Add(runnerType, result);
|
|
||||||
#if !REFLECTION_DISABLED
|
|
||||||
_runners.Add(result.Interface, result);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return (T)result;
|
public bool TryGetRunner<T>(out T runner) where T : IEcsProcess
|
||||||
|
{
|
||||||
|
if (_runners.TryGetValue(typeof(T), out IEcsRunner result))
|
||||||
|
{
|
||||||
|
runner = (T)result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
runner = default;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -123,7 +137,9 @@ namespace DCFApixels.DragonECS
|
|||||||
EcsDebug.PrintWarning($"This {nameof(EcsPipeline)} has already been initialized");
|
EcsDebug.PrintWarning($"This {nameof(EcsPipeline)} has already been initialized");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
_initBarker.Begin();
|
_initBarker.Begin();
|
||||||
|
#endif
|
||||||
EcsProcess<IEcsPipelineMember> members = GetProcess<IEcsPipelineMember>();
|
EcsProcess<IEcsPipelineMember> members = GetProcess<IEcsPipelineMember>();
|
||||||
foreach (var member in members)
|
foreach (var member in members)
|
||||||
{
|
{
|
||||||
@ -132,33 +148,31 @@ namespace DCFApixels.DragonECS
|
|||||||
_injector = _injectorBuilder.Build(this);
|
_injector = _injectorBuilder.Build(this);
|
||||||
_injectorBuilder = null;
|
_injectorBuilder = null;
|
||||||
|
|
||||||
var preInitRunner = GetRunner<IEcsPreInit>();
|
DeclareRunner<EcsPreInitRunner>().PreInit();
|
||||||
preInitRunner.PreInit();
|
DeclareRunner<EcsInitRunner>().Init();
|
||||||
EcsRunner.Destroy(preInitRunner);
|
_runRunnerCache = DeclareRunner<EcsRunRunner>();
|
||||||
var initRunner = GetRunner<IEcsInit>();
|
|
||||||
initRunner.Init();
|
|
||||||
EcsRunner.Destroy(initRunner);
|
|
||||||
|
|
||||||
_runRunnerCache = GetRunner<IEcsRun>();
|
|
||||||
_isInit = true;
|
_isInit = true;
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
_initBarker.End();
|
_initBarker.End();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run));
|
if (!_isInit) { Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run)); }
|
||||||
if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run));
|
if (_isDestoryed) { Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run)); }
|
||||||
#endif
|
#endif
|
||||||
_runRunnerCache.Run();
|
_runRunnerCache.Run();
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Destroy));
|
if (!_isInit) { Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Destroy)); }
|
||||||
#endif
|
#endif
|
||||||
if (_isDestoryed)
|
if (_isDestoryed)
|
||||||
{
|
{
|
||||||
@ -166,7 +180,7 @@ namespace DCFApixels.DragonECS
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_isDestoryed = true;
|
_isDestoryed = true;
|
||||||
GetRunner<IEcsDestroy>().Destroy();
|
DeclareRunner<EcsDestroyRunner>().Destroy();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -184,7 +198,10 @@ namespace DCFApixels.DragonECS
|
|||||||
public readonly LayerList Layers;
|
public readonly LayerList Layers;
|
||||||
private readonly IEcsPipelineConfigWriter _config;
|
private readonly IEcsPipelineConfigWriter _config;
|
||||||
private readonly Injector.Builder _injector;
|
private readonly Injector.Builder _injector;
|
||||||
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("EcsPipeline.Build");
|
private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("EcsPipeline.Build");
|
||||||
|
#endif
|
||||||
|
private List<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(4);
|
||||||
|
|
||||||
public IEcsPipelineConfigWriter Config
|
public IEcsPipelineConfigWriter Config
|
||||||
{
|
{
|
||||||
@ -196,8 +213,9 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public Builder(IEcsPipelineConfigWriter config = null)
|
public Builder(IEcsPipelineConfigWriter config = null)
|
||||||
{
|
{
|
||||||
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
_buildBarker.Begin();
|
_buildBarker.Begin();
|
||||||
|
#endif
|
||||||
if (config == null) { config = new EcsPipelineConfig(); }
|
if (config == null) { config = new EcsPipelineConfig(); }
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
@ -214,6 +232,11 @@ namespace DCFApixels.DragonECS
|
|||||||
_uniqueTypes = new HashSet<Type>();
|
_uniqueTypes = new HashSet<Type>();
|
||||||
_systems = new Dictionary<string, List<IEcsProcess>>(KEYS_CAPACITY);
|
_systems = new Dictionary<string, List<IEcsProcess>>(KEYS_CAPACITY);
|
||||||
}
|
}
|
||||||
|
public Builder DeclareRunner<T>() where T : EcsRunner, IEcsRunner, new()
|
||||||
|
{
|
||||||
|
_initDeclaredRunners.Add(new InitDeclaredRunner<T>());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public Builder Add(IEcsProcess system, string layerName = null)
|
public Builder Add(IEcsProcess system, string layerName = null)
|
||||||
{
|
{
|
||||||
AddInternal(system, layerName, false);
|
AddInternal(system, layerName, false);
|
||||||
@ -268,10 +291,28 @@ namespace DCFApixels.DragonECS
|
|||||||
if (_systems.TryGetValue(item, out var list))
|
if (_systems.TryGetValue(item, out var list))
|
||||||
result.AddRange(list);
|
result.AddRange(list);
|
||||||
}
|
}
|
||||||
|
EcsPipeline pipeline = new EcsPipeline(_config.GetPipelineConfig(), _injector, result.ToArray());
|
||||||
|
foreach (var item in _initDeclaredRunners)
|
||||||
|
{
|
||||||
|
item.Declare(pipeline);
|
||||||
|
}
|
||||||
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
_buildBarker.End();
|
_buildBarker.End();
|
||||||
return new EcsPipeline(_config.GetPipelineConfig(), _injector, result.ToArray());
|
#endif
|
||||||
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private abstract class InitDeclaredRunner
|
||||||
|
{
|
||||||
|
public abstract void Declare(EcsPipeline pipeline);
|
||||||
|
}
|
||||||
|
private class InitDeclaredRunner<T> : InitDeclaredRunner where T : EcsRunner, IEcsRunner, new()
|
||||||
|
{
|
||||||
|
public override void Declare(EcsPipeline pipeline)
|
||||||
|
{
|
||||||
|
pipeline.DeclareRunner<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
public class LayerList : IEnumerable<string>
|
public class LayerList : IEnumerable<string>
|
||||||
{
|
{
|
||||||
private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add
|
private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add
|
||||||
|
294
src/EcsRunner.cs
294
src/EcsRunner.cs
@ -1,4 +1,5 @@
|
|||||||
using DCFApixels.DragonECS.RunnersCore;
|
using DCFApixels.DragonECS.Internal;
|
||||||
|
using DCFApixels.DragonECS.RunnersCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -7,148 +8,66 @@ using static DCFApixels.DragonECS.EcsDebugUtility;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
#if UNITY_2020_3_OR_NEWER
|
|
||||||
[UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve]
|
|
||||||
#endif
|
|
||||||
[AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
|
|
||||||
public sealed class BindWithEcsRunnerAttribute : Attribute
|
|
||||||
{
|
|
||||||
private static readonly Type _baseType = typeof(EcsRunner<>);
|
|
||||||
public readonly Type runnerType;
|
|
||||||
public BindWithEcsRunnerAttribute(Type runnerType)
|
|
||||||
{
|
|
||||||
if (runnerType == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
}
|
|
||||||
if (!CheckSubclass(runnerType))
|
|
||||||
{
|
|
||||||
throw new ArgumentException();
|
|
||||||
}
|
|
||||||
this.runnerType = runnerType;
|
|
||||||
}
|
|
||||||
private bool CheckSubclass(Type type)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == _baseType)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (type.BaseType != null)
|
|
||||||
{
|
|
||||||
return CheckSubclass(type.BaseType);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IEcsProcess { }
|
public interface IEcsProcess { }
|
||||||
|
|
||||||
namespace RunnersCore
|
namespace RunnersCore
|
||||||
{
|
{
|
||||||
public interface IEcsRunner
|
public abstract class EcsRunner
|
||||||
|
{
|
||||||
|
internal abstract void Init_Internal(EcsPipeline source);
|
||||||
|
|
||||||
|
#region CheckRunnerValide
|
||||||
|
public static void CheckRunnerTypeIsValide(Type runnerType, Type processInterfaceType)
|
||||||
|
{
|
||||||
|
#region DEBUG
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
Throw.UndefinedException();
|
||||||
|
}
|
||||||
|
Type GetRunnerBaseType(Type inType)
|
||||||
|
{
|
||||||
|
if (inType.IsGenericType && inType.GetGenericTypeDefinition() == typeof(EcsRunner<>))
|
||||||
|
{
|
||||||
|
return inType;
|
||||||
|
}
|
||||||
|
if (inType.BaseType != null)
|
||||||
|
{
|
||||||
|
return GetRunnerBaseType(inType.BaseType);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Type baseType = GetRunnerBaseType(runnerType);
|
||||||
|
Type baseTypeArgument = baseType.GenericTypeArguments[0];
|
||||||
|
if (baseTypeArgument != targetInterface)
|
||||||
|
{
|
||||||
|
Throw.UndefinedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!runnerType.GetInterfaces().Any(o => o == targetInterface))
|
||||||
|
{
|
||||||
|
throw new EcsRunnerImplementationException($"Runner {GetGenericTypeFullName(runnerType, 1)} does not implement interface {GetGenericTypeFullName(baseTypeArgument, 1)}.");
|
||||||
|
}
|
||||||
|
#pragma warning restore IL2070 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations.
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
public interface IEcsRunner : IEcsProcess
|
||||||
{
|
{
|
||||||
EcsPipeline Pipeline { get; }
|
EcsPipeline Pipeline { get; }
|
||||||
Type Interface { get; }
|
Type Interface { get; }
|
||||||
EcsProcessRaw ProcessRaw { get; }
|
EcsProcessRaw ProcessRaw { get; }
|
||||||
bool IsDestroyed { get; }
|
|
||||||
bool IsEmpty { get; }
|
bool IsEmpty { get; }
|
||||||
void Destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_2020_3_OR_NEWER
|
public abstract class EcsRunner<TProcess> : EcsRunner, IEcsRunner, IEcsProcess
|
||||||
[UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve]
|
|
||||||
#endif
|
|
||||||
public abstract class EcsRunner<TProcess> : IEcsProcess, IEcsRunner
|
|
||||||
where TProcess : IEcsProcess
|
where TProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
#region Register
|
|
||||||
private static Type _runnerImplementationType;
|
|
||||||
internal static void Register(Type subclass)
|
|
||||||
{
|
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
|
||||||
if (_runnerImplementationType != null)
|
|
||||||
{
|
|
||||||
throw new EcsRunnerImplementationException($"The Runner<{typeof(TProcess).FullName}> can have only one implementing subclass");
|
|
||||||
}
|
|
||||||
|
|
||||||
Type interfaceType = typeof(TProcess);
|
|
||||||
|
|
||||||
var interfaces = interfaceType.GetInterfaces();
|
|
||||||
if (interfaceType.IsInterface == false)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"{typeof(TProcess).FullName} is not interface");
|
|
||||||
}
|
|
||||||
if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsProcess))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"{typeof(TProcess).FullName} does not directly inherit the {nameof(IEcsProcess)} interface");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_runnerImplementationType = subclass;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Instantiate
|
|
||||||
private static void CheckRunnerValide(Type type) //TODO доработать проверку валидности реалиазации ранера
|
|
||||||
{
|
|
||||||
Type targetInterface = typeof(TProcess);
|
|
||||||
if (type.IsAbstract)
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
Type GetRunnerBaseType(Type inType)
|
|
||||||
{
|
|
||||||
if (inType.IsGenericType && inType.GetGenericTypeDefinition() == typeof(EcsRunner<>))
|
|
||||||
return inType;
|
|
||||||
if (inType.BaseType != null)
|
|
||||||
return GetRunnerBaseType(inType.BaseType);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Type baseType = GetRunnerBaseType(type);
|
|
||||||
Type baseTypeArgument = baseType.GenericTypeArguments[0];
|
|
||||||
|
|
||||||
if (baseTypeArgument != targetInterface)
|
|
||||||
{
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!type.GetInterfaces().Any(o => o == targetInterface))
|
|
||||||
{
|
|
||||||
throw new EcsRunnerImplementationException($"Runner {GetGenericTypeFullName(type, 1)} does not implement interface {GetGenericTypeFullName(baseTypeArgument, 1)}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static TProcess Instantiate(EcsPipeline source)
|
|
||||||
{
|
|
||||||
EcsProcess<TProcess> process = source.GetProcess<TProcess>();
|
|
||||||
if (_runnerImplementationType == null)
|
|
||||||
{
|
|
||||||
Type interfaceType = typeof(TProcess);
|
|
||||||
if (interfaceType.TryGetCustomAttribute(out BindWithEcsRunnerAttribute atr))
|
|
||||||
{
|
|
||||||
Type runnerImplementationType = atr.runnerType;
|
|
||||||
if (interfaceType.IsGenericType)
|
|
||||||
{
|
|
||||||
Type[] genericTypes = interfaceType.GetGenericArguments();
|
|
||||||
runnerImplementationType = runnerImplementationType.MakeGenericType(genericTypes);
|
|
||||||
}
|
|
||||||
CheckRunnerValide(runnerImplementationType);
|
|
||||||
_runnerImplementationType = runnerImplementationType;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new EcsFrameworkException("Процесс не связан с раннером, используйте атрибуут BindWithEcsRunner(Type runnerType)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var instance = (EcsRunner<TProcess>)Activator.CreateInstance(_runnerImplementationType);
|
|
||||||
return (TProcess)(IEcsProcess)instance.Set(source, process);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private EcsPipeline _source;
|
private EcsPipeline _source;
|
||||||
private EcsProcess<TProcess> _process;
|
private EcsProcess<TProcess> _process;
|
||||||
private bool _isDestroyed;
|
private bool _isInit = false;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public EcsPipeline Pipeline
|
public EcsPipeline Pipeline
|
||||||
@ -167,46 +86,32 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
get { return _process; }
|
get { return _process; }
|
||||||
}
|
}
|
||||||
public bool IsDestroyed
|
|
||||||
{
|
|
||||||
get { return _isDestroyed; }
|
|
||||||
}
|
|
||||||
public bool IsEmpty
|
public bool IsEmpty
|
||||||
{
|
{
|
||||||
get { return _process.IsNullOrEmpty; }
|
get { return _process.IsNullOrEmpty; }
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private EcsRunner<TProcess> Set(EcsPipeline source, EcsProcess<TProcess> process)
|
#region Constructor Init OnSetup
|
||||||
|
public EcsRunner() { }
|
||||||
|
internal override sealed void Init_Internal(EcsPipeline source)
|
||||||
{
|
{
|
||||||
|
if (_isInit)
|
||||||
|
{
|
||||||
|
Throw.UndefinedException();
|
||||||
|
}
|
||||||
|
_isInit = true;
|
||||||
_source = source;
|
_source = source;
|
||||||
this._process = process;
|
_process = source.GetProcess<TProcess>();
|
||||||
OnSetup();
|
OnSetup();
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
internal void Rebuild()
|
protected virtual void OnSetup() { }
|
||||||
{
|
#endregion
|
||||||
Set(_source, _source.GetProcess<TProcess>());
|
|
||||||
}
|
|
||||||
public void Destroy()
|
|
||||||
{
|
|
||||||
_isDestroyed = true;
|
|
||||||
_source.OnRunnerDestroy_Internal(this);
|
|
||||||
_source = null;
|
|
||||||
_process = EcsProcess<TProcess>.Empty;
|
|
||||||
OnDestroy();
|
|
||||||
}
|
|
||||||
protected virtual void OnSetup() { } //TODO rename to OnInitialize
|
|
||||||
protected virtual void OnDestroy() { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Extensions
|
#region Extensions
|
||||||
public static class EcsRunner
|
public static class IEcsProcessExtensions
|
||||||
{
|
|
||||||
public static void Destroy(IEcsProcess runner) => ((IEcsRunner)runner).Destroy();
|
|
||||||
}
|
|
||||||
public static class IEcsSystemExtensions
|
|
||||||
{
|
{
|
||||||
public static bool IsRunner(this IEcsProcess self)
|
public static bool IsRunner(this IEcsProcess self)
|
||||||
{
|
{
|
||||||
@ -214,85 +119,4 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public static class EcsProcessUtility
|
|
||||||
{
|
|
||||||
private struct ProcessInterface
|
|
||||||
{
|
|
||||||
public Type interfaceType;
|
|
||||||
public string processName;
|
|
||||||
public ProcessInterface(Type interfaceType, string processName)
|
|
||||||
{
|
|
||||||
this.interfaceType = interfaceType;
|
|
||||||
this.processName = processName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static Dictionary<Type, ProcessInterface> _processes = new Dictionary<Type, ProcessInterface>();
|
|
||||||
private static HashSet<Type> _systems = new HashSet<Type>();
|
|
||||||
|
|
||||||
static EcsProcessUtility()
|
|
||||||
{
|
|
||||||
Type processBasicInterface = typeof(IEcsProcess);
|
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
var types = assembly.GetTypes();
|
|
||||||
foreach (var type in types)
|
|
||||||
{
|
|
||||||
if (type.GetInterface(nameof(IEcsProcess)) != null || type == processBasicInterface)
|
|
||||||
{
|
|
||||||
if (type.IsInterface)
|
|
||||||
{
|
|
||||||
string name = type.Name;
|
|
||||||
if (name[0] == 'I' && name.Length > 1 && char.IsUpper(name[1]))
|
|
||||||
name = name.Substring(1);
|
|
||||||
name = Regex.Replace(name, @"\bEcs|Process\b", "");
|
|
||||||
if (Regex.IsMatch(name, "`\\w{1,}$"))
|
|
||||||
{
|
|
||||||
var s = name.Split('`');
|
|
||||||
name = s[0] + $"<{s[1]}>";
|
|
||||||
}
|
|
||||||
_processes.Add(type, new ProcessInterface(type, name));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_systems.Add(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Systems
|
|
||||||
public static bool IsSystem(Type type) => _systems.Contains(type);
|
|
||||||
public static bool IsEcsSystem(this Type type) => _systems.Contains(type);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Process
|
|
||||||
public static bool IsProcessInterface(Type type)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
|
||||||
return _processes.ContainsKey(type);
|
|
||||||
}
|
|
||||||
public static bool IsEcsProcessInterface(this Type type) => IsProcessInterface(type);
|
|
||||||
|
|
||||||
public static string GetProcessInterfaceName(Type type)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
|
||||||
return _processes[type].processName;
|
|
||||||
}
|
|
||||||
public static bool TryGetProcessInterfaceName(Type type, out string name)
|
|
||||||
{
|
|
||||||
if (type.IsGenericType) type = type.GetGenericTypeDefinition();
|
|
||||||
bool result = _processes.TryGetValue(type, out ProcessInterface data);
|
|
||||||
name = data.processName;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<Type> GetEcsProcessInterfaces(this Type self)
|
|
||||||
{
|
|
||||||
return self.GetInterfaces().Where(o => o.IsEcsProcessInterface());
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using DCFApixels.DragonECS.Internal;
|
using DCFApixels.DragonECS.Internal;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
@ -110,12 +111,16 @@ namespace DCFApixels.DragonECS
|
|||||||
TPool newPool = new TPool();
|
TPool newPool = new TPool();
|
||||||
|
|
||||||
Type componentType = newPool.ComponentType;
|
Type componentType = newPool.ComponentType;
|
||||||
//#if DEBUG //проверка соответсвия типов
|
#if DEBUG //проверка соответсвия типов
|
||||||
// if(componentType != typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0])
|
#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.
|
||||||
// {
|
if (componentType != typeof(TPool).GetInterfaces()
|
||||||
// Throw.UndefinedException();
|
.First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>))
|
||||||
// }
|
.GetGenericArguments()[0])
|
||||||
//#endif
|
{
|
||||||
|
Throw.UndefinedException();
|
||||||
|
}
|
||||||
|
#pragma warning restore 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.
|
||||||
|
#endif
|
||||||
int componentTypeCode = EcsTypeCode.Get(componentType);
|
int componentTypeCode = EcsTypeCode.Get(componentType);
|
||||||
|
|
||||||
if (_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID))
|
if (_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID))
|
||||||
@ -136,11 +141,6 @@ namespace DCFApixels.DragonECS
|
|||||||
Array.Resize(ref _poolComponentCounts, _pools.Length);
|
Array.Resize(ref _poolComponentCounts, _pools.Length);
|
||||||
ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
|
||||||
|
|
||||||
//for (int i = 0; i < _entitiesCapacity; i++)
|
|
||||||
//{
|
|
||||||
// //Array.Resize(ref _entityComponentMasks[i], _pools.Length / 32 + 1);
|
|
||||||
//}
|
|
||||||
|
|
||||||
int newEntityComponentMaskLength = _pools.Length / COMPONENT_MATRIX_MASK_BITSIZE + 1;
|
int newEntityComponentMaskLength = _pools.Length / COMPONENT_MATRIX_MASK_BITSIZE + 1;
|
||||||
int dif = newEntityComponentMaskLength - _entityComponentMaskLength;
|
int dif = newEntityComponentMaskLength - _entityComponentMaskLength;
|
||||||
if (dif > 0)
|
if (dif > 0)
|
||||||
|
@ -124,7 +124,9 @@ namespace DCFApixels.DragonECS
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
InitNode(new InjectionNode<T>(type));
|
InitNode(new InjectionNode<T>(type));
|
||||||
|
#if !REFLECTION_DISABLED
|
||||||
if (IsCanInstantiated(type))
|
if (IsCanInstantiated(type))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
InitBranch(new InjectionBranch(this, type, true));
|
InitBranch(new InjectionBranch(this, type, true));
|
||||||
}
|
}
|
||||||
@ -184,3 +186,4 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,15 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
}
|
}
|
||||||
internal static unsafe class UnmanagedArrayUtility
|
internal static unsafe class UnmanagedArrayUtility
|
||||||
{
|
{
|
||||||
|
private static class MetaCache<T>
|
||||||
|
{
|
||||||
|
public readonly static int Size;
|
||||||
|
static MetaCache()
|
||||||
|
{
|
||||||
|
T def = default;
|
||||||
|
Size = Marshal.SizeOf(def);
|
||||||
|
}
|
||||||
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T* New<T>(int capacity) where T : unmanaged
|
public static T* New<T>(int capacity) where T : unmanaged
|
||||||
{
|
{
|
||||||
@ -133,7 +142,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static T* NewAndInit<T>(int capacity) where T : unmanaged
|
public static T* NewAndInit<T>(int capacity) where T : unmanaged
|
||||||
{
|
{
|
||||||
int newSize = Marshal.SizeOf(typeof(T)) * capacity;
|
int newSize = MetaCache<T>.Size * capacity;
|
||||||
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
||||||
|
|
||||||
for (int i = 0; i < newSize; i++)
|
for (int i = 0; i < newSize; i++)
|
||||||
@ -144,7 +153,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void NewAndInit<T>(out T* ptr, int capacity) where T : unmanaged
|
public static void NewAndInit<T>(out T* ptr, int capacity) where T : unmanaged
|
||||||
{
|
{
|
||||||
int newSize = Marshal.SizeOf(typeof(T)) * capacity;
|
int newSize = MetaCache<T>.Size * capacity;
|
||||||
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer();
|
||||||
|
|
||||||
for (int i = 0; i < newSize; i++)
|
for (int i = 0; i < newSize; i++)
|
||||||
@ -182,7 +191,7 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
{
|
{
|
||||||
return (T*)(Marshal.ReAllocHGlobal(
|
return (T*)(Marshal.ReAllocHGlobal(
|
||||||
new IntPtr(oldPointer),
|
new IntPtr(oldPointer),
|
||||||
new IntPtr(Marshal.SizeOf(typeof(T)) * newCount))).ToPointer();
|
new IntPtr(MetaCache<T>.Size * newCount))).ToPointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,40 +605,6 @@ namespace DCFApixels.DragonECS.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static TEnum AllFlags<TEnum>() where TEnum : unmanaged, Enum
|
|
||||||
{
|
|
||||||
return EnumCache<TEnum>.allFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class EnumCache<TEnum> where TEnum : unmanaged, Enum
|
|
||||||
{
|
|
||||||
public readonly static TEnum empty;
|
|
||||||
public readonly static TEnum allFlags;
|
|
||||||
public readonly static int valuesCount;
|
|
||||||
public readonly static int size;
|
|
||||||
|
|
||||||
static EnumCache()
|
|
||||||
{
|
|
||||||
Array values = Enum.GetValues(typeof(TEnum));
|
|
||||||
size = sizeof(TEnum);
|
|
||||||
|
|
||||||
long result = 0;
|
|
||||||
valuesCount = values.Length;
|
|
||||||
for (int i = 0; i < valuesCount; i++)
|
|
||||||
{
|
|
||||||
result |= (long)values.GetValue(i);
|
|
||||||
}
|
|
||||||
ulong emptyBits = 0;
|
|
||||||
|
|
||||||
allFlags = *(TEnum*)&result;
|
|
||||||
empty = *(TEnum*)&emptyBits;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region FindBitsResult removed
|
#region FindBitsResult removed
|
||||||
|
@ -21,17 +21,21 @@ namespace DCFApixels.DragonECS
|
|||||||
private T _fakeComponent;
|
private T _fakeComponent;
|
||||||
private EcsWorld.PoolsMediator _mediator;
|
private EcsWorld.PoolsMediator _mediator;
|
||||||
|
|
||||||
#region Constructors
|
#region CheckValide
|
||||||
|
#if DEBUG
|
||||||
private static bool _isInvalidType;
|
private static bool _isInvalidType;
|
||||||
static EcsTagPool()
|
static EcsTagPool()
|
||||||
{
|
{
|
||||||
|
#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.
|
||||||
_isInvalidType = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length > 0;
|
_isInvalidType = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length > 0;
|
||||||
|
#pragma warning restore IL2090
|
||||||
}
|
}
|
||||||
public EcsTagPool()
|
public EcsTagPool()
|
||||||
{
|
{
|
||||||
if (_isInvalidType)
|
if (_isInvalidType)
|
||||||
throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data.");
|
throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data.");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Properites
|
#region Properites
|
||||||
|
Loading…
Reference in New Issue
Block a user