diff --git a/src/Builtin/BaseProcesses.cs b/src/Builtin/BaseProcesses.cs index 468047e..bdf7b57 100644 --- a/src/Builtin/BaseProcesses.cs +++ b/src/Builtin/BaseProcesses.cs @@ -1,22 +1,27 @@ #pragma warning disable CS0162 // Обнаружен недостижимый код +using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.RunnersCore; using System; namespace DCFApixels.DragonECS { #region Interfaces + [EcsBindWithRunner(typeof(EcsPreInitProcessRunner))] public interface IEcsPreInitProcess : IEcsProcess { void PreInit(); } + [EcsBindWithRunner(typeof(EcsInitProcessRunner))] public interface IEcsInitProcess : IEcsProcess { void Init(); } + [EcsBindWithRunner(typeof(EcsRunProcessRunner))] public interface IEcsRunProcess : IEcsProcess { void Run(); } + [EcsBindWithRunner(typeof(EcsDestroyProcessRunner))] public interface IEcsDestroyProcess : IEcsProcess { void Destroy(); diff --git a/src/Builtin/InjectSystem.cs b/src/Builtin/InjectSystem.cs index 36d28d1..300a9c9 100644 --- a/src/Builtin/InjectSystem.cs +++ b/src/Builtin/InjectSystem.cs @@ -5,10 +5,12 @@ using System.Linq; namespace DCFApixels.DragonECS { + [EcsBindWithRunner(typeof(EcsPreInjectRunner))] public interface IEcsPreInject : IEcsProcess { void PreInject(object obj); } + [EcsBindWithRunner(typeof(EcsInjectRunner<>))] public interface IEcsInject : IEcsProcess { void Inject(T obj); diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index 704d3cd..0fbbf6e 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -23,6 +23,31 @@ namespace DCFApixels.DragonECS } public EcsRunnerFilterAttribute(object filter) : this(null, filter) { } } +#if UNITY_2020_3_OR_NEWER + [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve] +#endif + [AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)] + public sealed class EcsBindWithRunnerAttribute : Attribute + { + private static readonly Type baseType = typeof(EcsRunner<>); + public readonly Type runnerType; + public EcsBindWithRunnerAttribute(Type runnerType) + { + if (runnerType == null) + throw new ArgumentNullException(); + if (!Check(runnerType)) + throw new ArgumentException(); + this.runnerType = runnerType; + } + private bool Check(Type type) + { + if (type.IsGenericType && type.GetGenericTypeDefinition() == baseType) + return true; + if (type.BaseType != null) + return Check(type.BaseType); + return false; + } + } public interface IEcsProcess { } @@ -188,7 +213,25 @@ namespace DCFApixels.DragonECS #region Instantiate private static TInterface Instantiate(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter) { - if (_subclass == null) EcsRunnerActivator.InitFor(); + if(_subclass == null) + { + Type interfaceType = typeof(TInterface); + if (interfaceType.TryGetAttribute(out EcsBindWithRunnerAttribute atr)) + { + Type runnerType = atr.runnerType; + if (interfaceType.IsGenericType) + { + Type[] genericTypes = interfaceType.GetGenericArguments(); + runnerType = runnerType.MakeGenericType(genericTypes); + } + _subclass = runnerType; + } + else + { + EcsRunnerActivator.InitFor(); + } + } + var instance = (EcsRunner)Activator.CreateInstance(_subclass); return (TInterface)(IEcsProcess)instance.Set(source, targets, isHasFilter, filter); } @@ -201,7 +244,7 @@ namespace DCFApixels.DragonECS return Instantiate(source, FilterSystems(source.AllSystems, filter), true, filter); } #endregion - + private EcsPipeline _source; protected TInterface[] targets; private ReadOnlyCollection _targetsSealed;