mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
Optimization
This commit is contained in:
parent
a489f4cbae
commit
de7762861c
@ -22,12 +22,12 @@
|
||||
|
||||
public sealed class EcsPreInitRunner : EcsRunner<IEcsPreInitSystem>, IEcsPreInitSystem
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
private EcsProfilerMarker[] _markers;
|
||||
#endif
|
||||
public void PreInit(EcsPipeline pipeline)
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
using (_markers[i].Auto())
|
||||
@ -38,7 +38,7 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
protected override void OnSetup()
|
||||
{
|
||||
_markers = new EcsProfilerMarker[targets.Length];
|
||||
@ -51,12 +51,12 @@
|
||||
}
|
||||
public sealed class EcsInitRunner : EcsRunner<IEcsInitSystem>, IEcsInitSystem
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
private EcsProfilerMarker[] _markers;
|
||||
#endif
|
||||
public void Init(EcsPipeline pipeline)
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
using (_markers[i].Auto())
|
||||
@ -67,7 +67,7 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
protected override void OnSetup()
|
||||
{
|
||||
_markers = new EcsProfilerMarker[targets.Length];
|
||||
@ -80,12 +80,12 @@
|
||||
}
|
||||
public sealed class EcsRunRunner : EcsRunner<IEcsRunSystem>, IEcsRunSystem
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
private EcsProfilerMarker[] _markers;
|
||||
#endif
|
||||
public void Run(EcsPipeline pipeline)
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
using (_markers[i].Auto())
|
||||
@ -97,7 +97,7 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
protected override void OnSetup()
|
||||
{
|
||||
_markers = new EcsProfilerMarker[targets.Length];
|
||||
@ -110,12 +110,12 @@
|
||||
}
|
||||
public sealed class EcsDestroyRunner : EcsRunner<IEcsDestroySystem>, IEcsDestroySystem
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
private EcsProfilerMarker[] _markers;
|
||||
#endif
|
||||
public void Destroy(EcsPipeline pipeline)
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
for (int i = 0; i < targets.Length; i++)
|
||||
{
|
||||
using (_markers[i].Auto())
|
||||
@ -126,7 +126,7 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && !DISABLE_DRAGONECS_DEBUG
|
||||
protected override void OnSetup()
|
||||
{
|
||||
_markers = new EcsProfilerMarker[targets.Length];
|
87
src/Builtin/WorldRunners.cs
Normal file
87
src/Builtin/WorldRunners.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
public sealed class EcsDefaultWrold : EcsWorld<EcsDefaultWrold> { }
|
||||
public sealed class EcsEventWrold : EcsWorld<EcsDefaultWrold> { }
|
||||
public sealed class EcsDefaultWrold : EcsWorld<EcsDefaultWrold>
|
||||
{
|
||||
public EcsDefaultWrold(EcsPipeline pipeline) : base(pipeline) { }
|
||||
}
|
||||
public sealed class EcsEventWrold : EcsWorld<EcsDefaultWrold>
|
||||
{
|
||||
public EcsEventWrold(EcsPipeline pipeline) : base(pipeline) { }
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public AutoScope Auto() => new AutoScope(id);
|
||||
|
||||
public readonly struct AutoScope : IDisposable
|
||||
public readonly ref struct AutoScope
|
||||
{
|
||||
private readonly int id;
|
||||
public AutoScope(int id)
|
||||
@ -43,14 +43,14 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Print(string tag, object v)
|
||||
{
|
||||
#if !DISABLE_ECS_DEBUG
|
||||
#if !DISABLE_DRAGONECS_DEBUG
|
||||
DebugService.Instance.Print(tag, v);
|
||||
#endif
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int RegisterMark(string name)
|
||||
{
|
||||
#if !DISABLE_ECS_DEBUG
|
||||
#if !DISABLE_DRAGONECS_DEBUG
|
||||
return DebugService.Instance.RegisterMark(name);
|
||||
#else
|
||||
return 0;
|
||||
@ -59,21 +59,21 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void DeleteMark(string name)
|
||||
{
|
||||
#if !DISABLE_ECS_DEBUG
|
||||
#if !DISABLE_DRAGONECS_DEBUG
|
||||
DebugService.Instance.DeleteMark(name);
|
||||
#endif
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ProfileMarkBegin(int id)
|
||||
{
|
||||
#if !DISABLE_ECS_DEBUG
|
||||
#if !DISABLE_DRAGONECS_DEBUG
|
||||
DebugService.Instance.ProfileMarkBegin(id);
|
||||
#endif
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ProfileMarkEnd(int id)
|
||||
{
|
||||
#if !DISABLE_ECS_DEBUG
|
||||
#if !DISABLE_DRAGONECS_DEBUG
|
||||
DebugService.Instance.ProfileMarkEnd(id);
|
||||
#endif
|
||||
}
|
||||
@ -145,7 +145,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public DefaultDebugService()
|
||||
{
|
||||
#if !DISABLE_ECS_DEBUG
|
||||
#if !DISABLE_DRAGONECS_DEBUG
|
||||
_stopwatchs = new Stopwatch[64];
|
||||
_stopwatchsNames= new string[64];
|
||||
#endif
|
||||
|
@ -15,7 +15,7 @@ namespace DCFApixels.DragonECS
|
||||
public class EcsFilter : IEcsFilter
|
||||
{
|
||||
private readonly IEcsWorld _source;
|
||||
private readonly EcsGroup _entities;
|
||||
internal readonly EcsGroup entities;
|
||||
private readonly EcsMask _mask;
|
||||
|
||||
#region Properties
|
||||
@ -32,12 +32,12 @@ namespace DCFApixels.DragonECS
|
||||
public EcsReadonlyGroup Entities
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _entities.Readonly;
|
||||
get => entities.Readonly;
|
||||
}
|
||||
public int EntitiesCount
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _entities.Count;
|
||||
get => entities.Count;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -46,7 +46,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_source = source;
|
||||
_mask = mask;
|
||||
_entities = new EcsGroup(source, capasity);
|
||||
entities = new EcsGroup(source, capasity);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -54,19 +54,19 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void Add(int entityID)
|
||||
{
|
||||
_entities.Add(entityID);
|
||||
entities.UncheckedAdd(entityID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal void Remove(int entityID)
|
||||
{
|
||||
_entities.Remove(entityID);
|
||||
entities.UncheckedRemove(entityID);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetEnumerator
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public EcsGroup.Enumerator GetEnumerator() => _entities.GetEnumerator();
|
||||
public EcsGroup.Enumerator GetEnumerator() => entities.GetEnumerator();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
127
src/EcsGroup.cs
127
src/EcsGroup.cs
@ -17,6 +17,16 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _source.Count;
|
||||
}
|
||||
public int CapacityDense
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _source.CapacityDense;
|
||||
}
|
||||
public int CapacitySparce
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _source.CapacitySparce;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Contains(int entityID) => _source.Contains(entityID);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -51,6 +61,16 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _count;
|
||||
}
|
||||
public int CapacityDense
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _dense.Length;
|
||||
}
|
||||
public int CapacitySparce
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _sparse.Length;
|
||||
}
|
||||
public EcsReadonlyGroup Readonly
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -60,11 +80,29 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Constrcutors
|
||||
[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.RegisterGroup(this);
|
||||
_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];
|
||||
|
||||
@ -79,12 +117,29 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
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
|
||||
|
||||
#region add/remove
|
||||
public void UncheckedAdd(int entityID) => AddInternal(entityID);
|
||||
public void Add(int entityID)
|
||||
{
|
||||
if (Contains(entityID)) return;
|
||||
Add(entityID);
|
||||
}
|
||||
private void AddInternal(int entityID)
|
||||
{
|
||||
if (_lockCount > 0)
|
||||
{
|
||||
@ -92,40 +147,34 @@ namespace DCFApixels.DragonECS
|
||||
return;
|
||||
}
|
||||
|
||||
if (Contains(entityID))
|
||||
return;
|
||||
|
||||
if(++_count >= _dense.Length)
|
||||
if (++_count >= _dense.Length)
|
||||
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;
|
||||
_sparse[entityID] = _count;
|
||||
}
|
||||
|
||||
public void UncheckedRemove(int entityID) => RemoveInternal(entityID);
|
||||
public void Remove(int entityID)
|
||||
{
|
||||
if (!Contains(entityID)) return;
|
||||
RemoveInternal(entityID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void RemoveInternal(int entityID)
|
||||
{
|
||||
if (_lockCount > 0)
|
||||
{
|
||||
AddDelayedOp(entityID, DEALAYED_REMOVE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Contains(entityID))
|
||||
return;
|
||||
|
||||
_dense[_sparse[entityID]] = _dense[_count];
|
||||
_sparse[_dense[_count--]] = _sparse[entityID];
|
||||
_sparse[entityID] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void AddDelayedOp(int entityID, int isAddBitFlag)
|
||||
{
|
||||
@ -137,24 +186,32 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
//TODO добавить автосоритровку при каждом GetEnumerator
|
||||
internal void OnWorldResize(int newSize)
|
||||
{
|
||||
Array.Resize(ref _sparse, newSize);
|
||||
}
|
||||
|
||||
//TODO добавить метод Sort
|
||||
|
||||
//TODO добавить автосоритровку при каждом GetEnumerator и проверить будет ли прирост производительности или ее падение.
|
||||
//Суть в том что так возможно можно будет более плотно подавать данные в проц
|
||||
|
||||
#region AddGroup/RemoveGroup
|
||||
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)
|
||||
{
|
||||
foreach (var item in group) Remove(item.id);
|
||||
foreach (var item in group) UncheckedRemove(item.id);
|
||||
}
|
||||
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)
|
||||
{
|
||||
foreach (var item in group) Remove(item.id);
|
||||
foreach (var item in group) UncheckedRemove(item.id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -162,7 +219,7 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Unlock()
|
||||
{
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
if (_lockCount <= 0)
|
||||
{
|
||||
throw new Exception($"Invalid lock-unlock balance for {nameof(EcsGroup)}.");
|
||||
@ -175,11 +232,11 @@ namespace DCFApixels.DragonECS
|
||||
delayedOp op = _delayedOps[i];
|
||||
if (op >= 0) //delayedOp.IsAdded
|
||||
{
|
||||
Add(op & int.MaxValue); //delayedOp.Entity
|
||||
UncheckedAdd(op & int.MaxValue); //delayedOp.Entity
|
||||
}
|
||||
else
|
||||
{
|
||||
Remove(op & int.MaxValue); //delayedOp.Entity
|
||||
UncheckedRemove(op & int.MaxValue); //delayedOp.Entity
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +271,6 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
using (_marker.Auto())
|
||||
return _source.World.GetEntity(_source._dense[_pointer]);
|
||||
// return _source._dense[_pointer];
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,4 +294,19 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,21 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
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 Dictionary<Type, IEcsRunner> _runners;
|
||||
private IEcsRunSystem _runRunnerCache;
|
||||
@ -16,10 +31,12 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
private bool _isInit;
|
||||
private bool _isDestoryed;
|
||||
private bool _isEmptyDummy;
|
||||
|
||||
#region Properties
|
||||
public ReadOnlyCollection<IEcsSystem> AllSystems => _allSystemsSealed;
|
||||
public ReadOnlyDictionary<Type, IEcsRunner> AllRunners => _allRunnersSealed;
|
||||
public bool IsInit => _isInit;
|
||||
public bool IsDestoryed => _isDestoryed;
|
||||
#endregion
|
||||
|
||||
@ -33,6 +50,7 @@ namespace DCFApixels.DragonECS
|
||||
_allRunnersSealed = new ReadOnlyDictionary<Type, IEcsRunner>(_runners);
|
||||
|
||||
_isInit = false;
|
||||
_isEmptyDummy = false;
|
||||
_isDestoryed = false;
|
||||
}
|
||||
#endregion
|
||||
@ -57,7 +75,10 @@ namespace DCFApixels.DragonECS
|
||||
#region LifeCycle
|
||||
public void Init()
|
||||
{
|
||||
if(_isInit == true)
|
||||
if (_isEmptyDummy)
|
||||
return;
|
||||
|
||||
if (_isInit == true)
|
||||
{
|
||||
EcsDebug.Print("[Warning]", $"This {nameof(EcsPipeline)} has already been initialized");
|
||||
return;
|
||||
@ -80,7 +101,7 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Run()
|
||||
{
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
CheckBeforeInitForMethod(nameof(Run));
|
||||
CheckAfterDestroyForMethod(nameof(Run));
|
||||
#endif
|
||||
@ -88,7 +109,10 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
if (_isEmptyDummy)
|
||||
return;
|
||||
|
||||
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
CheckBeforeInitForMethod(nameof(Run));
|
||||
#endif
|
||||
if (_isDestoryed == true)
|
||||
@ -102,7 +126,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region StateChecks
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
private void CheckBeforeInitForMethod(string methodName)
|
||||
{
|
||||
if (!_isInit)
|
||||
|
128
src/EcsPool.cs
128
src/EcsPool.cs
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Profiling;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -15,6 +17,8 @@ namespace DCFApixels.DragonECS
|
||||
public bool Has(int index);
|
||||
public void Write(int index);
|
||||
public void Del(int index);
|
||||
|
||||
internal void OnWorldResize(int newSize);
|
||||
}
|
||||
|
||||
public interface IEcsPool<T> : IEcsPool
|
||||
@ -43,6 +47,8 @@ namespace DCFApixels.DragonECS
|
||||
public void Del(int index) { }
|
||||
public bool Has(int index) => false;
|
||||
public void Write(int index) { }
|
||||
|
||||
void IEcsPool.OnWorldResize(int newSize) { }
|
||||
}
|
||||
|
||||
public class EcsPool<T> : IEcsPool<T>
|
||||
@ -50,14 +56,21 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
private readonly int _id;
|
||||
private readonly IEcsWorld _source;
|
||||
private readonly SparseSet _sparseSet;
|
||||
private T[] _denseItems;
|
||||
// private readonly EcsGroup _entities;
|
||||
|
||||
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 PoolRunnres _poolRunnres;
|
||||
|
||||
#region Properites
|
||||
public int EntitiesCount => _sparseSet.Count;
|
||||
public int Capacity => _sparseSet.CapacityDense;
|
||||
public int EntitiesCount => _itemsCount;
|
||||
public int Capacity => _items.Length;
|
||||
|
||||
public IEcsWorld World => _source;
|
||||
public Type DataType => typeof(T);
|
||||
@ -65,47 +78,81 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsPool(IEcsWorld source, int id, int capacity)
|
||||
internal EcsPool(IEcsWorld source, int id, int capacity, PoolRunnres poolRunnres)
|
||||
{
|
||||
_source = source;
|
||||
_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>();
|
||||
_poolRunnres = poolRunnres;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Read/Write/Has/Del
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref readonly T Read(int entity)
|
||||
#region Write/Read/Has/Del
|
||||
|
||||
private ProfilerMarker _writeMark = new ProfilerMarker("EcsPoo.Write");
|
||||
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 ref _denseItems[_sparseSet.IndexOf(entity)];
|
||||
//using (_writeMark.Auto())
|
||||
//{
|
||||
ref int itemIndex = ref _mapping[entityID];
|
||||
if (itemIndex <= 0) //åñëè 0 òî íàäî äîáàâèòü
|
||||
{
|
||||
if (_recycledItemsCount > 0)
|
||||
{
|
||||
itemIndex = _recycledItems[--_recycledItemsCount];
|
||||
_itemsCount++;
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref T Write(int entity)
|
||||
else
|
||||
{
|
||||
if (!_sparseSet.Contains(entity))
|
||||
{
|
||||
_sparseSet.Add(entity);
|
||||
_sparseSet.Normalize(ref _denseItems);
|
||||
_source.OnEntityComponentAdded(entity, _id);
|
||||
_componentResetHandler.Reset(ref _denseItems[_sparseSet.IndexOf(entity)]);
|
||||
itemIndex = _itemsCount++;
|
||||
if (itemIndex >= _items.Length)
|
||||
Array.Resize(ref _items, _items.Length << 1);
|
||||
}
|
||||
return ref _denseItems[_sparseSet.IndexOf(entity)];
|
||||
_mapping[entityID] = itemIndex;
|
||||
_componentResetHandler.Reset(ref _items[itemIndex]);
|
||||
_source.OnEntityComponentAdded(entityID, _id);
|
||||
_poolRunnres.add.OnComponentAdd<T>(entityID);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Has(int entity)
|
||||
{
|
||||
return _sparseSet.IndexOf(entity) >= 0;
|
||||
_poolRunnres.write.OnComponentWrite<T>(entityID);
|
||||
return ref _items[itemIndex];
|
||||
// }
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Del(int entity)
|
||||
public ref readonly T Read(int entityID)
|
||||
{
|
||||
_sparseSet.RemoveAt(entity);
|
||||
_source.OnEntityComponentRemoved(entity, _id);
|
||||
//using (_readMark.Auto())
|
||||
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
|
||||
|
||||
@ -123,33 +170,10 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public override int GetHashCode() => _source.GetHashCode() + ID;
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region ComponentResetHandler
|
||||
internal static class ComponentResetHandler
|
||||
void IEcsPool.OnWorldResize(int newSize)
|
||||
{
|
||||
[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));
|
||||
Array.Resize(ref _mapping, newSize);
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace DCFApixels.DragonECS
|
||||
.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++)
|
||||
{
|
||||
var e = CheckRunnerValide(runnerHandlerTypes[i]);
|
||||
@ -136,7 +136,7 @@ namespace DCFApixels.DragonECS
|
||||
private static 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)
|
||||
{
|
||||
throw new EcsRunnerImplementationException($"The Runner<{typeof(TInterface).FullName}> can have only one implementing subclass");
|
||||
|
225
src/EcsWorld.cs
225
src/EcsWorld.cs
@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
@ -12,9 +14,12 @@ namespace DCFApixels.DragonECS
|
||||
public bool IsEmpty { get; }
|
||||
public Type ArchetypeType { get; }
|
||||
public int ID { get; }
|
||||
public EcsPipeline Pipeline { get; }
|
||||
public int EntitesCount { get; }
|
||||
public int EntitesCapacity { get; }
|
||||
public EcsReadonlyGroup Entities { get; }
|
||||
#endregion
|
||||
|
||||
|
||||
#region GetterMethods
|
||||
public ReadOnlySpan<IEcsPool> GetAllPools();
|
||||
|
||||
@ -22,12 +27,13 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Methods
|
||||
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, TExc>() where TInc : struct, IInc where TExc : struct, IExc;
|
||||
public ent NewEntity();
|
||||
public void DelEntity(ent entity);
|
||||
public bool EntityIsAlive(int entityID, short gen);
|
||||
public ent GetEntity(int entityID);
|
||||
public void DelEntity(int entityID);
|
||||
public void Destroy();
|
||||
|
||||
public bool IsMaskCompatible(EcsMask mask, int entity);
|
||||
@ -35,6 +41,10 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
internal void OnEntityComponentAdded(int entityID, int changedPoolID);
|
||||
internal void OnEntityComponentRemoved(int entityID, int changedPoolID);
|
||||
|
||||
public int GetComponentID<T>();
|
||||
|
||||
internal void RegisterGroup(EcsGroup group);
|
||||
#endregion
|
||||
}
|
||||
|
||||
@ -48,6 +58,8 @@ namespace DCFApixels.DragonECS
|
||||
public EcsWorld()
|
||||
{
|
||||
id = (short)_worldIdDispenser.GetFree();
|
||||
if(id >= Worlds.Length)
|
||||
Array.Resize(ref Worlds, Worlds.Length << 1);
|
||||
Worlds[id] = (IEcsWorld)this;
|
||||
}
|
||||
|
||||
@ -75,8 +87,19 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
private EcsFilter[] _filters;
|
||||
|
||||
private EcsPipeline _pipeline;
|
||||
|
||||
private List<EcsGroup> _groups;
|
||||
|
||||
#region RunnersCache
|
||||
private PoolRunnres _poolRunnres;
|
||||
private IEcsEntityCreate _entityCreate;
|
||||
private IEcsEntityDestroy _entityDestry;
|
||||
#endregion
|
||||
|
||||
#region GetterMethods
|
||||
public ReadOnlySpan<IEcsPool> GetAllPools() => new ReadOnlySpan<IEcsPool>(_pools);
|
||||
public int GetComponentID<T>() => ComponentType<T>.uniqueID;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -84,21 +107,38 @@ namespace DCFApixels.DragonECS
|
||||
public bool IsEmpty => _entities.Count < 0;
|
||||
public Type ArchetypeType => typeof(TArchetype);
|
||||
public int ID => id;
|
||||
public EcsPipeline Pipeline => _pipeline;
|
||||
|
||||
public int EntitesCount => _entities.Count;
|
||||
public int EntitesCapacity => _entities.CapacityDense;
|
||||
public EcsReadonlyGroup Entities => _entities.Readonly;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public EcsWorld()
|
||||
public EcsWorld(EcsPipeline pipline = null)
|
||||
{
|
||||
_pipeline = pipline ?? EcsPipeline.Empty;
|
||||
if (!_pipeline.IsInit) pipline.Init();
|
||||
_entityDispenser = new IntDispenser(1);
|
||||
_nullPool = new EcsNullPool(this);
|
||||
_pools = new IEcsPool[512];
|
||||
FillArray(_pools, _nullPool);
|
||||
//Array.Fill(_pools, _nullPool); //TODO Fix it
|
||||
|
||||
_gens = new short[512];
|
||||
_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];
|
||||
_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
|
||||
|
||||
@ -120,11 +160,14 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
public EcsPool<T> UncheckedGetPool<T>() where T : struct
|
||||
{
|
||||
return (EcsPool<T>)_pools[ComponentType<T>.uniqueID];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFilter
|
||||
@ -181,7 +224,6 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return filter;
|
||||
}
|
||||
#endregion
|
||||
@ -189,7 +231,7 @@ namespace DCFApixels.DragonECS
|
||||
#region IsMaskCompatible/IsMaskCompatibleWithout
|
||||
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))
|
||||
throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)");
|
||||
#endif
|
||||
@ -208,7 +250,7 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
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))
|
||||
throw new EcsFrameworkException("mask.WorldArchetypeType != typeof(TArchetype)");
|
||||
#endif
|
||||
@ -220,8 +262,8 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
for (int i = 0, iMax = mask.ExcCount; i < iMax; i++)
|
||||
{
|
||||
int poolID = mask.Exc[i];
|
||||
if (poolID != otherComponentID && _pools[poolID].Has(entity))
|
||||
int componentID = mask.Exc[i];
|
||||
if (componentID != otherComponentID && _pools[componentID].Has(entity))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -234,53 +276,59 @@ namespace DCFApixels.DragonECS
|
||||
var includeList = _filtersByIncludedComponents[componentID];
|
||||
var excludeList = _filtersByExcludedComponents[componentID];
|
||||
|
||||
if (includeList != null)
|
||||
{
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
if (IsMaskCompatible(filter.Mask, entityID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (includeList != null)
|
||||
//{
|
||||
// foreach (var filter in includeList)
|
||||
// {
|
||||
// if (IsMaskCompatible(filter.Mask, entityID))
|
||||
// {
|
||||
// filter.Add(entityID);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//if (excludeList != null)
|
||||
//{
|
||||
// foreach (var filter in excludeList)
|
||||
// {
|
||||
// if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID))
|
||||
// {
|
||||
// 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 excludeList = _filtersByExcludedComponents[changedPoolID];
|
||||
var includeList = _filtersByIncludedComponents[componentID];
|
||||
var excludeList = _filtersByExcludedComponents[componentID];
|
||||
|
||||
if (includeList != null)
|
||||
{
|
||||
foreach (var filter in includeList)
|
||||
{
|
||||
if (IsMaskCompatible(filter.Mask, entityID))
|
||||
{
|
||||
filter.Remove(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeList != null)
|
||||
{
|
||||
foreach (var filter in excludeList)
|
||||
{
|
||||
if (IsMaskCompatibleWithout(filter.Mask, entityID, changedPoolID))
|
||||
{
|
||||
filter.Add(entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (includeList != null)
|
||||
//{
|
||||
// foreach (var filter in includeList)
|
||||
// {
|
||||
// if (IsMaskCompatible(filter.Mask, entityID))
|
||||
// {
|
||||
// filter.Remove(entityID);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//if (excludeList != null)
|
||||
//{
|
||||
// foreach (var filter in excludeList)
|
||||
// {
|
||||
// if (IsMaskCompatibleWithout(filter.Mask, entityID, componentID))
|
||||
// {
|
||||
// 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
|
||||
|
||||
@ -288,23 +336,37 @@ namespace DCFApixels.DragonECS
|
||||
public ent NewEntity()
|
||||
{
|
||||
int entityID = _entityDispenser.GetFree();
|
||||
_entities.Add(entityID);
|
||||
_entities.UncheckedAdd(entityID);
|
||||
if (_gens.Length <= entityID)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (_entities.Contains(entityID) == false)
|
||||
return ent.NULL;
|
||||
|
||||
return new ent(entityID, _gens[entityID], id);
|
||||
}
|
||||
public void DelEntity(int entityID)
|
||||
{
|
||||
_entityDispenser.Release(entityID);
|
||||
_entities.Remove(entityID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool EntityIsAlive(int entityID, short gen)
|
||||
{
|
||||
@ -325,6 +387,11 @@ namespace DCFApixels.DragonECS
|
||||
_filters = null;
|
||||
Realeze();
|
||||
}
|
||||
public void DestryWithPipeline()
|
||||
{
|
||||
Destroy();
|
||||
_pipeline.Destroy();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
@ -344,7 +411,7 @@ namespace DCFApixels.DragonECS
|
||||
static ComponentType()
|
||||
{
|
||||
uniqueID = ComponentType.increment++;
|
||||
#if DEBUG || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
|
||||
if (ComponentType.increment + 1 > ushort.MaxValue)
|
||||
{
|
||||
throw new EcsFrameworkException($"No more room for new component for this {typeof(TArchetype).FullName} IWorldArchetype");
|
||||
@ -374,15 +441,27 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Extensions
|
||||
public static class IEcsWorldExtensions
|
||||
#region Other
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
src/Utils/ComponentResetHandler.cs
Normal file
32
src/Utils/ComponentResetHandler.cs
Normal 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);
|
||||
}
|
||||
}
|
16
src/ent.cs
16
src/ent.cs
@ -97,18 +97,18 @@ namespace DCFApixels.DragonECS
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
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);
|
||||
if (!result) self = ent.NULL;
|
||||
return result;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNull(this in ent self)
|
||||
{
|
||||
using (_IsNullMarker.Auto())
|
||||
//using (_IsNullMarker.Auto())
|
||||
return self == ent.NULL;
|
||||
}
|
||||
|
||||
@ -116,28 +116,28 @@ namespace DCFApixels.DragonECS
|
||||
public static ref readonly T Read<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
using (_ReadMarker.Auto())
|
||||
//using (_ReadMarker.Auto())
|
||||
return ref EcsWorld.Worlds[self.world].GetPool<T>().Read(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ref T Write<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
using (_WriteMarker.Auto())
|
||||
//using (_WriteMarker.Auto())
|
||||
return ref EcsWorld.Worlds[self.world].GetPool<T>().Write(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool Has<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
using (_HasMarker.Auto())
|
||||
//using (_HasMarker.Auto())
|
||||
return EcsWorld.Worlds[self.world].GetPool<T>().Has(self.id);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Del<T>(this in ent self)
|
||||
where T : struct
|
||||
{
|
||||
using (_DelMarker.Auto())
|
||||
//using (_DelMarker.Auto())
|
||||
EcsWorld.Worlds[self.world].GetPool<T>().Del(self.id);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user