remove Reflection except inside EcsHybridPool

This commit is contained in:
Mikhail 2024-02-23 18:34:40 +08:00
parent c14a513172
commit 4888ad82e4
11 changed files with 200 additions and 333 deletions

View File

@ -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>, IEcsPreInit
internal sealed class EcsPreInitRunner : EcsRunner<IEcsPreInit>, 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>, IEcsInit
internal sealed class EcsInitRunner : EcsRunner<IEcsInit>, 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>, IEcsRun
internal sealed class EcsRunRunner : EcsRunner<IEcsRun>, 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>, IEcsDestroy
internal sealed class EcsDestroyRunner : EcsRunner<IEcsDestroy>, 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++)

View File

@ -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

View File

@ -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

View File

@ -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<TAspect>();
#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<TPool>() where TPool : IEcsPoolImplementation, new()
{
IncludeImplicit(typeof(TPool).GetGenericArguments()[0]);
return _world.GetPool<TPool>();
var pool = _world.GetPool<TPool>();
IncludeImplicit(pool.ComponentType);
return pool;
}
public TPool Exclude<TPool>() where TPool : IEcsPoolImplementation, new()
{
ExcludeImplicit(typeof(TPool).GetGenericArguments()[0]);
return _world.GetPool<TPool>();
var pool = _world.GetPool<TPool>();
ExcludeImplicit(pool.ComponentType);
return pool;
}
public TPool Optional<TPool>() where TPool : IEcsPoolImplementation, new()
{

View File

@ -21,12 +21,14 @@ namespace DCFApixels.DragonECS
private IEcsProcess[] _allSystems;
private Dictionary<Type, Array> _processes = new Dictionary<Type, Array>();
private Dictionary<Type, IEcsRunner> _runners = new Dictionary<Type, IEcsRunner>();
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<T> GetProcess<T>() where T : IEcsProcess
{
Type type = typeof(T);
@ -80,31 +82,43 @@ namespace DCFApixels.DragonECS
}
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
{
Type interfaceType = typeof(T);
if (_runners.TryGetValue(interfaceType, out IEcsRunner result) == false)
if (_runners.TryGetValue(typeof(T), out IEcsRunner result))
{
result = (IEcsRunner)EcsRunner<T>.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<T>() where T : IEcsRunner, new()
public bool TryGetRunner<T>(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<IEcsPipelineMember> members = GetProcess<IEcsPipelineMember>();
foreach (var member in members)
{
@ -132,33 +148,31 @@ namespace DCFApixels.DragonECS
_injector = _injectorBuilder.Build(this);
_injectorBuilder = null;
var preInitRunner = GetRunner<IEcsPreInit>();
preInitRunner.PreInit();
EcsRunner.Destroy(preInitRunner);
var initRunner = GetRunner<IEcsInit>();
initRunner.Init();
EcsRunner.Destroy(initRunner);
DeclareRunner<EcsPreInitRunner>().PreInit();
DeclareRunner<EcsInitRunner>().Init();
_runRunnerCache = DeclareRunner<EcsRunRunner>();
_runRunnerCache = GetRunner<IEcsRun>();
_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<IEcsDestroy>().Destroy();
DeclareRunner<EcsDestroyRunner>().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<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(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<Type>();
_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)
{
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<T> : InitDeclaredRunner where T : EcsRunner, IEcsRunner, new()
{
public override void Declare(EcsPipeline pipeline)
{
pipeline.DeclareRunner<T>();
}
}
public class LayerList : IEnumerable<string>
{
private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add

View File

@ -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<TProcess> : IEcsProcess, IEcsRunner
public abstract class EcsRunner<TProcess> : 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<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 EcsProcess<TProcess> _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<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;
this._process = process;
_process = source.GetProcess<TProcess>();
OnSetup();
return this;
}
internal void Rebuild()
{
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() { }
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<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
}
}

View File

@ -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)

View File

@ -124,7 +124,9 @@ namespace DCFApixels.DragonECS
return false;
}
InitNode(new InjectionNode<T>(type));
#if !REFLECTION_DISABLED
if (IsCanInstantiated(type))
#endif
{
InitBranch(new InjectionBranch(this, type, true));
}
@ -184,3 +186,4 @@ namespace DCFApixels.DragonECS
#endregion
}
}

View File

@ -119,6 +119,15 @@ namespace DCFApixels.DragonECS.Internal
}
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)]
public static T* New<T>(int capacity) where T : unmanaged
{
@ -133,7 +142,7 @@ namespace DCFApixels.DragonECS.Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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();
for (int i = 0; i < newSize; i++)
@ -144,7 +153,7 @@ namespace DCFApixels.DragonECS.Internal
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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();
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<T>.Size * newCount))).ToPointer();
}
}

View File

@ -605,40 +605,6 @@ namespace DCFApixels.DragonECS.Internal
}
}
#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

View File

@ -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