update/add component count/auto delete empty entity

This commit is contained in:
Mikhail 2023-04-26 16:45:37 +08:00
parent 7ef7fb0d14
commit d5e1700029
18 changed files with 265 additions and 127 deletions

View File

@ -138,38 +138,35 @@ namespace DCFApixels.DragonECS
{ {
public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data) public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data)
{ {
self.Add(new InjectSystem<T>(data)); return self.Add(new InjectSystem<T>(data));
return self;
} }
public static EcsPipeline.Builder Inject<A, B>(this EcsPipeline.Builder self, A a, B b) public static EcsPipeline.Builder Inject<A, B>(this EcsPipeline.Builder self, A a, B b)
{ {
self.Inject(a).Inject(b); return self.Inject(a).Inject(b);
return self; }
public static EcsPipeline.Builder Inject<A, B, C>(this EcsPipeline.Builder self, A a, B b, C c)
{
return self.Inject(a).Inject(b).Inject(c);
} }
public static EcsPipeline.Builder Inject<A, B, C, D>(this EcsPipeline.Builder self, A a, B b, C c, D d) public static EcsPipeline.Builder Inject<A, B, C, D>(this EcsPipeline.Builder self, A a, B b, C c, D d)
{ {
self.Inject(a).Inject(b).Inject(c).Inject(d); return self.Inject(a).Inject(b).Inject(c).Inject(d);
return self;
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e) public static EcsPipeline.Builder Inject<A, B, C, D, E>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e)
{ {
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e); return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e);
return self;
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E, F>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f) public static EcsPipeline.Builder Inject<A, B, C, D, E, F>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f)
{ {
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f); return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f);
return self;
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g) public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g)
{ {
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g); return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g);
return self;
} }
public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G, H>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g, H h) public static EcsPipeline.Builder Inject<A, B, C, D, E, F, G, H>(this EcsPipeline.Builder self, A a, B b, C c, D d, E e, F f, G g, H h)
{ {
self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g).Inject(h); return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g).Inject(h);
return self;
} }
} }
} }

View File

@ -1,4 +1,6 @@
namespace DCFApixels.DragonECS using System.Collections.Generic;
namespace DCFApixels.DragonECS
{ {
[DebugColor(DebugColor.Black)] [DebugColor(DebugColor.Black)]
public class SystemsBlockMarkerSystem : IEcsSystem public class SystemsBlockMarkerSystem : IEcsSystem
@ -10,4 +12,60 @@
this.name = name; this.name = name;
} }
} }
[DebugHide, DebugColor(DebugColor.Grey)]
public class DeleteEmptyEntitesSsytem : IEcsRunSystem, IEcsPreInject
{
private List<EcsWorld> _worlds = new List<EcsWorld>();
public void PreInject(object obj)
{
if (obj is EcsWorld world)
_worlds.Add(world);
}
public void Run(EcsPipeline pipeline)
{
foreach (var world in _worlds)
world.DeleteEmptyEntites();
}
}
public class DeleteOneFrameComponentSystem<TWorld, TComponent> : IEcsRunSystem, IEcsInject<TWorld>
where TWorld : EcsWorld<TWorld>
where TComponent : struct, IEcsComponent
{
private TWorld _world;
public void Inject(TWorld obj) => _world = obj;
private sealed class Query : EcsQuery
{
public EcsPool<TComponent> pool;
public Query(Builder b)
{
pool = b.Include<TComponent>();
}
}
public void Run(EcsPipeline pipeline)
{
foreach (var e in _world.Where(out Query q))
q.pool.Del(e);
}
}
public static class DeleteOneFrameComponentSystemExt
{
public static EcsPipeline.Builder AutoDel<TWorld, TComponent>(this EcsPipeline.Builder b)
where TWorld : EcsWorld<TWorld>
where TComponent : struct, IEcsComponent
{
b.Add(new DeleteOneFrameComponentSystem<TWorld, TComponent>());
return b;
}
/// <summary> for EcsDefaultWorld </summary>
public static EcsPipeline.Builder AutoDel<TComponent>(this EcsPipeline.Builder b)
where TComponent : struct, IEcsComponent
{
b.Add(new DeleteOneFrameComponentSystem<EcsDefaultWorld, TComponent>());
return b;
}
}
} }

View File

@ -50,7 +50,7 @@ namespace DCFApixels.DragonECS
} }
public interface IEcsEntityDestroy : IEcsSystem public interface IEcsEntityDestroy : IEcsSystem
{ {
public void OnEntityDestroy(EcsEntity entity); public void OnEntityDestroy(int entityID);
} }
public interface IEcsEntityLifecycle : IEcsEntityCreate, IEcsEntityDestroy { } public interface IEcsEntityLifecycle : IEcsEntityCreate, IEcsEntityDestroy { }
@ -67,9 +67,9 @@ namespace DCFApixels.DragonECS
[DebugColor(DebugColor.Orange)] [DebugColor(DebugColor.Orange)]
public sealed class EcsEntityDestroyRunner : EcsRunner<IEcsEntityDestroy>, IEcsEntityDestroy public sealed class EcsEntityDestroyRunner : EcsRunner<IEcsEntityDestroy>, IEcsEntityDestroy
{ {
public void OnEntityDestroy(EcsEntity entity) public void OnEntityDestroy(int entityID)
{ {
foreach (var item in targets) item.OnEntityDestroy(entity); foreach (var item in targets) item.OnEntityDestroy(entityID);
} }
} }
} }

View File

@ -9,14 +9,17 @@
public sealed class EcsDefaultWorld : EcsWorld<EcsDefaultWorld> public sealed class EcsDefaultWorld : EcsWorld<EcsDefaultWorld>
{ {
public EcsDefaultWorld(EcsPipeline pipeline = null) : base(pipeline) { } public EcsDefaultWorld() : base(null) { }
public EcsDefaultWorld(EcsPipeline pipeline) : base(pipeline) { }
} }
public sealed class EcsEventWorld : EcsWorld<EcsEventWorld> public sealed class EcsEventWorld : EcsWorld<EcsEventWorld>
{ {
public EcsEventWorld(EcsPipeline pipeline = null) : base(pipeline) { } public EcsEventWorld() : base(null) { }
public EcsEventWorld(EcsPipeline pipeline) : base(pipeline) { }
} }
public sealed class EcsUIWorld : EcsWorld<EcsUIWorld> public sealed class EcsUIWorld : EcsWorld<EcsUIWorld>
{ {
public EcsUIWorld(EcsPipeline pipeline = null) : base(pipeline) { } public EcsUIWorld() : base(null) { }
public EcsUIWorld(EcsPipeline pipeline) : base(pipeline) { }
} }
} }

View File

@ -6,5 +6,12 @@
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";
public const string PRE_BEGIN_SYSTEMS_BLOCK = nameof(PRE_BEGIN_SYSTEMS_BLOCK);
public const string BEGIN_SYSTEMS_BLOCK = nameof(BEGIN_SYSTEMS_BLOCK);
public const string BASIC_SYSTEMS_BLOCK = nameof(BASIC_SYSTEMS_BLOCK);
public const string END_SYSTEMS_BLOCK = nameof(END_SYSTEMS_BLOCK);
public const string POST_END_SYSTEMS_BLOCK = nameof(POST_END_SYSTEMS_BLOCK);
} }
} }

View File

@ -463,6 +463,8 @@ namespace DCFApixels.DragonECS
public bool Equals(EcsReadonlyGroup other) => Equals(other.GetGroupInternal()); public bool Equals(EcsReadonlyGroup other) => Equals(other.GetGroupInternal());
public bool Equals(EcsGroup other) public bool Equals(EcsGroup other)
{ {
if (ReferenceEquals(other, null))
return false;
if (other.Count != Count) if (other.Count != Count)
return false; return false;
foreach (var item in other) foreach (var item in other)
@ -480,10 +482,17 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region operators #region operators
public static bool operator ==(EcsGroup a, EcsGroup b) => a.Equals(b); private static bool StaticEquals(EcsGroup a, EcsReadonlyGroup b) => StaticEquals(a, b.GetGroupInternal());
public static bool operator ==(EcsGroup a, EcsReadonlyGroup b) => a.Equals(b); private static bool StaticEquals(EcsGroup a, EcsGroup b)
public static bool operator !=(EcsGroup a, EcsGroup b) => !a.Equals(b); {
public static bool operator !=(EcsGroup a, EcsReadonlyGroup b) => !a.Equals(b); if (ReferenceEquals(a, null))
return false;
return a.Equals(b);
}
public static bool operator ==(EcsGroup a, EcsGroup b) => StaticEquals(a, b);
public static bool operator ==(EcsGroup a, EcsReadonlyGroup b) => StaticEquals(a, b);
public static bool operator !=(EcsGroup a, EcsGroup b) => !StaticEquals(a, b);
public static bool operator !=(EcsGroup a, EcsReadonlyGroup b) => !StaticEquals(a, b);
#endregion #endregion
#region OnWorldResize #region OnWorldResize

View File

@ -174,6 +174,10 @@ namespace DCFApixels.DragonECS
} }
} }
//TODO
// реализовать возможность получить список всех связей между двумя сущьностями одной напрваленности, и сделать метод для получения одной такой связи
//
public void Join(WhereResult firstWorldWhereQuery, WhereResult secondWorldWhereQuery) public void Join(WhereResult firstWorldWhereQuery, WhereResult secondWorldWhereQuery)
{ {
_executeJoin.Begin(); _executeJoin.Begin();

View File

@ -157,17 +157,20 @@ namespace DCFApixels.DragonECS
private HashSet<Type> _uniqueTypes; private HashSet<Type> _uniqueTypes;
private readonly List<object> _blockExecutionOrder; private readonly List<object> _blockExecutionOrder;
private readonly Dictionary<object, List<IEcsSystem>> _systems; private readonly Dictionary<object, List<IEcsSystem>> _systems;
private readonly object _basicBlocKey; private readonly string _basicBlocKey;
private bool _isBasicBlockDeclared; private bool _isBasicBlockDeclared;
private bool _isOnlyBasicBlock; private bool _isOnlyBasicBlock;
public Builder() public Builder()
{ {
_basicBlocKey = "Basic"; _basicBlocKey = EcsConsts.BASIC_SYSTEMS_BLOCK;
_uniqueTypes = new HashSet<Type>(); _uniqueTypes = new HashSet<Type>();
_blockExecutionOrder = new List<object>(KEYS_CAPACITY); _blockExecutionOrder = new List<object>(KEYS_CAPACITY);
_systems = new Dictionary<object, List<IEcsSystem>>(KEYS_CAPACITY); _systems = new Dictionary<object, List<IEcsSystem>>(KEYS_CAPACITY);
_isBasicBlockDeclared = false; _isBasicBlockDeclared = false;
_isOnlyBasicBlock = true; _isOnlyBasicBlock = true;
SystemsBlock(EcsConsts.PRE_BEGIN_SYSTEMS_BLOCK);
SystemsBlock(EcsConsts.BEGIN_SYSTEMS_BLOCK);
} }
public Builder Add(IEcsSystem system, object blockKey = null) public Builder Add(IEcsSystem system, object blockKey = null)
@ -196,7 +199,7 @@ namespace DCFApixels.DragonECS
list.Add(system); list.Add(system);
} }
public Builder Add(IEcsModule module) public Builder AddModule(IEcsModule module)
{ {
module.ImportSystems(this); module.ImportSystems(this);
return this; return this;
@ -208,15 +211,29 @@ namespace DCFApixels.DragonECS
_blockExecutionOrder.Add(_basicBlocKey); _blockExecutionOrder.Add(_basicBlocKey);
return this; return this;
} }
public Builder SystemsBlock(object blockKey) public Builder SystemsBlock(string blockKey)
{ {
if (blockKey == null) if (blockKey == null || blockKey == _basicBlocKey)
return BasicSystemsBlock(); return BasicSystemsBlock();
_isOnlyBasicBlock = false; _isOnlyBasicBlock = false;
_blockExecutionOrder.Add(blockKey); _blockExecutionOrder.Add(blockKey);
return this; return this;
} }
public Builder InsertSystemsBlock(string blockKey, string beforeBlockKey)
{
if (blockKey == null || blockKey == _basicBlocKey)
{
_isBasicBlockDeclared = true;
blockKey = _basicBlocKey;
}
_isOnlyBasicBlock = false;
int index = _blockExecutionOrder.IndexOf(beforeBlockKey);
index = index < 0 ? _blockExecutionOrder.Count - 1 : index;
_blockExecutionOrder.Insert(index, blockKey);
return this;
}
public EcsPipeline Build() public EcsPipeline Build()
{ {
@ -226,7 +243,10 @@ namespace DCFApixels.DragonECS
} }
if(_isBasicBlockDeclared == false) if(_isBasicBlockDeclared == false)
_blockExecutionOrder.Insert(0, _basicBlocKey); _blockExecutionOrder.Insert(_blockExecutionOrder.IndexOf(EcsConsts.BEGIN_SYSTEMS_BLOCK) + 1, _basicBlocKey);//вставить после BEGIN_SYSTEMS_BLOCK
SystemsBlock(EcsConsts.END_SYSTEMS_BLOCK);
SystemsBlock(EcsConsts.POST_END_SYSTEMS_BLOCK);
Add(new DeleteEmptyEntitesSsytem(), EcsConsts.POST_END_SYSTEMS_BLOCK);
List<IEcsSystem> result = new List<IEcsSystem>(32); List<IEcsSystem> result = new List<IEcsSystem>(32);
@ -255,12 +275,16 @@ namespace DCFApixels.DragonECS
public interface IEcsModule public interface IEcsModule
{ {
public void ImportSystems(EcsPipeline.Builder builder); public void ImportSystems(EcsPipeline.Builder b);
} }
#region Extensions #region Extensions
public static class EcsSystemsExtensions public static class EcsPipelineExtensions
{ {
public static void GetRunner<T>(this EcsPipeline self, out T runner) where T : IEcsSystem
{
runner = self.GetRunner<T>();
}
public static bool IsNullOrDestroyed(this EcsPipeline self) public static bool IsNullOrDestroyed(this EcsPipeline self)
{ {
return self == null || self.IsDestoryed; return self == null || self.IsDestoryed;

View File

@ -21,7 +21,7 @@ namespace DCFApixels.DragonECS
private int _entitiesCount; private int _entitiesCount;
private int _entitesCapacity; private int _entitesCapacity;
private short[] _gens; //старший бит указывает на то жива ли сущьность. private short[] _gens; //старший бит указывает на то жива ли сущьность.
//private short[] _componentCounts; //TODO private short[] _componentCounts;
private EcsGroup _allEntites; private EcsGroup _allEntites;
//буфер удаления откладывает освобождение андишников сущьностей. //буфер удаления откладывает освобождение андишников сущьностей.
@ -73,6 +73,8 @@ namespace DCFApixels.DragonECS
ArrayUtility.Fill(pools, _nullPool); ArrayUtility.Fill(pools, _nullPool);
_gens = new short[_entitesCapacity]; _gens = new short[_entitesCapacity];
_componentCounts = new short[_entitesCapacity];
ArrayUtility.Fill(_gens, DEATH_GEN_BIT); ArrayUtility.Fill(_gens, DEATH_GEN_BIT);
_delEntBufferCount = 0; _delEntBufferCount = 0;
_delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET]; _delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET];
@ -127,6 +129,7 @@ namespace DCFApixels.DragonECS
{ {
var pool = new TPool(); var pool = new TPool();
pools[uniqueID] = pool; pools[uniqueID] = pool;
pool.PreInitInternal(this, uniqueID);
pool.InvokeInit(this); pool.InvokeInit(this);
//EcsDebug.Print(pool.GetType().FullName); //EcsDebug.Print(pool.GetType().FullName);
@ -200,6 +203,7 @@ namespace DCFApixels.DragonECS
if (_gens.Length <= entityID) if (_gens.Length <= entityID)
{ {
Array.Resize(ref _gens, _gens.Length << 1); Array.Resize(ref _gens, _gens.Length << 1);
Array.Resize(ref _componentCounts, _gens.Length);
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity); ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity);
_entitesCapacity = _gens.Length; _entitesCapacity = _gens.Length;
@ -225,13 +229,14 @@ namespace DCFApixels.DragonECS
_allEntites.Add(entityID); _allEntites.Add(entityID);
return entity; return entity;
} }
public void DelEntity(EcsEntity entity)
public void DelEntity(int entityID)
{ {
_allEntites.Remove(entity.id); _allEntites.Remove(entityID);
_delEntBuffer[_delEntBufferCount++] = entity.id; _delEntBuffer[_delEntBufferCount++] = entityID;
_gens[entity.id] |= DEATH_GEN_BIT; _gens[entityID] |= DEATH_GEN_BIT;
_entitiesCount--; _entitiesCount--;
_entityDestry.OnEntityDestroy(entity); _entityDestry.OnEntityDestroy(entityID);
if (_delEntBufferCount >= _delEntBuffer.Length) if (_delEntBufferCount >= _delEntBuffer.Length)
ReleaseDelEntityBuffer(); ReleaseDelEntityBuffer();
@ -248,6 +253,35 @@ namespace DCFApixels.DragonECS
_entityDispenser.Release(_delEntBuffer[i]); _entityDispenser.Release(_delEntBuffer[i]);
_delEntBufferCount = 0; _delEntBufferCount = 0;
} }
public short GetGen(int entityID) => _gens[entityID];
public short GetComponentCount(int entityID) => _componentCounts[entityID];
public void DeleteEmptyEntites()
{
foreach (var e in _allEntites)
{
if (_componentCounts[e] <= 0)
DelEntity(e);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void IncrementEntityComponentCount(int entityID)
{
_componentCounts[entityID]++;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void DecrementEntityComponentCount(int entityID)
{
var count = --_componentCounts[entityID];
if(count == 0)
DelEntity(entityID);
#if (DEBUG && !DISABLE_DRAGONECS_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (count < 0) throw new EcsFrameworkException("нарушен баланс инкремента.декремента компонентов");
#endif
}
#endregion #endregion
#region Groups #region Groups

View File

@ -93,6 +93,8 @@ namespace DCFApixels.DragonECS
return this != NULL; return this != NULL;
} }
} }
public EcsWorld GetWorld() => EcsWorld.Worlds[world];
} }
public static partial class entExtensions public static partial class entExtensions

View File

@ -4,11 +4,10 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
//не влияет на счетчик компонентов на сущности
public sealed class EcsAttachPool<T> : EcsPoolBase<T> public sealed class EcsAttachPool<T> : EcsPoolBase<T>
where T : struct, IEcsAttachComponent where T : struct, IEcsAttachComponent
{ {
private EcsWorld _source;
private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID
private T[] _items; //sparse private T[] _items; //sparse
private int _count; private int _count;
@ -31,13 +30,11 @@ namespace DCFApixels.DragonECS
#region Properites #region Properites
public int Count => _count; public int Count => _count;
public int Capacity => _items.Length; public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
_source = world;
_poolRunners = new PoolRunners(world.Pipeline); _poolRunners = new PoolRunners(world.Pipeline);
_entities = EcsGroup.New(world); _entities = EcsGroup.New(world);

View File

@ -4,11 +4,10 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
//не влияет на счетчик компонентов на сущности
public sealed class EcsNotNullPool<T> : EcsPoolBase<T> public sealed class EcsNotNullPool<T> : EcsPoolBase<T>
where T : struct, INotNullComponent where T : struct, INotNullComponent
{ {
private EcsWorld _source;
private T[] _items; //sparse private T[] _items; //sparse
private int _count; private int _count;
@ -18,14 +17,11 @@ namespace DCFApixels.DragonECS
#region Properites #region Properites
public int Count => _count; public int Count => _count;
public int Capacity => _items.Length; public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
_source = world;
_items = new T[world.Capacity]; _items = new T[world.Capacity];
_count = 0; _count = 0;

View File

@ -6,66 +6,11 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public abstract class EcsPoolBase
{
#region Properties
public abstract Type ComponentType { get; }
public abstract EcsWorld World { get; }
#endregion
#region Methods
public abstract bool Has(int entityID);
protected abstract void Init(EcsWorld world);
protected abstract void OnWorldResize(int newSize);
protected abstract void OnDestroy();
#endregion
#region Internal
internal void InvokeInit(EcsWorld world) => Init(world);
internal void InvokeOnWorldResize(int newSize) => OnWorldResize(newSize);
internal void InvokeOnDestroy() => OnDestroy();
#endregion
}
public abstract class EcsPoolBase<T> : EcsPoolBase, IEnumerable<T>
{
public sealed override Type ComponentType => typeof(T);
//Ðåëàçèàöèÿ èíòåðôåéñà IEnumerator íå ðàáîòàåò, íóæíî òîëüêî ÷òîáû IntelliSense ïðåäëàãàëà íàçâàíèÿ íà îñíîâå T. Íå íàøåë äðóãîãî ñïîñîáà
#region IEnumerable
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
#endregion
}
public struct NullComponent { }
public sealed class EcsNullPool : EcsPoolBase
{
public static EcsNullPool instance => new EcsNullPool(null);
private EcsWorld _source;
private EcsNullPool(EcsWorld source) => _source = source;
#region Properties
public sealed override Type ComponentType => typeof(NullComponent);
public sealed override EcsWorld World => _source;
#endregion
#region Methods
public sealed override bool Has(int index) => false;
#endregion
#region Callbacks
protected override void Init(EcsWorld world) { }
protected override void OnWorldResize(int newSize) { }
protected override void OnDestroy() { }
#endregion
}
public sealed class EcsPool<T> : EcsPoolBase<T> public sealed class EcsPool<T> : EcsPoolBase<T>
where T : struct, IEcsComponent where T : struct, IEcsComponent
{ {
public static string name = typeof(T).Name; public static string name = typeof(T).Name;
private EcsWorld _source;
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
private T[] _items; //dense private T[] _items; //dense
private int _itemsCount; private int _itemsCount;
@ -78,14 +23,12 @@ namespace DCFApixels.DragonECS
#region Properites #region Properites
public int Count => _itemsCount; public int Count => _itemsCount;
public int Capacity => _items.Length; public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
const int capacity = 512; const int capacity = 512;
_source = world;
_mapping = new int[world.Capacity]; _mapping = new int[world.Capacity];
_recycledItems = new int[128]; _recycledItems = new int[128];
@ -124,6 +67,7 @@ namespace DCFApixels.DragonECS
} }
//_mapping[entityID] = itemIndex; TODO ïðîâåðèòü ÷òî ýòî ëèøíåå äåéñâèå //_mapping[entityID] = itemIndex; TODO ïðîâåðèòü ÷òî ýòî ëèøíåå äåéñâèå
IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _poolRunners.add.OnComponentAdd<T>(entityID);
} }
_poolRunners.write.OnComponentWrite<T>(entityID); _poolRunners.write.OnComponentWrite<T>(entityID);
@ -153,6 +97,7 @@ namespace DCFApixels.DragonECS
{ {
// using (_delMark.Auto()) // using (_delMark.Auto())
// { // {
ref int itemIndex = ref _mapping[entityID]; ref int itemIndex = ref _mapping[entityID];
_componentResetHandler.Reset(ref _items[itemIndex]); _componentResetHandler.Reset(ref _items[itemIndex]);
if (_recycledItemsCount >= _recycledItems.Length) if (_recycledItemsCount >= _recycledItems.Length)
@ -160,6 +105,7 @@ namespace DCFApixels.DragonECS
_recycledItems[_recycledItemsCount++] = itemIndex; _recycledItems[_recycledItemsCount++] = itemIndex;
itemIndex = 0; itemIndex = 0;
_itemsCount--; _itemsCount--;
DecrementEntityComponentCount(entityID);
_poolRunners.del.OnComponentDel<T>(entityID); _poolRunners.del.OnComponentDel<T>(entityID);
// } // }
} }

77
src/Pools/EcsPoolBase.cs Normal file
View File

@ -0,0 +1,77 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public abstract class EcsPoolBase
{
private int _id = -1;
private EcsWorld _world;
internal void PreInitInternal(EcsWorld world, int id)
{
_id = id;
_world = world;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected void IncrementEntityComponentCount(int entityID)
{
_world.IncrementEntityComponentCount(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected void DecrementEntityComponentCount(int entityID)
{
_world.DecrementEntityComponentCount(entityID);
}
#region Properties
public abstract Type ComponentType { get; }
public EcsWorld World => _world;
#endregion
#region Methods
public abstract bool Has(int entityID);
protected abstract void Init(EcsWorld world);
protected abstract void OnWorldResize(int newSize);
protected abstract void OnDestroy();
#endregion
#region Internal
internal void InvokeInit(EcsWorld world) => Init(world);
internal void InvokeOnWorldResize(int newSize) => OnWorldResize(newSize);
internal void InvokeOnDestroy() => OnDestroy();
#endregion
}
public abstract class EcsPoolBase<T> : EcsPoolBase, IEnumerable<T>
{
public sealed override Type ComponentType => typeof(T);
//Релазиация интерфейса IEnumerator не работает, нужно только чтобы IntelliSense предлагала названия на основе T. Не нашел другого способа
#region IEnumerable
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
#endregion
}
public struct NullComponent { }
public sealed class EcsNullPool : EcsPoolBase
{
public static EcsNullPool instance => new EcsNullPool();
#region Properties
public sealed override Type ComponentType => typeof(NullComponent);
#endregion
#region Methods
public sealed override bool Has(int index) => false;
#endregion
#region Callbacks
protected override void Init(EcsWorld world) { }
protected override void OnWorldResize(int newSize) { }
protected override void OnDestroy() { }
#endregion
}
}

View File

@ -11,8 +11,6 @@ namespace DCFApixels.DragonECS
{ {
public static string name = typeof(T).Name; public static string name = typeof(T).Name;
private EcsWorld _source;
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
private T[] _items; //dense private T[] _items; //dense
private int _itemsCount; private int _itemsCount;
@ -25,14 +23,12 @@ namespace DCFApixels.DragonECS
#region Properites #region Properites
public int Count => _itemsCount; public int Count => _itemsCount;
public int Capacity => _items.Length; public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
const int capacity = 512; const int capacity = 512;
_source = world;
_mapping = new int[world.Capacity]; _mapping = new int[world.Capacity];
_recycledItems = new int[128]; _recycledItems = new int[128];

View File

@ -4,11 +4,10 @@ using Unity.Profiling;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
//не влияет на счетчик компонентов на сущности
public sealed class EcsRelationPool<T> : EcsPoolBase<T> public sealed class EcsRelationPool<T> : EcsPoolBase<T>
where T : struct, IEcsRelationComponent where T : struct, IEcsRelationComponent
{ {
private EcsWorld _source;
private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID
private T[] _items; //sparse private T[] _items; //sparse
private int _count; private int _count;
@ -25,13 +24,11 @@ namespace DCFApixels.DragonECS
#region Properites #region Properites
public int Count => _count; public int Count => _count;
public int Capacity => _items.Length; public int Capacity => _items.Length;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
_source = world;
_poolRunners = new PoolRunners(world.Pipeline); _poolRunners = new PoolRunners(world.Pipeline);
_entityFlags = new bool[world.Capacity]; _entityFlags = new bool[world.Capacity];

View File

@ -7,13 +7,7 @@ namespace DCFApixels.DragonECS
public sealed class EcsSinglePool<T> : EcsPoolBase<T> public sealed class EcsSinglePool<T> : EcsPoolBase<T>
where T : struct, IEcsSingleComponent where T : struct, IEcsSingleComponent
{ {
private EcsWorld _source; private int[] _mapping;
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
//private T[] _items; //dense
//private int _count;
//private int[] _recycledItems;
//private int _recycledItemsCount;
private int _count; private int _count;
private T _component; private T _component;
@ -27,13 +21,11 @@ namespace DCFApixels.DragonECS
get => ref _component; get => ref _component;
} }
public int Count => _count; public int Count => _count;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
_source = world;
_mapping = new int[world.Capacity]; _mapping = new int[world.Capacity];
_count = 0; _count = 0;
_poolRunners = new PoolRunners(world.Pipeline); _poolRunners = new PoolRunners(world.Pipeline);
@ -53,6 +45,7 @@ namespace DCFApixels.DragonECS
if (_mapping[entityID] <= 0) if (_mapping[entityID] <= 0)
{ {
_mapping[entityID] = ++_count; _mapping[entityID] = ++_count;
IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _poolRunners.add.OnComponentAdd<T>(entityID);
} }
return ref _component; return ref _component;
@ -84,6 +77,7 @@ namespace DCFApixels.DragonECS
// { // {
_mapping[entityID] = 0; _mapping[entityID] = 0;
_count--; _count--;
DecrementEntityComponentCount(entityID);
_poolRunners.del.OnComponentDel<T>(entityID); _poolRunners.del.OnComponentDel<T>(entityID);
// } // }
} }

View File

@ -7,8 +7,6 @@ namespace DCFApixels.DragonECS
public sealed class EcsTagPool<T> : EcsPoolBase<T> public sealed class EcsTagPool<T> : EcsPoolBase<T>
where T : struct, IEcsTagComponent where T : struct, IEcsTagComponent
{ {
private EcsWorld _source;
private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
private int _count; private int _count;
@ -16,14 +14,11 @@ namespace DCFApixels.DragonECS
#region Properites #region Properites
public int Count => _count; public int Count => _count;
public sealed override EcsWorld World => _source;
#endregion #endregion
#region Init #region Init
protected override void Init(EcsWorld world) protected override void Init(EcsWorld world)
{ {
_source = world;
_mapping = new bool[world.Capacity]; _mapping = new bool[world.Capacity];
_count = 0; _count = 0;
@ -43,6 +38,7 @@ namespace DCFApixels.DragonECS
{ {
_count++; _count++;
_mapping[entityID] = true; _mapping[entityID] = true;
IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _poolRunners.add.OnComponentAdd<T>(entityID);
} }
// } // }
@ -59,6 +55,7 @@ namespace DCFApixels.DragonECS
// { // {
_mapping[entityID] = false; _mapping[entityID] = false;
_count--; _count--;
DecrementEntityComponentCount(entityID);
_poolRunners.del.OnComponentDel<T>(entityID); _poolRunners.del.OnComponentDel<T>(entityID);
// } // }
} }