mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
173 lines
6.7 KiB
C#
173 lines
6.7 KiB
C#
using DCFApixels.DragonECS.Internal;
|
||
using DCFApixels.DragonECS.RunnersCore;
|
||
using System.Linq;
|
||
|
||
namespace DCFApixels.DragonECS
|
||
{
|
||
//TODO развить идею инжектов
|
||
//1) добавить расширенный метод инжекта, с 2 джинерик-аргументами, первый базовый тип и второй инжектируемый тип.
|
||
//напримере это будет работать так Inject<object, Foo> делает инжект объекта типа Foo для систем с IEcsInject<object> или с IEcsInject<Foo>
|
||
//2) добавить контейнер, который автоматически создается, собирает в себя все пре-инжекты и авто-инжектится во все системы.
|
||
//но это спорная идея
|
||
namespace Internal
|
||
{
|
||
internal class PreInitInjectController
|
||
{
|
||
private EcsPipeline _source;
|
||
private InjectSystemBase[] _injectSystems;
|
||
private int _injectCount;
|
||
public PreInitInjectController(EcsPipeline source)
|
||
{
|
||
_injectCount = 0;
|
||
_source = source;
|
||
_injectSystems = _source.AllSystems.OfType<InjectSystemBase>().ToArray();
|
||
}
|
||
public bool OnInject()
|
||
{
|
||
_injectCount++;
|
||
return IsInjectionEnd;
|
||
}
|
||
public bool IsInjectionEnd => _injectCount >= _injectSystems.Length;
|
||
public void Destroy()
|
||
{
|
||
_source = null;
|
||
_injectSystems = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
public interface IEcsPreInject : IEcsSystem
|
||
{
|
||
public void PreInject(object obj);
|
||
}
|
||
public interface IEcsInject<T> : IEcsSystem
|
||
{
|
||
public void Inject(T obj);
|
||
}
|
||
public interface IEcsPreInitInjectCallbacks : IEcsSystem
|
||
{
|
||
public void OnPreInitInjectionBefore();
|
||
public void OnPreInitInjectionAfter();
|
||
}
|
||
|
||
namespace Internal
|
||
{
|
||
[DebugHide, DebugColor(DebugColor.Gray)]
|
||
public sealed class PreInjectRunner : EcsRunner<IEcsPreInject>, IEcsPreInject
|
||
{
|
||
void IEcsPreInject.PreInject(object obj)
|
||
{
|
||
foreach (var item in targets) item.PreInject(obj);
|
||
}
|
||
}
|
||
[DebugHide, DebugColor(DebugColor.Gray)]
|
||
public sealed class InjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
|
||
{
|
||
private IEcsPreInject _preInjectchache;
|
||
void IEcsInject<T>.Inject(T obj)
|
||
{
|
||
_preInjectchache.PreInject(obj);
|
||
foreach (var item in targets) item.Inject(obj);
|
||
}
|
||
protected override void OnSetup()
|
||
{
|
||
_preInjectchache = Source.GetRunner<IEcsPreInject>();
|
||
}
|
||
}
|
||
[DebugHide, DebugColor(DebugColor.Gray)]
|
||
public sealed class InjectCallbacksRunner : EcsRunner<IEcsPreInitInjectCallbacks>, IEcsPreInitInjectCallbacks
|
||
{
|
||
public void OnPreInitInjectionAfter()
|
||
{
|
||
foreach (var item in targets) item.OnPreInitInjectionAfter();
|
||
}
|
||
public void OnPreInitInjectionBefore()
|
||
{
|
||
foreach (var item in targets) item.OnPreInitInjectionBefore();
|
||
}
|
||
}
|
||
}
|
||
|
||
public class InjectSystemBase { }
|
||
|
||
[DebugHide, DebugColor(DebugColor.Gray)]
|
||
public class InjectSystem<T> : InjectSystemBase, IEcsPreInitSystem, IEcsInject<PreInitInjectController>, IEcsPreInitInjectCallbacks
|
||
{
|
||
private T _injectedData;
|
||
|
||
private PreInitInjectController _injectController;
|
||
void IEcsInject<PreInitInjectController>.Inject(PreInitInjectController obj) => _injectController = obj;
|
||
|
||
public InjectSystem(T injectedData)
|
||
{
|
||
_injectedData = injectedData;
|
||
}
|
||
|
||
public void PreInit(EcsPipeline pipeline)
|
||
{
|
||
|
||
if (_injectController == null)
|
||
{
|
||
_injectController = new PreInitInjectController(pipeline);
|
||
var injectMapRunner = pipeline.GetRunner<IEcsInject<PreInitInjectController>>();
|
||
pipeline.GetRunner<IEcsPreInitInjectCallbacks>().OnPreInitInjectionBefore();
|
||
injectMapRunner.Inject(_injectController);
|
||
}
|
||
|
||
var injectRunnerGeneric = pipeline.GetRunner<IEcsInject<T>>();
|
||
injectRunnerGeneric.Inject(_injectedData);
|
||
|
||
if (_injectController.OnInject())
|
||
{
|
||
_injectController.Destroy();
|
||
var injectCallbacksRunner = pipeline.GetRunner<IEcsPreInitInjectCallbacks>();
|
||
injectCallbacksRunner.OnPreInitInjectionAfter();
|
||
EcsRunner.Destroy(injectCallbacksRunner);
|
||
}
|
||
}
|
||
|
||
public void OnPreInitInjectionBefore() { }
|
||
|
||
public void OnPreInitInjectionAfter()
|
||
{
|
||
_injectController = null;
|
||
}
|
||
}
|
||
|
||
public static class InjectSystemExstensions
|
||
{
|
||
public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data)
|
||
{
|
||
return self.Add(new InjectSystem<T>(data));
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B>(this EcsPipeline.Builder self, A a, B b)
|
||
{
|
||
return self.Inject(a).Inject(b);
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B, C>(this EcsPipeline.Builder self, A a, B b, C c)
|
||
{
|
||
return self.Inject(a).Inject(b).Inject(c);
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B, C, D>(this EcsPipeline.Builder self, A a, B b, C c, D d)
|
||
{
|
||
return self.Inject(a).Inject(b).Inject(c).Inject(d);
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B, C, D, E>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e)
|
||
{
|
||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e);
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B, C, D, E, F>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f)
|
||
{
|
||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f);
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g)
|
||
{
|
||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g);
|
||
}
|
||
public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G, H>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g, H h)
|
||
{
|
||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g).Inject(h);
|
||
}
|
||
}
|
||
}
|