mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 18:14:37 +08:00
update/add component count/auto delete empty entity
This commit is contained in:
parent
7ef7fb0d14
commit
d5e1700029
@ -138,38 +138,35 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
public static EcsPipeline.Builder Inject<T>(this EcsPipeline.Builder self, T data)
|
||||
{
|
||||
self.Add(new InjectSystem<T>(data));
|
||||
return self;
|
||||
return self.Add(new InjectSystem<T>(data));
|
||||
}
|
||||
public static EcsPipeline.Builder Inject<A, B>(this EcsPipeline.Builder self, A a, B b)
|
||||
{
|
||||
self.Inject(a).Inject(b);
|
||||
return self;
|
||||
return self.Inject(a).Inject(b);
|
||||
}
|
||||
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)
|
||||
{
|
||||
self.Inject(a).Inject(b).Inject(c).Inject(d);
|
||||
return self;
|
||||
return self.Inject(a).Inject(b).Inject(c).Inject(d);
|
||||
}
|
||||
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;
|
||||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e);
|
||||
}
|
||||
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;
|
||||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f);
|
||||
}
|
||||
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;
|
||||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g);
|
||||
}
|
||||
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;
|
||||
return self.Inject(a).Inject(b).Inject(c).Inject(d).Inject(e).Inject(f).Inject(g).Inject(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace DCFApixels.DragonECS
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
[DebugColor(DebugColor.Black)]
|
||||
public class SystemsBlockMarkerSystem : IEcsSystem
|
||||
@ -10,4 +12,60 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public interface IEcsEntityDestroy : IEcsSystem
|
||||
{
|
||||
public void OnEntityDestroy(EcsEntity entity);
|
||||
public void OnEntityDestroy(int entityID);
|
||||
}
|
||||
public interface IEcsEntityLifecycle : IEcsEntityCreate, IEcsEntityDestroy { }
|
||||
|
||||
@ -67,9 +67,9 @@ namespace DCFApixels.DragonECS
|
||||
[DebugColor(DebugColor.Orange)]
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,14 +9,17 @@
|
||||
|
||||
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 EcsEventWorld(EcsPipeline pipeline = null) : base(pipeline) { }
|
||||
public EcsEventWorld() : base(null) { }
|
||||
public EcsEventWorld(EcsPipeline pipeline) : base(pipeline) { }
|
||||
}
|
||||
public sealed class EcsUIWorld : EcsWorld<EcsUIWorld>
|
||||
{
|
||||
public EcsUIWorld(EcsPipeline pipeline = null) : base(pipeline) { }
|
||||
public EcsUIWorld() : base(null) { }
|
||||
public EcsUIWorld(EcsPipeline pipeline) : base(pipeline) { }
|
||||
}
|
||||
}
|
||||
|
@ -6,5 +6,12 @@
|
||||
public const string DEBUG_PREFIX = "[DEBUG] ";
|
||||
public const string DEBUG_WARNING_TAG = "WARNING";
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -463,6 +463,8 @@ namespace DCFApixels.DragonECS
|
||||
public bool Equals(EcsReadonlyGroup other) => Equals(other.GetGroupInternal());
|
||||
public bool Equals(EcsGroup other)
|
||||
{
|
||||
if (ReferenceEquals(other, null))
|
||||
return false;
|
||||
if (other.Count != Count)
|
||||
return false;
|
||||
foreach (var item in other)
|
||||
@ -480,10 +482,17 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region operators
|
||||
public static bool operator ==(EcsGroup a, EcsGroup b) => a.Equals(b);
|
||||
public static bool operator ==(EcsGroup a, EcsReadonlyGroup b) => a.Equals(b);
|
||||
public static bool operator !=(EcsGroup a, EcsGroup b) => !a.Equals(b);
|
||||
public static bool operator !=(EcsGroup a, EcsReadonlyGroup b) => !a.Equals(b);
|
||||
private static bool StaticEquals(EcsGroup a, EcsReadonlyGroup b) => StaticEquals(a, b.GetGroupInternal());
|
||||
private static bool StaticEquals(EcsGroup a, EcsGroup 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
|
||||
|
||||
#region OnWorldResize
|
||||
|
@ -174,6 +174,10 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
|
||||
//TODO
|
||||
// реализовать возможность получить список всех связей между двумя сущьностями одной напрваленности, и сделать метод для получения одной такой связи
|
||||
//
|
||||
|
||||
public void Join(WhereResult firstWorldWhereQuery, WhereResult secondWorldWhereQuery)
|
||||
{
|
||||
_executeJoin.Begin();
|
||||
|
@ -157,17 +157,20 @@ namespace DCFApixels.DragonECS
|
||||
private HashSet<Type> _uniqueTypes;
|
||||
private readonly List<object> _blockExecutionOrder;
|
||||
private readonly Dictionary<object, List<IEcsSystem>> _systems;
|
||||
private readonly object _basicBlocKey;
|
||||
private readonly string _basicBlocKey;
|
||||
private bool _isBasicBlockDeclared;
|
||||
private bool _isOnlyBasicBlock;
|
||||
public Builder()
|
||||
{
|
||||
_basicBlocKey = "Basic";
|
||||
_basicBlocKey = EcsConsts.BASIC_SYSTEMS_BLOCK;
|
||||
_uniqueTypes = new HashSet<Type>();
|
||||
_blockExecutionOrder = new List<object>(KEYS_CAPACITY);
|
||||
_systems = new Dictionary<object, List<IEcsSystem>>(KEYS_CAPACITY);
|
||||
_isBasicBlockDeclared = false;
|
||||
_isOnlyBasicBlock = true;
|
||||
|
||||
SystemsBlock(EcsConsts.PRE_BEGIN_SYSTEMS_BLOCK);
|
||||
SystemsBlock(EcsConsts.BEGIN_SYSTEMS_BLOCK);
|
||||
}
|
||||
|
||||
public Builder Add(IEcsSystem system, object blockKey = null)
|
||||
@ -196,7 +199,7 @@ namespace DCFApixels.DragonECS
|
||||
list.Add(system);
|
||||
}
|
||||
|
||||
public Builder Add(IEcsModule module)
|
||||
public Builder AddModule(IEcsModule module)
|
||||
{
|
||||
module.ImportSystems(this);
|
||||
return this;
|
||||
@ -208,15 +211,29 @@ namespace DCFApixels.DragonECS
|
||||
_blockExecutionOrder.Add(_basicBlocKey);
|
||||
return this;
|
||||
}
|
||||
public Builder SystemsBlock(object blockKey)
|
||||
public Builder SystemsBlock(string blockKey)
|
||||
{
|
||||
if (blockKey == null)
|
||||
if (blockKey == null || blockKey == _basicBlocKey)
|
||||
return BasicSystemsBlock();
|
||||
|
||||
_isOnlyBasicBlock = false;
|
||||
_blockExecutionOrder.Add(blockKey);
|
||||
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()
|
||||
{
|
||||
@ -226,7 +243,10 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -255,12 +275,16 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public interface IEcsModule
|
||||
{
|
||||
public void ImportSystems(EcsPipeline.Builder builder);
|
||||
public void ImportSystems(EcsPipeline.Builder b);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
return self == null || self.IsDestoryed;
|
||||
|
@ -21,7 +21,7 @@ namespace DCFApixels.DragonECS
|
||||
private int _entitiesCount;
|
||||
private int _entitesCapacity;
|
||||
private short[] _gens; //старший бит указывает на то жива ли сущьность.
|
||||
//private short[] _componentCounts; //TODO
|
||||
private short[] _componentCounts;
|
||||
private EcsGroup _allEntites;
|
||||
|
||||
//буфер удаления откладывает освобождение андишников сущьностей.
|
||||
@ -73,6 +73,8 @@ namespace DCFApixels.DragonECS
|
||||
ArrayUtility.Fill(pools, _nullPool);
|
||||
|
||||
_gens = new short[_entitesCapacity];
|
||||
_componentCounts = new short[_entitesCapacity];
|
||||
|
||||
ArrayUtility.Fill(_gens, DEATH_GEN_BIT);
|
||||
_delEntBufferCount = 0;
|
||||
_delEntBuffer = new int[_entitesCapacity >> DEL_ENT_BUFFER_SIZE_OFFSET];
|
||||
@ -127,6 +129,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
var pool = new TPool();
|
||||
pools[uniqueID] = pool;
|
||||
pool.PreInitInternal(this, uniqueID);
|
||||
pool.InvokeInit(this);
|
||||
|
||||
//EcsDebug.Print(pool.GetType().FullName);
|
||||
@ -200,6 +203,7 @@ namespace DCFApixels.DragonECS
|
||||
if (_gens.Length <= entityID)
|
||||
{
|
||||
Array.Resize(ref _gens, _gens.Length << 1);
|
||||
Array.Resize(ref _componentCounts, _gens.Length);
|
||||
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitesCapacity);
|
||||
_entitesCapacity = _gens.Length;
|
||||
|
||||
@ -225,13 +229,14 @@ namespace DCFApixels.DragonECS
|
||||
_allEntites.Add(entityID);
|
||||
return entity;
|
||||
}
|
||||
public void DelEntity(EcsEntity entity)
|
||||
|
||||
public void DelEntity(int entityID)
|
||||
{
|
||||
_allEntites.Remove(entity.id);
|
||||
_delEntBuffer[_delEntBufferCount++] = entity.id;
|
||||
_gens[entity.id] |= DEATH_GEN_BIT;
|
||||
_allEntites.Remove(entityID);
|
||||
_delEntBuffer[_delEntBufferCount++] = entityID;
|
||||
_gens[entityID] |= DEATH_GEN_BIT;
|
||||
_entitiesCount--;
|
||||
_entityDestry.OnEntityDestroy(entity);
|
||||
_entityDestry.OnEntityDestroy(entityID);
|
||||
|
||||
if (_delEntBufferCount >= _delEntBuffer.Length)
|
||||
ReleaseDelEntityBuffer();
|
||||
@ -248,6 +253,35 @@ namespace DCFApixels.DragonECS
|
||||
_entityDispenser.Release(_delEntBuffer[i]);
|
||||
_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
|
||||
|
||||
#region Groups
|
||||
|
@ -93,6 +93,8 @@ namespace DCFApixels.DragonECS
|
||||
return this != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public EcsWorld GetWorld() => EcsWorld.Worlds[world];
|
||||
}
|
||||
|
||||
public static partial class entExtensions
|
||||
|
@ -4,11 +4,10 @@ using Unity.Profiling;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
//не влияет на счетчик компонентов на сущности
|
||||
public sealed class EcsAttachPool<T> : EcsPoolBase<T>
|
||||
where T : struct, IEcsAttachComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
|
||||
private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID
|
||||
private T[] _items; //sparse
|
||||
private int _count;
|
||||
@ -31,13 +30,11 @@ namespace DCFApixels.DragonECS
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
public int Capacity => _items.Length;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
_source = world;
|
||||
_poolRunners = new PoolRunners(world.Pipeline);
|
||||
|
||||
_entities = EcsGroup.New(world);
|
||||
|
@ -4,11 +4,10 @@ using Unity.Profiling;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
//не влияет на счетчик компонентов на сущности
|
||||
public sealed class EcsNotNullPool<T> : EcsPoolBase<T>
|
||||
where T : struct, INotNullComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
|
||||
private T[] _items; //sparse
|
||||
private int _count;
|
||||
|
||||
@ -18,14 +17,11 @@ namespace DCFApixels.DragonECS
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
public int Capacity => _items.Length;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
_source = world;
|
||||
|
||||
_items = new T[world.Capacity];
|
||||
_count = 0;
|
||||
|
||||
|
@ -6,66 +6,11 @@ using Unity.Profiling;
|
||||
|
||||
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>
|
||||
where T : struct, IEcsComponent
|
||||
{
|
||||
public static string name = typeof(T).Name;
|
||||
|
||||
private EcsWorld _source;
|
||||
|
||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
private T[] _items; //dense
|
||||
private int _itemsCount;
|
||||
@ -78,14 +23,12 @@ namespace DCFApixels.DragonECS
|
||||
#region Properites
|
||||
public int Count => _itemsCount;
|
||||
public int Capacity => _items.Length;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
const int capacity = 512;
|
||||
_source = world;
|
||||
|
||||
_mapping = new int[world.Capacity];
|
||||
_recycledItems = new int[128];
|
||||
@ -124,6 +67,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
|
||||
//_mapping[entityID] = itemIndex; TODO ïðîâåðèòü ÷òî ýòî ëèøíåå äåéñâèå
|
||||
IncrementEntityComponentCount(entityID);
|
||||
_poolRunners.add.OnComponentAdd<T>(entityID);
|
||||
}
|
||||
_poolRunners.write.OnComponentWrite<T>(entityID);
|
||||
@ -153,6 +97,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
// using (_delMark.Auto())
|
||||
// {
|
||||
|
||||
ref int itemIndex = ref _mapping[entityID];
|
||||
_componentResetHandler.Reset(ref _items[itemIndex]);
|
||||
if (_recycledItemsCount >= _recycledItems.Length)
|
||||
@ -160,6 +105,7 @@ namespace DCFApixels.DragonECS
|
||||
_recycledItems[_recycledItemsCount++] = itemIndex;
|
||||
itemIndex = 0;
|
||||
_itemsCount--;
|
||||
DecrementEntityComponentCount(entityID);
|
||||
_poolRunners.del.OnComponentDel<T>(entityID);
|
||||
// }
|
||||
}
|
||||
|
77
src/Pools/EcsPoolBase.cs
Normal file
77
src/Pools/EcsPoolBase.cs
Normal 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
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
public static string name = typeof(T).Name;
|
||||
|
||||
private EcsWorld _source;
|
||||
|
||||
private int[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
private T[] _items; //dense
|
||||
private int _itemsCount;
|
||||
@ -25,14 +23,12 @@ namespace DCFApixels.DragonECS
|
||||
#region Properites
|
||||
public int Count => _itemsCount;
|
||||
public int Capacity => _items.Length;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
const int capacity = 512;
|
||||
_source = world;
|
||||
|
||||
_mapping = new int[world.Capacity];
|
||||
_recycledItems = new int[128];
|
||||
|
@ -4,11 +4,10 @@ using Unity.Profiling;
|
||||
|
||||
namespace DCFApixels.DragonECS
|
||||
{
|
||||
//не влияет на счетчик компонентов на сущности
|
||||
public sealed class EcsRelationPool<T> : EcsPoolBase<T>
|
||||
where T : struct, IEcsRelationComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
|
||||
private bool[] _entityFlags;// index = entityID / value = entityFlag;/ value = 0 = no entityID
|
||||
private T[] _items; //sparse
|
||||
private int _count;
|
||||
@ -25,13 +24,11 @@ namespace DCFApixels.DragonECS
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
public int Capacity => _items.Length;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
_source = world;
|
||||
_poolRunners = new PoolRunners(world.Pipeline);
|
||||
|
||||
_entityFlags = new bool[world.Capacity];
|
||||
|
@ -7,13 +7,7 @@ namespace DCFApixels.DragonECS
|
||||
public sealed class EcsSinglePool<T> : EcsPoolBase<T>
|
||||
where T : struct, IEcsSingleComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
|
||||
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[] _mapping;
|
||||
|
||||
private int _count;
|
||||
private T _component;
|
||||
@ -27,13 +21,11 @@ namespace DCFApixels.DragonECS
|
||||
get => ref _component;
|
||||
}
|
||||
public int Count => _count;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
_source = world;
|
||||
_mapping = new int[world.Capacity];
|
||||
_count = 0;
|
||||
_poolRunners = new PoolRunners(world.Pipeline);
|
||||
@ -53,6 +45,7 @@ namespace DCFApixels.DragonECS
|
||||
if (_mapping[entityID] <= 0)
|
||||
{
|
||||
_mapping[entityID] = ++_count;
|
||||
IncrementEntityComponentCount(entityID);
|
||||
_poolRunners.add.OnComponentAdd<T>(entityID);
|
||||
}
|
||||
return ref _component;
|
||||
@ -84,6 +77,7 @@ namespace DCFApixels.DragonECS
|
||||
// {
|
||||
_mapping[entityID] = 0;
|
||||
_count--;
|
||||
DecrementEntityComponentCount(entityID);
|
||||
_poolRunners.del.OnComponentDel<T>(entityID);
|
||||
// }
|
||||
}
|
||||
|
@ -7,8 +7,6 @@ namespace DCFApixels.DragonECS
|
||||
public sealed class EcsTagPool<T> : EcsPoolBase<T>
|
||||
where T : struct, IEcsTagComponent
|
||||
{
|
||||
private EcsWorld _source;
|
||||
|
||||
private bool[] _mapping;// index = entityID / value = itemIndex;/ value = 0 = no entityID
|
||||
private int _count;
|
||||
|
||||
@ -16,14 +14,11 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Properites
|
||||
public int Count => _count;
|
||||
public sealed override EcsWorld World => _source;
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
protected override void Init(EcsWorld world)
|
||||
{
|
||||
_source = world;
|
||||
|
||||
_mapping = new bool[world.Capacity];
|
||||
_count = 0;
|
||||
|
||||
@ -43,6 +38,7 @@ namespace DCFApixels.DragonECS
|
||||
{
|
||||
_count++;
|
||||
_mapping[entityID] = true;
|
||||
IncrementEntityComponentCount(entityID);
|
||||
_poolRunners.add.OnComponentAdd<T>(entityID);
|
||||
}
|
||||
// }
|
||||
@ -59,6 +55,7 @@ namespace DCFApixels.DragonECS
|
||||
// {
|
||||
_mapping[entityID] = false;
|
||||
_count--;
|
||||
DecrementEntityComponentCount(entityID);
|
||||
_poolRunners.del.OnComponentDel<T>(entityID);
|
||||
// }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user