Merge branch 'dev'

This commit is contained in:
Mikhail 2023-05-31 04:10:18 +08:00
commit d5c3fe4f84
17 changed files with 304 additions and 367 deletions

View File

@ -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);
} }

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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)

View File

@ -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;
}
} }
} }

View File

@ -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);
@ -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();
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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
@ -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
{ {

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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
}
}

View 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>();
}
}
}
}