mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 09:54:35 +08:00
Merge branch 'dev'
This commit is contained in:
commit
d5c3fe4f84
@ -3,19 +3,19 @@
|
|||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
#region Interfaces
|
#region Interfaces
|
||||||
public interface IEcsPreInitProcess : IEcsSystem
|
public interface IEcsPreInitProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void PreInit(EcsPipeline pipeline);
|
void PreInit(EcsPipeline pipeline);
|
||||||
}
|
}
|
||||||
public interface IEcsInitProcess : IEcsSystem
|
public interface IEcsInitProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Init(EcsPipeline pipeline);
|
void Init(EcsPipeline pipeline);
|
||||||
}
|
}
|
||||||
public interface IEcsRunProcess : IEcsSystem
|
public interface IEcsRunProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Run(EcsPipeline pipeline);
|
void Run(EcsPipeline pipeline);
|
||||||
}
|
}
|
||||||
public interface IEcsDestroyProcess : IEcsSystem
|
public interface IEcsDestroyProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Destroy(EcsPipeline pipeline);
|
void Destroy(EcsPipeline pipeline);
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,15 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
public interface IEcsPreInject : IEcsSystem
|
public interface IEcsPreInject : IEcsProcess
|
||||||
{
|
{
|
||||||
void PreInject(object obj);
|
void PreInject(object obj);
|
||||||
}
|
}
|
||||||
public interface IEcsInject<T> : IEcsSystem
|
public interface IEcsInject<T> : IEcsProcess
|
||||||
{
|
{
|
||||||
void Inject(T obj);
|
void Inject(T obj);
|
||||||
}
|
}
|
||||||
public interface IEcsPreInitInjectProcess : IEcsSystem
|
public interface IEcsPreInitInjectProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void OnPreInitInjectionBefore();
|
void OnPreInitInjectionBefore();
|
||||||
void OnPreInitInjectionAfter();
|
void OnPreInitInjectionAfter();
|
||||||
@ -129,6 +129,7 @@ namespace DCFApixels.DragonECS
|
|||||||
injectCallbacksRunner.OnPreInitInjectionAfter();
|
injectCallbacksRunner.OnPreInitInjectionAfter();
|
||||||
EcsRunner.Destroy(injectCallbacksRunner);
|
EcsRunner.Destroy(injectCallbacksRunner);
|
||||||
}
|
}
|
||||||
|
_injectedData = default;
|
||||||
}
|
}
|
||||||
public void OnPreInitInjectionBefore() { }
|
public void OnPreInitInjectionBefore() { }
|
||||||
public void OnPreInitInjectionAfter() => _injectController = null;
|
public void OnPreInitInjectionAfter() => _injectController = null;
|
||||||
|
@ -6,7 +6,7 @@ namespace DCFApixels.DragonECS
|
|||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
[DebugHide, DebugColor(DebugColor.Black)]
|
[DebugHide, DebugColor(DebugColor.Black)]
|
||||||
public class SystemsLayerMarkerSystem : IEcsSystem
|
public class SystemsLayerMarkerSystem : IEcsProcess
|
||||||
{
|
{
|
||||||
public readonly string name;
|
public readonly string name;
|
||||||
public SystemsLayerMarkerSystem(string name) => this.name = name;
|
public SystemsLayerMarkerSystem(string name) => this.name = name;
|
||||||
@ -53,7 +53,7 @@ namespace DCFApixels.DragonECS
|
|||||||
public static EcsPipeline.Builder AutoDel<TComponent>(this EcsPipeline.Builder b, string layerName = AUTO_DEL_LAYER)
|
public static EcsPipeline.Builder AutoDel<TComponent>(this EcsPipeline.Builder b, string layerName = AUTO_DEL_LAYER)
|
||||||
where TComponent : struct, IEcsComponent
|
where TComponent : struct, IEcsComponent
|
||||||
{
|
{
|
||||||
if(AUTO_DEL_LAYER == layerName)
|
if (AUTO_DEL_LAYER == layerName)
|
||||||
b.Layers.Insert(EcsConsts.POST_END_LAYER, AUTO_DEL_LAYER);
|
b.Layers.Insert(EcsConsts.POST_END_LAYER, AUTO_DEL_LAYER);
|
||||||
b.AddUnique(new DeleteOneFrameComponentSystem<TComponent>(), layerName);
|
b.AddUnique(new DeleteOneFrameComponentSystem<TComponent>(), layerName);
|
||||||
return b;
|
return b;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
public const string FRAMEWORK_NAME = "DragonECS";
|
public const string FRAMEWORK_NAME = "DragonECS";
|
||||||
|
|
||||||
public const string EXCEPTION_MESSAGE_PREFIX = "["+ FRAMEWORK_NAME + "] ";
|
public const string EXCEPTION_MESSAGE_PREFIX = "[" + FRAMEWORK_NAME + "] ";
|
||||||
public const string DEBUG_PREFIX = "[DEBUG] ";
|
public const string DEBUG_PREFIX = "[DEBUG] ";
|
||||||
public const string DEBUG_WARNING_TAG = "WARNING";
|
public const string DEBUG_WARNING_TAG = "WARNING";
|
||||||
public const string DEBUG_ERROR_TAG = "ERROR";
|
public const string DEBUG_ERROR_TAG = "ERROR";
|
||||||
|
@ -117,7 +117,7 @@ namespace DCFApixels.DragonECS
|
|||||||
public int RegisterMark(string name)
|
public int RegisterMark(string name)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
if(!_nameIdTable.TryGetValue(name, out id))
|
if (!_nameIdTable.TryGetValue(name, out id))
|
||||||
{
|
{
|
||||||
id = _idDispenser.GetFree();
|
id = _idDispenser.GetFree();
|
||||||
_nameIdTable.Add(name, id);
|
_nameIdTable.Add(name, id);
|
||||||
@ -149,7 +149,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
#if !DISABLE_DRAGONECS_DEBUGGER
|
#if !DISABLE_DRAGONECS_DEBUGGER
|
||||||
_stopwatchs = new Stopwatch[64];
|
_stopwatchs = new Stopwatch[64];
|
||||||
_stopwatchsNames= new string[64];
|
_stopwatchsNames = new string[64];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
public override void Print(string tag, object v)
|
public override void Print(string tag, object v)
|
||||||
|
@ -54,5 +54,11 @@ namespace DCFApixels.DragonECS
|
|||||||
var atr = type.GetCustomAttribute<DebugColorAttribute>();
|
var atr = type.GetCustomAttribute<DebugColorAttribute>();
|
||||||
return atr != null ? (atr.r, atr.g, atr.b) : ((byte)255, (byte)255, (byte)255);
|
return atr != null ? (atr.r, atr.g, atr.b) : ((byte)255, (byte)255, (byte)255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsHidden<T>() => IsHidden(typeof(T));
|
||||||
|
public static bool IsHidden(Type type)
|
||||||
|
{
|
||||||
|
return type.GetCustomAttribute<DebugHideAttribute>() != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (group.World != _source) throw new ArgumentException("groupFilter.WorldIndex != WorldIndex");
|
if (group.World != _source) throw new ArgumentException("groupFilter.WorldIndex != WorldIndex");
|
||||||
#endif
|
#endif
|
||||||
if(_count > 0)
|
if (_count > 0)
|
||||||
Clear();
|
Clear();
|
||||||
foreach (var item in group)
|
foreach (var item in group)
|
||||||
AddInternal(item);
|
AddInternal(item);
|
||||||
@ -371,14 +371,14 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Enumerator
|
#region Enumerator
|
||||||
public ref struct Enumerator// : IDisposable
|
public ref struct Enumerator// : IDisposable
|
||||||
{
|
{
|
||||||
// private readonly EcsGroup source;
|
// private readonly EcsGroup source;
|
||||||
private readonly int[] _dense;
|
private readonly int[] _dense;
|
||||||
private readonly int _count;
|
private readonly int _count;
|
||||||
private int _index;
|
private int _index;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public Enumerator(EcsGroup group)
|
public Enumerator(EcsGroup group)
|
||||||
{
|
{
|
||||||
// source = group;
|
// source = group;
|
||||||
_dense = group._dense;
|
_dense = group._dense;
|
||||||
_count = group._count;
|
_count = group._count;
|
||||||
_index = 0;
|
_index = 0;
|
||||||
@ -389,7 +389,7 @@ namespace DCFApixels.DragonECS
|
|||||||
get => _dense[_index];
|
get => _dense[_index];
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool MoveNext() => ++_index <= _count && _count<_dense.Length; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны
|
public bool MoveNext() => ++_index <= _count && _count < _dense.Length; // <= потму что отсчет начинается с индекса 1 //_count < _dense.Length дает среде понять что проверки на выход за границы не нужны
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
//public void Dispose() => source.Unlock();
|
//public void Dispose() => source.Unlock();
|
||||||
}
|
}
|
||||||
|
@ -11,30 +11,30 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public sealed class EcsPipeline
|
public sealed class EcsPipeline
|
||||||
{
|
{
|
||||||
private IEcsSystem[] _allSystems;
|
private IEcsProcess[] _allSystems;
|
||||||
private Dictionary<Type, IEcsRunner> _runners;
|
private Dictionary<Type, IEcsRunner> _runners;
|
||||||
private IEcsRunProcess _runRunnerCache;
|
private IEcsRunProcess _runRunnerCache;
|
||||||
|
|
||||||
private ReadOnlyCollection<IEcsSystem> _allSystemsSealed;
|
private ReadOnlyCollection<IEcsProcess> _allSystemsSealed;
|
||||||
private ReadOnlyDictionary<Type, IEcsRunner> _allRunnersSealed;
|
private ReadOnlyDictionary<Type, IEcsRunner> _allRunnersSealed;
|
||||||
|
|
||||||
private bool _isInit;
|
private bool _isInit;
|
||||||
private bool _isDestoryed;
|
private bool _isDestoryed;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public ReadOnlyCollection<IEcsSystem> AllSystems => _allSystemsSealed;
|
public ReadOnlyCollection<IEcsProcess> AllSystems => _allSystemsSealed;
|
||||||
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed;
|
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed;
|
||||||
public bool IsInit => _isInit;
|
public bool IsInit => _isInit;
|
||||||
public bool IsDestoryed => _isDestoryed;
|
public bool IsDestoryed => _isDestoryed;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
private EcsPipeline(IEcsSystem[] systems)
|
private EcsPipeline(IEcsProcess[] systems)
|
||||||
{
|
{
|
||||||
_allSystems = systems;
|
_allSystems = systems;
|
||||||
_runners = new Dictionary<Type, IEcsRunner>();
|
_runners = new Dictionary<Type, IEcsRunner>();
|
||||||
|
|
||||||
_allSystemsSealed = new ReadOnlyCollection<IEcsSystem>(_allSystems);
|
_allSystemsSealed = new ReadOnlyCollection<IEcsProcess>(_allSystems);
|
||||||
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
|
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
|
||||||
|
|
||||||
_isInit = false;
|
_isInit = false;
|
||||||
@ -43,7 +43,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Runners
|
#region Runners
|
||||||
public T GetRunner<T>() where T : IEcsSystem
|
public T GetRunner<T>() where T : IEcsProcess
|
||||||
{
|
{
|
||||||
Type type = typeof(T);
|
Type type = typeof(T);
|
||||||
if (_runners.TryGetValue(type, out IEcsRunner result))
|
if (_runners.TryGetValue(type, out IEcsRunner result))
|
||||||
@ -132,7 +132,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
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<IEcsSystem>> _systems;
|
private readonly Dictionary<string, List<IEcsProcess>> _systems;
|
||||||
private readonly string _basicLayer;
|
private readonly string _basicLayer;
|
||||||
public readonly LayerList Layers;
|
public readonly LayerList Layers;
|
||||||
public Builder()
|
public Builder()
|
||||||
@ -142,14 +142,14 @@ namespace DCFApixels.DragonECS
|
|||||||
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<IEcsSystem>>(KEYS_CAPACITY);
|
_systems = new Dictionary<string, List<IEcsProcess>>(KEYS_CAPACITY);
|
||||||
}
|
}
|
||||||
public Builder Add(IEcsSystem system, string layerName = null)
|
public Builder Add(IEcsProcess system, string layerName = null)
|
||||||
{
|
{
|
||||||
AddInternal(system, layerName, false);
|
AddInternal(system, layerName, false);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Builder AddUnique(IEcsSystem system, string layerName = null)
|
public Builder AddUnique(IEcsProcess system, string layerName = null)
|
||||||
{
|
{
|
||||||
AddInternal(system, layerName, true);
|
AddInternal(system, layerName, true);
|
||||||
return this;
|
return this;
|
||||||
@ -161,13 +161,13 @@ namespace DCFApixels.DragonECS
|
|||||||
list.RemoveAll(o => o is TSystem);
|
list.RemoveAll(o => o is TSystem);
|
||||||
return this;
|
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;
|
if (layerName == null) layerName = _basicLayer;
|
||||||
List<IEcsSystem> list;
|
List<IEcsProcess> list;
|
||||||
if (!_systems.TryGetValue(layerName, out list))
|
if (!_systems.TryGetValue(layerName, out list))
|
||||||
{
|
{
|
||||||
list = new List<IEcsSystem> { new SystemsLayerMarkerSystem(layerName.ToString()) };
|
list = new List<IEcsProcess> { 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))
|
||||||
@ -179,14 +179,14 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public Builder AddModule(IEcsModule module)
|
public Builder AddModule(IEcsModule module)
|
||||||
{
|
{
|
||||||
module.ImportSystems(this);
|
module.Import(this);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public EcsPipeline Build()
|
public EcsPipeline Build()
|
||||||
{
|
{
|
||||||
Add(new DeleteEmptyEntitesSystem(), EcsConsts.POST_END_LAYER);
|
Add(new DeleteEmptyEntitesSystem(), 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))
|
||||||
@ -194,7 +194,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
foreach (var item in Layers)
|
foreach (var item in Layers)
|
||||||
{
|
{
|
||||||
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(result.ToArray());
|
||||||
@ -308,19 +308,19 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
public interface IEcsModule
|
public interface IEcsModule
|
||||||
{
|
{
|
||||||
void ImportSystems(EcsPipeline.Builder b);
|
void Import(EcsPipeline.Builder b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Extensions
|
#region Extensions
|
||||||
public static class EcsPipelineExtensions
|
public static class EcsPipelineExtensions
|
||||||
{
|
{
|
||||||
public static bool IsNullOrDestroyed(this EcsPipeline self) => self == null || self.IsDestoryed;
|
public static bool IsNullOrDestroyed(this EcsPipeline self) => self == null || self.IsDestoryed;
|
||||||
public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable<IEcsSystem> range, string layerName = null)
|
public static EcsPipeline.Builder Add(this EcsPipeline.Builder self, IEnumerable<IEcsProcess> range, string layerName = null)
|
||||||
{
|
{
|
||||||
foreach (var item in range) self.Add(item, layerName);
|
foreach (var item in range) self.Add(item, layerName);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable<IEcsSystem> range, string layerName = null)
|
public static EcsPipeline.Builder AddUnique(this EcsPipeline.Builder self, IEnumerable<IEcsProcess> 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;
|
||||||
|
@ -23,7 +23,7 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsRunnerFilterAttribute(object filter) : this(null, filter) { }
|
public EcsRunnerFilterAttribute(object filter) : this(null, filter) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IEcsSystem { }
|
public interface IEcsProcess { }
|
||||||
|
|
||||||
namespace RunnersCore
|
namespace RunnersCore
|
||||||
{
|
{
|
||||||
@ -103,7 +103,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static void InitFor<TInterface>() where TInterface : IEcsSystem
|
internal static void InitFor<TInterface>() where TInterface : IEcsProcess
|
||||||
{
|
{
|
||||||
Type interfaceType = typeof(TInterface);
|
Type interfaceType = typeof(TInterface);
|
||||||
|
|
||||||
@ -122,8 +122,8 @@ 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> : IEcsSystem, IEcsRunner
|
public abstract class EcsRunner<TInterface> : IEcsProcess, IEcsRunner
|
||||||
where TInterface : IEcsSystem
|
where TInterface : IEcsProcess
|
||||||
{
|
{
|
||||||
#region Register
|
#region Register
|
||||||
private static Type _subclass;
|
private static Type _subclass;
|
||||||
@ -142,9 +142,9 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
throw new ArgumentException($"{typeof(TInterface).FullName} is not interface");
|
throw new ArgumentException($"{typeof(TInterface).FullName} is not interface");
|
||||||
}
|
}
|
||||||
if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsSystem))
|
if (interfaces.Length != 1 || interfaces[0] != typeof(IEcsProcess))
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsSystem)} interface");
|
throw new ArgumentException($"{typeof(TInterface).FullName} does not directly inherit the {nameof(IEcsProcess)} interface");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_subclass = subclass;
|
_subclass = subclass;
|
||||||
@ -152,15 +152,15 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region FilterSystems
|
#region FilterSystems
|
||||||
private static TInterface[] FilterSystems(IEnumerable<IEcsSystem> targets)
|
private static TInterface[] FilterSystems(IEnumerable<IEcsProcess> targets)
|
||||||
{
|
{
|
||||||
return targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray();
|
return targets.Where(o => o is TInterface).Select(o => (TInterface)o).ToArray();
|
||||||
}
|
}
|
||||||
private static TInterface[] FilterSystems(IEnumerable<IEcsSystem> targets, object filter)
|
private static TInterface[] FilterSystems(IEnumerable<IEcsProcess> targets, object filter)
|
||||||
{
|
{
|
||||||
Type interfaceType = typeof(TInterface);
|
Type interfaceType = typeof(TInterface);
|
||||||
|
|
||||||
IEnumerable<IEcsSystem> newTargets;
|
IEnumerable<IEcsProcess> newTargets;
|
||||||
|
|
||||||
if (filter != null)
|
if (filter != null)
|
||||||
{
|
{
|
||||||
@ -189,7 +189,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
if (_subclass == null) EcsRunnerActivator.InitFor<TInterface>();
|
if (_subclass == null) EcsRunnerActivator.InitFor<TInterface>();
|
||||||
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
|
var instance = (EcsRunner<TInterface>)Activator.CreateInstance(_subclass);
|
||||||
return (TInterface)(IEcsSystem)instance.Set(source, targets, isHasFilter, filter);
|
return (TInterface)(IEcsProcess)instance.Set(source, targets, isHasFilter, filter);
|
||||||
}
|
}
|
||||||
public static TInterface Instantiate(EcsPipeline source)
|
public static TInterface Instantiate(EcsPipeline source)
|
||||||
{
|
{
|
||||||
@ -253,11 +253,11 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Extensions
|
#region Extensions
|
||||||
public static class EcsRunner
|
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 class IEcsSystemExtensions
|
||||||
{
|
{
|
||||||
public static bool IsRunner(this IEcsSystem self)
|
public static bool IsRunner(this IEcsProcess self)
|
||||||
{
|
{
|
||||||
return self is IEcsRunner;
|
return self is IEcsRunner;
|
||||||
}
|
}
|
||||||
|
179
src/EcsWorld.cs
179
src/EcsWorld.cs
@ -40,6 +40,8 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
private List<IEcsWorldEventListener> _listeners;
|
private List<IEcsWorldEventListener> _listeners;
|
||||||
|
|
||||||
|
private object[] _components;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public abstract Type Archetype { get; }
|
public abstract Type Archetype { get; }
|
||||||
public int UniqueID => uniqueID;
|
public int UniqueID => uniqueID;
|
||||||
@ -85,6 +87,8 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
_subjects = new EcsSubject[128];
|
_subjects = new EcsSubject[128];
|
||||||
_executors = new EcsQueryExecutor[128];
|
_executors = new EcsQueryExecutor[128];
|
||||||
|
|
||||||
|
_components = new object[2];
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
@ -138,16 +142,30 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public TExecutor GetExecutor<TExecutor>() where TExecutor : EcsQueryExecutor, new()
|
public TExecutor GetExecutor<TExecutor>() where TExecutor : EcsQueryExecutor, new()
|
||||||
{
|
{
|
||||||
int id = WorldMetaStorage.GetExecutorId<TExecutor>(_worldTypeID);
|
int index = WorldMetaStorage.GetExecutorId<TExecutor>(_worldTypeID);
|
||||||
if (id >= _executors.Length)
|
if (index >= _executors.Length)
|
||||||
Array.Resize(ref _executors, _executors.Length << 1);
|
Array.Resize(ref _executors, _executors.Length << 1);
|
||||||
if (_executors[id] == null)
|
if (_executors[index] == null)
|
||||||
{
|
{
|
||||||
var executor = new TExecutor();
|
var executor = new TExecutor();
|
||||||
executor.Initialize(this);
|
executor.Initialize(this);
|
||||||
_executors[id] = executor;
|
_executors[index] = executor;
|
||||||
}
|
}
|
||||||
return (TExecutor)_executors[id];
|
return (TExecutor)_executors[index];
|
||||||
|
}
|
||||||
|
public T Get<T>() where T : class, new()
|
||||||
|
{
|
||||||
|
int index = WorldMetaStorage.GetWorldComponentId<T>(_worldTypeID);
|
||||||
|
if (index >= _components.Length)
|
||||||
|
Array.Resize(ref _executors, _executors.Length << 1);
|
||||||
|
|
||||||
|
var result = _components[index];
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
result = new T();
|
||||||
|
_components[index] = result;
|
||||||
|
}
|
||||||
|
return (T)result;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -348,7 +366,7 @@ namespace DCFApixels.DragonECS
|
|||||||
for (var i = 0; i < _pools.Length; i++)
|
for (var i = 0; i < _pools.Length; i++)
|
||||||
{
|
{
|
||||||
if (_pools[i].Has(entityID))
|
if (_pools[i].Has(entityID))
|
||||||
list.Add(_pools[i].GetRaw(entityID));
|
list.Add(_pools[i].GetRaw(entityID));
|
||||||
if (list.Count >= itemsCount)
|
if (list.Count >= itemsCount)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -369,155 +387,6 @@ namespace DCFApixels.DragonECS
|
|||||||
internal EcsWorld(bool isIndexable) : base(isIndexable) { }
|
internal EcsWorld(bool isIndexable) : base(isIndexable) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
#region WorldMetaStorage
|
|
||||||
internal static class WorldMetaStorage
|
|
||||||
{
|
|
||||||
private static List<Resizer> _resizer = new List<Resizer>();
|
|
||||||
private static int _tokenCount = 0;
|
|
||||||
|
|
||||||
private static WorldTypeMeta[] _metas = new WorldTypeMeta[0];
|
|
||||||
private static Dictionary<Type, int> _worldIds = new Dictionary<Type, int>();
|
|
||||||
private static class WorldIndex<TWorldArchetype>
|
|
||||||
{
|
|
||||||
public static int id = GetWorldID(typeof(TWorldArchetype));
|
|
||||||
}
|
|
||||||
private static int GetToken()
|
|
||||||
{
|
|
||||||
WorldTypeMeta meta = new WorldTypeMeta();
|
|
||||||
meta.id = _tokenCount;
|
|
||||||
Array.Resize(ref _metas, ++_tokenCount);
|
|
||||||
_metas[_tokenCount - 1] = meta;
|
|
||||||
|
|
||||||
foreach (var item in _resizer)
|
|
||||||
item.Resize(_tokenCount);
|
|
||||||
return _tokenCount - 1;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int GetWorldID(Type archetype)
|
|
||||||
{
|
|
||||||
if(!_worldIds.TryGetValue(archetype, out int id))
|
|
||||||
{
|
|
||||||
id = GetToken();
|
|
||||||
_worldIds.Add(archetype, id);
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int GetWorldId<TWorldArchetype>() => WorldIndex<TWorldArchetype>.id;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int GetComponentId<T>(int worldID) => Component<T>.Get(worldID);
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int GetSubjectId<T>(int worldID) => Subject<T>.Get(worldID);
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int GetExecutorId<T>(int worldID) => Executor<T>.Get(worldID);
|
|
||||||
|
|
||||||
public static bool IsComponentTypeDeclared(int worldID, Type type) => _metas[worldID].IsDeclaredType(type);
|
|
||||||
public static Type GetComponentType(int worldID, int componentID) => _metas[worldID].GetComponentType(componentID);
|
|
||||||
|
|
||||||
#region Resizer
|
|
||||||
private abstract class Resizer
|
|
||||||
{
|
|
||||||
public abstract void Resize(int size);
|
|
||||||
}
|
|
||||||
private sealed class Resizer<T> : Resizer
|
|
||||||
{
|
|
||||||
public override void Resize(int size)
|
|
||||||
{
|
|
||||||
Array.Resize(ref Component<T>.ids, size);
|
|
||||||
Array.Resize(ref Subject<T>.ids, size);
|
|
||||||
Array.Resize(ref Executor<T>.ids, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
private static class Component<T>
|
|
||||||
{
|
|
||||||
public static int[] ids;
|
|
||||||
static Component()
|
|
||||||
{
|
|
||||||
ids = new int[_tokenCount];
|
|
||||||
for (int i = 0; i < ids.Length; i++)
|
|
||||||
ids[i] = -1;
|
|
||||||
_resizer.Add(new Resizer<T>());
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int Get(int token)
|
|
||||||
{
|
|
||||||
ref int id = ref ids[token];
|
|
||||||
if (id < 0)
|
|
||||||
{
|
|
||||||
var meta = _metas[token];
|
|
||||||
id = meta.componentCount++;
|
|
||||||
meta.AddType(id, typeof(T));
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static class Subject<T>
|
|
||||||
{
|
|
||||||
public static int[] ids;
|
|
||||||
static Subject()
|
|
||||||
{
|
|
||||||
ids = new int[_tokenCount];
|
|
||||||
for (int i = 0; i < ids.Length; i++)
|
|
||||||
ids[i] = -1;
|
|
||||||
_resizer.Add(new Resizer<T>());
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int Get(int token)
|
|
||||||
{
|
|
||||||
ref int id = ref ids[token];
|
|
||||||
if (id < 0)
|
|
||||||
id = _metas[token].subjectsCount++;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static class Executor<T>
|
|
||||||
{
|
|
||||||
public static int[] ids;
|
|
||||||
static Executor()
|
|
||||||
{
|
|
||||||
ids = new int[_tokenCount];
|
|
||||||
for (int i = 0; i < ids.Length; i++)
|
|
||||||
ids[i] = -1;
|
|
||||||
_resizer.Add(new Resizer<T>());
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static int Get(int token)
|
|
||||||
{
|
|
||||||
ref int id = ref ids[token];
|
|
||||||
if (id < 0)
|
|
||||||
id = _metas[token].executorsCount++;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WorldTypeMeta
|
|
||||||
{
|
|
||||||
public int id;
|
|
||||||
public int componentCount;
|
|
||||||
public int subjectsCount;
|
|
||||||
public int executorsCount;
|
|
||||||
private Type[] types;
|
|
||||||
private HashSet<Type> declaredComponentTypes;
|
|
||||||
public void AddType(int id, Type type)
|
|
||||||
{
|
|
||||||
if(types.Length <= id)
|
|
||||||
Array.Resize(ref types, id + 10);
|
|
||||||
types[id] = type;
|
|
||||||
|
|
||||||
declaredComponentTypes.Add(type);
|
|
||||||
}
|
|
||||||
public Type GetComponentType(int componentID) => types[componentID];
|
|
||||||
public bool IsDeclaredType(Type type) => declaredComponentTypes.Contains(type);
|
|
||||||
public WorldTypeMeta()
|
|
||||||
{
|
|
||||||
types = new Type[10];
|
|
||||||
declaredComponentTypes = new HashSet<Type>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Callbacks Interface
|
#region Callbacks Interface
|
||||||
public interface IEcsWorldEventListener
|
public interface IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
using (_executeWhere.Auto())
|
using (_executeWhere.Auto())
|
||||||
{
|
{
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
|
if (sourceGroup.IsNull) throw new System.ArgumentNullException();//TODO составить текст исключения.
|
||||||
#endif
|
#endif
|
||||||
_subject.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup);
|
_subject.GetIteratorFor(sourceGroup).CopyTo(_filteredGroup);
|
||||||
return new EcsWhereResult<TSubject>(this, _filteredGroup.Readonly);
|
return new EcsWhereResult<TSubject>(this, _filteredGroup.Readonly);
|
||||||
|
@ -56,8 +56,6 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Methods
|
#region Methods
|
||||||
public ref T Add(int entityID)
|
public ref T Add(int entityID)
|
||||||
{
|
{
|
||||||
// using (_addMark.Auto())
|
|
||||||
// {
|
|
||||||
ref int itemIndex = ref _mapping[entityID];
|
ref int itemIndex = ref _mapping[entityID];
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (itemIndex > 0) ThrowAlreadyHasComponent<T>(entityID);
|
if (itemIndex > 0) ThrowAlreadyHasComponent<T>(entityID);
|
||||||
@ -74,30 +72,27 @@ namespace DCFApixels.DragonECS
|
|||||||
Array.Resize(ref _items, _items.Length << 1);
|
Array.Resize(ref _items, _items.Length << 1);
|
||||||
}
|
}
|
||||||
this.IncrementEntityComponentCount(entityID);
|
this.IncrementEntityComponentCount(entityID);
|
||||||
_listeners.InvokeOnAddAndWrite(entityID);
|
_listeners.InvokeOnAddAndGet(entityID);
|
||||||
return ref _items[itemIndex];
|
return ref _items[itemIndex];
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ref T Write(int entityID)
|
public ref T Get(int entityID)
|
||||||
{
|
{
|
||||||
// using (_writeMark.Auto())
|
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
||||||
#endif
|
#endif
|
||||||
_listeners.InvokeOnWrite(entityID);
|
_listeners.InvokeOnGet(entityID);
|
||||||
return ref _items[_mapping[entityID]];
|
return ref _items[_mapping[entityID]];
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public ref readonly T Read(int entityID)
|
public ref readonly T Read(int entityID)
|
||||||
{
|
{
|
||||||
// using (_readMark.Auto())
|
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
||||||
#endif
|
#endif
|
||||||
return ref _items[_mapping[entityID]];
|
return ref _items[_mapping[entityID]];
|
||||||
}
|
}
|
||||||
public ref T TryAddOrWrite(int entityID)
|
public ref T TryAddOrGet(int entityID)
|
||||||
{
|
{
|
||||||
ref int itemIndex = ref _mapping[entityID];
|
ref int itemIndex = ref _mapping[entityID];
|
||||||
if (itemIndex <= 0)
|
if (itemIndex <= 0)
|
||||||
@ -116,7 +111,7 @@ namespace DCFApixels.DragonECS
|
|||||||
this.IncrementEntityComponentCount(entityID);
|
this.IncrementEntityComponentCount(entityID);
|
||||||
_listeners.InvokeOnAdd(entityID);
|
_listeners.InvokeOnAdd(entityID);
|
||||||
}
|
}
|
||||||
_listeners.InvokeOnWrite(entityID);
|
_listeners.InvokeOnGet(entityID);
|
||||||
return ref _items[itemIndex];
|
return ref _items[itemIndex];
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -148,14 +143,14 @@ namespace DCFApixels.DragonECS
|
|||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
|
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
|
||||||
#endif
|
#endif
|
||||||
_componentCopyHandler.Copy(ref Write(fromEntityID), ref TryAddOrWrite(toEntityID));
|
_componentCopyHandler.Copy(ref Get(fromEntityID), ref TryAddOrGet(toEntityID));
|
||||||
}
|
}
|
||||||
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
public void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID)
|
||||||
{
|
{
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
|
if (!Has(fromEntityID)) ThrowNotHaveComponent<T>(fromEntityID);
|
||||||
#endif
|
#endif
|
||||||
_componentCopyHandler.Copy(ref Write(fromEntityID), ref toWorld.GetPool<T>().TryAddOrWrite(toEntityID));
|
_componentCopyHandler.Copy(ref Get(fromEntityID), ref toWorld.GetPool<T>().TryAddOrGet(toEntityID));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -175,20 +170,20 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Other
|
#region Other
|
||||||
void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID) = (T)dataRaw;
|
void IEcsPool.AddRaw(int entityID, object dataRaw) => Add(entityID) = (T)dataRaw;
|
||||||
object IEcsPool.GetRaw(int entityID) => Read(entityID);
|
object IEcsPool.GetRaw(int entityID) => Read(entityID);
|
||||||
void IEcsPool.SetRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw;
|
void IEcsPool.SetRaw(int entityID, object dataRaw) => Get(entityID) = (T)dataRaw;
|
||||||
ref readonly T IEcsPool<T>.Read(int entityID) => ref Read(entityID);
|
ref readonly T IEcsPool<T>.Read(int entityID) => ref Read(entityID);
|
||||||
ref T IEcsPool<T>.Write(int entityID) => ref Write(entityID);
|
ref T IEcsPool<T>.Get(int entityID) => ref Get(entityID);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Listeners
|
#region Listeners
|
||||||
public void AddListener(IEcsPoolEventListener listener)
|
public void AddListener(IEcsPoolEventListener listener)
|
||||||
{
|
{
|
||||||
if(listener == null) { throw new ArgumentNullException("listener is null"); }
|
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||||
_listeners.Add(listener);
|
_listeners.Add(listener);
|
||||||
}
|
}
|
||||||
public void RemoveListener(IEcsPoolEventListener listener)
|
public void RemoveListener(IEcsPoolEventListener listener)
|
||||||
{
|
{
|
||||||
if(listener == null) { throw new ArgumentNullException("listener is null"); }
|
if (listener == null) { throw new ArgumentNullException("listener is null"); }
|
||||||
_listeners.Remove(listener);
|
_listeners.Remove(listener);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -35,7 +35,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
ref T Add(int entityID);
|
ref T Add(int entityID);
|
||||||
ref readonly T Read(int entityID);
|
ref readonly T Read(int entityID);
|
||||||
ref T Write(int entityID);
|
ref T Get(int entityID);
|
||||||
}
|
}
|
||||||
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
|
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
|
||||||
public interface IEcsPoolImplementation : IEcsPool
|
public interface IEcsPoolImplementation : IEcsPool
|
||||||
@ -106,7 +106,7 @@ namespace DCFApixels.DragonECS
|
|||||||
void IEcsPool.Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) => throw new NotImplementedException();
|
void IEcsPool.Copy(int fromEntityID, EcsWorld toWorld, int toEntityID) => throw new NotImplementedException();
|
||||||
ref NullComponent IEcsPool<NullComponent>.Add(int entityID) => throw new NotImplementedException();
|
ref NullComponent IEcsPool<NullComponent>.Add(int entityID) => throw new NotImplementedException();
|
||||||
ref readonly NullComponent IEcsPool<NullComponent>.Read(int entityID) => throw new NotImplementedException();
|
ref readonly NullComponent IEcsPool<NullComponent>.Read(int entityID) => throw new NotImplementedException();
|
||||||
ref NullComponent IEcsPool<NullComponent>.Write(int entityID) => throw new NotImplementedException();
|
ref NullComponent IEcsPool<NullComponent>.Get(int entityID) => throw new NotImplementedException();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
@ -201,10 +201,10 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Callbacks Interface
|
#region Callbacks Interface
|
||||||
public interface IEcsPoolEventListener
|
public interface IEcsPoolEventListener
|
||||||
{
|
{
|
||||||
/// <summary>Called after adding an entity to the pool, but before changing values.</summary>
|
/// <summary>Called after adding an entity to the pool, but before changing values</summary>
|
||||||
void OnAdd(int entityID);
|
void OnAdd(int entityID);
|
||||||
/// <summary>Is called when EcsPool.Write or EcsPool.Add is called, but before changing values.</summary>
|
/// <summary>Is called when EcsPool.Get or EcsPool.Add is called, but before changing values</summary>
|
||||||
void OnWrite(int entityID);
|
void OnGet(int entityID);
|
||||||
/// <summary>Called after deleting an entity from the pool</summary>
|
/// <summary>Called after deleting an entity from the pool</summary>
|
||||||
void OnDel(int entityID);
|
void OnDel(int entityID);
|
||||||
}
|
}
|
||||||
@ -216,18 +216,18 @@ namespace DCFApixels.DragonECS
|
|||||||
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnAdd(entityID);
|
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnAdd(entityID);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void InvokeOnAddAndWrite(this List<IEcsPoolEventListener> self, int entityID)
|
public static void InvokeOnAddAndGet(this List<IEcsPoolEventListener> self, int entityID)
|
||||||
{
|
{
|
||||||
for (int i = 0, iMax = self.Count; i < iMax; i++)
|
for (int i = 0, iMax = self.Count; i < iMax; i++)
|
||||||
{
|
{
|
||||||
self[i].OnAdd(entityID);
|
self[i].OnAdd(entityID);
|
||||||
self[i].OnWrite(entityID);
|
self[i].OnGet(entityID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void InvokeOnWrite(this List<IEcsPoolEventListener> self, int entityID)
|
public static void InvokeOnGet(this List<IEcsPoolEventListener> self, int entityID)
|
||||||
{
|
{
|
||||||
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnWrite(entityID);
|
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnGet(entityID);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void InvokeOnDel(this List<IEcsPoolEventListener> self, int entityID)
|
public static void InvokeOnDel(this List<IEcsPoolEventListener> self, int entityID)
|
||||||
|
@ -143,7 +143,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endif
|
#endif
|
||||||
return ref _fakeComponent;
|
return ref _fakeComponent;
|
||||||
}
|
}
|
||||||
ref T IEcsPool<T>.Write(int entityID)
|
ref T IEcsPool<T>.Get(int entityID)
|
||||||
{
|
{
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public class EntityLinkedList
|
|
||||||
{
|
|
||||||
private const int ENTER = 0;
|
|
||||||
|
|
||||||
private Node[] _nodes;
|
|
||||||
private int _count;
|
|
||||||
private int _lastNodeIndex;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public int Count => _count;
|
|
||||||
public int Capacity => _nodes.Length;
|
|
||||||
public int Last => _lastNodeIndex;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
public EntityLinkedList(int capacity)
|
|
||||||
{
|
|
||||||
_nodes = new Node[capacity + 10];
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public void Resize(int newCapacity)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _nodes, newCapacity + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
//ArrayUtility.Fill(_nodes, Node.Empty);
|
|
||||||
for (int i = 0; i < _nodes.Length; i++)
|
|
||||||
_nodes[i].next = 0;
|
|
||||||
_lastNodeIndex = ENTER;
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Set(int nodeIndex, int entityID) => _nodes[nodeIndex].entityID = entityID;
|
|
||||||
public int Get(int nodeIndex) => _nodes[nodeIndex].entityID;
|
|
||||||
|
|
||||||
/// <summary> Insert after</summary>
|
|
||||||
/// <returns> new node index</returns>
|
|
||||||
public int Insert(int nodeIndex, int entityID)
|
|
||||||
{
|
|
||||||
_nodes[++_count].Set(entityID, _nodes[nodeIndex].next);
|
|
||||||
_nodes[nodeIndex].next = _count;
|
|
||||||
_lastNodeIndex = _count;
|
|
||||||
return _count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Add(int entityID) => Insert(_lastNodeIndex, entityID);
|
|
||||||
|
|
||||||
public Enumerator GetEnumerator() => new Enumerator(_nodes);
|
|
||||||
public EnumerableSpan Span(int startNodeIndex, int count) => new EnumerableSpan(this, startNodeIndex, count);
|
|
||||||
|
|
||||||
#region Utils
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
|
||||||
public struct Node
|
|
||||||
{
|
|
||||||
public static readonly Node Empty = new Node() { entityID = 0, next = -1 };
|
|
||||||
public int entityID;
|
|
||||||
/// <summary>next node index</summary>
|
|
||||||
public int next;
|
|
||||||
|
|
||||||
public void Set(int entityID, int next)
|
|
||||||
{
|
|
||||||
this.entityID = entityID;
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Enumerator
|
|
||||||
{
|
|
||||||
private readonly Node[] _nodes;
|
|
||||||
private int _index;
|
|
||||||
private int _next;
|
|
||||||
public Enumerator(Node[] nodes)
|
|
||||||
{
|
|
||||||
_nodes = nodes;
|
|
||||||
_index = -1;
|
|
||||||
_next = ENTER;
|
|
||||||
}
|
|
||||||
public int Current => _nodes[_index].entityID;
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
_index = _next;
|
|
||||||
_next = _nodes[_next].next;
|
|
||||||
return _index > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly ref struct EnumerableSpan
|
|
||||||
{
|
|
||||||
private readonly EntityLinkedList _source;
|
|
||||||
private readonly int _startNodeIndex;
|
|
||||||
private readonly int _count;
|
|
||||||
public EnumerableSpan(EntityLinkedList source, int startNodeIndex, int count)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
_startNodeIndex = startNodeIndex;
|
|
||||||
_count = count;
|
|
||||||
}
|
|
||||||
public SpanEnumerator GetEnumerator() => new SpanEnumerator(_source._nodes, _startNodeIndex, _count);
|
|
||||||
}
|
|
||||||
public struct SpanEnumerator
|
|
||||||
{
|
|
||||||
private readonly Node[] _nodes;
|
|
||||||
private int _index;
|
|
||||||
private int _count;
|
|
||||||
private int _next;
|
|
||||||
public SpanEnumerator(Node[] nodes, int startIndex, int count)
|
|
||||||
{
|
|
||||||
_nodes = nodes;
|
|
||||||
_index = -1;
|
|
||||||
_count = count;
|
|
||||||
_next = startIndex;
|
|
||||||
}
|
|
||||||
public int Current => _nodes[_index].entityID;
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
_index = _next;
|
|
||||||
_next = _nodes[_next].next;
|
|
||||||
return _index > 0 && _count-- > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
198
src/Utils/WorldMetaStorage.cs
Normal file
198
src/Utils/WorldMetaStorage.cs
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
using DCFApixels.DragonECS.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
internal static class WorldMetaStorage
|
||||||
|
{
|
||||||
|
private static int _tokenCount = 0;
|
||||||
|
private static List<ResizerBase> _resizers = new List<ResizerBase>();
|
||||||
|
private static WorldTypeMeta[] _metas = new WorldTypeMeta[0];
|
||||||
|
private static Dictionary<Type, int> _worldIds = new Dictionary<Type, int>();
|
||||||
|
private static class WorldIndex<TWorldArchetype>
|
||||||
|
{
|
||||||
|
public static int id = GetWorldID(typeof(TWorldArchetype));
|
||||||
|
}
|
||||||
|
private static int GetToken()
|
||||||
|
{
|
||||||
|
WorldTypeMeta meta = new WorldTypeMeta();
|
||||||
|
meta.id = _tokenCount;
|
||||||
|
Array.Resize(ref _metas, ++_tokenCount);
|
||||||
|
_metas[_tokenCount - 1] = meta;
|
||||||
|
|
||||||
|
foreach (var item in _resizers)
|
||||||
|
item.Resize(_tokenCount);
|
||||||
|
return _tokenCount - 1;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetWorldID(Type archetype)
|
||||||
|
{
|
||||||
|
if (!_worldIds.TryGetValue(archetype, out int id))
|
||||||
|
{
|
||||||
|
id = GetToken();
|
||||||
|
_worldIds.Add(archetype, id);
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetWorldId<TWorldArchetype>() => WorldIndex<TWorldArchetype>.id;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetComponentId<T>(int worldID) => Component<T>.Get(worldID);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetSubjectId<T>(int worldID) => Subject<T>.Get(worldID);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetExecutorId<T>(int worldID) => Executor<T>.Get(worldID);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int GetWorldComponentId<T>(int worldID) => WorldComponent<T>.Get(worldID);
|
||||||
|
public static bool IsComponentTypeDeclared(int worldID, Type type) => _metas[worldID].IsDeclaredType(type);
|
||||||
|
public static Type GetComponentType(int worldID, int componentID) => _metas[worldID].GetComponentType(componentID);
|
||||||
|
|
||||||
|
private abstract class ResizerBase
|
||||||
|
{
|
||||||
|
public abstract void Resize(int size);
|
||||||
|
}
|
||||||
|
private static class Component<T>
|
||||||
|
{
|
||||||
|
public static int[] ids;
|
||||||
|
static Component()
|
||||||
|
{
|
||||||
|
ids = new int[_tokenCount];
|
||||||
|
for (int i = 0; i < ids.Length; i++)
|
||||||
|
ids[i] = -1;
|
||||||
|
_resizers.Add(new Resizer());
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int Get(int token)
|
||||||
|
{
|
||||||
|
ref int id = ref ids[token];
|
||||||
|
if (id < 0)
|
||||||
|
{
|
||||||
|
var meta = _metas[token];
|
||||||
|
id = (ushort)meta.componentCount++;
|
||||||
|
meta.AddType(id, typeof(T));
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
private sealed class Resizer : ResizerBase
|
||||||
|
{
|
||||||
|
public override void Resize(int size)
|
||||||
|
{
|
||||||
|
int oldSize = ids.Length;
|
||||||
|
Array.Resize(ref ids, size);
|
||||||
|
ArrayUtility.Fill(ids, -1, oldSize, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static class Subject<T>
|
||||||
|
{
|
||||||
|
public static int[] ids;
|
||||||
|
static Subject()
|
||||||
|
{
|
||||||
|
ids = new int[_tokenCount];
|
||||||
|
for (int i = 0; i < ids.Length; i++)
|
||||||
|
ids[i] = -1;
|
||||||
|
_resizers.Add(new Resizer());
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int Get(int token)
|
||||||
|
{
|
||||||
|
ref int id = ref ids[token];
|
||||||
|
if (id < 0)
|
||||||
|
id = _metas[token].subjectsCount++;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
private sealed class Resizer : ResizerBase
|
||||||
|
{
|
||||||
|
public override void Resize(int size)
|
||||||
|
{
|
||||||
|
int oldSize = ids.Length;
|
||||||
|
Array.Resize(ref ids, size);
|
||||||
|
ArrayUtility.Fill(ids, -1, oldSize, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static class Executor<T>
|
||||||
|
{
|
||||||
|
public static int[] ids;
|
||||||
|
static Executor()
|
||||||
|
{
|
||||||
|
ids = new int[_tokenCount];
|
||||||
|
for (int i = 0; i < ids.Length; i++)
|
||||||
|
ids[i] = -1;
|
||||||
|
_resizers.Add(new Resizer());
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int Get(int token)
|
||||||
|
{
|
||||||
|
ref int id = ref ids[token];
|
||||||
|
if (id < 0)
|
||||||
|
id = _metas[token].executorsCount++;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
private sealed class Resizer : ResizerBase
|
||||||
|
{
|
||||||
|
public override void Resize(int size)
|
||||||
|
{
|
||||||
|
int oldSize = ids.Length;
|
||||||
|
Array.Resize(ref ids, size);
|
||||||
|
ArrayUtility.Fill(ids, -1, oldSize, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static class WorldComponent<T>
|
||||||
|
{
|
||||||
|
public static int[] ids;
|
||||||
|
static WorldComponent()
|
||||||
|
{
|
||||||
|
ids = new int[_tokenCount];
|
||||||
|
for (int i = 0; i < ids.Length; i++)
|
||||||
|
ids[i] = -1;
|
||||||
|
_resizers.Add(new Resizer());
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static int Get(int token)
|
||||||
|
{
|
||||||
|
ref int id = ref ids[token];
|
||||||
|
if (id < 0)
|
||||||
|
id = _metas[token].worldComponentCount++;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
private sealed class Resizer : ResizerBase
|
||||||
|
{
|
||||||
|
public override void Resize(int size)
|
||||||
|
{
|
||||||
|
int oldSize = ids.Length;
|
||||||
|
Array.Resize(ref ids, size);
|
||||||
|
ArrayUtility.Fill(ids, -1, oldSize, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private class WorldTypeMeta
|
||||||
|
{
|
||||||
|
public int id;
|
||||||
|
public int componentCount;
|
||||||
|
public int subjectsCount;
|
||||||
|
public int executorsCount;
|
||||||
|
public int worldComponentCount;
|
||||||
|
private Type[] _types;
|
||||||
|
private HashSet<Type> _declaredComponentTypes;
|
||||||
|
public void AddType(int id, Type type)
|
||||||
|
{
|
||||||
|
if (_types.Length <= id)
|
||||||
|
Array.Resize(ref _types, id + 10);
|
||||||
|
_types[id] = type;
|
||||||
|
|
||||||
|
_declaredComponentTypes.Add(type);
|
||||||
|
}
|
||||||
|
public Type GetComponentType(int componentID) => _types[componentID];
|
||||||
|
public bool IsDeclaredType(Type type) => _declaredComponentTypes.Contains(type);
|
||||||
|
public WorldTypeMeta()
|
||||||
|
{
|
||||||
|
_types = new Type[10];
|
||||||
|
_declaredComponentTypes = new HashSet<Type>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user