rework System/Process/Runner logic. rework injections.

This commit is contained in:
Mikhail 2024-02-22 15:39:37 +08:00
parent 19b1ddbc7d
commit 92fa358c33
27 changed files with 1062 additions and 699 deletions

View File

@ -5,81 +5,79 @@ using System;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
#region Interfaces
[MetaName(nameof(PreInit))] [MetaName(nameof(PreInit))]
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsPreInitProcessRunner))] [BindWithEcsRunner(typeof(EcsPreInitRunner))]
public interface IEcsPreInitProcess : IEcsProcess public interface IEcsPreInit : IEcsSystem
{ {
void PreInit(); void PreInit();
} }
[MetaName(nameof(Init))] [MetaName(nameof(Init))]
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsInitProcessRunner))] [BindWithEcsRunner(typeof(EcsInitRunner))]
public interface IEcsInitProcess : IEcsProcess public interface IEcsInit : IEcsSystem
{ {
void Init(); void Init();
} }
[MetaName(nameof(Run))] [MetaName(nameof(Run))]
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsRunProcessRunner))] [BindWithEcsRunner(typeof(EcsRunRunner))]
public interface IEcsRunProcess : IEcsProcess public interface IEcsRun : IEcsSystem
{ {
void Run(); void Run();
} }
[MetaName(nameof(Destroy))] [MetaName(nameof(Destroy))]
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
[BindWithEcsRunner(typeof(EcsDestroyProcessRunner))] [BindWithEcsRunner(typeof(EcsDestroyRunner))]
public interface IEcsDestroyProcess : IEcsProcess public interface IEcsDestroy : IEcsSystem
{ {
void Destroy(); void Destroy();
} }
}
#endregion namespace DCFApixels.DragonECS.Internal
{
namespace Internal
{
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
public sealed class EcsPreInitProcessRunner : EcsRunner<IEcsPreInitProcess>, IEcsPreInitProcess public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInit>, IEcsPreInit
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[Process.Length];
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < Process.Length; i++)
{ {
_markers[i] = new EcsProfilerMarker($"{targets[i].GetType().Name}.{nameof(PreInit)}"); _markers[i] = new EcsProfilerMarker($"{Process[i].GetType().Name}.{nameof(PreInit)}");
} }
} }
#endif #endif
public void PreInit() public void PreInit()
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
{ {
_markers[i].Begin(); _markers[i].Begin();
try try
{ {
targets[i].PreInit(); Process[i].PreInit();
} }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
_markers[i].End(); _markers[i].End();
} }
#else #else
foreach (var item in targets) foreach (var item in Process)
{ {
try { item.PreInit(); } try { item.PreInit(); }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
@ -88,46 +86,46 @@ namespace DCFApixels.DragonECS
} }
} }
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
public sealed class EcsInitProcessRunner : EcsRunner<IEcsInitProcess>, IEcsInitProcess public sealed class EcsInitRunner : EcsRunner<IEcsInit>, IEcsInit
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[Process.Length];
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < Process.Length; i++)
{ {
_markers[i] = new EcsProfilerMarker($"{targets[i].GetType().Name}.{nameof(Init)}"); _markers[i] = new EcsProfilerMarker($"{Process[i].GetType().Name}.{nameof(Init)}");
} }
} }
#endif #endif
public void Init() public void Init()
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
{ {
_markers[i].Begin(); _markers[i].Begin();
try try
{ {
targets[i].Init(); Process[i].Init();
} }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
_markers[i].End(); _markers[i].End();
} }
#else #else
foreach (var item in targets) foreach (var item in Process)
{ {
try { item.Init(); } try { item.Init(); }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
@ -136,46 +134,46 @@ namespace DCFApixels.DragonECS
} }
} }
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
public sealed class EcsRunProcessRunner : EcsRunner<IEcsRunProcess>, IEcsRunProcess public sealed class EcsRunRunner : EcsRunner<IEcsRun>, IEcsRun
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[Process.Length];
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < Process.Length; i++)
{ {
_markers[i] = new EcsProfilerMarker($"{targets[i].GetType().Name}.{nameof(Run)}"); _markers[i] = new EcsProfilerMarker($"{Process[i].GetType().Name}.{nameof(Run)}");
} }
} }
#endif #endif
public void Run() public void Run()
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
{ {
_markers[i].Begin(); _markers[i].Begin();
try try
{ {
targets[i].Run(); Process[i].Run();
} }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
_markers[i].End(); _markers[i].End();
} }
#else #else
foreach (var item in targets) foreach (var item in Process)
{ {
try { item.Run(); } try { item.Run(); }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
@ -184,46 +182,46 @@ namespace DCFApixels.DragonECS
} }
} }
[MetaColor(MetaColor.Orange)] [MetaColor(MetaColor.Orange)]
public sealed class EcsDestroyProcessRunner : EcsRunner<IEcsDestroyProcess>, IEcsDestroyProcess public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroy>, IEcsDestroy
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[Process.Length];
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < Process.Length; i++)
{ {
_markers[i] = new EcsProfilerMarker($"{targets[i].GetType().Name}.{nameof(IEcsDestroyProcess.Destroy)}"); _markers[i] = new EcsProfilerMarker($"{Process[i].GetType().Name}.{nameof(IEcsDestroy.Destroy)}");
} }
} }
#endif #endif
void IEcsDestroyProcess.Destroy() void IEcsDestroy.Destroy()
{ {
#if DEBUG && !DISABLE_DEBUG #if DEBUG && !DISABLE_DEBUG
for (int i = 0; i < targets.Length && targets.Length <= _markers.Length; i++) for (int i = 0, n = Process.Length < _markers.Length ? Process.Length : _markers.Length; i < n; i++)
{ {
_markers[i].Begin(); _markers[i].Begin();
try try
{ {
targets[i].Destroy(); Process[i].Destroy();
} }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
_markers[i].End(); _markers[i].End();
} }
#else #else
foreach (var item in targets) foreach (var item in Process)
{ {
try { item.Destroy(); } try { item.Destroy(); }
catch (Exception e) catch (Exception e)
{ {
#if DISABLE_CATH_EXCEPTIONS #if DISABLE_CATH_EXCEPTIONS
throw e; throw;
#endif #endif
EcsDebug.PrintError(e); EcsDebug.PrintError(e);
} }
@ -231,5 +229,4 @@ namespace DCFApixels.DragonECS
#endif #endif
} }
} }
}
} }

View File

@ -1,241 +0,0 @@
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.RunnersCore;
using System;
namespace DCFApixels.DragonECS
{
public readonly struct Injector
{
private readonly EcsPipeline _pipeline;
public Injector(EcsPipeline pipeline)
{
_pipeline = pipeline;
}
public void Inject<T>(T data)
{
_pipeline.Inject(data);
}
}
public interface IInjectionBlock
{
void InjectTo(Injector i);
}
[MetaName(nameof(PreInject))]
[BindWithEcsRunner(typeof(EcsPreInjectRunner))]
public interface IEcsPreInject : IEcsProcess
{
void PreInject(object obj);
}
[MetaName(nameof(Inject))]
[BindWithEcsRunner(typeof(EcsInjectRunner<>))]
public interface IEcsInject<T> : IEcsProcess
{
void Inject(T obj);
}
[MetaName("PreInitInject")]
[BindWithEcsRunner(typeof(EcsPreInitInjectProcessRunner))]
public interface IEcsPreInitInjectProcess : IEcsProcess
{
void OnPreInitInjectionBefore();
void OnPreInitInjectionAfter();
}
namespace Internal
{
internal class InitInjectController
{
private EcsPipeline _source;
private InitInjectSystemBase[] _injectSystems;
private int _injectCount;
public bool IsInjectionEnd
{
get { return _injectCount >= _injectSystems.Length; }
}
public InitInjectController(EcsPipeline source)
{
_injectCount = 0;
_source = source;
_injectSystems = _source.GetSystems<InitInjectSystemBase>();
}
public bool OnInject()
{
_injectCount++;
return IsInjectionEnd;
}
public void Destroy()
{
_source = null;
_injectSystems = null;
}
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsPreInjectRunner : EcsRunner<IEcsPreInject>, IEcsPreInject
{
void IEcsPreInject.PreInject(object obj)
{
if (obj is IInjectionBlock container)
{
container.InjectTo(new Injector(Pipeline));
}
foreach (var item in targets)
{
item.PreInject(obj);
}
}
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsInjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
{
private EcsBaseTypeInjectRunner _baseTypeInjectRunner;
void IEcsInject<T>.Inject(T obj)
{
if (obj == null) Throw.ArgumentNull();
_baseTypeInjectRunner.Inject(obj);
foreach (var item in targets) item.Inject(obj);
}
protected override void OnSetup()
{
Type baseType = typeof(T).BaseType;
if (baseType != typeof(object) && baseType != typeof(ValueType) && baseType != null)
_baseTypeInjectRunner = (EcsBaseTypeInjectRunner)Activator.CreateInstance(typeof(EcsBaseTypeInjectRunner<>).MakeGenericType(baseType), Pipeline);
else
_baseTypeInjectRunner = new EcsObjectTypePreInjectRunner(Pipeline);
}
}
internal abstract class EcsBaseTypeInjectRunner
{
public abstract void Inject(object obj);
}
internal sealed class EcsBaseTypeInjectRunner<T> : EcsBaseTypeInjectRunner
{
private IEcsInject<T> _runner;
public EcsBaseTypeInjectRunner(EcsPipeline pipeline) => _runner = pipeline.GetRunner<IEcsInject<T>>();
public sealed override void Inject(object obj) => _runner.Inject((T)obj);
}
internal sealed class EcsObjectTypePreInjectRunner : EcsBaseTypeInjectRunner
{
private IEcsPreInject _runner;
public EcsObjectTypePreInjectRunner(EcsPipeline pipeline) => _runner = pipeline.GetRunner<IEcsPreInject>();
public sealed override void Inject(object obj) => _runner.PreInject(obj);
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsPreInitInjectProcessRunner : EcsRunner<IEcsPreInitInjectProcess>, IEcsPreInitInjectProcess
{
public void OnPreInitInjectionAfter()
{
foreach (var item in targets) item.OnPreInitInjectionAfter();
}
public void OnPreInitInjectionBefore()
{
foreach (var item in targets) item.OnPreInitInjectionBefore();
}
}
public abstract class InitInjectSystemBase { }
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public class InitInjectSystem<T> : InitInjectSystemBase, IEcsPipelineMember, IEcsInject<InitInjectController>, IEcsPreInitInjectProcess
{
private EcsPipeline _pipeline;
public EcsPipeline Pipeline
{
get { return Pipeline; }
set
{
_pipeline = value;
if (_injectedData == null)
{
return;
}
if (_injectController == null)
{
var injectPipelineRunner = _pipeline.GetRunner<IEcsInject<EcsPipeline>>();
injectPipelineRunner.Inject(_pipeline);
EcsRunner.Destroy(injectPipelineRunner);
_injectController = new InitInjectController(_pipeline);
var injectMapRunner = _pipeline.GetRunner<IEcsInject<InitInjectController>>();
_pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore();
injectMapRunner.Inject(_injectController);
EcsRunner.Destroy(injectMapRunner);
}
var injectRunnerGeneric = _pipeline.GetRunner<IEcsInject<T>>();
injectRunnerGeneric.Inject(_injectedData);
if (_injectController.OnInject())
{
_injectController.Destroy();
var injectCallbacksRunner = _pipeline.GetRunner<IEcsPreInitInjectProcess>();
injectCallbacksRunner.OnPreInitInjectionAfter();
EcsRunner.Destroy(injectCallbacksRunner);
}
_injectedData = default;
}
}
private InitInjectController _injectController;
void IEcsInject<InitInjectController>.Inject(InitInjectController obj) { _injectController = obj; }
private T _injectedData;
internal InitInjectSystem(T injectedData)
{
if (injectedData == null) Throw.ArgumentNull();
_injectedData = injectedData;
}
void IEcsPreInitInjectProcess.OnPreInitInjectionBefore() { }
void IEcsPreInitInjectProcess.OnPreInitInjectionAfter() { _injectController = null; }
}
}
public static partial class EcsPipelineExtensions
{
public static void Inject<T>(this EcsPipeline self, T data)
{
self.GetRunner<IEcsInject<T>>().Inject(data);
}
}
public static partial class EcsPipelineBuilderExtensions
{
public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data)
{
if (data == null) Throw.ArgumentNull();
self.Add(new InitInjectSystem<T>(data));
if (data is IEcsModule module)
self.AddModule(module);
return self;
}
public static EcsPipeline.Builder Inject<T0, T1>(this EcsPipeline.Builder self, T0 d0, T1 d1)
{
return self.Inject(d0).Inject(d1);
}
public static EcsPipeline.Builder Inject<T0, T1, T2>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2)
{
return self.Inject(d0).Inject(d1).Inject(d2);
}
public static EcsPipeline.Builder Inject<T0, T1, T2, T3>(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<T0, T1, T2, T3, T4>(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<T0, T1, T2, T3, T4, T5>(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<T0, T1, T2, T3, T4, T5, T6>(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<T0, T1, T2, T3, T4, T5, T6, T7>(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);
}
}
}

View File

@ -0,0 +1,66 @@
using DCFApixels.DragonECS.DI.Internal;
namespace DCFApixels.DragonECS
{
public static partial class EcsPipelineExtensions
{
public static void Inject<T>(this EcsPipeline self, T data)
{
self.GetRunner<IEcsInject<T>>().Inject(data);
}
}
public static partial class EcsPipelineBuilderExtensions
{
public static EcsPipeline.Builder AddInjectionGraph(this EcsPipeline.Builder self, InjectionGraph graph)
{
self.Config.Set(InjectionGraph.CONFIG_NAME, graph);
return self;
}
public static EcsPipeline.Builder GetInjectionGraph(this EcsPipeline.Builder self, out InjectionGraph graph)
{
graph = self.Config.Get<InjectionGraph>(InjectionGraph.CONFIG_NAME);
return self;
}
public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data)
{
if (data == null)
{
Throw.ArgumentNull();
}
self.Add(new InitInjectionSystem<T>(data));
if (data is IEcsModule module)
{
self.AddModule(module);
}
return self;
}
public static EcsPipeline.Builder Inject<T0, T1>(this EcsPipeline.Builder self, T0 d0, T1 d1)
{
return self.Inject(d0).Inject(d1);
}
public static EcsPipeline.Builder Inject<T0, T1, T2>(this EcsPipeline.Builder self, T0 d0, T1 d1, T2 d2)
{
return self.Inject(d0).Inject(d1).Inject(d2);
}
public static EcsPipeline.Builder Inject<T0, T1, T2, T3>(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<T0, T1, T2, T3, T4>(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<T0, T1, T2, T3, T4, T5>(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<T0, T1, T2, T3, T4, T5, T6>(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<T0, T1, T2, T3, T4, T5, T6, T7>(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);
}
}
}

View File

@ -0,0 +1,12 @@
using System;
namespace DCFApixels.DragonECS.DI.Internal
{
internal class Throw
{
public static void ArgumentNull()
{
throw new ArgumentNullException();
}
}
}

View File

@ -0,0 +1,29 @@
namespace DCFApixels.DragonECS
{
public readonly struct Injector
{
private readonly InjectionGraph _injectionGraph;
public Injector(InjectionGraph injectionGraph)
{
_injectionGraph = injectionGraph;
}
public void Inject<T>(T obj)
{
_injectionGraph.Inject(obj);
}
public void InjectNoBoxing<T>(T data)
{
_injectionGraph.InjectNoBoxing(data);
}
#if !REFLECTION_DISABLED
public void InjectRaw(object obj)
{
_injectionGraph.InjectRaw(obj);
}
#endif
}
public interface IInjectionBlock
{
void InjectTo(Injector i);
}
}

View File

@ -0,0 +1,62 @@
namespace DCFApixels.DragonECS.DI.Internal
{
public abstract class InitInjectSystemBase : IEcsSystem { }
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public class InitInjectionSystem<T> : InitInjectSystemBase, IEcsPipelineMember, IEcsInject<InitInjectController>, IEcsPreInitInjectProcess
{
private EcsPipeline _pipeline;
public EcsPipeline Pipeline
{
get { return Pipeline; }
set
{
_pipeline = value;
if (_injectedData == null)
{
return;
}
if (_injectController == null)
{
_pipeline.Config.Get<InjectionGraph>(InjectionGraph.CONFIG_NAME).Init(_pipeline);
var injectPipelineRunner = _pipeline.GetRunner<IEcsInject<EcsPipeline>>();
injectPipelineRunner.Inject(_pipeline);
EcsRunner.Destroy(injectPipelineRunner);
_injectController = new InitInjectController(_pipeline);
var injectMapRunner = _pipeline.GetRunner<IEcsInject<InitInjectController>>();
_pipeline.GetRunner<IEcsPreInitInjectProcess>().OnPreInitInjectionBefore(_pipeline);
injectMapRunner.Inject(_injectController);
EcsRunner.Destroy(injectMapRunner);
}
var injectRunnerGeneric = _pipeline.GetRunner<IEcsInject<T>>();
injectRunnerGeneric.Inject(_injectedData);
if (_injectController.OnInject())
{
_injectController.Destroy();
var injectCallbacksRunner = _pipeline.GetRunner<IEcsPreInitInjectProcess>();
injectCallbacksRunner.OnPreInitInjectionAfter();
EcsRunner.Destroy(injectCallbacksRunner);
}
_injectedData = default;
}
}
private InitInjectController _injectController;
void IEcsInject<InitInjectController>.Inject(InitInjectController obj) { _injectController = obj; }
private T _injectedData;
internal InitInjectionSystem(T injectedData)
{
if (injectedData == null)
{
Throw.ArgumentNull();
}
_injectedData = injectedData;
}
void IEcsPreInitInjectProcess.OnPreInitInjectionBefore(EcsPipeline pipeline) { }
void IEcsPreInitInjectProcess.OnPreInitInjectionAfter() { _injectController = null; }
}
}

View File

@ -0,0 +1,75 @@
using DCFApixels.DragonECS.DI.Internal;
using DCFApixels.DragonECS.RunnersCore;
namespace DCFApixels.DragonECS
{
[MetaName(nameof(Inject))]
[BindWithEcsRunner(typeof(EcsInjectRunner<>))]
public interface IEcsInject<T> : IEcsSystem
{
void Inject(T obj);
}
[MetaName("PreInitInject")]
[BindWithEcsRunner(typeof(EcsInitInjectProcessRunner))]
public interface IEcsPreInitInjectProcess : IEcsSystem
{
void OnPreInitInjectionBefore(EcsPipeline pipeline);
void OnPreInitInjectionAfter();
}
}
namespace DCFApixels.DragonECS.DI.Internal
{
internal class InitInjectController
{
private EcsPipeline _source;
private EcsProcess<InitInjectSystemBase> _injectSystems;
private int _injectCount;
public bool IsInjectionEnd
{
get { return _injectCount >= _injectSystems.Length; }
}
public InitInjectController(EcsPipeline source)
{
_injectCount = 0;
_source = source;
_injectSystems = _source.GetProcess<InitInjectSystemBase>();
}
public bool OnInject()
{
_injectCount++;
return IsInjectionEnd;
}
public void Destroy()
{
_source = null;
_injectSystems = EcsProcess<InitInjectSystemBase>.Empty;
}
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsInjectRunner<T> : EcsRunner<IEcsInject<T>>, IEcsInject<T>
{
private InjectionGraph _injectionGraph;
void IEcsInject<T>.Inject(T obj)
{
_injectionGraph.Inject(obj);
}
protected override void OnSetup()
{
_injectionGraph = Pipeline.Config.Get<InjectionGraph>(InjectionGraph.CONFIG_NAME);
}
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Gray)]
public sealed class EcsInitInjectProcessRunner : EcsRunner<IEcsPreInitInjectProcess>, IEcsPreInitInjectProcess
{
public void OnPreInitInjectionAfter()
{
foreach (var item in Process) item.OnPreInitInjectionAfter();
}
public void OnPreInitInjectionBefore(EcsPipeline pipeline)
{
foreach (var item in Process) item.OnPreInitInjectionBefore(pipeline);
}
}
}

View File

@ -0,0 +1,65 @@
using System;
namespace DCFApixels.DragonECS
{
public class InjectionBranch
{
private InjectionGraph _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(InjectionGraph 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 Injector(_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<InjectionNodeBase>();
return;
}
InjectionNodeBase[] newNodes = new InjectionNodeBase[_nodesCount];
for (int i = 0; i < newNodes.Length; i++)
{
newNodes[i] = _nodes[i];
}
}
}
}

View File

@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public class InjectionGraph
{
internal const string CONFIG_NAME = "DCFApixels.DragonECS.DI:" + nameof(InjectionGraph);
private EcsPipeline _pipeline;
private Dictionary<Type, InjectionBranch> _branches = new Dictionary<Type, InjectionBranch>(32);
private Dictionary<Type, InjectionNodeBase> _nodes = new Dictionary<Type, InjectionNodeBase>(32);
private bool _isInit = false;
public InjectionGraph()
{
Declare<object>();
Declare<EcsWorld>();
}
public void Init(EcsPipeline pipeline)
{
if (_isInit)
{
throw new Exception("Already initialized");
}
_pipeline = pipeline;
foreach (var node in _nodes.Values)
{
node.Init(pipeline);
}
_isInit = true;
}
public bool TryDeclare<T>()
{
Type type = typeof(T);
if (_nodes.ContainsKey(type))
{
return false;
}
InitNode(new InjectionNode<T>(type));
if (IsCanInstantiated(type))
{
InitBranch(new InjectionBranch(this, type, true));
}
return true;
}
public void Declare<T>()
{
if (TryDeclare<T>() == false)
{
throw new Exception();
}
}
public void InjectNoBoxing<T>(T data)
{
_pipeline.GetRunner<IEcsInject<T>>().Inject(data);
}
public void Inject<T>(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<T>(type));
branch = new InjectionBranch(this, type, true);
InitBranch(branch);
}
branch.Inject(obj);
}
#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
private void InitBranch(InjectionBranch branch)
{
_branches.Add(branch.Type, branch);
foreach (var (type, node) in _nodes)
{
if (branch.Type.IsAssignableTo(type))
{
branch.AddNode(node);
}
}
}
private void InitNode(InjectionNodeBase node)
{
if (_pipeline != null)
{
node.Init(_pipeline);
}
_nodes.Add(node.Type, node);
foreach (var (type, branch) in _branches)
{
if (branch.Type.IsAssignableTo(type))
{
branch.AddNode(node);
}
}
}
private bool IsCanInstantiated(Type type)
{
return !type.IsAbstract && !type.IsInterface;
}
}
}

View File

@ -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<T> : InjectionNodeBase
{
private EcsProcess<IEcsInject<T>> _process;
public InjectionNode(Type type) : base(type) { }
public override void Init(EcsPipeline pipeline)
{
_process = pipeline.GetProcess<IEcsInject<T>>();
}
public override void Inject(object obj)
{
for (int i = 0; i < _process.Length; i++)
{
_process[i].Inject((T)obj);
}
}
}
}

View File

@ -1,69 +0,0 @@
using DCFApixels.DragonECS.Internal;
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
namespace Internal
{
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Black)]
public class SystemsLayerMarkerSystem : IEcsProcess
{
public readonly string name;
public SystemsLayerMarkerSystem(string name) => this.name = name;
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Grey)]
public class EndFrameSystem : IEcsRunProcess, IEcsInject<EcsWorld>
{
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
public void Inject(EcsWorld obj) => _worlds.Add(obj);
public void Run()
{
foreach (var world in _worlds)
{
world.DeleteEmptyEntites();
world.ReleaseDelEntityBufferAll();
}
}
}
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Grey)]
public class DeleteOneFrameComponentSystem<TComponent> : IEcsRunProcess, IEcsInject<EcsWorld>
where TComponent : struct, IEcsComponent
{
public EcsPipeline pipeline { get; set; }
private sealed class Aspect : EcsAspect
{
public EcsPool<TComponent> pool;
public Aspect(Builder b) => pool = b.Include<TComponent>();
}
private readonly List<EcsWorld> _worlds = new List<EcsWorld>();
public void Inject(EcsWorld obj) => _worlds.Add(obj);
public void Run()
{
for (int i = 0, iMax = _worlds.Count; i < iMax; i++)
{
EcsWorld world = _worlds[i];
if (world.IsComponentTypeDeclared<TComponent>())
{
foreach (var e in world.WhereToGroup(out Aspect a))
a.pool.Del(e);
}
}
}
}
}
public static class DeleteOneFrameComponentSystemExtensions
{
private const string AUTO_DEL_LAYER = nameof(AUTO_DEL_LAYER);
public static EcsPipeline.Builder AutoDel<TComponent>(this EcsPipeline.Builder b, string layerName = AUTO_DEL_LAYER)
where TComponent : struct, IEcsComponent
{
if (AUTO_DEL_LAYER == layerName)
b.Layers.InsertAfter(EcsConsts.POST_END_LAYER, AUTO_DEL_LAYER);
b.AddUnique(new DeleteOneFrameComponentSystem<TComponent>(), layerName);
return b;
}
}
}

View File

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5f3a2f2b184d60e43a2c2b019213d6c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,90 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public interface IEcsPipelineConfig : IConfig { }
public interface IEcsPipelineConfigWriter : IConfigWriter
{
IEcsPipelineConfig GetPipelineConfig();
}
[Serializable]
public class EcsPipelineConfig : IEcsPipelineConfigWriter, IEcsPipelineConfig, IEnumerable<KeyValuePair<string, object>>
{
public static readonly IEcsWorldConfig Empty = new EmptyConfig();
private Dictionary<string, object> _storage = new Dictionary<string, object>();
public EcsPipelineConfig() { }
public EcsPipelineConfig(IEnumerable<KeyValuePair<string, object>> range)
{
_storage = new Dictionary<string, object>(range);
}
public EcsPipelineConfig(params KeyValuePair<string, object>[] range)
{
_storage = new Dictionary<string, object>(range);
}
public int Count
{
get { return _storage.Count; }
}
public T Get<T>(string valueName)
{
return (T)_storage[valueName];
}
public bool Has(string valueName)
{
return _storage.ContainsKey(valueName);
}
public void Remove(string valueName)
{
_storage.Remove(valueName);
}
public void Set<T>(string valueName, T value)
{
_storage[valueName] = value;
}
public void Add(string key, object value)
{
_storage.Add(key, value);
}
public void Add(KeyValuePair<string, object> pair)
{
_storage.Add(pair.Key, pair.Value);
}
public bool TryGet<T>(string valueName, out T value)
{
bool result = _storage.TryGetValue(valueName, out object rawValue);
value = rawValue == null ? default : (T)rawValue;
return result;
}
public IEnumerable<KeyValuePair<string, object>> GetAllConfigs()
{
return _storage;
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return GetAllConfigs().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetAllConfigs().GetEnumerator();
}
public IEcsPipelineConfig GetPipelineConfig()
{
return this;
}
private class EmptyConfig : IEcsWorldConfig
{
public int Count { get { return 0; } }
public T Get<T>(string valueName) { return default; }
public IEnumerable<KeyValuePair<string, object>> GetAllConfigs() { return Array.Empty<KeyValuePair<string, object>>(); }
public bool Has(string valueName) { return false; }
public bool TryGet<T>(string valueName, out T value) { value = default; return false; }
}
}
}

View File

@ -4,23 +4,10 @@ using System.Collections.Generic;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public interface IEcsWorldConfig public interface IEcsWorldConfig : IConfig { }
public interface IEcsWorldConfigWriter : IConfigWriter
{ {
int Count { get; } IEcsWorldConfig GetWorldConfig();
bool Has(string valueName);
T Get<T>(string valueName);
bool TryGet<T>(string valueName, out T value);
IEnumerable<KeyValuePair<string, object>> GetAllConfigs();
}
public interface IEcsWorldConfigWriter
{
int Count { get; }
void Set<T>(string valueName, T value);
bool Has(string valueName);
T Get<T>(string valueName);
bool TryGet<T>(string valueName, out T value);
void Remove(string valueName);
IEnumerable<KeyValuePair<string, object>> GetAllConfigs();
} }
[Serializable] [Serializable]
public class EcsWorldConfig : IEcsWorldConfigWriter, IEcsWorldConfig, IEnumerable<KeyValuePair<string, object>> public class EcsWorldConfig : IEcsWorldConfigWriter, IEcsWorldConfig, IEnumerable<KeyValuePair<string, object>>
@ -86,6 +73,11 @@ namespace DCFApixels.DragonECS
return GetAllConfigs().GetEnumerator(); return GetAllConfigs().GetEnumerator();
} }
public IEcsWorldConfig GetWorldConfig()
{
return this;
}
private class EmptyConfig : IEcsWorldConfig private class EmptyConfig : IEcsWorldConfig
{ {
public int Count { get { return 0; } } public int Count { get { return 0; } }

34
src/Configs/IConfig.cs Normal file
View File

@ -0,0 +1,34 @@
using System.Collections.Generic;
namespace DCFApixels.DragonECS
{
public interface IConfig
{
int Count { get; }
bool Has(string valueName);
T Get<T>(string valueName);
bool TryGet<T>(string valueName, out T value);
IEnumerable<KeyValuePair<string, object>> GetAllConfigs();
}
public interface IConfigWriter
{
int Count { get; }
void Set<T>(string valueName, T value);
bool Has(string valueName);
T Get<T>(string valueName);
bool TryGet<T>(string valueName, out T value);
void Remove(string valueName);
IEnumerable<KeyValuePair<string, object>> GetAllConfigs();
}
public static class ConfigExtensions
{
public static T GetOrDefault<T>(this IConfig self, string valueName, T defaultValue)
{
if (self.TryGet(valueName, out T value))
{
return value;
}
return defaultValue;
}
}
}

View File

@ -3,80 +3,104 @@ using DCFApixels.DragonECS.RunnersCore;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public interface IEcsPipelineMember public interface IEcsPipelineMember : IEcsSystem
{ {
public EcsPipeline Pipeline { get; set; } public EcsPipeline Pipeline { get; set; }
} }
public sealed class EcsPipeline public sealed class EcsPipeline
{ {
private IEcsProcess[] _allSystems; private readonly IEcsPipelineConfig _config;
private Dictionary<Type, IEcsRunner> _runners = new Dictionary<Type, IEcsRunner>();
private IEcsRunProcess _runRunnerCache;
private ReadOnlyCollection<IEcsProcess> _allSystemsSealed; private IEcsSystem[] _allSystems;
private ReadOnlyDictionary<Type, IEcsRunner> _allRunnersSealed; private Dictionary<Type, Array> _processes = new Dictionary<Type, Array>();
private Dictionary<Type, IEcsRunner> _runners = new Dictionary<Type, IEcsRunner>();
private IEcsRun _runRunnerCache;
private bool _isInit = false; private bool _isInit = false;
private bool _isDestoryed = false; private bool _isDestoryed = false;
#region Properties #region Properties
public ReadOnlyCollection<IEcsProcess> AllSystems => _allSystemsSealed; public IEcsPipelineConfig Config
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed; {
public bool IsInit => _isInit; get { return _config; }
public bool IsDestoryed => _isDestoryed; }
public EcsProcess<IEcsSystem> AllSystems
{
get { return new EcsProcess<IEcsSystem>(_allSystems); }
}
public IReadOnlyDictionary<Type, IEcsRunner> AllRunners
{
get { return _runners; }
}
public bool IsInit
{
get { return _isInit; }
}
public bool IsDestoryed
{
get { return _isDestoryed; }
}
#endregion #endregion
#region Constructors #region Constructors
private EcsPipeline(IEcsProcess[] systems) private EcsPipeline(IEcsPipelineConfig config, IEcsSystem[] systems)
{ {
_config = config;
_allSystems = systems; _allSystems = systems;
_allSystemsSealed = new ReadOnlyCollection<IEcsProcess>(_allSystems);
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
} }
#endregion #endregion
#region GetSystems #region Get Process/Runner
public T[] GetSystems<T>() public EcsProcess<T> GetProcess<T>() where T : IEcsSystem
{
return _allSystems.OfType<T>().ToArray();
}
public int GetSystemsNoAllock<T>(ref T[] array)
{
int count = 0;
for (int i = 0; i < _allSystems.Length; i++)
{
if (_allSystems is T targetSystem)
{
if (array.Length <= count)
{
Array.Resize(ref array, array.Length << 1);
}
array[count++] = targetSystem;
}
}
return count;
}
#endregion
#region Runners
public T GetRunner<T>() where T : IEcsProcess
{ {
Type type = typeof(T); Type type = typeof(T);
if (_runners.TryGetValue(type, out IEcsRunner result)) T[] result;
if(_processes.TryGetValue(type, out Array array))
{ {
return (T)result; result = (T[])array;
} }
else
{
result = _allSystems.OfType<T>().ToArray();
_processes.Add(type, result);
}
return new EcsProcess<T>(result);
}
#if !REFLECTION_DISABLED
public T GetRunner<T>() where T : IEcsSystem
{
Type interfaceType = typeof(T);
if (_runners.TryGetValue(interfaceType, out IEcsRunner result) == false)
{
result = (IEcsRunner)EcsRunner<T>.Instantiate(this); result = (IEcsRunner)EcsRunner<T>.Instantiate(this);
_runners.Add(type, result); _runners.Add(result.GetType(), result);
_runners.Add(interfaceType, result);
}
return (T)result; return (T)result;
} }
internal void OnRunnerDestroy(IEcsRunner runner) #endif
public T GetRunnerInstance<T>() where T : IEcsRunner, new()
{
Type runnerType = typeof(T);
if (_runners.TryGetValue(runnerType, out IEcsRunner result) == false)
{
result = new T();
_runners.Add(runnerType, result);
#if !REFLECTION_DISABLED
_runners.Add(result.Interface, result);
#endif
}
return (T)result;
}
#endregion
#region Internal
internal void OnRunnerDestroy_Internal(IEcsRunner runner)
{ {
_runners.Remove(runner.Interface); _runners.Remove(runner.Interface);
} }
@ -91,20 +115,20 @@ namespace DCFApixels.DragonECS
return; return;
} }
IEcsPipelineMember[] members = GetSystems<IEcsPipelineMember>(); EcsProcess<IEcsPipelineMember> members = GetProcess<IEcsPipelineMember>();
foreach (var member in members) foreach (var member in members)
{ {
member.Pipeline = this; member.Pipeline = this;
} }
var preInitRunner = GetRunner<IEcsPreInitProcess>(); var preInitRunner = GetRunner<IEcsPreInit>();
preInitRunner.PreInit(); preInitRunner.PreInit();
EcsRunner.Destroy(preInitRunner); EcsRunner.Destroy(preInitRunner);
var initRunner = GetRunner<IEcsInitProcess>(); var initRunner = GetRunner<IEcsInit>();
initRunner.Init(); initRunner.Init();
EcsRunner.Destroy(initRunner); EcsRunner.Destroy(initRunner);
_runRunnerCache = GetRunner<IEcsRunProcess>(); _runRunnerCache = GetRunner<IEcsRun>();
_isInit = true; _isInit = true;
GC.Collect(); GC.Collect();
} }
@ -129,34 +153,47 @@ namespace DCFApixels.DragonECS
return; return;
} }
_isDestoryed = true; _isDestoryed = true;
GetRunner<IEcsDestroyProcess>().Destroy(); GetRunner<IEcsDestroy>().Destroy();
} }
#endregion #endregion
#region Builder #region Builder
public static Builder New() => new Builder(); public static Builder New(IEcsPipelineConfigWriter config = null)
{
return new Builder(config);
}
public class Builder public class Builder
{ {
private const int KEYS_CAPACITY = 4; private const int KEYS_CAPACITY = 4;
private HashSet<Type> _uniqueTypes; private HashSet<Type> _uniqueTypes;
private readonly Dictionary<string, List<IEcsProcess>> _systems; private readonly Dictionary<string, List<IEcsSystem>> _systems;
private readonly string _basicLayer; private readonly string _basicLayer;
public readonly LayerList Layers; public readonly LayerList Layers;
public Builder() private readonly IEcsPipelineConfigWriter _config;
public IEcsPipelineConfigWriter Config
{ {
get { return _config; }
}
public Builder(IEcsPipelineConfigWriter config = null)
{
if (config == null)
{
config = new EcsPipelineConfig();
}
_config = config;
_basicLayer = EcsConsts.BASIC_LAYER; _basicLayer = EcsConsts.BASIC_LAYER;
Layers = new LayerList(this, _basicLayer); Layers = new LayerList(this, _basicLayer);
Layers.Insert(EcsConsts.BASIC_LAYER, EcsConsts.PRE_BEGIN_LAYER, EcsConsts.BEGIN_LAYER); Layers.Insert(EcsConsts.BASIC_LAYER, EcsConsts.PRE_BEGIN_LAYER, EcsConsts.BEGIN_LAYER);
Layers.InsertAfter(EcsConsts.BASIC_LAYER, EcsConsts.END_LAYER, EcsConsts.POST_END_LAYER); Layers.InsertAfter(EcsConsts.BASIC_LAYER, EcsConsts.END_LAYER, EcsConsts.POST_END_LAYER);
_uniqueTypes = new HashSet<Type>(); _uniqueTypes = new HashSet<Type>();
_systems = new Dictionary<string, List<IEcsProcess>>(KEYS_CAPACITY); _systems = new Dictionary<string, List<IEcsSystem>>(KEYS_CAPACITY);
} }
public Builder Add(IEcsProcess system, string layerName = null) public Builder Add(IEcsSystem system, string layerName = null)
{ {
AddInternal(system, layerName, false); AddInternal(system, layerName, false);
return this; return this;
} }
public Builder AddUnique(IEcsProcess system, string layerName = null) public Builder AddUnique(IEcsSystem system, string layerName = null)
{ {
AddInternal(system, layerName, true); AddInternal(system, layerName, true);
return this; return this;
@ -168,13 +205,13 @@ namespace DCFApixels.DragonECS
list.RemoveAll(o => o is TSystem); list.RemoveAll(o => o is TSystem);
return this; return this;
} }
private void AddInternal(IEcsProcess system, string layerName, bool isUnique) private void AddInternal(IEcsSystem system, string layerName, bool isUnique)
{ {
if (layerName == null) layerName = _basicLayer; if (layerName == null) layerName = _basicLayer;
List<IEcsProcess> list; List<IEcsSystem> list;
if (!_systems.TryGetValue(layerName, out list)) if (!_systems.TryGetValue(layerName, out list))
{ {
list = new List<IEcsProcess> { new SystemsLayerMarkerSystem(layerName.ToString()) }; list = new List<IEcsSystem> { new SystemsLayerMarkerSystem(layerName.ToString()) };
_systems.Add(layerName, list); _systems.Add(layerName, list);
} }
if ((_uniqueTypes.Add(system.GetType()) == false && isUnique)) if ((_uniqueTypes.Add(system.GetType()) == false && isUnique))
@ -191,9 +228,8 @@ namespace DCFApixels.DragonECS
} }
public EcsPipeline Build() public EcsPipeline Build()
{ {
Add(new EndFrameSystem(), EcsConsts.POST_END_LAYER); List<IEcsSystem> result = new List<IEcsSystem>(32);
List<IEcsProcess> result = new List<IEcsProcess>(32); List<IEcsSystem> basicBlockList = _systems[_basicLayer];
List<IEcsProcess> basicBlockList = _systems[_basicLayer];
foreach (var item in _systems) foreach (var item in _systems)
{ {
if (!Layers.Contains(item.Key)) if (!Layers.Contains(item.Key))
@ -204,7 +240,7 @@ namespace DCFApixels.DragonECS
if (_systems.TryGetValue(item, out var list)) if (_systems.TryGetValue(item, out var list))
result.AddRange(list); result.AddRange(list);
} }
return new EcsPipeline(result.ToArray()); return new EcsPipeline(_config.GetPipelineConfig(), result.ToArray());
} }
public class LayerList : IEnumerable<string> public class LayerList : IEnumerable<string>
{ {
@ -321,15 +357,24 @@ namespace DCFApixels.DragonECS
#region Extensions #region Extensions
public static partial class EcsPipelineExtensions public static partial class EcsPipelineExtensions
{ {
public static bool IsNullOrDestroyed(this EcsPipeline self) => self == null || self.IsDestoryed; public static bool IsNullOrDestroyed(this EcsPipeline self)
public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable<IEcsProcess> range, string layerName = null)
{ {
foreach (var item in range) self.Add(item, layerName); return self == null || self.IsDestoryed;
}
public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable<IEcsSystem> range, string layerName = null)
{
foreach (var item in range)
{
self.Add(item, layerName);
}
return self; return self;
} }
public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable<IEcsProcess> range, string layerName = null) public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable<IEcsSystem> range, string layerName = null)
{ {
foreach (var item in range) self.AddUnique(item, layerName); foreach (var item in range)
{
self.AddUnique(item, layerName);
}
return self; return self;
} }
public static EcsPipeline BuildAndInit(this EcsPipeline.Builder self) public static EcsPipeline BuildAndInit(this EcsPipeline.Builder self)
@ -340,4 +385,110 @@ namespace DCFApixels.DragonECS
} }
} }
#endregion #endregion
#region SystemsLayerMarkerSystem
[MetaTags(MetaTags.HIDDEN)]
[MetaColor(MetaColor.Black)]
public class SystemsLayerMarkerSystem : IEcsSystem
{
public readonly string name;
public SystemsLayerMarkerSystem(string name) => this.name = name;
}
#endregion
#region EcsProcess
public readonly struct EcsProcessRaw : IEnumerable
{
private readonly Array _systems;
public int Length
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _systems.Length; }
}
public IEcsSystem this[int index]
{
get { return (IEcsSystem)_systems.GetValue(index); }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsProcessRaw(Array systems)
{
_systems = systems;
}
public IEnumerator GetEnumerator()
{
return _systems.GetEnumerator();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal T[] GetSystems_Internal<T>()
{
return (T[])_systems;
}
}
public readonly struct EcsProcess<TProcess> : IReadOnlyCollection<TProcess>
where TProcess : IEcsSystem
{
public readonly static EcsProcess<TProcess> Empty = new EcsProcess<TProcess>(Array.Empty<TProcess>());
private readonly TProcess[] _systems;
public bool IsNullOrEmpty
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _systems == null || _systems.Length <= 0; }
}
public int Length
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _systems.Length; }
}
int IReadOnlyCollection<TProcess>.Count
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _systems.Length; }
}
public TProcess this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _systems[index]; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsProcess(TProcess[] systems)
{
_systems = systems;
}
public static explicit operator EcsProcess<TProcess>(EcsProcessRaw raw)
{
return new EcsProcess<TProcess>(raw.GetSystems_Internal<TProcess>());
}
public static implicit operator EcsProcessRaw(EcsProcess<TProcess> process)
{
return new EcsProcessRaw(process._systems);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() { return new Enumerator(_systems); }
IEnumerator<TProcess> IEnumerable<TProcess>.GetEnumerator() { return GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public struct Enumerator : IEnumerator<TProcess>
{
private readonly TProcess[] _systems;
private int _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(TProcess[] systems)
{
_systems = systems;
_index = -1;
}
public TProcess Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _systems[_index]; }
}
object IEnumerator.Current { get { return Current; } }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() { return ++_index < _systems.Length; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset() { _index = -1; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose() { }
}
}
#endregion
} }

View File

@ -1,27 +1,12 @@
using DCFApixels.DragonECS.RunnersCore; using DCFApixels.DragonECS.RunnersCore;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using static DCFApixels.DragonECS.EcsDebugUtility; using static DCFApixels.DragonECS.EcsDebugUtility;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
sealed class EcsRunnerFilterAttribute : Attribute
{
public readonly Type interfaceType;
public readonly object filter;
public EcsRunnerFilterAttribute(Type interfaceType, object filter)
{
this.interfaceType = interfaceType;
this.filter = filter;
}
public EcsRunnerFilterAttribute(object filter) : this(null, filter) { }
}
#if UNITY_2020_3_OR_NEWER #if UNITY_2020_3_OR_NEWER
[UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve] [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve]
#endif #endif
@ -33,22 +18,30 @@ namespace DCFApixels.DragonECS
public BindWithEcsRunnerAttribute(Type runnerType) public BindWithEcsRunnerAttribute(Type runnerType)
{ {
if (runnerType == null) if (runnerType == null)
{
throw new ArgumentNullException(); throw new ArgumentNullException();
}
if (!CheckSubclass(runnerType)) if (!CheckSubclass(runnerType))
{
throw new ArgumentException(); throw new ArgumentException();
}
this.runnerType = runnerType; this.runnerType = runnerType;
} }
private bool CheckSubclass(Type type) private bool CheckSubclass(Type type)
{ {
if (type.IsGenericType && type.GetGenericTypeDefinition() == _baseType) if (type.IsGenericType && type.GetGenericTypeDefinition() == _baseType)
{
return true; return true;
}
if (type.BaseType != null) if (type.BaseType != null)
{
return CheckSubclass(type.BaseType); return CheckSubclass(type.BaseType);
}
return false; return false;
} }
} }
public interface IEcsProcess { } public interface IEcsSystem { }
namespace RunnersCore namespace RunnersCore
{ {
@ -56,9 +49,7 @@ namespace DCFApixels.DragonECS
{ {
EcsPipeline Pipeline { get; } EcsPipeline Pipeline { get; }
Type Interface { get; } Type Interface { get; }
IList TargetsRaw { get; } EcsProcessRaw ProcessRaw { get; }
object Filter { get; }
bool IsHasFilter { get; }
bool IsDestroyed { get; } bool IsDestroyed { get; }
bool IsEmpty { get; } bool IsEmpty { get; }
void Destroy(); void Destroy();
@ -67,72 +58,39 @@ namespace DCFApixels.DragonECS
#if UNITY_2020_3_OR_NEWER #if UNITY_2020_3_OR_NEWER
[UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve] [UnityEngine.Scripting.RequireDerived, UnityEngine.Scripting.Preserve]
#endif #endif
public abstract class EcsRunner<TInterface> : IEcsProcess, IEcsRunner public abstract class EcsRunner<TProcess> : IEcsSystem, IEcsRunner
where TInterface : IEcsProcess where TProcess : IEcsSystem
{ {
#region Register #region Register
private static Type _subclass; private static Type _runnerImplementationType;
internal static void Register(Type subclass) internal static void Register(Type subclass)
{ {
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
if (_subclass != null) if (_runnerImplementationType != null)
{ {
throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); throw new EcsRunnerImplementationException($"The Runner<{typeof(TProcess).FullName}> can have only one implementing subclass");
} }
Type interfaceType = typeof(TInterface); Type interfaceType = typeof(TProcess);
var interfaces = interfaceType.GetInterfaces(); var interfaces = interfaceType.GetInterfaces();
if (interfaceType.IsInterface == false) if (interfaceType.IsInterface == false)
{ {
throw new ArgumentException($"{typeof(TInterface).FullName} is not interface"); throw new ArgumentException($"{typeof(TProcess).FullName} is not interface");
} }
if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsProcess)) if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem))
{ {
throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsProcess)} interface"); throw new ArgumentException($"{typeof(TProcess).FullName} does not directly inherit the {nameof(IEcsSystem)} interface");
} }
#endif #endif
_subclass = subclass; _runnerImplementationType = subclass;
}
#endregion
#region FilterSystems
private static TInterface[] FilterSystems(IEnumerable<IEcsProcess> targets)
{
return targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray();
}
private static TInterface[] FilterSystems(IEnumerable<IEcsProcess> targets, object filter)
{
Type interfaceType = typeof(TInterface);
IEnumerable<IEcsProcess> newTargets;
if (filter != null)
{
newTargets = targets.Where(o =>
{
if (o is TInterface == false) return false;
var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>();
return atr != null && atr.interfaceType == interfaceType && atr.filter.Equals(filter);
});
}
else
{
newTargets = targets.Where(o =>
{
if (o is TInterface == false) return false;
var atr = o.GetType().GetCustomAttribute<EcsRunnerFilterAttribute>();
return atr == null || atr.interfaceType == interfaceType && atr.filter == null;
});
}
return newTargets.Select(o => (TInterface)o).ToArray();
} }
#endregion #endregion
#region Instantiate #region Instantiate
private static void CheckRunnerValide(Type type) //TODO доработать проверку валидности реалиазации ранера private static void CheckRunnerValide(Type type) //TODO доработать проверку валидности реалиазации ранера
{ {
Type targetInterface = typeof(TInterface); Type targetInterface = typeof(TProcess);
if (type.IsAbstract) if (type.IsAbstract)
{ {
throw new Exception(); throw new Exception();
@ -160,91 +118,85 @@ namespace DCFApixels.DragonECS
} }
} }
private static TInterface Instantiate(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter)
public static TProcess Instantiate(EcsPipeline source)
{ {
if (_subclass == null) EcsProcess<TProcess> process = source.GetProcess<TProcess>();
if (_runnerImplementationType == null)
{ {
Type interfaceType = typeof(TInterface); Type interfaceType = typeof(TProcess);
if (interfaceType.TryGetCustomAttribute(out BindWithEcsRunnerAttribute atr)) if (interfaceType.TryGetCustomAttribute(out BindWithEcsRunnerAttribute atr))
{ {
Type runnerType = atr.runnerType; Type runnerImplementationType = atr.runnerType;
if (interfaceType.IsGenericType) if (interfaceType.IsGenericType)
{ {
Type[] genericTypes = interfaceType.GetGenericArguments(); Type[] genericTypes = interfaceType.GetGenericArguments();
runnerType = runnerType.MakeGenericType(genericTypes); runnerImplementationType = runnerImplementationType.MakeGenericType(genericTypes);
} }
CheckRunnerValide(runnerType); CheckRunnerValide(runnerImplementationType);
_subclass = runnerType; _runnerImplementationType = runnerImplementationType;
} }
else else
{ {
throw new EcsFrameworkException("Процесс не связан с раннером, используйте атрибуут BindWithEcsRunner(Type runnerType)"); throw new EcsFrameworkException("Процесс не связан с раннером, используйте атрибуут BindWithEcsRunner(Type runnerType)");
} }
} }
var instance = (EcsRunner<TProcess>)Activator.CreateInstance(_runnerImplementationType);
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass); return (TProcess)(IEcsSystem)instance.Set(source, process);
return (TInterface)(IEcsProcess)instance.Set(source, targets, isHasFilter, filter);
}
public static TInterface Instantiate(EcsPipeline source)
{
return Instantiate(source, FilterSystems(source.AllSystems), false, null);
}
public static TInterface Instantiate(EcsPipeline source, object filter)
{
return Instantiate(source, FilterSystems(source.AllSystems, filter), true, filter);
} }
#endregion #endregion
private EcsPipeline _source; private EcsPipeline _source;
protected TInterface[] targets; private EcsProcess<TProcess> _process;
private ReadOnlyCollection<TInterface> _targetsSealed;
private object _filter;
private bool _isHasFilter;
private bool _isDestroyed; private bool _isDestroyed;
#region Properties #region Properties
public EcsPipeline Pipeline => _source; public EcsPipeline Pipeline
public Type Interface => typeof(TInterface); {
public IList TargetsRaw => _targetsSealed; get { return _source; }
public ReadOnlySpan<TInterface> Targets => targets; }
public object Filter => _filter; public Type Interface
public bool IsHasFilter => _isHasFilter; {
public bool IsDestroyed => _isDestroyed; get { return typeof(TProcess); }
public bool IsEmpty => targets == null || targets.Length <= 0; }
public EcsProcessRaw ProcessRaw
{
get { return _process; }
}
public EcsProcess<TProcess> Process
{
get { return _process; }
}
public bool IsDestroyed
{
get { return _isDestroyed; }
}
public bool IsEmpty
{
get { return _process.IsNullOrEmpty;}
}
#endregion #endregion
private EcsRunner<TInterface> Set(EcsPipeline source, TInterface[] targets, bool isHasFilter, object filter) private EcsRunner<TProcess> Set(EcsPipeline source, EcsProcess<TProcess> process)
{ {
_source = source; _source = source;
this.targets = targets; this._process = process;
_targetsSealed = new ReadOnlyCollection<TInterface>(targets);
_filter = filter;
_isHasFilter = isHasFilter;
OnSetup(); OnSetup();
return this; return this;
} }
internal void Rebuild() internal void Rebuild()
{ {
if (_isHasFilter) Set(_source, _source.GetProcess<TProcess>());
{
Set(_source, FilterSystems(_source.AllSystems), _isHasFilter, _filter);
}
else
{
Set(_source, FilterSystems(_source.AllSystems, _filter), _isHasFilter, _filter);
}
} }
public void Destroy() public void Destroy()
{ {
_isDestroyed = true; _isDestroyed = true;
_source.OnRunnerDestroy(this); _source.OnRunnerDestroy_Internal(this);
_source = null; _source = null;
targets = null; _process = EcsProcess<TProcess>.Empty;
_targetsSealed = null;
_filter = null;
OnDestroy(); OnDestroy();
} }
protected virtual void OnSetup() { } //rename to OnInitialize protected virtual void OnSetup() { } //TODO rename to OnInitialize
protected virtual void OnDestroy() { } protected virtual void OnDestroy() { }
} }
} }
@ -252,11 +204,11 @@ namespace DCFApixels.DragonECS
#region Extensions #region Extensions
public static class EcsRunner public static class EcsRunner
{ {
public static void Destroy(IEcsProcess runner) => ((IEcsRunner)runner).Destroy(); public static void Destroy(IEcsSystem runner) => ((IEcsRunner)runner).Destroy();
} }
public static class IEcsSystemExtensions public static class IEcsSystemExtensions
{ {
public static bool IsRunner(this IEcsProcess self) public static bool IsRunner(this IEcsSystem self)
{ {
return self is IEcsRunner; return self is IEcsRunner;
} }
@ -280,13 +232,13 @@ namespace DCFApixels.DragonECS
static EcsProcessUtility() static EcsProcessUtility()
{ {
Type processBasicInterface = typeof(IEcsProcess); Type processBasicInterface = typeof(IEcsSystem);
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{ {
var types = assembly.GetTypes(); var types = assembly.GetTypes();
foreach (var type in types) foreach (var type in types)
{ {
if (type.GetInterface(nameof(IEcsProcess)) != null || type == processBasicInterface) if (type.GetInterface(nameof(IEcsSystem)) != null || type == processBasicInterface)
{ {
if (type.IsInterface) if (type.IsInterface)
{ {

View File

@ -1,6 +1,6 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public abstract partial class EcsWorld public partial class EcsWorld
{ {
internal readonly struct PoolCache<T> : IEcsWorldComponent<PoolCache<T>> internal readonly struct PoolCache<T> : IEcsWorldComponent<PoolCache<T>>
where T : IEcsPoolImplementation, new() where T : IEcsPoolImplementation, new()

View File

@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public abstract partial class EcsWorld : IEntityStorage public partial class EcsWorld : IEntityStorage
{ {
public readonly short id; public readonly short id;
private IEcsWorldConfig _config; private IEcsWorldConfig _config;

View File

@ -4,7 +4,7 @@ using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public abstract partial class EcsWorld public partial class EcsWorld
{ {
private SparseArray<int> _poolTypeCode_2_CmpTypeIDs = new SparseArray<int>(); private SparseArray<int> _poolTypeCode_2_CmpTypeIDs = new SparseArray<int>();
private SparseArray<int> _componentTypeCode_2_CmpTypeIDs = new SparseArray<int>(); private SparseArray<int> _componentTypeCode_2_CmpTypeIDs = new SparseArray<int>();
@ -110,12 +110,12 @@ namespace DCFApixels.DragonECS
TPool newPool = new TPool(); TPool newPool = new TPool();
Type componentType = newPool.ComponentType; Type componentType = newPool.ComponentType;
//#if DEBUG //проверка соответсвия типов //#if DEBUG //проверка соответсвия типов
// if(componentType != typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0]) // if(componentType != typeof(TPool).GetInterfaces().First(o => o.IsGenericType && o.GetGenericTypeDefinition() == typeof(IEcsPoolImplementation<>)).GetGenericArguments()[0])
// { // {
// Throw.UndefinedException(); // Throw.UndefinedException();
// } // }
//#endif //#endif
int componentTypeCode = EcsTypeCode.Get(componentType); int componentTypeCode = EcsTypeCode.Get(componentType);
if (_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID)) if (_componentTypeCode_2_CmpTypeIDs.TryGetValue(componentTypeCode, out int componentTypeID))

View File

@ -14,7 +14,7 @@ namespace DCFApixels.DragonECS
public EcsWorld World => EcsWorld.GetWorld(_worldID); public EcsWorld World => EcsWorld.GetWorld(_worldID);
public ref T Value => ref EcsWorld.GetData<T>(_worldID); public ref T Value => ref EcsWorld.GetData<T>(_worldID);
} }
public abstract partial class EcsWorld public partial class EcsWorld
{ {
private const short GEN_MASK = 0x7fff; private const short GEN_MASK = 0x7fff;
private const short DEATH_GEN_BIT = short.MinValue; private const short DEATH_GEN_BIT = short.MinValue;

View File

@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS.Internal namespace DCFApixels.DragonECS.Internal
{ {
public static class EcsTypeCode internal static class EcsTypeCode
{ {
private static readonly Dictionary<Type, int> _codes = new Dictionary<Type, int>(); private static readonly Dictionary<Type, int> _codes = new Dictionary<Type, int>();
private static int _increment = 1; private static int _increment = 1;
@ -29,11 +29,11 @@ namespace DCFApixels.DragonECS.Internal
public static bool Has<T>() { return _codes.ContainsKey(typeof(T)); } public static bool Has<T>() { return _codes.ContainsKey(typeof(T)); }
public static IEnumerable<TypeCodeInfo> GetDeclaredTypes() { return _codes.Select(o => new TypeCodeInfo(o.Key, o.Value)); } public static IEnumerable<TypeCodeInfo> GetDeclaredTypes() { return _codes.Select(o => new TypeCodeInfo(o.Key, o.Value)); }
} }
public static class EcsTypeCodeCache<T> internal static class EcsTypeCodeCache<T>
{ {
public static readonly int code = EcsTypeCode.Get(typeof(T)); public static readonly int code = EcsTypeCode.Get(typeof(T));
} }
public struct TypeCodeInfo internal struct TypeCodeInfo
{ {
public Type type; public Type type;
public int code; public int code;

View File

@ -299,7 +299,7 @@ namespace DCFApixels.DragonECS
} }
} }
public abstract partial class EcsWorld public partial class EcsWorld
{ {
private Dictionary<Type, HybridMapping> _hybridMapping = new Dictionary<Type, HybridMapping>(); private Dictionary<Type, HybridMapping> _hybridMapping = new Dictionary<Type, HybridMapping>();
internal HybridMapping GetHybridMapping(Type type) internal HybridMapping GetHybridMapping(Type type)