diff --git a/src/Builtin/BaseProcesses.cs b/src/Builtin/BaseProcesses.cs index e9d277c..a9384d5 100644 --- a/src/Builtin/BaseProcesses.cs +++ b/src/Builtin/BaseProcesses.cs @@ -1,5 +1,4 @@ #pragma warning disable CS0162 // Обнаружен недостижимый код -using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.RunnersCore; using System; @@ -7,28 +6,24 @@ namespace DCFApixels.DragonECS { [MetaName(nameof(PreInit))] [MetaColor(MetaColor.Orange)] - [BindWithEcsRunner(typeof(EcsPreInitRunner))] public interface IEcsPreInit : IEcsProcess { void PreInit(); } [MetaName(nameof(Init))] [MetaColor(MetaColor.Orange)] - [BindWithEcsRunner(typeof(EcsInitRunner))] public interface IEcsInit : IEcsProcess { void Init(); } [MetaName(nameof(Run))] [MetaColor(MetaColor.Orange)] - [BindWithEcsRunner(typeof(EcsRunRunner))] public interface IEcsRun : IEcsProcess { void Run(); } [MetaName(nameof(Destroy))] [MetaColor(MetaColor.Orange)] - [BindWithEcsRunner(typeof(EcsDestroyRunner))] public interface IEcsDestroy : IEcsProcess { void Destroy(); @@ -38,7 +33,7 @@ namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS.Internal { [MetaColor(MetaColor.Orange)] - public sealed class EcsPreInitRunner : EcsRunner, IEcsPreInit + internal sealed class EcsPreInitRunner : EcsRunner, IEcsPreInit { #if DEBUG && !DISABLE_DEBUG private EcsProfilerMarker[] _markers; @@ -73,7 +68,10 @@ namespace DCFApixels.DragonECS.Internal #else foreach (var item in Process) { - try { item.PreInit(); } + try + { + item.PreInit(); + } catch (Exception e) { #if DISABLE_CATH_EXCEPTIONS @@ -86,7 +84,7 @@ namespace DCFApixels.DragonECS.Internal } } [MetaColor(MetaColor.Orange)] - public sealed class EcsInitRunner : EcsRunner, IEcsInit + internal sealed class EcsInitRunner : EcsRunner, IEcsInit { #if DEBUG && !DISABLE_DEBUG private EcsProfilerMarker[] _markers; @@ -134,7 +132,7 @@ namespace DCFApixels.DragonECS.Internal } } [MetaColor(MetaColor.Orange)] - public sealed class EcsRunRunner : EcsRunner, IEcsRun + internal sealed class EcsRunRunner : EcsRunner, IEcsRun { #if DEBUG && !DISABLE_DEBUG private EcsProfilerMarker[] _markers; @@ -182,7 +180,7 @@ namespace DCFApixels.DragonECS.Internal } } [MetaColor(MetaColor.Orange)] - public sealed class EcsDestroyRunner : EcsRunner, IEcsDestroy + internal sealed class EcsDestroyRunner : EcsRunner, IEcsDestroy { #if DEBUG && !DISABLE_DEBUG private EcsProfilerMarker[] _markers; @@ -195,7 +193,7 @@ namespace DCFApixels.DragonECS.Internal } } #endif - void IEcsDestroy.Destroy() + public void Destroy() { #if DEBUG && !DISABLE_DEBUG for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++) diff --git a/src/Consts.cs b/src/Consts.cs index 572b286..9d65478 100644 --- a/src/Consts.cs +++ b/src/Consts.cs @@ -44,6 +44,15 @@ true; #else false; +#endif + public const bool DISABLE_CATH_EXCEPTIONS = +#if DISABLE_CATH_EXCEPTIONS + true; +#else + false; #endif } } +//#if UNITY_2020_3_OR_NEWER +// [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve] +//#endif diff --git a/src/Debug/EcsDebugUtility.cs b/src/Debug/EcsDebugUtility.cs index bef2053..184a502 100644 --- a/src/Debug/EcsDebugUtility.cs +++ b/src/Debug/EcsDebugUtility.cs @@ -49,8 +49,11 @@ namespace DCFApixels.DragonECS } private static string AutoToString(object target, Type type, bool isWriteName) { +#if !REFLECTION_DISABLED //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); +#pragma warning restore IL2070 string[] values = new string[fields.Length]; for (int i = 0; i < fields.Length; i++) values[i] = (fields[i].GetValue(target) ?? "NULL").ToString(); @@ -58,6 +61,9 @@ namespace DCFApixels.DragonECS return $"{type.Name}({string.Join(", ", values)})"; else return $"({string.Join(", ", values)})"; +#endif + EcsDebug.PrintWarning($"Reflection is not available, the {nameof(AutoToString)} method does not work."); + return string.Empty; } #endregion diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs index af53d08..ce6c633 100644 --- a/src/EcsAspect.cs +++ b/src/EcsAspect.cs @@ -48,15 +48,20 @@ namespace DCFApixels.DragonECS { Builder builder = new Builder(world); Type aspectType = typeof(TAspect); - ConstructorInfo constructorInfo = aspectType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Builder) }, null); 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) { newAspect = (EcsAspect)constructorInfo.Invoke(new object[] { builder }); } 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(); +#pragma warning restore IL2091 newAspect.Init(builder); } newAspect._source = world; @@ -92,13 +97,15 @@ namespace DCFApixels.DragonECS #region Include/Exclude/Optional/Combine public TPool Include() where TPool : IEcsPoolImplementation, new() { - IncludeImplicit(typeof(TPool).GetGenericArguments()[0]); - return _world.GetPool(); + var pool = _world.GetPool(); + IncludeImplicit(pool.ComponentType); + return pool; } public TPool Exclude() where TPool : IEcsPoolImplementation, new() { - ExcludeImplicit(typeof(TPool).GetGenericArguments()[0]); - return _world.GetPool(); + var pool = _world.GetPool(); + ExcludeImplicit(pool.ComponentType); + return pool; } public TPool Optional() where TPool : IEcsPoolImplementation, new() { diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index ac2db02..260a97c 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -21,12 +21,14 @@ namespace DCFApixels.DragonECS private IEcsProcess[] _allSystems; private Dictionary _processes = new Dictionary(); private Dictionary _runners = new Dictionary(); - private IEcsRun _runRunnerCache; + private EcsRunRunner _runRunnerCache; private bool _isInit = false; private bool _isDestoryed = false; +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS private EcsProfilerMarker _initBarker = new EcsProfilerMarker("EcsPipeline.Init"); +#endif #region Properties public IEcsPipelineConfig Config @@ -64,7 +66,7 @@ namespace DCFApixels.DragonECS } #endregion - #region Get Process/Runner + #region Get Process public EcsProcess GetProcess() where T : IEcsProcess { Type type = typeof(T); @@ -80,31 +82,43 @@ namespace DCFApixels.DragonECS } return new EcsProcess(result); } -#if !REFLECTION_DISABLED + #endregion + + #region Declare/Get Runner + public TRunner DeclareRunner() 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() where T : IEcsProcess { - Type interfaceType = typeof(T); - if (_runners.TryGetValue(interfaceType, out IEcsRunner result) == false) + if (_runners.TryGetValue(typeof(T), out IEcsRunner result)) { - result = (IEcsRunner)EcsRunner.Instantiate(this); - _runners.Add(result.GetType(), result); - _runners.Add(interfaceType, result); + return (T)result; } - return (T)result; + Throw.UndefinedException(); + return default; } -#endif - public T GetRunnerInstance() where T : IEcsRunner, new() + public bool TryGetRunner(out T runner) where T : IEcsProcess { - Type runnerType = typeof(T); - if (_runners.TryGetValue(runnerType, out IEcsRunner result) == false) + if (_runners.TryGetValue(typeof(T), out IEcsRunner result)) { - result = new T(); - _runners.Add(runnerType, result); -#if !REFLECTION_DISABLED - _runners.Add(result.Interface, result); -#endif + runner = (T)result; + return true; } - return (T)result; + runner = default; + return false; } #endregion @@ -123,7 +137,9 @@ namespace DCFApixels.DragonECS EcsDebug.PrintWarning($"This {nameof(EcsPipeline)} has already been initialized"); return; } +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS _initBarker.Begin(); +#endif EcsProcess members = GetProcess(); foreach (var member in members) { @@ -132,33 +148,31 @@ namespace DCFApixels.DragonECS _injector = _injectorBuilder.Build(this); _injectorBuilder = null; - var preInitRunner = GetRunner(); - preInitRunner.PreInit(); - EcsRunner.Destroy(preInitRunner); - var initRunner = GetRunner(); - initRunner.Init(); - EcsRunner.Destroy(initRunner); + DeclareRunner().PreInit(); + DeclareRunner().Init(); + _runRunnerCache = DeclareRunner(); - _runRunnerCache = GetRunner(); _isInit = true; GC.Collect(); +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS _initBarker.End(); +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Run() { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run)); - if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run)); + if (!_isInit) { Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run)); } + if (_isDestoryed) { Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run)); } #endif _runRunnerCache.Run(); } public void Destroy() { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Destroy)); + if (!_isInit) { Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Destroy)); } #endif if (_isDestoryed) { @@ -166,7 +180,7 @@ namespace DCFApixels.DragonECS return; } _isDestoryed = true; - GetRunner().Destroy(); + DeclareRunner().Destroy(); } #endregion @@ -184,7 +198,10 @@ namespace DCFApixels.DragonECS public readonly LayerList Layers; private readonly IEcsPipelineConfigWriter _config; private readonly Injector.Builder _injector; +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("EcsPipeline.Build"); +#endif + private List _initDeclaredRunners = new List(4); public IEcsPipelineConfigWriter Config { @@ -196,8 +213,9 @@ namespace DCFApixels.DragonECS } public Builder(IEcsPipelineConfigWriter config = null) { +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS _buildBarker.Begin(); - +#endif if (config == null) { config = new EcsPipelineConfig(); } _config = config; @@ -214,6 +232,11 @@ namespace DCFApixels.DragonECS _uniqueTypes = new HashSet(); _systems = new Dictionary>(KEYS_CAPACITY); } + public Builder DeclareRunner() where T : EcsRunner, IEcsRunner, new() + { + _initDeclaredRunners.Add(new InitDeclaredRunner()); + return this; + } public Builder Add(IEcsProcess system, string layerName = null) { AddInternal(system, layerName, false); @@ -268,10 +291,28 @@ namespace DCFApixels.DragonECS if (_systems.TryGetValue(item, out var 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(); - return new EcsPipeline(_config.GetPipelineConfig(), _injector, result.ToArray()); +#endif + return pipeline; } + private abstract class InitDeclaredRunner + { + public abstract void Declare(EcsPipeline pipeline); + } + private class InitDeclaredRunner : InitDeclaredRunner where T : EcsRunner, IEcsRunner, new() + { + public override void Declare(EcsPipeline pipeline) + { + pipeline.DeclareRunner(); + } + } public class LayerList : IEnumerable { private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index 95a9b91..68eb516 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -1,4 +1,5 @@ -using DCFApixels.DragonECS.RunnersCore; +using DCFApixels.DragonECS.Internal; +using DCFApixels.DragonECS.RunnersCore; using System; using System.Collections.Generic; using System.Linq; @@ -7,148 +8,66 @@ using static DCFApixels.DragonECS.EcsDebugUtility; 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 { } 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; } Type Interface { get; } EcsProcessRaw ProcessRaw { get; } - bool IsDestroyed { get; } bool IsEmpty { get; } - void Destroy(); } -#if UNITY_2020_3_OR_NEWER - [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve] -#endif - public abstract class EcsRunner : IEcsProcess, IEcsRunner + public abstract class EcsRunner : EcsRunner, IEcsRunner, 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 process = source.GetProcess(); - 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)Activator.CreateInstance(_runnerImplementationType); - return (TProcess)(IEcsProcess)instance.Set(source, process); - } - #endregion - private EcsPipeline _source; private EcsProcess _process; - private bool _isDestroyed; + private bool _isInit = false; #region Properties public EcsPipeline Pipeline @@ -167,46 +86,32 @@ namespace DCFApixels.DragonECS { get { return _process; } } - public bool IsDestroyed - { - get { return _isDestroyed; } - } public bool IsEmpty { get { return _process.IsNullOrEmpty; } } #endregion - private EcsRunner Set(EcsPipeline source, EcsProcess process) + #region Constructor Init OnSetup + public EcsRunner() { } + internal override sealed void Init_Internal(EcsPipeline source) { + if (_isInit) + { + Throw.UndefinedException(); + } + _isInit = true; _source = source; - this._process = process; + _process = source.GetProcess(); OnSetup(); - return this; } - internal void Rebuild() - { - Set(_source, _source.GetProcess()); - } - public void Destroy() - { - _isDestroyed = true; - _source.OnRunnerDestroy_Internal(this); - _source = null; - _process = EcsProcess.Empty; - OnDestroy(); - } - protected virtual void OnSetup() { } //TODO rename to OnInitialize - protected virtual void OnDestroy() { } + protected virtual void OnSetup() { } + #endregion } } #region Extensions - public static class EcsRunner - { - public static void Destroy(IEcsProcess runner) => ((IEcsRunner)runner).Destroy(); - } - public static class IEcsSystemExtensions + public static class IEcsProcessExtensions { public static bool IsRunner(this IEcsProcess self) { @@ -214,85 +119,4 @@ namespace DCFApixels.DragonECS } } #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 _processes = new Dictionary(); - private static HashSet _systems = new HashSet(); - - 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 GetEcsProcessInterfaces(this Type self) - { - return self.GetInterfaces().Where(o => o.IsEcsProcessInterface()); - } - #endregion - - } } diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs index 0df9e46..cd34e23 100644 --- a/src/EcsWorld.pools.cs +++ b/src/EcsWorld.pools.cs @@ -1,5 +1,6 @@ using DCFApixels.DragonECS.Internal; using System; +using System.Linq; using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS @@ -110,12 +111,16 @@ namespace DCFApixels.DragonECS TPool newPool = new TPool(); Type componentType = newPool.ComponentType; - //#if DEBUG //проверка соответсвия типов - // if(componentType != typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0]) - // { - // Throw.UndefinedException(); - // } - //#endif +#if DEBUG //проверка соответсвия типов +#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() + .First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)) + .GetGenericArguments()[0]) + { + 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); if (_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID)) @@ -136,11 +141,6 @@ namespace DCFApixels.DragonECS Array.Resize(ref _poolComponentCounts, _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 dif = newEntityComponentMaskLength - _entityComponentMaskLength; if (dif > 0) diff --git a/src/Injections/Injector.cs b/src/Injections/Injector.cs index 728c991..9a17f34 100644 --- a/src/Injections/Injector.cs +++ b/src/Injections/Injector.cs @@ -124,7 +124,9 @@ namespace DCFApixels.DragonECS return false; } InitNode(new InjectionNode(type)); +#if !REFLECTION_DISABLED if (IsCanInstantiated(type)) +#endif { InitBranch(new InjectionBranch(this, type, true)); } @@ -184,3 +186,4 @@ namespace DCFApixels.DragonECS #endregion } } + diff --git a/src/Internal/ArrayUtility.cs b/src/Internal/ArrayUtility.cs index 9087337..1dd3e79 100644 --- a/src/Internal/ArrayUtility.cs +++ b/src/Internal/ArrayUtility.cs @@ -119,6 +119,15 @@ namespace DCFApixels.DragonECS.Internal } internal static unsafe class UnmanagedArrayUtility { + private static class MetaCache + { + public readonly static int Size; + static MetaCache() + { + T def = default; + Size = Marshal.SizeOf(def); + } + } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T* New(int capacity) where T : unmanaged { @@ -133,7 +142,7 @@ namespace DCFApixels.DragonECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T* NewAndInit(int capacity) where T : unmanaged { - int newSize = Marshal.SizeOf(typeof(T)) * capacity; + int newSize = MetaCache.Size * capacity; byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer(); for (int i = 0; i < newSize; i++) @@ -144,7 +153,7 @@ namespace DCFApixels.DragonECS.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void NewAndInit(out T* ptr, int capacity) where T : unmanaged { - int newSize = Marshal.SizeOf(typeof(T)) * capacity; + int newSize = MetaCache.Size * capacity; byte* newPointer = (byte*)Marshal.AllocHGlobal(newSize).ToPointer(); for (int i = 0; i < newSize; i++) @@ -182,7 +191,7 @@ namespace DCFApixels.DragonECS.Internal { return (T*)(Marshal.ReAllocHGlobal( new IntPtr(oldPointer), - new IntPtr(Marshal.SizeOf(typeof(T)) * newCount))).ToPointer(); + new IntPtr(MetaCache.Size * newCount))).ToPointer(); } } diff --git a/src/Internal/BitsUtility.cs b/src/Internal/BitsUtility.cs index 40fef17..c1f7497 100644 --- a/src/Internal/BitsUtility.cs +++ b/src/Internal/BitsUtility.cs @@ -605,40 +605,6 @@ namespace DCFApixels.DragonECS.Internal } } #endregion - - #region Other - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static TEnum AllFlags() where TEnum : unmanaged, Enum - { - return EnumCache.allFlags; - } - - private static class EnumCache 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 diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 92218d5..06f8d47 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -21,17 +21,21 @@ namespace DCFApixels.DragonECS private T _fakeComponent; private EcsWorld.PoolsMediator _mediator; - #region Constructors + #region CheckValide +#if DEBUG private static bool _isInvalidType; 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; +#pragma warning restore IL2090 } public EcsTagPool() { if (_isInvalidType) throw new EcsFrameworkException($"{typeof(T).Name} type must not contain any data."); } +#endif #endregion #region Properites