diff --git a/src/Attributes/AutoInjectAttribute.cs b/src/Attributes/AutoInjectAttribute.cs index 9bacdc4..39f92b2 100644 --- a/src/Attributes/AutoInjectAttribute.cs +++ b/src/Attributes/AutoInjectAttribute.cs @@ -5,7 +5,12 @@ namespace DCFApixels.DragonECS [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class AutoInjectAttribute : Attribute { + public readonly Type notNullDummyType; + public AutoInjectAttribute(Type notNullDummyType = null) + { + this.notNullDummyType = notNullDummyType; + } } } diff --git a/src/AutoInjectSystem.cs b/src/AutoInjectSystem.cs index 7d69a3e..b954b34 100644 --- a/src/AutoInjectSystem.cs +++ b/src/AutoInjectSystem.cs @@ -4,25 +4,35 @@ using System.Reflection; namespace DCFApixels.DragonECS { + internal static class DummyInstance + { + public static T intsance = (T)Activator.CreateInstance(typeof(T)); + } internal class AutoInjectionMap { private readonly EcsPipeline _source; private Dictionary> _systems; + private HashSet _notInjected; + + private Type dummyInstance = typeof(DummyInstance<>); + + private bool _isDummyInjected = false; public AutoInjectionMap(EcsPipeline source) { _source = source; var allsystems = _source.AllSystems; _systems = new Dictionary>(); + _notInjected = new HashSet(); foreach (var system in allsystems) { Type systemType = system.GetType(); foreach (var field in systemType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { - if(field.GetCustomAttribute() != null) + AutoInjectAttribute autoInjectAttribute = field.GetCustomAttribute(); + if (autoInjectAttribute != null) { - Type fieldType = field.FieldType; List list; if (!_systems.TryGetValue(fieldType, out list)) @@ -31,16 +41,19 @@ namespace DCFApixels.DragonECS _systems.Add(fieldType, list); } - list.Add(new FiledRecord(system, field)); - - + list.Add(new FiledRecord(system, field, autoInjectAttribute)); } } } + foreach (var item in _systems.Keys) + { + _notInjected.Add(item); + } } public void Inject(object obj) { + _notInjected.Remove(obj.GetType()); Type objectType = obj.GetType(); if(_systems.TryGetValue(objectType, out List list)) { @@ -51,26 +64,59 @@ namespace DCFApixels.DragonECS } } + public void InjectDummy() + { + if (_isDummyInjected) + return; + + _isDummyInjected = true; + foreach (var notInjectedItem in _notInjected) + { + foreach (var systemRecord in _systems[notInjectedItem]) + { + if (systemRecord.attribute.notNullDummyType == null) + continue; + if (systemRecord.field.GetValue(systemRecord.target) != null) + continue; + if (systemRecord.field.FieldType.IsAssignableFrom(systemRecord.attribute.notNullDummyType) == false) + { + EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, $"The {systemRecord.attribute.notNullDummyType} dummy cannot be assigned to the {systemRecord.field.FieldType.Name} field"); + continue; + } + + systemRecord.field.SetValue(systemRecord.target, + dummyInstance.MakeGenericType(systemRecord.attribute.notNullDummyType).GetField("intsance", BindingFlags.Static | BindingFlags.Public).GetValue(null)); + } + } + + _notInjected.Clear(); + _notInjected= null; + } + private readonly struct FiledRecord { public readonly IEcsSystem target; public readonly FieldInfo field; - public FiledRecord(IEcsSystem target, FieldInfo field) + public readonly AutoInjectAttribute attribute; + public FiledRecord(IEcsSystem target, FieldInfo field, AutoInjectAttribute attribute) { this.target = target; this.field = field; + this.attribute = attribute; } } } [DebugHide, DebugColor(DebugColor.Gray)] - public class AutoInjectSystem : IEcsPreInitSystem, IEcsPreInject + public class AutoInjectSystem : IEcsPreInitSystem, IEcsPreInject, IEcsPreInitInjectCallbacks { private EcsPipeline _pipeline; private List _injectQueue = new List(); private AutoInjectionMap _autoInjectionMap; + private bool _isPreInjectionComplete = false; + public void PreInject(object obj) { if(_pipeline == null) @@ -91,11 +137,25 @@ namespace DCFApixels.DragonECS } _injectQueue.Clear(); _injectQueue = null; + if (_isPreInjectionComplete) + { + _autoInjectionMap.InjectDummy(); + } } private void AutoInject(object obj) { _autoInjectionMap.Inject(obj); } + + public void OnPreInitInjectionBefore() { } + public void OnPreInitInjectionAfter() + { + _isPreInjectionComplete = true; + if (_autoInjectionMap != null) + { + _autoInjectionMap.InjectDummy(); + } + } } } \ No newline at end of file