From bb35fa61502cc45c3ed332fc9d5def248d84aefd Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Thu, 22 Feb 2024 22:16:03 +0800 Subject: [PATCH] return di, rework di, update for support unity 2020.1.0^ --- src/Builtin/BaseProcesses.cs | 8 +- src/Builtin/Worlds.cs | 11 ++ src/Builtin/Worlds.cs.meta | 11 ++ src/Configs.meta | 8 + src/Configs/EcsPipelineConfig.cs | 12 +- src/Configs/EcsPipelineConfig.cs.meta | 11 ++ src/Configs/EcsWorldConfig.cs | 12 +- src/Configs/IConfig.cs.meta | 11 ++ src/EcsPipeline.cs | 77 +++++--- src/EcsRunner.cs | 20 +- src/EcsWorld.cs | 3 +- src/Executors/EcsWhereToGroupExecutor.cs.meta | 11 ++ src/Executors/Queries.cs.meta | 11 ++ src/Injections.meta | 8 + src/Injections/EcsPipelineExtensions.cs | 50 +++++ src/Injections/EcsPipelineExtensions.cs.meta | 11 ++ src/Injections/Graph.meta | 8 + src/Injections/Graph/InjectionBranch.cs | 65 +++++++ src/Injections/Graph/InjectionBranch.cs.meta | 11 ++ src/Injections/Graph/InjectionNode.cs | 35 ++++ src/Injections/Graph/InjectionNode.cs.meta | 11 ++ src/Injections/InitInjectionSystem.cs | 54 ++++++ src/Injections/InitInjectionSystem.cs.meta | 11 ++ src/Injections/Injector.cs | 174 ++++++++++++++++++ src/Injections/Injector.cs.meta | 11 ++ src/Injections/Processes.cs | 61 ++++++ src/Injections/Processes.cs.meta | 11 ++ src/Injections/Utils.meta | 8 + src/Injections/Utils/Exceptions.cs | 12 ++ src/Injections/Utils/Exceptions.cs.meta | 11 ++ src/Injections/Utils/IInjectionBlock.cs | 29 +++ src/Injections/Utils/IInjectionBlock.cs.meta | 11 ++ src/Internal.meta | 8 + 33 files changed, 759 insertions(+), 47 deletions(-) create mode 100644 src/Builtin/Worlds.cs create mode 100644 src/Builtin/Worlds.cs.meta create mode 100644 src/Configs.meta create mode 100644 src/Configs/EcsPipelineConfig.cs.meta create mode 100644 src/Configs/IConfig.cs.meta create mode 100644 src/Executors/EcsWhereToGroupExecutor.cs.meta create mode 100644 src/Executors/Queries.cs.meta create mode 100644 src/Injections.meta create mode 100644 src/Injections/EcsPipelineExtensions.cs create mode 100644 src/Injections/EcsPipelineExtensions.cs.meta create mode 100644 src/Injections/Graph.meta create mode 100644 src/Injections/Graph/InjectionBranch.cs create mode 100644 src/Injections/Graph/InjectionBranch.cs.meta create mode 100644 src/Injections/Graph/InjectionNode.cs create mode 100644 src/Injections/Graph/InjectionNode.cs.meta create mode 100644 src/Injections/InitInjectionSystem.cs create mode 100644 src/Injections/InitInjectionSystem.cs.meta create mode 100644 src/Injections/Injector.cs create mode 100644 src/Injections/Injector.cs.meta create mode 100644 src/Injections/Processes.cs create mode 100644 src/Injections/Processes.cs.meta create mode 100644 src/Injections/Utils.meta create mode 100644 src/Injections/Utils/Exceptions.cs create mode 100644 src/Injections/Utils/Exceptions.cs.meta create mode 100644 src/Injections/Utils/IInjectionBlock.cs create mode 100644 src/Injections/Utils/IInjectionBlock.cs.meta create mode 100644 src/Internal.meta diff --git a/src/Builtin/BaseProcesses.cs b/src/Builtin/BaseProcesses.cs index 8cc945f..e9d277c 100644 --- a/src/Builtin/BaseProcesses.cs +++ b/src/Builtin/BaseProcesses.cs @@ -8,28 +8,28 @@ namespace DCFApixels.DragonECS [MetaName(nameof(PreInit))] [MetaColor(MetaColor.Orange)] [BindWithEcsRunner(typeof(EcsPreInitRunner))] - public interface IEcsPreInit : IEcsSystem + public interface IEcsPreInit : IEcsProcess { void PreInit(); } [MetaName(nameof(Init))] [MetaColor(MetaColor.Orange)] [BindWithEcsRunner(typeof(EcsInitRunner))] - public interface IEcsInit : IEcsSystem + public interface IEcsInit : IEcsProcess { void Init(); } [MetaName(nameof(Run))] [MetaColor(MetaColor.Orange)] [BindWithEcsRunner(typeof(EcsRunRunner))] - public interface IEcsRun : IEcsSystem + public interface IEcsRun : IEcsProcess { void Run(); } [MetaName(nameof(Destroy))] [MetaColor(MetaColor.Orange)] [BindWithEcsRunner(typeof(EcsDestroyRunner))] - public interface IEcsDestroy : IEcsSystem + public interface IEcsDestroy : IEcsProcess { void Destroy(); } diff --git a/src/Builtin/Worlds.cs b/src/Builtin/Worlds.cs new file mode 100644 index 0000000..db3c5a2 --- /dev/null +++ b/src/Builtin/Worlds.cs @@ -0,0 +1,11 @@ +namespace DCFApixels.DragonECS +{ + public sealed class EcsDefaultWorld : EcsWorld + { + public EcsDefaultWorld(IEcsWorldConfig config = null, short worldID = -1) : base(config, worldID) { } + } + public sealed class EcsEventWorld : EcsWorld + { + public EcsEventWorld(IEcsWorldConfig config = null, short worldID = -1) : base(config, worldID) { } + } +} diff --git a/src/Builtin/Worlds.cs.meta b/src/Builtin/Worlds.cs.meta new file mode 100644 index 0000000..6c52533 --- /dev/null +++ b/src/Builtin/Worlds.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 76bb6fc0896102347bbd36ed235e45f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Configs.meta b/src/Configs.meta new file mode 100644 index 0000000..8e150ad --- /dev/null +++ b/src/Configs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 180397e9b3d73d143a3239dd05b2a84b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Configs/EcsPipelineConfig.cs b/src/Configs/EcsPipelineConfig.cs index 46af458..c5f8859 100644 --- a/src/Configs/EcsPipelineConfig.cs +++ b/src/Configs/EcsPipelineConfig.cs @@ -19,11 +19,19 @@ namespace DCFApixels.DragonECS public EcsPipelineConfig() { } public EcsPipelineConfig(IEnumerable> range) { - _storage = new Dictionary(range); + _storage = new Dictionary(); + foreach (var item in range) + { + _storage.Add(item.Key, item.Value); + } } public EcsPipelineConfig(params KeyValuePair[] range) { - _storage = new Dictionary(range); + _storage = new Dictionary(); + foreach (var item in range) + { + _storage.Add(item.Key, item.Value); + } } public int Count diff --git a/src/Configs/EcsPipelineConfig.cs.meta b/src/Configs/EcsPipelineConfig.cs.meta new file mode 100644 index 0000000..12a7b60 --- /dev/null +++ b/src/Configs/EcsPipelineConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3699ffd374c5074ebd5240c20ae5ba5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Configs/EcsWorldConfig.cs b/src/Configs/EcsWorldConfig.cs index 7945574..0fbea2b 100644 --- a/src/Configs/EcsWorldConfig.cs +++ b/src/Configs/EcsWorldConfig.cs @@ -19,11 +19,19 @@ namespace DCFApixels.DragonECS public EcsWorldConfig() { } public EcsWorldConfig(IEnumerable> range) { - _storage = new Dictionary(range); + _storage = new Dictionary(); + foreach (var item in range) + { + _storage.Add(item.Key, item.Value); + } } public EcsWorldConfig(params KeyValuePair[] range) { - _storage = new Dictionary(range); + _storage = new Dictionary(); + foreach (var item in range) + { + _storage.Add(item.Key, item.Value); + } } public int Count diff --git a/src/Configs/IConfig.cs.meta b/src/Configs/IConfig.cs.meta new file mode 100644 index 0000000..c66d2c3 --- /dev/null +++ b/src/Configs/IConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8df433b2b6b0f2b4e83130a3d1c0cdd3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index c8e2da5..270fb5e 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -8,15 +8,16 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { - public interface IEcsPipelineMember : IEcsSystem + public interface IEcsPipelineMember : IEcsProcess { - public EcsPipeline Pipeline { get; set; } + EcsPipeline Pipeline { get; set; } } public sealed class EcsPipeline { private readonly IEcsPipelineConfig _config; + private readonly Injector _injector; - private IEcsSystem[] _allSystems; + private IEcsProcess[] _allSystems; private Dictionary _processes = new Dictionary(); private Dictionary _runners = new Dictionary(); private IEcsRun _runRunnerCache; @@ -29,9 +30,13 @@ namespace DCFApixels.DragonECS { get { return _config; } } - public EcsProcess AllSystems + public Injector Injector { - get { return new EcsProcess(_allSystems); } + get { return _injector; } + } + public EcsProcess AllSystems + { + get { return new EcsProcess(_allSystems); } } public IReadOnlyDictionary AllRunners { @@ -48,15 +53,16 @@ namespace DCFApixels.DragonECS #endregion #region Constructors - private EcsPipeline(IEcsPipelineConfig config, IEcsSystem[] systems) + private EcsPipeline(IEcsPipelineConfig config, Injector.Builder injector, IEcsProcess[] systems) { _config = config; _allSystems = systems; + _injector = injector.Build(this); } #endregion #region Get Process/Runner - public EcsProcess GetProcess() where T : IEcsSystem + public EcsProcess GetProcess() where T : IEcsProcess { Type type = typeof(T); T[] result; @@ -72,7 +78,7 @@ namespace DCFApixels.DragonECS return new EcsProcess(result); } #if !REFLECTION_DISABLED - public T GetRunner() where T : IEcsSystem + public T GetRunner() where T : IEcsProcess { Type interfaceType = typeof(T); if (_runners.TryGetValue(interfaceType, out IEcsRunner result) == false) @@ -120,6 +126,7 @@ namespace DCFApixels.DragonECS { member.Pipeline = this; } + Injector.Inject(this); var preInitRunner = GetRunner(); preInitRunner.PreInit(); @@ -130,6 +137,7 @@ namespace DCFApixels.DragonECS _runRunnerCache = GetRunner(); _isInit = true; + GC.Collect(); } @@ -166,37 +174,47 @@ namespace DCFApixels.DragonECS { private const int KEYS_CAPACITY = 4; private HashSet _uniqueTypes; - private readonly Dictionary> _systems; + private readonly Dictionary> _systems; private readonly string _basicLayer; public readonly LayerList Layers; private readonly IEcsPipelineConfigWriter _config; + private readonly Injector.Builder _injector; private EcsProfilerMarker _buildBarker = new EcsProfilerMarker("Build Marker"); public IEcsPipelineConfigWriter Config { get { return _config; } } + public Injector.Builder Injector + { + get { return _injector; } + } public Builder(IEcsPipelineConfigWriter config = null) { _buildBarker.Begin(); - if (config == null) - { - config = new EcsPipelineConfig(); - } + + if (config == null) { config = new EcsPipelineConfig(); } _config = config; + + _injector = new Injector.Builder(this); + _injector.Declare(); + _injector.Declare(); + _injector.Declare(); + _basicLayer = EcsConsts.BASIC_LAYER; Layers = new LayerList(this, _basicLayer); Layers.Insert(EcsConsts.BASIC_LAYER, EcsConsts.PRE_BEGIN_LAYER, EcsConsts.BEGIN_LAYER); Layers.InsertAfter(EcsConsts.BASIC_LAYER, EcsConsts.END_LAYER, EcsConsts.POST_END_LAYER); + _uniqueTypes = new HashSet(); - _systems = new Dictionary>(KEYS_CAPACITY); + _systems = new Dictionary>(KEYS_CAPACITY); } - public Builder Add(IEcsSystem system, string layerName = null) + public Builder Add(IEcsProcess system, string layerName = null) { AddInternal(system, layerName, false); return this; } - public Builder AddUnique(IEcsSystem system, string layerName = null) + public Builder AddUnique(IEcsProcess system, string layerName = null) { AddInternal(system, layerName, true); return this; @@ -205,16 +223,18 @@ namespace DCFApixels.DragonECS { _uniqueTypes.Remove(typeof(TSystem)); foreach (var list in _systems.Values) + { list.RemoveAll(o => o is TSystem); + } return this; } - private void AddInternal(IEcsSystem system, string layerName, bool isUnique) + private void AddInternal(IEcsProcess system, string layerName, bool isUnique) { if (layerName == null) layerName = _basicLayer; - List list; + List list; if (!_systems.TryGetValue(layerName, out list)) { - list = new List { new SystemsLayerMarkerSystem(layerName.ToString()) }; + list = new List { new SystemsLayerMarkerSystem(layerName.ToString()) }; _systems.Add(layerName, list); } if ((_uniqueTypes.Add(system.GetType()) == false && isUnique)) @@ -231,8 +251,8 @@ namespace DCFApixels.DragonECS } public EcsPipeline Build() { - List result = new List(32); - List basicBlockList = _systems[_basicLayer]; + List result = new List(32); + List basicBlockList = _systems[_basicLayer]; foreach (var item in _systems) { if (!Layers.Contains(item.Key)) @@ -244,8 +264,9 @@ namespace DCFApixels.DragonECS result.AddRange(list); } _buildBarker.End(); - return new EcsPipeline(_config.GetPipelineConfig(), result.ToArray()); + return new EcsPipeline(_config.GetPipelineConfig(), _injector, result.ToArray()); } + public class LayerList : IEnumerable { private const string ADD_LAYER = nameof(ADD_LAYER); // автоматический слой нужный только для метода Add @@ -365,7 +386,7 @@ namespace DCFApixels.DragonECS { return self == null || self.IsDestoryed; } - public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable range, string layerName = null) + public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable range, string layerName = null) { foreach (var item in range) { @@ -373,7 +394,7 @@ namespace DCFApixels.DragonECS } return self; } - public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable range, string layerName = null) + public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable range, string layerName = null) { foreach (var item in range) { @@ -393,7 +414,7 @@ namespace DCFApixels.DragonECS #region SystemsLayerMarkerSystem [MetaTags(MetaTags.HIDDEN)] [MetaColor(MetaColor.Black)] - public class SystemsLayerMarkerSystem : IEcsSystem + public class SystemsLayerMarkerSystem : IEcsProcess { public readonly string name; public SystemsLayerMarkerSystem(string name) => this.name = name; @@ -409,9 +430,9 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _systems.Length; } } - public IEcsSystem this[int index] + public IEcsProcess this[int index] { - get { return (IEcsSystem)_systems.GetValue(index); } + get { return (IEcsProcess)_systems.GetValue(index); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal EcsProcessRaw(Array systems) @@ -429,7 +450,7 @@ namespace DCFApixels.DragonECS } } public readonly struct EcsProcess : IReadOnlyCollection - where TProcess : IEcsSystem + where TProcess : IEcsProcess { public readonly static EcsProcess Empty = new EcsProcess(Array.Empty()); private readonly TProcess[] _systems; diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index eab554c..49c59cf 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -41,7 +41,7 @@ namespace DCFApixels.DragonECS } } - public interface IEcsSystem { } + public interface IEcsProcess { } namespace RunnersCore { @@ -58,8 +58,8 @@ namespace DCFApixels.DragonECS #if UNITY_2020_3_OR_NEWER [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve] #endif - public abstract class EcsRunner : IEcsSystem, IEcsRunner - where TProcess : IEcsSystem + public abstract class EcsRunner : IEcsProcess, IEcsRunner + where TProcess : IEcsProcess { #region Register private static Type _runnerImplementationType; @@ -78,9 +78,9 @@ namespace DCFApixels.DragonECS { throw new ArgumentException($"{typeof(TProcess).FullName} is not interface"); } - if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem)) + if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsProcess)) { - throw new ArgumentException($"{typeof(TProcess).FullName} does not directly inherit the {nameof(IEcsSystem)} interface"); + throw new ArgumentException($"{typeof(TProcess).FullName} does not directly inherit the {nameof(IEcsProcess)} interface"); } #endif _runnerImplementationType = subclass; @@ -142,7 +142,7 @@ namespace DCFApixels.DragonECS } } var instance = (EcsRunner)Activator.CreateInstance(_runnerImplementationType); - return (TProcess)(IEcsSystem)instance.Set(source, process); + return (TProcess)(IEcsProcess)instance.Set(source, process); } #endregion @@ -204,11 +204,11 @@ namespace DCFApixels.DragonECS #region Extensions public static class EcsRunner { - public static void Destroy(IEcsSystem runner) => ((IEcsRunner)runner).Destroy(); + public static void Destroy(IEcsProcess runner) => ((IEcsRunner)runner).Destroy(); } public static class IEcsSystemExtensions { - public static bool IsRunner(this IEcsSystem self) + public static bool IsRunner(this IEcsProcess self) { return self is IEcsRunner; } @@ -232,13 +232,13 @@ namespace DCFApixels.DragonECS static EcsProcessUtility() { - Type processBasicInterface = typeof(IEcsSystem); + Type processBasicInterface = typeof(IEcsProcess); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { var types = assembly.GetTypes(); foreach (var type in types) { - if (type.GetInterface(nameof(IEcsSystem)) != null || type == processBasicInterface) + if (type.GetInterface(nameof(IEcsProcess)) != null || type == processBasicInterface) { if (type.IsInterface) { diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 0dbb9b8..37e463a 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -404,7 +404,8 @@ namespace DCFApixels.DragonECS return; } unchecked { _version++; } - count = Math.Clamp(count, 0, _delEntBufferCount); + count = Math.Min(count, _delEntBufferCount); + count = Math.Max(count, 0); _delEntBufferCount -= count; ReadOnlySpan buffer = new ReadOnlySpan(_delEntBuffer, _delEntBufferCount, count); for (int i = 0; i < _poolsCount; i++) diff --git a/src/Executors/EcsWhereToGroupExecutor.cs.meta b/src/Executors/EcsWhereToGroupExecutor.cs.meta new file mode 100644 index 0000000..6497ae1 --- /dev/null +++ b/src/Executors/EcsWhereToGroupExecutor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5623a418399b20d46b965dcd1e8ef983 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Executors/Queries.cs.meta b/src/Executors/Queries.cs.meta new file mode 100644 index 0000000..1977501 --- /dev/null +++ b/src/Executors/Queries.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41740479532f2a543acd1ba18bf95af9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections.meta b/src/Injections.meta new file mode 100644 index 0000000..594eb60 --- /dev/null +++ b/src/Injections.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 546107521fffb574e8db9730a87c7337 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/EcsPipelineExtensions.cs b/src/Injections/EcsPipelineExtensions.cs new file mode 100644 index 0000000..159048c --- /dev/null +++ b/src/Injections/EcsPipelineExtensions.cs @@ -0,0 +1,50 @@ +using DCFApixels.DragonECS.Internal; + +namespace DCFApixels.DragonECS +{ + public static partial class EcsPipelineBuilderExtensions + { + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T data) + { + if (data == null) + { + Throw.ArgumentNull(); + } + self.Injector.Inject(data); + //self.Add(new InitInjectionSystem(data)); + if (data is IEcsModule module) + { + self.AddModule(module); + } + return self; + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1) + { + return self.Inject(d0).Inject(d1); + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2) + { + return self.Inject(d0).Inject(d1).Inject(d2); + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3) + { + return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3); + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4) + { + return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4); + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f) + { + return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f); + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f, T6 d6) + { + return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f).Inject(d6); + } + public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2, T3 d3, T4 d4, T5 f, T6 d6, T7 d7) + { + return self.Inject(d0).Inject(d1).Inject(d2).Inject(d3).Inject(d4).Inject(f).Inject(d6).Inject(d7); + } + } +} \ No newline at end of file diff --git a/src/Injections/EcsPipelineExtensions.cs.meta b/src/Injections/EcsPipelineExtensions.cs.meta new file mode 100644 index 0000000..13a3fb9 --- /dev/null +++ b/src/Injections/EcsPipelineExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6e83a9465b34a8148936bba8c2ee46ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Graph.meta b/src/Injections/Graph.meta new file mode 100644 index 0000000..1fe57f6 --- /dev/null +++ b/src/Injections/Graph.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b2dfe81532e7bfc4b805fdad7e75885c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Graph/InjectionBranch.cs b/src/Injections/Graph/InjectionBranch.cs new file mode 100644 index 0000000..e1df68f --- /dev/null +++ b/src/Injections/Graph/InjectionBranch.cs @@ -0,0 +1,65 @@ +using System; + +namespace DCFApixels.DragonECS +{ + public class InjectionBranch + { + private Injector _source; + private Type _type; + private InjectionNodeBase[] _nodes = new InjectionNodeBase[2]; + private int _nodesCount = 0; + private bool _isDeclared = false; + + public Type Type + { + get { return _type; } + } + public bool IsDeclared + { + get { return _isDeclared; } + } + public InjectionBranch(Injector source, Type type, bool isDeclared) + { + _source = source; + _isDeclared = isDeclared; + _type = type; + } + public void SetDeclaredTrue() + { + _isDeclared = true; + } + public void Inject(object obj) + { + for (int i = 0; i < _nodesCount; i++) + { + _nodes[i].Inject(obj); + } + if (obj is IInjectionBlock container) + { + container.InjectTo(new BlockInjector(_source)); + } + } + public void AddNode(InjectionNodeBase node) + { + if (_nodesCount >= _nodes.Length) + { + Array.Resize(ref _nodes, (_nodes.Length << 1) + 1); + } + _nodes[_nodesCount++] = node; + } + public void Trim() + { + if (_nodesCount <= 0) + { + _nodes = Array.Empty(); + return; + } + + InjectionNodeBase[] newNodes = new InjectionNodeBase[_nodesCount]; + for (int i = 0; i < newNodes.Length; i++) + { + newNodes[i] = _nodes[i]; + } + } + } +} diff --git a/src/Injections/Graph/InjectionBranch.cs.meta b/src/Injections/Graph/InjectionBranch.cs.meta new file mode 100644 index 0000000..6dc976c --- /dev/null +++ b/src/Injections/Graph/InjectionBranch.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb1a80182ece42c4281aaf3257cd727c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Graph/InjectionNode.cs b/src/Injections/Graph/InjectionNode.cs new file mode 100644 index 0000000..a5efc97 --- /dev/null +++ b/src/Injections/Graph/InjectionNode.cs @@ -0,0 +1,35 @@ +using System; + +namespace DCFApixels.DragonECS +{ + public abstract class InjectionNodeBase + { + private readonly Type _type; + public Type Type + { + get { return _type; } + } + protected InjectionNodeBase(Type type) + { + _type = type; + } + public abstract void Inject(object obj); + public abstract void Init(EcsPipeline pipeline); + } + public class InjectionNode : InjectionNodeBase + { + private EcsProcess> _process; + public InjectionNode(Type type) : base(type) { } + public override void Init(EcsPipeline pipeline) + { + _process = pipeline.GetProcess>(); + } + public override void Inject(object obj) + { + for (int i = 0; i < _process.Length; i++) + { + _process[i].Inject((T)obj); + } + } + } +} diff --git a/src/Injections/Graph/InjectionNode.cs.meta b/src/Injections/Graph/InjectionNode.cs.meta new file mode 100644 index 0000000..d0e662b --- /dev/null +++ b/src/Injections/Graph/InjectionNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da1da7839b55e5e45a04ee8fa740ba5a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/InitInjectionSystem.cs b/src/Injections/InitInjectionSystem.cs new file mode 100644 index 0000000..11e7f8e --- /dev/null +++ b/src/Injections/InitInjectionSystem.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; + +namespace DCFApixels.DragonECS.Internal +{ + public abstract class InitInjectSystemBase : IEcsProcess { } + + [MetaTags(MetaTags.HIDDEN)] + [MetaColor(MetaColor.Gray)] + public class InitInjectionSystem : InitInjectSystemBase, IEcsPipelineMember, IEcsInject, IEcsPreInitInjectProcess + { + private EcsPipeline _pipeline; + public EcsPipeline Pipeline + { + get { return Pipeline; } + set { _pipeline = value; Init(); } + } + private InitInjectController _injectController; + void IEcsInject.Inject(InitInjectController obj) { _injectController = obj; } + + private T _injectedData; + internal InitInjectionSystem(T injectedData) + { + if (injectedData == null) + { + Throw.ArgumentNull(); + } + _injectedData = injectedData; + } + private void Init() + { + if (_injectedData == null) + { + return; + } + if (_injectController == null) + { + _injectController = new InitInjectController(_pipeline); + _pipeline.GetRunner().OnPreInitInjectionBefore(_pipeline); + _pipeline.Injector.Inject(_injectController); + } + _pipeline.Injector.Inject(_injectedData); + if (_injectController.OnInject()) + { + _injectController.Destroy(); + var injectCallbacksRunner = _pipeline.GetRunner(); + injectCallbacksRunner.OnPreInitInjectionAfter(); + EcsRunner.Destroy(injectCallbacksRunner); + } + _injectedData = default; + } + void IEcsPreInitInjectProcess.OnPreInitInjectionBefore(EcsPipeline pipeline) { } + void IEcsPreInitInjectProcess.OnPreInitInjectionAfter() { _injectController = null; } + } +} diff --git a/src/Injections/InitInjectionSystem.cs.meta b/src/Injections/InitInjectionSystem.cs.meta new file mode 100644 index 0000000..ba65998 --- /dev/null +++ b/src/Injections/InitInjectionSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca86cb991f1d9204d98af8ff27199b70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Injector.cs b/src/Injections/Injector.cs new file mode 100644 index 0000000..e5f6c0b --- /dev/null +++ b/src/Injections/Injector.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; + +namespace DCFApixels.DragonECS +{ + [MetaName(nameof(Inject))] + public interface IEcsInject : IEcsProcess + { + void Inject(T obj); + } + public class Injector + { + private EcsPipeline _pipeline; + private Dictionary _branches = new Dictionary(32); + private Dictionary _nodes = new Dictionary(32); + private bool _isInit = false; + + private Injector() { } + + public void Inject(T obj) + { + Type type = typeof(T); +#if DEBUG + if (obj.GetType() != type) + { + throw new ArgumentException(); + } + if (IsCanInstantiated(type) == false) + { + throw new Exception(); + } +#endif + if (_branches.TryGetValue(type, out InjectionBranch branch) == false) + { + InitNode(new InjectionNode(type)); + branch = new InjectionBranch(this, type, true); + InitBranch(branch); + } + branch.Inject(obj); + } +// public void InjectNoBoxing(T data) where T : struct +// { +// foreach (var system in _pipeline.GetProcess>()) +// { +// system.Inject(data); +// } +// } +//#if !REFLECTION_DISABLED +// public void InjectRaw(object obj) +// { +// Type type = obj.GetType(); +// if (_branches.TryGetValue(type, out InjectionBranch branch) == false) +// { +// branch = new InjectionBranch(this, type, false); +// InitBranch(branch); +// } +// branch.Inject(obj); +// } +//#endif + + #region Internal + private void InitBranch(InjectionBranch branch) + { + _branches.Add(branch.Type, branch); + foreach (var item in _nodes) + { + var type = item.Key; + var node = item.Value; + if (type.IsAssignableFrom(branch.Type)) + { + branch.AddNode(node); + } + } + } + private void InitNode(InjectionNodeBase node) + { + if (_pipeline != null) + { + node.Init(_pipeline); + } + _nodes.Add(node.Type, node); + foreach (var item in _branches) + { + var type = item.Key; + var branch = item.Value; + if (type.IsAssignableFrom(branch.Type)) + { + branch.AddNode(node); + } + } + } + private bool IsCanInstantiated(Type type) + { + return !type.IsAbstract && !type.IsInterface; + } + #endregion + + #region Build + private void Init(EcsPipeline pipeline) + { + if (_isInit) + { + throw new Exception("Already initialized"); + } + _pipeline = pipeline; + foreach (var node in _nodes.Values) + { + node.Init(pipeline); + } + _isInit = true; + } + private bool TryDeclare() + { + Type type = typeof(T); + if (_nodes.ContainsKey(type)) + { + return false; + } + InitNode(new InjectionNode(type)); + if (IsCanInstantiated(type)) + { + InitBranch(new InjectionBranch(this, type, true)); + } + return true; + } + public class Builder + { + private EcsPipeline.Builder _source; + private Injector _instance; + private List _initInjections = new List(16); + internal Builder(EcsPipeline.Builder source) + { + _source = source; + _instance = new Injector(); + } + public EcsPipeline.Builder Declare() + { + _instance.TryDeclare(); + return _source; + } + public void Inject(T obj) + { + _initInjections.Add(new InitInject(obj)); + } + public Injector Build(EcsPipeline pipeline) + { + _instance.Init(pipeline); + foreach (var item in _initInjections) + { + item.InjectTo(_instance); + } + return _instance; + } + + private abstract class InitInjectBase + { + public abstract void InjectTo(Injector instance); + } + private sealed class InitInject : InitInjectBase + { + private T _injectedData; + public InitInject(T injectedData) + { + _injectedData = injectedData; + } + public override void InjectTo(Injector instance) + { + instance.Inject(_injectedData); + } + } + } + #endregion + } +} diff --git a/src/Injections/Injector.cs.meta b/src/Injections/Injector.cs.meta new file mode 100644 index 0000000..9068269 --- /dev/null +++ b/src/Injections/Injector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 06cb87ee84ccf854d95ddb744081f667 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Processes.cs b/src/Injections/Processes.cs new file mode 100644 index 0000000..5a0cb8e --- /dev/null +++ b/src/Injections/Processes.cs @@ -0,0 +1,61 @@ +using DCFApixels.DragonECS.Internal; +using DCFApixels.DragonECS.RunnersCore; + +namespace DCFApixels.DragonECS +{ + [MetaName("PreInitInject")] + [BindWithEcsRunner(typeof(EcsInitInjectProcessRunner))] + public interface IEcsPreInitInjectProcess : IEcsProcess + { + void OnPreInitInjectionBefore(EcsPipeline pipeline); + void OnPreInitInjectionAfter(); + } +} +namespace DCFApixels.DragonECS.Internal +{ + internal class InitInjectController + { + private EcsPipeline _source; + private EcsProcess _injectSystems; + private int _injectCount; + public bool IsInjectionEnd + { + get { return _injectCount >= _injectSystems.Length; } + } + public InitInjectController(EcsPipeline source) + { + _injectCount = 0; + _source = source; + _injectSystems = _source.GetProcess(); + } + public bool OnInject() + { + _injectCount++; + return IsInjectionEnd; + } + public void Destroy() + { + _source = null; + _injectSystems = EcsProcess.Empty; + } + } + [MetaTags(MetaTags.HIDDEN)] + [MetaColor(MetaColor.Gray)] + public sealed class EcsInitInjectProcessRunner : EcsRunner, IEcsPreInitInjectProcess + { + public void OnPreInitInjectionAfter() + { + foreach (var item in Process) + { + item.OnPreInitInjectionAfter(); + } + } + public void OnPreInitInjectionBefore(EcsPipeline pipeline) + { + foreach (var item in Process) + { + item.OnPreInitInjectionBefore(pipeline); + } + } + } +} diff --git a/src/Injections/Processes.cs.meta b/src/Injections/Processes.cs.meta new file mode 100644 index 0000000..e6d8bef --- /dev/null +++ b/src/Injections/Processes.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 37d3cc800496c9442ad9f81bc94e94ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Utils.meta b/src/Injections/Utils.meta new file mode 100644 index 0000000..4b8d9a2 --- /dev/null +++ b/src/Injections/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f5d8c72b3decc2b488a616932366ff0f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Utils/Exceptions.cs b/src/Injections/Utils/Exceptions.cs new file mode 100644 index 0000000..c48f0d9 --- /dev/null +++ b/src/Injections/Utils/Exceptions.cs @@ -0,0 +1,12 @@ +using System; + +namespace DCFApixels.DragonECS.DI.Internal +{ + internal class Throw + { + public static void ArgumentNull() + { + throw new ArgumentNullException(); + } + } +} diff --git a/src/Injections/Utils/Exceptions.cs.meta b/src/Injections/Utils/Exceptions.cs.meta new file mode 100644 index 0000000..412cb97 --- /dev/null +++ b/src/Injections/Utils/Exceptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 790577d4144473d448401799f01ddf50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Injections/Utils/IInjectionBlock.cs b/src/Injections/Utils/IInjectionBlock.cs new file mode 100644 index 0000000..87ffa6c --- /dev/null +++ b/src/Injections/Utils/IInjectionBlock.cs @@ -0,0 +1,29 @@ +namespace DCFApixels.DragonECS +{ + public readonly struct BlockInjector + { + private readonly Injector _injectionGraph; + public BlockInjector(Injector injectionGraph) + { + _injectionGraph = injectionGraph; + } + public void Inject(T obj) + { + _injectionGraph.Inject(obj); + } +// public void InjectNoBoxing(T data) where T : struct +// { +// _injectionGraph.InjectNoBoxing(data); +// } +//#if !REFLECTION_DISABLED +// public void InjectRaw(object obj) +// { +// _injectionGraph.InjectRaw(obj); +// } +//#endif + } + public interface IInjectionBlock + { + void InjectTo(BlockInjector i); + } +} diff --git a/src/Injections/Utils/IInjectionBlock.cs.meta b/src/Injections/Utils/IInjectionBlock.cs.meta new file mode 100644 index 0000000..10d486c --- /dev/null +++ b/src/Injections/Utils/IInjectionBlock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee045b3db15333b46944240b586a7d92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/Internal.meta b/src/Internal.meta new file mode 100644 index 0000000..05d32c8 --- /dev/null +++ b/src/Internal.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8aab9d072e532314286f6c3a2d3fe128 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: