Optimization

This commit is contained in:
Mikhail 2023-04-01 20:45:37 +08:00
parent a489f4cbae
commit de7762861c
12 changed files with 525 additions and 202 deletions

View File

@ -22,12 +22,12 @@
public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInitSystem>, IEcsPreInitSystem public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInitSystem>, IEcsPreInitSystem
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
#endif #endif
public void PreInit(EcsPipeline pipeline) public void PreInit(EcsPipeline pipeline)
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < targets.Length; i++)
{ {
using (_markers[i].Auto()) using (_markers[i].Auto())
@ -38,7 +38,7 @@
#endif #endif
} }
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[targets.Length];
@ -51,12 +51,12 @@
} }
public sealed class EcsInitRunner : EcsRunner<IEcsInitSystem>, IEcsInitSystem public sealed class EcsInitRunner : EcsRunner<IEcsInitSystem>, IEcsInitSystem
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
#endif #endif
public void Init(EcsPipeline pipeline) public void Init(EcsPipeline pipeline)
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < targets.Length; i++)
{ {
using (_markers[i].Auto()) using (_markers[i].Auto())
@ -67,7 +67,7 @@
#endif #endif
} }
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[targets.Length];
@ -80,12 +80,12 @@
} }
public sealed class EcsRunRunner : EcsRunner<IEcsRunSystem>, IEcsRunSystem public sealed class EcsRunRunner : EcsRunner<IEcsRunSystem>, IEcsRunSystem
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
#endif #endif
public void Run(EcsPipeline pipeline) public void Run(EcsPipeline pipeline)
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < targets.Length; i++)
{ {
using (_markers[i].Auto()) using (_markers[i].Auto())
@ -97,7 +97,7 @@
#endif #endif
} }
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[targets.Length];
@ -110,12 +110,12 @@
} }
public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroySystem>, IEcsDestroySystem public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroySystem>, IEcsDestroySystem
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
private EcsProfilerMarker[] _markers; private EcsProfilerMarker[] _markers;
#endif #endif
public void Destroy(EcsPipeline pipeline) public void Destroy(EcsPipeline pipeline)
{ {
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < targets.Length; i++)
{ {
using (_markers[i].Auto()) using (_markers[i].Auto())
@ -126,7 +126,7 @@
#endif #endif
} }
#if DEBUG #if DEBUG && !DISABLE_DRAGONECS_DEBUG
protected override void OnSetup() protected override void OnSetup()
{ {
_markers = new EcsProfilerMarker[targets.Length]; _markers = new EcsProfilerMarker[targets.Length];

View File

@ -0,0 +1,87 @@
namespace DCFApixels.DragonECS
{
public interface IEcsComponentAdd : IEcsSystem
{
public void OnComponentAdd<T>(int entityID);
}
public interface IEcsComponentWrite : IEcsSystem
{
public void OnComponentWrite<T>(int entityID);
}
public interface IEcsComponentDel : IEcsSystem
{
public void OnComponentDel<T>(int entityID);
}
public interface IEcsComponentLifecycle : IEcsComponentAdd, IEcsComponentWrite, IEcsComponentDel { }
public sealed class EcsEntityAddComponentRunner : EcsRunner<IEcsComponentAdd>, IEcsComponentAdd
{
public void OnComponentAdd<T>(int entityID)
{
foreach (var item in targets) item.OnComponentAdd<T>(entityID);
}
}
public sealed class EcsEntityChangeComponentRunner : EcsRunner<IEcsComponentWrite>, IEcsComponentWrite
{
public void OnComponentWrite<T>(int entityID)
{
foreach (var item in targets) item.OnComponentWrite<T>(entityID);
}
}
public sealed class EcsEntityDelComponentRunner : EcsRunner<IEcsComponentDel>, IEcsComponentDel
{
public void OnComponentDel<T>(int entityID)
{
foreach (var item in targets) item.OnComponentDel<T>(entityID);
}
}
public interface IEcsEntityCreate : IEcsSystem
{
public void OnEntityCreate(ent entity);
}
public interface IEcsEntityDestroy : IEcsSystem
{
public void OnEntityDestroy(ent entity);
}
public interface IEcsEntityLifecycle : IEcsEntityCreate, IEcsEntityDestroy { }
public sealed class EcsEntityCreateRunner : EcsRunner<IEcsEntityCreate>, IEcsEntityCreate
{
public void OnEntityCreate(ent entity)
{
foreach (var item in targets) item.OnEntityCreate(entity);
}
}
public sealed class EcsEntityDestroyRunner : EcsRunner<IEcsEntityDestroy>, IEcsEntityDestroy
{
public void OnEntityDestroy(ent entity)
{
foreach (var item in targets) item.OnEntityDestroy(entity);
}
}
public interface IEcsWorldCreate : IEcsSystem
{
public void OnWorldCreate(IEcsWorld world);
}
public interface IEcsWorldDestroy : IEcsSystem
{
public void OnWorldDestroy(IEcsWorld world);
}
public interface IEcsWorldLifecycle : IEcsWorldCreate, IEcsWorldDestroy { }
public sealed class EcsWorldCreateRunner : EcsRunner<IEcsWorldCreate>, IEcsWorldCreate
{
public void OnWorldCreate(IEcsWorld world)
{
foreach (var item in targets) item.OnWorldCreate(world);
}
}
public sealed class EcsWorldDestryRunner : EcsRunner<IEcsWorldDestroy>, IEcsWorldDestroy
{
public void OnWorldDestroy(IEcsWorld world)
{
foreach (var item in targets) item.OnWorldDestroy(world);
}
}
}

View File

@ -1,5 +1,11 @@
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public sealed class EcsDefaultWrold : EcsWorld<EcsDefaultWrold> { } public sealed class EcsDefaultWrold : EcsWorld<EcsDefaultWrold>
public sealed class EcsEventWrold : EcsWorld<EcsDefaultWrold> { } {
public EcsDefaultWrold(EcsPipeline pipeline) : base(pipeline) { }
}
public sealed class EcsEventWrold : EcsWorld<EcsDefaultWrold>
{
public EcsEventWrold(EcsPipeline pipeline) : base(pipeline) { }
}
} }

View File

@ -17,7 +17,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public AutoScope Auto() => new AutoScope(id); public AutoScope Auto() => new AutoScope(id);
public readonly struct AutoScope : IDisposable public readonly ref struct AutoScope
{ {
private readonly int id; private readonly int id;
public AutoScope(int id) public AutoScope(int id)
@ -43,14 +43,14 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Print(string tag, object v) public static void Print(string tag, object v)
{ {
#if !DISABLE_ECS_DEBUG #if !DISABLE_DRAGONECS_DEBUG
DebugService.Instance.Print(tag, v); DebugService.Instance.Print(tag, v);
#endif #endif
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int RegisterMark(string name) public static int RegisterMark(string name)
{ {
#if !DISABLE_ECS_DEBUG #if !DISABLE_DRAGONECS_DEBUG
return DebugService.Instance.RegisterMark(name); return DebugService.Instance.RegisterMark(name);
#else #else
return 0; return 0;
@ -59,21 +59,21 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void DeleteMark(string name) public static void DeleteMark(string name)
{ {
#if !DISABLE_ECS_DEBUG #if !DISABLE_DRAGONECS_DEBUG
DebugService.Instance.DeleteMark(name); DebugService.Instance.DeleteMark(name);
#endif #endif
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ProfileMarkBegin(int id) public static void ProfileMarkBegin(int id)
{ {
#if !DISABLE_ECS_DEBUG #if !DISABLE_DRAGONECS_DEBUG
DebugService.Instance.ProfileMarkBegin(id); DebugService.Instance.ProfileMarkBegin(id);
#endif #endif
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ProfileMarkEnd(int id) public static void ProfileMarkEnd(int id)
{ {
#if !DISABLE_ECS_DEBUG #if !DISABLE_DRAGONECS_DEBUG
DebugService.Instance.ProfileMarkEnd(id); DebugService.Instance.ProfileMarkEnd(id);
#endif #endif
} }
@ -145,7 +145,7 @@ namespace DCFApixels.DragonECS
public DefaultDebugService() public DefaultDebugService()
{ {
#if !DISABLE_ECS_DEBUG #if !DISABLE_DRAGONECS_DEBUG
_stopwatchs = new Stopwatch[64]; _stopwatchs = new Stopwatch[64];
_stopwatchsNames= new string[64]; _stopwatchsNames= new string[64];
#endif #endif

View File

@ -15,7 +15,7 @@ namespace DCFApixels.DragonECS
public class EcsFilter : IEcsFilter public class EcsFilter : IEcsFilter
{ {
private readonly IEcsWorld _source; private readonly IEcsWorld _source;
private readonly EcsGroup _entities; internal readonly EcsGroup entities;
private readonly EcsMask _mask; private readonly EcsMask _mask;
#region Properties #region Properties
@ -32,12 +32,12 @@ namespace DCFApixels.DragonECS
public EcsReadonlyGroup Entities public EcsReadonlyGroup Entities
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _entities.Readonly; get => entities.Readonly;
} }
public int EntitiesCount public int EntitiesCount
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _entities.Count; get => entities.Count;
} }
#endregion #endregion
@ -46,7 +46,7 @@ namespace DCFApixels.DragonECS
{ {
_source = source; _source = source;
_mask = mask; _mask = mask;
_entities = new EcsGroup(source, capasity); entities = new EcsGroup(source, capasity);
} }
#endregion #endregion
@ -54,19 +54,19 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Add(int entityID) internal void Add(int entityID)
{ {
_entities.Add(entityID); entities.UncheckedAdd(entityID);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Remove(int entityID) internal void Remove(int entityID)
{ {
_entities.Remove(entityID); entities.UncheckedRemove(entityID);
} }
#endregion #endregion
#region GetEnumerator #region GetEnumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsGroup.Enumerator GetEnumerator() => _entities.GetEnumerator(); public EcsGroup.Enumerator GetEnumerator() => entities.GetEnumerator();
#endregion #endregion
} }
} }

View File

@ -17,6 +17,16 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.Count; get => _source.Count;
} }
public int CapacityDense
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.CapacityDense;
}
public int CapacitySparce
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _source.CapacitySparce;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(int entityID) => _source.Contains(entityID); public bool Contains(int entityID) => _source.Contains(entityID);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -51,6 +61,16 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _count; get => _count;
} }
public int CapacityDense
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _dense.Length;
}
public int CapacitySparce
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _sparse.Length;
}
public EcsReadonlyGroup Readonly public EcsReadonlyGroup Readonly
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -60,11 +80,29 @@ namespace DCFApixels.DragonECS
#region Constrcutors #region Constrcutors
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsGroup(IEcsWorld source, int denseCapacity = 64, int sparseCapacity = 256, int delayedOpsCapacity = 128) internal EcsGroup(IEcsWorld source, int denseCapacity, int sparceCapacity, int delayedOpsCapacity)
{ {
_source = source; _source = source;
source.RegisterGroup(this);
_dense = new int[denseCapacity]; _dense = new int[denseCapacity];
_sparse = new int[sparseCapacity]; _sparse = new int[sparceCapacity];
_delayedOps = new delayedOp[delayedOpsCapacity];
_lockCount = 0;
_delayedOpsCount = 0;
_count = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsGroup(IEcsWorld source, int denseCapacity = 64, int delayedOpsCapacity = 128)
{
_source = source;
source.RegisterGroup(this);
_dense = new int[denseCapacity];
_sparse = new int[source.Entities.CapacitySparce];
_delayedOps = new delayedOp[delayedOpsCapacity]; _delayedOps = new delayedOp[delayedOpsCapacity];
@ -79,53 +117,64 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(int entityID) public bool Contains(int entityID)
{ {
return /*entityID > 0 && */ entityID < _sparse.Length && _sparse[entityID] > 0; //TODO добавить проверку на больше 0 в #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
#endif
return /*entityID > 0 && entityID < _sparse.Length && */ _sparse[entityID] > 0;
}
#endregion
#region IndexOf
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int IndexOf(int entityID)
{
return _sparse[entityID];
} }
#endregion #endregion
#region add/remove #region add/remove
public void UncheckedAdd(int entityID) => AddInternal(entityID);
public void Add(int entityID) public void Add(int entityID)
{ {
if (_lockCount > 0) if (Contains(entityID)) return;
Add(entityID);
}
private void AddInternal(int entityID)
{
if (_lockCount > 0)
{ {
AddDelayedOp(entityID, DEALAYED_ADD); AddDelayedOp(entityID, DEALAYED_ADD);
return; return;
} }
if (Contains(entityID)) if (++_count >= _dense.Length)
return;
if(++_count >= _dense.Length)
Array.Resize(ref _dense, _dense.Length << 1); Array.Resize(ref _dense, _dense.Length << 1);
if (entityID >= _sparse.Length)
{
int neadedSpace = _sparse.Length;
while (entityID >= neadedSpace)
neadedSpace <<= 1;
Array.Resize(ref _sparse, neadedSpace);
}
_dense[_count] = entityID; _dense[_count] = entityID;
_sparse[entityID] = _count; _sparse[entityID] = _count;
} }
public void UncheckedRemove(int entityID) => RemoveInternal(entityID);
public void Remove(int entityID) public void Remove(int entityID)
{
if (!Contains(entityID)) return;
RemoveInternal(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void RemoveInternal(int entityID)
{ {
if (_lockCount > 0) if (_lockCount > 0)
{ {
AddDelayedOp(entityID, DEALAYED_REMOVE); AddDelayedOp(entityID, DEALAYED_REMOVE);
return; return;
} }
if (!Contains(entityID))
return;
_dense[_sparse[entityID]] = _dense[_count]; _dense[_sparse[entityID]] = _dense[_count];
_sparse[_dense[_count--]] = _sparse[entityID]; _sparse[_dense[_count--]] = _sparse[entityID];
_sparse[entityID] = 0; _sparse[entityID] = 0;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void AddDelayedOp(int entityID, int isAddBitFlag) private void AddDelayedOp(int entityID, int isAddBitFlag)
{ {
@ -137,24 +186,32 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
//TODO добавить автосоритровку при каждом GetEnumerator internal void OnWorldResize(int newSize)
{
Array.Resize(ref _sparse, newSize);
}
//TODO добавить метод Sort
//TODO добавить автосоритровку при каждом GetEnumerator и проверить будет ли прирост производительности или ее падение.
//Суть в том что так возможно можно будет более плотно подавать данные в проц
#region AddGroup/RemoveGroup #region AddGroup/RemoveGroup
public void AddGroup(EcsReadonlyGroup group) public void AddGroup(EcsReadonlyGroup group)
{ {
foreach (var item in group) Add(item.id); foreach (var item in group) UncheckedAdd(item.id);
} }
public void RemoveGroup(EcsReadonlyGroup group) public void RemoveGroup(EcsReadonlyGroup group)
{ {
foreach (var item in group) Remove(item.id); foreach (var item in group) UncheckedRemove(item.id);
} }
public void AddGroup(EcsGroup group) public void AddGroup(EcsGroup group)
{ {
foreach (var item in group) Add(item.id); foreach (var item in group) UncheckedAdd(item.id);
} }
public void RemoveGroup(EcsGroup group) public void RemoveGroup(EcsGroup group)
{ {
foreach (var item in group) Remove(item.id); foreach (var item in group) UncheckedRemove(item.id);
} }
#endregion #endregion
@ -162,7 +219,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Unlock() private void Unlock()
{ {
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (_lockCount <= 0) if (_lockCount <= 0)
{ {
throw new Exception($"Invalid lock-unlock balance for {nameof(EcsGroup)}."); throw new Exception($"Invalid lock-unlock balance for {nameof(EcsGroup)}.");
@ -175,11 +232,11 @@ namespace DCFApixels.DragonECS
delayedOp op = _delayedOps[i]; delayedOp op = _delayedOps[i];
if (op >= 0) //delayedOp.IsAdded if (op >= 0) //delayedOp.IsAdded
{ {
Add(op & int.MaxValue); //delayedOp.Entity UncheckedAdd(op & int.MaxValue); //delayedOp.Entity
} }
else else
{ {
Remove(op & int.MaxValue); //delayedOp.Entity UncheckedRemove(op & int.MaxValue); //delayedOp.Entity
} }
} }
} }
@ -214,7 +271,6 @@ namespace DCFApixels.DragonECS
{ {
using (_marker.Auto()) using (_marker.Auto())
return _source.World.GetEntity(_source._dense[_pointer]); return _source.World.GetEntity(_source._dense[_pointer]);
// return _source._dense[_pointer];
} }
} }
@ -238,4 +294,19 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
} }
public static class EcsGroupExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Normalize<T>(this EcsGroup self, ref T[] array)
{
if (array.Length < self.CapacityDense) Array.Resize(ref array, self.CapacityDense);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Normalize<T>(this EcsReadonlyGroup self, ref T[] array)
{
if (array.Length < self.CapacityDense) Array.Resize(ref array, self.CapacityDense);
}
}
} }

View File

@ -7,6 +7,21 @@ namespace DCFApixels.DragonECS
{ {
public sealed class EcsPipeline public sealed class EcsPipeline
{ {
private static EcsPipeline _empty;
public static EcsPipeline Empty
{
get
{
if(_empty == null)
{
_empty = new EcsPipeline(Array.Empty<IEcsSystem>());
_empty.Init();
_empty._isEmptyDummy = true;
}
return _empty;
}
}
private IEcsSystem[] _allSystems; private IEcsSystem[] _allSystems;
private Dictionary<Type, IEcsRunner> _runners; private Dictionary<Type, IEcsRunner> _runners;
private IEcsRunSystem _runRunnerCache; private IEcsRunSystem _runRunnerCache;
@ -16,10 +31,12 @@ namespace DCFApixels.DragonECS
private bool _isInit; private bool _isInit;
private bool _isDestoryed; private bool _isDestoryed;
private bool _isEmptyDummy;
#region Properties #region Properties
public ReadOnlyCollection<IEcsSystem> AllSystems => _allSystemsSealed; public ReadOnlyCollection<IEcsSystem> AllSystems => _allSystemsSealed;
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed; public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed;
public bool IsInit => _isInit;
public bool IsDestoryed => _isDestoryed; public bool IsDestoryed => _isDestoryed;
#endregion #endregion
@ -33,6 +50,7 @@ namespace DCFApixels.DragonECS
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners); _allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
_isInit = false; _isInit = false;
_isEmptyDummy = false;
_isDestoryed = false; _isDestoryed = false;
} }
#endregion #endregion
@ -57,7 +75,10 @@ namespace DCFApixels.DragonECS
#region LifeCycle #region LifeCycle
public void Init() public void Init()
{ {
if(_isInit == true) if (_isEmptyDummy)
return;
if (_isInit == true)
{ {
EcsDebug.Print("[Warning]", $"This {nameof(EcsPipeline)} has already been initialized"); EcsDebug.Print("[Warning]", $"This {nameof(EcsPipeline)} has already been initialized");
return; return;
@ -80,7 +101,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Run() public void Run()
{ {
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
CheckBeforeInitForMethod(nameof(Run)); CheckBeforeInitForMethod(nameof(Run));
CheckAfterDestroyForMethod(nameof(Run)); CheckAfterDestroyForMethod(nameof(Run));
#endif #endif
@ -88,7 +109,10 @@ namespace DCFApixels.DragonECS
} }
public void Destroy() public void Destroy()
{ {
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS if (_isEmptyDummy)
return;
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
CheckBeforeInitForMethod(nameof(Run)); CheckBeforeInitForMethod(nameof(Run));
#endif #endif
if (_isDestoryed == true) if (_isDestoryed == true)
@ -102,7 +126,7 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region StateChecks #region StateChecks
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
private void CheckBeforeInitForMethod(string methodName) private void CheckBeforeInitForMethod(string methodName)
{ {
if (!_isInit) if (!_isInit)

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Unity.Profiling;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
@ -15,6 +17,8 @@ namespace DCFApixels.DragonECS
public bool Has(int index); public bool Has(int index);
public void Write(int index); public void Write(int index);
public void Del(int index); public void Del(int index);
internal void OnWorldResize(int newSize);
} }
public interface IEcsPool<T> : IEcsPool public interface IEcsPool<T> : IEcsPool
@ -43,6 +47,8 @@ namespace DCFApixels.DragonECS
public void Del(int index) { } public void Del(int index) { }
public bool Has(int index) => false; public bool Has(int index) => false;
public void Write(int index) { } public void Write(int index) { }
void IEcsPool.OnWorldResize(int newSize) { }
} }
public class EcsPool<T> : IEcsPool<T> public class EcsPool<T> : IEcsPool<T>
@ -50,14 +56,21 @@ namespace DCFApixels.DragonECS
{ {
private readonly int _id; private readonly int _id;
private readonly IEcsWorld _source; private readonly IEcsWorld _source;
private readonly SparseSet _sparseSet; // private readonly EcsGroup _entities;
private T[] _denseItems;
private int[] _mapping;// index = entity / value = itemIndex;/ value = 0 = no entity
private T[] _items; //dense
private int _itemsCount;
private int[] _recycledItems;
private int _recycledItemsCount;
private IEcsComponentReset<T> _componentResetHandler; private IEcsComponentReset<T> _componentResetHandler;
private PoolRunnres _poolRunnres;
#region Properites #region Properites
public int EntitiesCount => _sparseSet.Count; public int EntitiesCount => _itemsCount;
public int Capacity => _sparseSet.CapacityDense; public int Capacity => _items.Length;
public IEcsWorld World => _source; public IEcsWorld World => _source;
public Type DataType => typeof(T); public Type DataType => typeof(T);
@ -65,47 +78,81 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Constructors #region Constructors
public EcsPool(IEcsWorld source, int id, int capacity) internal EcsPool(IEcsWorld source, int id, int capacity, PoolRunnres poolRunnres)
{ {
_source = source; _source = source;
_id = id; _id = id;
_sparseSet = new SparseSet(capacity, capacity);
_denseItems =new T[capacity]; _mapping = new int[source.EntitesCapacity];
_recycledItems = new int[128];
_recycledItemsCount = 0;
_items =new T[capacity];
_itemsCount = 0;
_componentResetHandler = ComponentResetHandler.New<T>(); _componentResetHandler = ComponentResetHandler.New<T>();
_poolRunnres = poolRunnres;
} }
#endregion #endregion
#region Read/Write/Has/Del #region Write/Read/Has/Del
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref readonly T Read(int entity)
{
return ref _denseItems[_sparseSet.IndexOf(entity)];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Write(int entity)
{
if (!_sparseSet.Contains(entity))
{
_sparseSet.Add(entity);
_sparseSet.Normalize(ref _denseItems);
_source.OnEntityComponentAdded(entity, _id);
_componentResetHandler.Reset(ref _denseItems[_sparseSet.IndexOf(entity)]);
}
return ref _denseItems[_sparseSet.IndexOf(entity)];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] private ProfilerMarker _writeMark = new ProfilerMarker("EcsPoo.Write");
public bool Has(int entity) private ProfilerMarker _readMark = new ProfilerMarker("EcsPoo.Read");
private ProfilerMarker _hasMark = new ProfilerMarker("EcsPoo.Has");
private ProfilerMarker _delMark = new ProfilerMarker("EcsPoo.Del");
public ref T Write(int entityID)
{ {
return _sparseSet.IndexOf(entity) >= 0; //using (_writeMark.Auto())
//{
ref int itemIndex = ref _mapping[entityID];
if (itemIndex <= 0) //åñëè 0 òî íàäî äîáàâèòü
{
if (_recycledItemsCount > 0)
{
itemIndex = _recycledItems[--_recycledItemsCount];
_itemsCount++;
}
else
{
itemIndex = _itemsCount++;
if (itemIndex >= _items.Length)
Array.Resize(ref _items, _items.Length << 1);
}
_mapping[entityID] = itemIndex;
_componentResetHandler.Reset(ref _items[itemIndex]);
_source.OnEntityComponentAdded(entityID, _id);
_poolRunnres.add.OnComponentAdd<T>(entityID);
}
_poolRunnres.write.OnComponentWrite<T>(entityID);
return ref _items[itemIndex];
// }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Del(int entity) public ref readonly T Read(int entityID)
{ {
_sparseSet.RemoveAt(entity); //using (_readMark.Auto())
_source.OnEntityComponentRemoved(entity, _id); return ref _items[_mapping[entityID]];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID)
{
//using (_hasMark.Auto())
return _mapping[entityID] > 0;
}
public void Del(int entityID)
{
//using (_delMark.Auto())
//{
if(_recycledItemsCount >= _recycledItems.Length)
Array.Resize(ref _recycledItems, _recycledItems.Length << 1);
_recycledItems[_recycledItemsCount++] = _mapping[entityID];
_mapping[entityID] = 0;
_itemsCount--;
//_entities.UncheckedRemove(entityID);
_source.OnEntityComponentRemoved(entityID, _id);
_poolRunnres.del.OnComponentDel<T>(entityID);
//}
} }
#endregion #endregion
@ -123,33 +170,10 @@ namespace DCFApixels.DragonECS
} }
public override int GetHashCode() => _source.GetHashCode() + ID; public override int GetHashCode() => _source.GetHashCode() + ID;
#endregion #endregion
}
#region ComponentResetHandler void IEcsPool.OnWorldResize(int newSize)
internal static class ComponentResetHandler
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEcsComponentReset<T> New<T>()
{ {
Type targetType = typeof(T); Array.Resize(ref _mapping, newSize);
if (targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType)))
{
return (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType));
}
return (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetDummy<>).MakeGenericType(targetType));
} }
} }
internal sealed class ComponentResetDummy<T> : IEcsComponentReset<T>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(ref T component) => component = default;
}
internal sealed class ComponentResetHandler<T> : IEcsComponentReset<T>
where T : IEcsComponentReset<T>
{
private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(ref T component) => _fakeInstnace.Reset(ref component);
}
#endregion
} }

View File

@ -51,7 +51,7 @@ namespace DCFApixels.DragonECS
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && runnerBaseType == type.BaseType.GetGenericTypeDefinition())); .Where(type => type.BaseType != null && type.BaseType.IsGenericType && runnerBaseType == type.BaseType.GetGenericTypeDefinition()));
} }
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
for (int i = 0; i < runnerHandlerTypes.Count; i++) for (int i = 0; i < runnerHandlerTypes.Count; i++)
{ {
var e = CheckRunnerValide(runnerHandlerTypes[i]); var e = CheckRunnerValide(runnerHandlerTypes[i]);
@ -136,7 +136,7 @@ namespace DCFApixels.DragonECS
private static Type _subclass; private static Type _subclass;
internal static void Register(Type subclass) internal static void Register(Type subclass)
{ {
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (_subclass != null) if (_subclass != null)
{ {
throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass"); throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass");

View File

@ -2,6 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Xml;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
@ -12,9 +14,12 @@ namespace DCFApixels.DragonECS
public bool IsEmpty { get; } public bool IsEmpty { get; }
public Type ArchetypeType { get; } public Type ArchetypeType { get; }
public int ID { get; } public int ID { get; }
public EcsPipeline Pipeline { get; }
public int EntitesCount { get; }
public int EntitesCapacity { get; }
public EcsReadonlyGroup Entities { get; }
#endregion #endregion
#region GetterMethods #region GetterMethods
public ReadOnlySpan<IEcsPool> GetAllPools(); public ReadOnlySpan<IEcsPool> GetAllPools();
@ -22,12 +27,13 @@ namespace DCFApixels.DragonECS
#region Methods #region Methods
public EcsPool<T> GetPool<T>() where T : struct; public EcsPool<T> GetPool<T>() where T : struct;
public EcsPool<T> UncheckedGetPool<T>() where T : struct;
public EcsFilter Filter<TInc>() where TInc : struct, IInc; public EcsFilter Filter<TInc>() where TInc : struct, IInc;
public EcsFilter Filter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc; public EcsFilter Filter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc;
public ent NewEntity(); public ent NewEntity();
public void DelEntity(ent entity);
public bool EntityIsAlive(int entityID, short gen); public bool EntityIsAlive(int entityID, short gen);
public ent GetEntity(int entityID); public ent GetEntity(int entityID);
public void DelEntity(int entityID);
public void Destroy(); public void Destroy();
public bool IsMaskCompatible(EcsMask mask, int entity); public bool IsMaskCompatible(EcsMask mask, int entity);
@ -35,6 +41,10 @@ namespace DCFApixels.DragonECS
internal void OnEntityComponentAdded(int entityID, int changedPoolID); internal void OnEntityComponentAdded(int entityID, int changedPoolID);
internal void OnEntityComponentRemoved(int entityID, int changedPoolID); internal void OnEntityComponentRemoved(int entityID, int changedPoolID);
public int GetComponentID<T>();
internal void RegisterGroup(EcsGroup group);
#endregion #endregion
} }
@ -48,6 +58,8 @@ namespace DCFApixels.DragonECS
public EcsWorld() public EcsWorld()
{ {
id = (short)_worldIdDispenser.GetFree(); id = (short)_worldIdDispenser.GetFree();
if(id >= Worlds.Length)
Array.Resize(ref Worlds, Worlds.Length << 1);
Worlds[id] = (IEcsWorld)this; Worlds[id] = (IEcsWorld)this;
} }
@ -75,8 +87,19 @@ namespace DCFApixels.DragonECS
private EcsFilter[] _filters; private EcsFilter[] _filters;
private EcsPipeline _pipeline;
private List<EcsGroup> _groups;
#region RunnersCache
private PoolRunnres _poolRunnres;
private IEcsEntityCreate _entityCreate;
private IEcsEntityDestroy _entityDestry;
#endregion
#region GetterMethods #region GetterMethods
public ReadOnlySpan<IEcsPool> GetAllPools() => new ReadOnlySpan<IEcsPool>(_pools); public ReadOnlySpan<IEcsPool> GetAllPools() => new ReadOnlySpan<IEcsPool>(_pools);
public int GetComponentID<T>() => ComponentType<T>.uniqueID;
#endregion #endregion
@ -84,21 +107,38 @@ namespace DCFApixels.DragonECS
public bool IsEmpty => _entities.Count < 0; public bool IsEmpty => _entities.Count < 0;
public Type ArchetypeType => typeof(TArchetype); public Type ArchetypeType => typeof(TArchetype);
public int ID => id; public int ID => id;
public EcsPipeline Pipeline => _pipeline;
public int EntitesCount => _entities.Count;
public int EntitesCapacity => _entities.CapacityDense;
public EcsReadonlyGroup Entities => _entities.Readonly;
#endregion #endregion
#region Constructors #region Constructors
public EcsWorld() public EcsWorld(EcsPipeline pipline = null)
{ {
_pipeline = pipline ?? EcsPipeline.Empty;
if (!_pipeline.IsInit) pipline.Init();
_entityDispenser = new IntDispenser(1); _entityDispenser = new IntDispenser(1);
_nullPool = new EcsNullPool(this); _nullPool = new EcsNullPool(this);
_pools = new IEcsPool[512]; _pools = new IEcsPool[512];
FillArray(_pools, _nullPool); FillArray(_pools, _nullPool);
//Array.Fill(_pools, _nullPool); //TODO Fix it
_gens = new short[512]; _gens = new short[512];
_filters = new EcsFilter[64]; _filters = new EcsFilter[64];
_entities = new EcsGroup(this, 512); _groups = new List<EcsGroup>(128);
_entities = new EcsGroup(this, 512, 512, 0);
_filtersByIncludedComponents = new List<EcsFilter>[16]; _filtersByIncludedComponents = new List<EcsFilter>[16];
_filtersByExcludedComponents = new List<EcsFilter>[16]; _filtersByExcludedComponents = new List<EcsFilter>[16];
_poolRunnres = new PoolRunnres(_pipeline);
_entityCreate = _pipeline.GetRunner<IEcsEntityCreate>();
_entityDestry = _pipeline.GetRunner<IEcsEntityDestroy>();
_pipeline.GetRunner<IEcsInject<TArchetype>>().Inject((TArchetype)this);
_pipeline.GetRunner<IEcsInject<IEcsWorld>>().Inject(this);
_pipeline.GetRunner<IEcsWorldCreate>().OnWorldCreate(this);
} }
#endregion #endregion
@ -120,14 +160,17 @@ namespace DCFApixels.DragonECS
if (_pools[uniqueID] == _nullPool) if (_pools[uniqueID] == _nullPool)
{ {
_pools[uniqueID] = new EcsPool<T>(this, ComponentType<T>.uniqueID, 512); _pools[uniqueID] = new EcsPool<T>(this, ComponentType<T>.uniqueID, 512, _poolRunnres);
} }
return (EcsPool<T>)_pools[uniqueID]; return (EcsPool<T>)_pools[uniqueID];
} }
public EcsPool<T> UncheckedGetPool<T>() where T : struct
{
return (EcsPool<T>)_pools[ComponentType<T>.uniqueID];
}
#endregion #endregion
#region GetFilter #region GetFilter
public EcsFilter Filter<TInc>() where TInc : struct, IInc => Filter<TInc, Exc>(); public EcsFilter Filter<TInc>() where TInc : struct, IInc => Filter<TInc, Exc>();
public EcsFilter Filter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc public EcsFilter Filter<TInc, TExc>() where TInc : struct, IInc where TExc : struct, IExc
{ {
@ -181,7 +224,6 @@ namespace DCFApixels.DragonECS
} }
} }
return filter; return filter;
} }
#endregion #endregion
@ -189,7 +231,7 @@ namespace DCFApixels.DragonECS
#region IsMaskCompatible/IsMaskCompatibleWithout #region IsMaskCompatible/IsMaskCompatibleWithout
public bool IsMaskCompatible(EcsMask mask, int entity) public bool IsMaskCompatible(EcsMask mask, int entity)
{ {
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (mask.WorldArchetypeType != typeof(TArchetype)) if (mask.WorldArchetypeType != typeof(TArchetype))
throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)"); throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)");
#endif #endif
@ -208,7 +250,7 @@ namespace DCFApixels.DragonECS
public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherComponentID) public bool IsMaskCompatibleWithout(EcsMask mask, int entity, int otherComponentID)
{ {
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (mask.WorldArchetypeType != typeof(TArchetype)) if (mask.WorldArchetypeType != typeof(TArchetype))
throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)"); throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)");
#endif #endif
@ -220,8 +262,8 @@ namespace DCFApixels.DragonECS
} }
for (int i = 0, iMax = mask.ExcCount; i < iMax; i++) for (int i = 0, iMax = mask.ExcCount; i < iMax; i++)
{ {
int poolID = mask.Exc[i]; int componentID = mask.Exc[i];
if (poolID != otherComponentID && _pools[poolID].Has(entity)) if (componentID != otherComponentID && _pools[componentID].Has(entity))
return false; return false;
} }
return true; return true;
@ -234,53 +276,59 @@ namespace DCFApixels.DragonECS
var includeList = _filtersByIncludedComponents[componentID]; var includeList = _filtersByIncludedComponents[componentID];
var excludeList = _filtersByExcludedComponents[componentID]; var excludeList = _filtersByExcludedComponents[componentID];
if (includeList != null) //if (includeList != null)
{ //{
foreach (var filter in includeList) // foreach (var filter in includeList)
{ // {
if (IsMaskCompatible(filter.Mask, entityID)) // if (IsMaskCompatible(filter.Mask, entityID))
{ // {
filter.Add(entityID); // filter.Add(entityID);
} // }
} // }
} //}
if (excludeList != null) //if (excludeList != null)
{ //{
foreach (var filter in excludeList) // foreach (var filter in excludeList)
{ // {
if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID)) // if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID))
{ // {
filter.Remove(entityID); // filter.Remove(entityID);
} // }
} // }
} //}
if (includeList != null) foreach (var filter in includeList) filter.entities.Add(entityID);
if (excludeList != null) foreach (var filter in excludeList) filter.entities.Remove(entityID);
} }
void IEcsWorld.OnEntityComponentRemoved(int entityID, int changedPoolID) void IEcsWorld.OnEntityComponentRemoved(int entityID, int componentID)
{ {
var includeList = _filtersByIncludedComponents[changedPoolID]; var includeList = _filtersByIncludedComponents[componentID];
var excludeList = _filtersByExcludedComponents[changedPoolID]; var excludeList = _filtersByExcludedComponents[componentID];
if (includeList != null) //if (includeList != null)
{ //{
foreach (var filter in includeList) // foreach (var filter in includeList)
{ // {
if (IsMaskCompatible(filter.Mask, entityID)) // if (IsMaskCompatible(filter.Mask, entityID))
{ // {
filter.Remove(entityID); // filter.Remove(entityID);
} // }
} // }
} //}
if (excludeList != null) //if (excludeList != null)
{ //{
foreach (var filter in excludeList) // foreach (var filter in excludeList)
{ // {
if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID)) // if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID))
{ // {
filter.Add(entityID); // filter.Add(entityID);
} // }
} // }
} //}
if (includeList != null) foreach (var filter in includeList) filter.entities.Remove(entityID);
if (excludeList != null) foreach (var filter in excludeList) filter.entities.Add(entityID);
} }
#endregion #endregion
@ -288,23 +336,37 @@ namespace DCFApixels.DragonECS
public ent NewEntity() public ent NewEntity()
{ {
int entityID = _entityDispenser.GetFree(); int entityID = _entityDispenser.GetFree();
_entities.Add(entityID); _entities.UncheckedAdd(entityID);
if (_gens.Length <= entityID) if (_gens.Length <= entityID)
{
Array.Resize(ref _gens, _gens.Length << 1); Array.Resize(ref _gens, _gens.Length << 1);
return new ent(entityID, _gens[entityID]++, id); _entities.OnWorldResize(_gens.Length);
foreach (var item in _groups)
{
item.OnWorldResize(_gens.Length);
}
foreach (var item in _pools)
{
item.OnWorldResize(_gens.Length);
}
}
ent entity = new ent(entityID, _gens[entityID]++, id);
_entityCreate.OnEntityCreate(entity);
return entity;
} }
public void DelEntity(ent entity)
{
_entityDispenser.Release(entity.id);
_entities.UncheckedRemove(entity.id);
_entityDestry.OnEntityDestroy(entity);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ent GetEntity(int entityID) public ent GetEntity(int entityID)
{ {
if (_entities.Contains(entityID) == false)
return ent.NULL;
return new ent(entityID, _gens[entityID], id); return new ent(entityID, _gens[entityID], id);
} }
public void DelEntity(int entityID)
{
_entityDispenser.Release(entityID);
_entities.Remove(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool EntityIsAlive(int entityID, short gen) public bool EntityIsAlive(int entityID, short gen)
{ {
@ -325,6 +387,11 @@ namespace DCFApixels.DragonECS
_filters = null; _filters = null;
Realeze(); Realeze();
} }
public void DestryWithPipeline()
{
Destroy();
_pipeline.Destroy();
}
#endregion #endregion
#region Utils #region Utils
@ -344,7 +411,7 @@ namespace DCFApixels.DragonECS
static ComponentType() static ComponentType()
{ {
uniqueID = ComponentType.increment++; uniqueID = ComponentType.increment++;
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (ComponentType.increment + 1 > ushort.MaxValue) if (ComponentType.increment + 1 > ushort.MaxValue)
{ {
throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype"); throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype");
@ -374,15 +441,27 @@ namespace DCFApixels.DragonECS
} }
} }
#endregion #endregion
}
#region Extensions #region Other
public static class IEcsWorldExtensions void IEcsWorld.RegisterGroup(EcsGroup group)
{
public static void DelEntity(this IEcsWorld self, ent entity)
{ {
self.DelEntity(entity.id); _groups.Add(group);
}
#endregion
}
[StructLayout(LayoutKind.Sequential, Pack = 8, Size = 24)]
internal readonly struct PoolRunnres
{
public readonly IEcsComponentAdd add;
public readonly IEcsComponentWrite write;
public readonly IEcsComponentDel del;
public PoolRunnres(EcsPipeline pipeline)
{
add = pipeline.GetRunner<IEcsComponentAdd>();
write = pipeline.GetRunner<IEcsComponentWrite>();
del = pipeline.GetRunner<IEcsComponentDel>();
} }
} }
#endregion
} }

View File

@ -0,0 +1,32 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
internal static class ComponentResetHandler
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEcsComponentReset<T> New<T>()
{
Type targetType = typeof(T);
if (targetType.GetInterfaces().Contains(typeof(IEcsComponentReset<>).MakeGenericType(targetType)))
{
return (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetHandler<>).MakeGenericType(targetType));
}
return (IEcsComponentReset<T>)Activator.CreateInstance(typeof(ComponentResetDummy<>).MakeGenericType(targetType));
}
}
internal sealed class ComponentResetDummy<T> : IEcsComponentReset<T>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(ref T component) => component = default;
}
internal sealed class ComponentResetHandler<T> : IEcsComponentReset<T>
where T : IEcsComponentReset<T>
{
private T _fakeInstnace = default;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset(ref T component) => _fakeInstnace.Reset(ref component);
}
}

View File

@ -97,18 +97,18 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsAlive(this ref ent self) public static bool IsAlive(this ref ent self)
{ {
using (_IsAliveMarker.Auto()) //using (_IsAliveMarker.Auto())
{ //{
bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen); bool result = EcsWorld.Worlds[self.world].EntityIsAlive(self.id, self.gen);
if (!result) self = ent.NULL; if (!result) self = ent.NULL;
return result; return result;
} //}
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsNull(this in ent self) public static bool IsNull(this in ent self)
{ {
using (_IsNullMarker.Auto()) //using (_IsNullMarker.Auto())
return self == ent.NULL; return self == ent.NULL;
} }
@ -116,28 +116,28 @@ namespace DCFApixels.DragonECS
public static ref readonly T Read<T>(this in ent self) public static ref readonly T Read<T>(this in ent self)
where T : struct where T : struct
{ {
using (_ReadMarker.Auto()) //using (_ReadMarker.Auto())
return ref EcsWorld.Worlds[self.world].GetPool<T>().Read(self.id); return ref EcsWorld.Worlds[self.world].GetPool<T>().Read(self.id);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T Write<T>(this in ent self) public static ref T Write<T>(this in ent self)
where T : struct where T : struct
{ {
using (_WriteMarker.Auto()) //using (_WriteMarker.Auto())
return ref EcsWorld.Worlds[self.world].GetPool<T>().Write(self.id); return ref EcsWorld.Worlds[self.world].GetPool<T>().Write(self.id);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Has<T>(this in ent self) public static bool Has<T>(this in ent self)
where T : struct where T : struct
{ {
using (_HasMarker.Auto()) //using (_HasMarker.Auto())
return EcsWorld.Worlds[self.world].GetPool<T>().Has(self.id); return EcsWorld.Worlds[self.world].GetPool<T>().Has(self.id);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Del<T>(this in ent self) public static void Del<T>(this in ent self)
where T : struct where T : struct
{ {
using (_DelMarker.Auto()) //using (_DelMarker.Auto())
EcsWorld.Worlds[self.world].GetPool<T>().Del(self.id); EcsWorld.Worlds[self.world].GetPool<T>().Del(self.id);
} }
} }