remove Pipeline from EcsWorld & add event subscription

This commit is contained in:
Mikhail 2023-05-23 15:58:31 +08:00
parent ffeddfae8a
commit 3fa030e95d
9 changed files with 215 additions and 70 deletions

View File

@ -9,7 +9,7 @@ namespace DCFApixels.DragonECS
internal sealed class EcsNullWorld : EcsWorld<EcsNullWorld> internal sealed class EcsNullWorld : EcsWorld<EcsNullWorld>
{ {
public EcsNullWorld() : base(null, false) { } public EcsNullWorld() : base(false) { }
} }
public abstract class EcsWorld public abstract class EcsWorld
@ -44,20 +44,16 @@ namespace DCFApixels.DragonECS
private EcsSubject[] _subjects; private EcsSubject[] _subjects;
private EcsQueryExecutor[] _executors; private EcsQueryExecutor[] _executors;
private EcsPipeline _pipeline;
private List<WeakReference<EcsGroup>> _groups; private List<WeakReference<EcsGroup>> _groups;
private Stack<EcsGroup> _groupsPool = new Stack<EcsGroup>(64); private Stack<EcsGroup> _groupsPool = new Stack<EcsGroup>(64);
private IEcsEntityCreate _entityCreate; private List<IEcsWorldEventListener> _listeners;
private IEcsEntityDestroy _entityDestry;
#region Properties #region Properties
public abstract Type Archetype { get; } public abstract Type Archetype { get; }
public int UniqueID => uniqueID; public int UniqueID => uniqueID;
public int Count => _entitiesCount; public int Count => _entitiesCount;
public int Capacity => _entitesCapacity; //_denseEntities.Length; public int Capacity => _entitesCapacity; //_denseEntities.Length;
public EcsPipeline Pipeline => _pipeline;
public EcsReadonlyGroup Entities => _allEntites.Readonly; public EcsReadonlyGroup Entities => _allEntites.Readonly;
public ReadOnlySpan<IEcsPoolImplementation> AllPools => pools;// new ReadOnlySpan<IEcsPoolImplementation>(pools, 0, _poolsCount); public ReadOnlySpan<IEcsPoolImplementation> AllPools => pools;// new ReadOnlySpan<IEcsPoolImplementation>(pools, 0, _poolsCount);
public int PoolsCount => _poolsCount; public int PoolsCount => _poolsCount;
@ -69,11 +65,13 @@ namespace DCFApixels.DragonECS
EcsNullWorld nullWorld = new EcsNullWorld(); EcsNullWorld nullWorld = new EcsNullWorld();
Worlds[0] = nullWorld; Worlds[0] = nullWorld;
} }
public EcsWorld(EcsPipeline pipline) : this(pipline, true) { } public EcsWorld() : this(true) { }
internal EcsWorld(EcsPipeline pipline, bool isIndexable) internal EcsWorld(bool isIndexable)
{ {
_entitesCapacity = 512; _entitesCapacity = 512;
_listeners = new List<IEcsWorldEventListener>();
if (isIndexable) if (isIndexable)
{ {
uniqueID = (short)_worldIdDispenser.GetFree(); uniqueID = (short)_worldIdDispenser.GetFree();
@ -84,8 +82,6 @@ namespace DCFApixels.DragonECS
_worldTypeID = WorldMetaStorage.GetWorldId(Archetype); _worldTypeID = WorldMetaStorage.GetWorldId(Archetype);
_pipeline = pipline ?? EcsPipeline.Empty;
if (!_pipeline.IsInit) pipline.Init();
_entityDispenser = new IntDispenser(0); _entityDispenser = new IntDispenser(0);
_nullPool = EcsNullPool.instance; _nullPool = EcsNullPool.instance;
pools = new IEcsPoolImplementation[512]; pools = new IEcsPoolImplementation[512];
@ -103,14 +99,8 @@ namespace DCFApixels.DragonECS
_subjects = new EcsSubject[128]; _subjects = new EcsSubject[128];
_executors = new EcsQueryExecutor[128]; _executors = new EcsQueryExecutor[128];
_entityCreate = _pipeline.GetRunner<IEcsEntityCreate>();
_entityDestry = _pipeline.GetRunner<IEcsEntityDestroy>();
_pipeline.GetRunner<IEcsInject<EcsWorld>>().Inject(this);
_pipeline.GetRunner<IEcsWorldCreate>().OnWorldCreate(this);
} }
public void Destroy() public void Destroy()
{ {
_entityDispenser = null; _entityDispenser = null;
@ -127,7 +117,6 @@ namespace DCFApixels.DragonECS
public void DestryWithPipeline() public void DestryWithPipeline()
{ {
Destroy(); Destroy();
_pipeline.Destroy();
} }
#endregion #endregion
@ -319,10 +308,11 @@ namespace DCFApixels.DragonECS
foreach (var item in pools) foreach (var item in pools)
item.OnWorldResize(_gens.Length); item.OnWorldResize(_gens.Length);
_listeners.InvokeOnWorldResize(_gens.Length);
} }
_gens[entityID] &= GEN_BITS; _gens[entityID] &= GEN_BITS;
_entityCreate.OnEntityCreate(entityID);
_allEntites.Add(entityID); _allEntites.Add(entityID);
_listeners.InvokeOnNewEntity(entityID);
return entityID; return entityID;
} }
public entlong NewEmptyEntityLong() public entlong NewEmptyEntityLong()
@ -337,7 +327,7 @@ namespace DCFApixels.DragonECS
_delEntBuffer[_delEntBufferCount++] = entityID; _delEntBuffer[_delEntBufferCount++] = entityID;
_gens[entityID] |= DEATH_GEN_BIT; _gens[entityID] |= DEATH_GEN_BIT;
_entitiesCount--; _entitiesCount--;
_entityDestry.OnEntityDestroy(entityID); _listeners.InvokeOnDelEntity(entityID);
if (_delEntBufferCount >= _delEntBuffer.Length) if (_delEntBufferCount >= _delEntBuffer.Length)
ReleaseDelEntityBuffer(); ReleaseDelEntityBuffer();
@ -353,6 +343,7 @@ namespace DCFApixels.DragonECS
ReadOnlySpan<int> buffser = new ReadOnlySpan<int>(_delEntBuffer, 0, _delEntBufferCount); ReadOnlySpan<int> buffser = new ReadOnlySpan<int>(_delEntBuffer, 0, _delEntBufferCount);
foreach (var pool in pools) foreach (var pool in pools)
pool.OnReleaseDelEntityBuffer(buffser); pool.OnReleaseDelEntityBuffer(buffser);
_listeners.InvokeOnReleaseDelEntityBuffer(buffser);
for (int i = 0; i < _delEntBufferCount; i++) for (int i = 0; i < _delEntBufferCount; i++)
_entityDispenser.Release(_delEntBuffer[i]); _entityDispenser.Release(_delEntBuffer[i]);
_delEntBufferCount = 0; _delEntBufferCount = 0;
@ -489,8 +480,8 @@ namespace DCFApixels.DragonECS
where TWorldArchetype : EcsWorld<TWorldArchetype> where TWorldArchetype : EcsWorld<TWorldArchetype>
{ {
public override Type Archetype => typeof(TWorldArchetype); public override Type Archetype => typeof(TWorldArchetype);
public EcsWorld(EcsPipeline pipline) : base(pipline) { } public EcsWorld() : base() { }
internal EcsWorld(EcsPipeline pipline, bool isIndexable) : base(pipline, isIndexable) { } internal EcsWorld(bool isIndexable) : base(isIndexable) { }
} }
#region Utils #region Utils
@ -621,12 +612,45 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
// #region Callbacks Interface //TODO #region Callbacks Interface //TODO
// public interface IWorldCallbacks public interface IEcsWorldEventListener
// { {
// void OnWorldResize(int newSize); void OnWorldResize(int newSize);
// void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer); void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer);
// void OnWorldDestroy(); void OnWorldDestroy();
// } void OnNewEntity(int entityID);
// #endregion void OnDelEntity(int entityID);
}
#endregion
#region Extensions
public static class WorldEventListExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnWorldResize(this List<IEcsWorldEventListener> self, int newSize)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnWorldResize(newSize);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnReleaseDelEntityBuffer(this List<IEcsWorldEventListener> self, ReadOnlySpan<int> buffer)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnReleaseDelEntityBuffer(buffer);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnWorldDestroy(this List<IEcsWorldEventListener> self)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnWorldDestroy();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnNewEntity(this List<IEcsWorldEventListener> self, int entityID)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnNewEntity(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnDelEntity(this List<IEcsWorldEventListener> self, int entityID)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnDelEntity(entityID);
}
}
#endregion
} }

View File

@ -17,7 +17,8 @@ namespace DCFApixels.DragonECS
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;
private PoolRunners _poolRunners;
private List<IEcsPoolEventListener> _listeners;
private EcsGroup _entities; private EcsGroup _entities;
public EcsReadonlyGroup Entities public EcsReadonlyGroup Entities
@ -47,7 +48,7 @@ namespace DCFApixels.DragonECS
_source = world; _source = world;
_id = componentID; _id = componentID;
_poolRunners = new PoolRunners(world.Pipeline); _listeners = new List<IEcsPoolEventListener>();
_entities = EcsGroup.New(world); _entities = EcsGroup.New(world);
@ -71,9 +72,9 @@ namespace DCFApixels.DragonECS
entityFlag = true; entityFlag = true;
_count++; _count++;
_entities.Add(entityID); _entities.Add(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); foreach (var item in _listeners) item.OnAdd(entityID);
} }
_poolRunners.write.OnComponentWrite<T>(entityID); foreach (var item in _listeners) item.OnWrite(entityID);
_items[entityID].Target = target; _items[entityID].Target = target;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -84,7 +85,7 @@ namespace DCFApixels.DragonECS
if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) ThrowWorldDifferent<T>(entityID); if (_sanitizeTargetWorld >= 0 && target.world != _sanitizeTargetWorld) ThrowWorldDifferent<T>(entityID);
_sanitizeTargetWorld = target.world; _sanitizeTargetWorld = target.world;
#endif #endif
_poolRunners.write.OnComponentWrite<T>(entityID); _listeners.InvokeOnWrite(entityID);
_items[entityID].Target = target; _items[entityID].Target = target;
} }
public void AddOrSet(int entityID, entlong target) public void AddOrSet(int entityID, entlong target)
@ -115,7 +116,7 @@ namespace DCFApixels.DragonECS
_entities.Remove(entityID); _entities.Remove(entityID);
_entityFlags[entityID] = false; _entityFlags[entityID] = false;
_count--; _count--;
_poolRunners.del.OnComponentDel<T>(entityID); _listeners.InvokeOnDel(entityID);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TryDel(int entityID) public void TryDel(int entityID)
@ -177,6 +178,19 @@ namespace DCFApixels.DragonECS
void IEcsPool.SetRaw(int entityID, object dataRaw) => ((IEcsPool<T>)this).Write(entityID) = (T)dataRaw; void IEcsPool.SetRaw(int entityID, object dataRaw) => ((IEcsPool<T>)this).Write(entityID) = (T)dataRaw;
#endregion #endregion
#region Listeners
public void AddListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Add(listener);
}
public void RemoveListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Remove(listener);
}
#endregion
#region IEnumerator - IntelliSense hack #region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

View File

@ -18,7 +18,8 @@ namespace DCFApixels.DragonECS
private IEcsComponentReset<T> _componentResetHandler; private IEcsComponentReset<T> _componentResetHandler;
private IEcsComponentCopy<T> _componentCopyHandler; private IEcsComponentCopy<T> _componentCopyHandler;
private PoolRunners _poolRunners;
private List<IEcsPoolEventListener> _listeners;
#region Properites #region Properites
public int Count => _count; public int Count => _count;
@ -37,9 +38,10 @@ namespace DCFApixels.DragonECS
_items = new T[world.Capacity]; _items = new T[world.Capacity];
_count = 0; _count = 0;
_listeners = new List<IEcsPoolEventListener>();
_componentResetHandler = EcsComponentResetHandler<T>.instance; _componentResetHandler = EcsComponentResetHandler<T>.instance;
_componentCopyHandler = EcsComponentCopyHandler<T>.instance; _componentCopyHandler = EcsComponentCopyHandler<T>.instance;
_poolRunners = new PoolRunners(world.Pipeline);
} }
#endregion #endregion
@ -47,7 +49,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T Write(int entityID) public ref T Write(int entityID)
{ {
_poolRunners.write.OnComponentWrite<T>(entityID); _listeners.InvokeOnWrite(entityID);
return ref _items[entityID]; return ref _items[entityID];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -93,6 +95,19 @@ namespace DCFApixels.DragonECS
void IEcsPool.SetRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw; void IEcsPool.SetRaw(int entityID, object dataRaw) => Write(entityID) = (T)dataRaw;
#endregion #endregion
#region Listeners
public void AddListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Add(listener);
}
public void RemoveListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Remove(listener);
}
#endregion
#region IEnumerator - IntelliSense hack #region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

View File

@ -21,7 +21,8 @@ namespace DCFApixels.DragonECS
private IEcsComponentReset<T> _componentResetHandler; private IEcsComponentReset<T> _componentResetHandler;
private IEcsComponentCopy<T> _componentCopyHandler; private IEcsComponentCopy<T> _componentCopyHandler;
private PoolRunners _poolRunners;
private List<IEcsPoolEventListener> _listeners;
#region Properites #region Properites
public int Count => _itemsCount; public int Count => _itemsCount;
@ -45,9 +46,10 @@ namespace DCFApixels.DragonECS
_items = new T[capacity]; _items = new T[capacity];
_itemsCount = 0; _itemsCount = 0;
_listeners = new List<IEcsPoolEventListener>();
_componentResetHandler = EcsComponentResetHandler<T>.instance; _componentResetHandler = EcsComponentResetHandler<T>.instance;
_componentCopyHandler = EcsComponentCopyHandler<T>.instance; _componentCopyHandler = EcsComponentCopyHandler<T>.instance;
_poolRunners = new PoolRunners(world.Pipeline);
} }
#endregion #endregion
@ -72,8 +74,7 @@ namespace DCFApixels.DragonECS
Array.Resize(ref _items, _items.Length << 1); Array.Resize(ref _items, _items.Length << 1);
} }
this.IncrementEntityComponentCount(entityID); this.IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _listeners.InvokeOnAddAndWrite(entityID);
_poolRunners.write.OnComponentWrite<T>(entityID);
return ref _items[itemIndex]; return ref _items[itemIndex];
// } // }
} }
@ -84,7 +85,7 @@ namespace DCFApixels.DragonECS
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID); if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
#endif #endif
_poolRunners.write.OnComponentWrite<T>(entityID); _listeners.InvokeOnWrite(entityID);
return ref _items[_mapping[entityID]]; return ref _items[_mapping[entityID]];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -113,9 +114,9 @@ namespace DCFApixels.DragonECS
Array.Resize(ref _items, _items.Length << 1); Array.Resize(ref _items, _items.Length << 1);
} }
this.IncrementEntityComponentCount(entityID); this.IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _listeners.InvokeOnAdd(entityID);
} }
_poolRunners.write.OnComponentWrite<T>(entityID); _listeners.InvokeOnWrite(entityID);
return ref _items[itemIndex]; return ref _items[itemIndex];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -136,7 +137,7 @@ namespace DCFApixels.DragonECS
_mapping[entityID] = 0; _mapping[entityID] = 0;
_itemsCount--; _itemsCount--;
this.DecrementEntityComponentCount(entityID); this.DecrementEntityComponentCount(entityID);
_poolRunners.del.OnComponentDel<T>(entityID); _listeners.InvokeOnDel(entityID);
} }
public void TryDel(int entityID) public void TryDel(int entityID)
{ {
@ -179,6 +180,19 @@ namespace DCFApixels.DragonECS
ref T IEcsPool<T>.Write(int entityID) => ref Write(entityID); ref T IEcsPool<T>.Write(int entityID) => ref Write(entityID);
#endregion #endregion
#region Listeners
public void AddListener(IEcsPoolEventListener listener)
{
if(listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Add(listener);
}
public void RemoveListener(IEcsPoolEventListener listener)
{
if(listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Remove(listener);
}
#endregion
#region IEnumerator - IntelliSense hack #region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

View File

@ -1,5 +1,6 @@
using DCFApixels.DragonECS.Internal; using DCFApixels.DragonECS.Internal;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -24,6 +25,20 @@ namespace DCFApixels.DragonECS
void Copy(int fromEntityID, int toEntityID); void Copy(int fromEntityID, int toEntityID);
void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID); void Copy(int fromEntityID, EcsWorld toWorld, int toEntityID);
#endregion #endregion
#region Add/Remove Listeners
void AddListener(IEcsPoolEventListener listener);
void RemoveListener(IEcsPoolEventListener listener);
#endregion
}
public interface IEcsPoolEventListener
{
/// <summary>Called after adding an entity to the pool, but before changing values.</summary>
void OnAdd(int entityID);
/// <summary>Is called when EcsPool.Write or EcsPool.Add is called, but before changing values.</summary>
void OnWrite(int entityID);
/// <summary>Called after deleting an entity from the pool</summary>
void OnDel(int entityID);
} }
public interface IEcsPool<T> public interface IEcsPool<T>
{ {
@ -43,6 +58,7 @@ namespace DCFApixels.DragonECS
/// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary> /// <summary>Only used to implement a custom pool. In other contexts use IEcsPool or IEcsPool<T>.</summary>
/// <typeparam name="T">Component type</typeparam> /// <typeparam name="T">Component type</typeparam>
public interface IEcsPoolImplementation<T> : IEcsPool<T>, IEcsPoolImplementation { } public interface IEcsPoolImplementation<T> : IEcsPool<T>, IEcsPoolImplementation { }
public static class EcsPoolThrowHalper public static class EcsPoolThrowHalper
{ {
public static void ThrowAlreadyHasComponent<T>(int entityID) public static void ThrowAlreadyHasComponent<T>(int entityID)
@ -117,6 +133,11 @@ namespace DCFApixels.DragonECS
void IEcsPoolImplementation.OnWorldResize(int newSize) { } void IEcsPoolImplementation.OnWorldResize(int newSize) { }
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { } void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
#endregion #endregion
#region Listeners
public void AddListener(IEcsPoolEventListener listener) { }
public void RemoveListener(IEcsPoolEventListener listener) { }
#endregion
} }
} }
#endregion #endregion
@ -194,4 +215,34 @@ namespace DCFApixels.DragonECS
public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to); public void Copy(ref T from, ref T to) => _fakeInstnace.Copy(ref from, ref to);
} }
#endregion #endregion
#region Extensions
public static class PoolEventListExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnAdd(this List<IEcsPoolEventListener> self, int entityID)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnAdd(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnAddAndWrite(this List<IEcsPoolEventListener> self, int entityID)
{
for (int i = 0, iMax = self.Count; i < iMax; i++)
{
self[i].OnAdd(entityID);
self[i].OnWrite(entityID);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnWrite(this List<IEcsPoolEventListener> self, int entityID)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnWrite(entityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeOnDel(this List<IEcsPoolEventListener> self, int entityID)
{
for (int i = 0, iMax = self.Count; i < iMax; i++) self[i].OnDel(entityID);
}
}
#endregion
} }

View File

@ -17,7 +17,7 @@ namespace DCFApixels.DragonECS
private int _count; private int _count;
private T _component; private T _component;
private PoolRunners _poolRunners; private List<IEcsPoolEventListener> _listeners;
#region Properites #region Properites
public ref T Instance public ref T Instance
@ -40,7 +40,7 @@ namespace DCFApixels.DragonECS
_mapping = new int[world.Capacity]; _mapping = new int[world.Capacity];
_count = 0; _count = 0;
_poolRunners = new PoolRunners(world.Pipeline); _listeners = new List<IEcsPoolEventListener>();
} }
#endregion #endregion
@ -52,7 +52,7 @@ namespace DCFApixels.DragonECS
#endif #endif
_mapping[entityID] = ++_count; _mapping[entityID] = ++_count;
this.IncrementEntityComponentCount(entityID); this.IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _listeners.InvokeOnAddAndWrite(entityID);
return ref _component; return ref _component;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -61,7 +61,7 @@ namespace DCFApixels.DragonECS
#if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS #if (DEBUG && !DISABLE_DEBUG) || !DRAGONECS_NO_SANITIZE_CHECKS
if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID); if (!Has(entityID)) ThrowNotHaveComponent<T>(entityID);
#endif #endif
_poolRunners.write.OnComponentWrite<T>(entityID); _listeners.InvokeOnWrite(entityID);
return ref _component; return ref _component;
} }
public ref T TryAddOrWrite(int entityID) public ref T TryAddOrWrite(int entityID)
@ -92,7 +92,7 @@ namespace DCFApixels.DragonECS
_mapping[entityID] = 0; _mapping[entityID] = 0;
_count--; _count--;
this.DecrementEntityComponentCount(entityID); this.DecrementEntityComponentCount(entityID);
_poolRunners.del.OnComponentDel<T>(entityID); _listeners.InvokeOnDel(entityID);
} }
public void TryDel(int entityID) public void TryDel(int entityID)
{ {
@ -133,6 +133,19 @@ namespace DCFApixels.DragonECS
void IEcsPool.SetRaw(int entityID, object dataRaw) => Instance = (T)dataRaw; void IEcsPool.SetRaw(int entityID, object dataRaw) => Instance = (T)dataRaw;
#endregion #endregion
#region Listeners
public void AddListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Add(listener);
}
public void RemoveListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Remove(listener);
}
#endregion
#region IEnumerator - IntelliSense hack #region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

View File

@ -15,7 +15,7 @@ namespace DCFApixels.DragonECS
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;
private PoolRunners _poolRunners; private List<IEcsPoolEventListener> _listeners;
private T _fakeComponent; private T _fakeComponent;
@ -36,7 +36,7 @@ namespace DCFApixels.DragonECS
_mapping = new bool[world.Capacity]; _mapping = new bool[world.Capacity];
_count = 0; _count = 0;
_poolRunners = new PoolRunners(world.Pipeline); _listeners = new List<IEcsPoolEventListener>();
} }
#endregion #endregion
@ -49,7 +49,7 @@ namespace DCFApixels.DragonECS
_count++; _count++;
_mapping[entityID] = true; _mapping[entityID] = true;
this.IncrementEntityComponentCount(entityID); this.IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _listeners.InvokeOnAdd(entityID);
} }
public void TryAdd(int entityID) public void TryAdd(int entityID)
{ {
@ -58,7 +58,7 @@ namespace DCFApixels.DragonECS
_count++; _count++;
_mapping[entityID] = true; _mapping[entityID] = true;
this.IncrementEntityComponentCount(entityID); this.IncrementEntityComponentCount(entityID);
_poolRunners.add.OnComponentAdd<T>(entityID); _listeners.InvokeOnAdd(entityID);
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -74,7 +74,7 @@ namespace DCFApixels.DragonECS
_mapping[entityID] = false; _mapping[entityID] = false;
_count--; _count--;
this.DecrementEntityComponentCount(entityID); this.DecrementEntityComponentCount(entityID);
_poolRunners.del.OnComponentDel<T>(entityID); _listeners.InvokeOnDel(entityID);
} }
public void TryDel(int entityID) public void TryDel(int entityID)
{ {
@ -166,6 +166,19 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
#region Listeners
public void AddListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Add(listener);
}
public void RemoveListener(IEcsPoolEventListener listener)
{
if (listener == null) { throw new ArgumentNullException("listener is null"); }
_listeners.Remove(listener);
}
#endregion
#region IEnumerator - IntelliSense hack #region IEnumerator - IntelliSense hack
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();

View File

@ -8,30 +8,22 @@ namespace DCFApixels.DragonECS
public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1) public static void Fill<T>(T[] array, T value, int startIndex = 0, int length = -1)
{ {
if (length < 0) if (length < 0)
{
length = array.Length; length = array.Length;
}
else else
{
length = startIndex + length; length = startIndex + length;
}
for (int i = startIndex; i < length; i++) for (int i = startIndex; i < length; i++)
{
array[i] = value; array[i] = value;
}
} }
} }
internal static unsafe class UnmanagedArray internal static unsafe class UnmanagedArrayUtility
{ {
public static void* New<T>(int elementCount) public static void* New<T>(int elementCount) where T : struct
where T : struct
{ {
return Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)) * elementCount).ToPointer(); return Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)) * elementCount).ToPointer();
} }
public static void* NewAndInit<T>(int elementCount) public static void* NewAndInit<T>(int elementCount) where T : struct
where T : struct
{ {
int newSizeInBytes = Marshal.SizeOf(typeof(T)) * elementCount; int newSizeInBytes = Marshal.SizeOf(typeof(T)) * elementCount;
byte* newArrayPointer = (byte*)Marshal.AllocHGlobal(newSizeInBytes).ToPointer(); byte* newArrayPointer = (byte*)Marshal.AllocHGlobal(newSizeInBytes).ToPointer();
@ -39,7 +31,7 @@ namespace DCFApixels.DragonECS
for (int i = 0; i < newSizeInBytes; i++) for (int i = 0; i < newSizeInBytes; i++)
*(newArrayPointer + i) = 0; *(newArrayPointer + i) = 0;
return (void*)newArrayPointer; return newArrayPointer;
} }
public static void Free(void* pointerToUnmanagedMemory) public static void Free(void* pointerToUnmanagedMemory)
@ -47,8 +39,7 @@ namespace DCFApixels.DragonECS
Marshal.FreeHGlobal(new IntPtr(pointerToUnmanagedMemory)); Marshal.FreeHGlobal(new IntPtr(pointerToUnmanagedMemory));
} }
public static void* Resize<T>(void* oldPointer, int newElementCount) public static void* Resize<T>(void* oldPointer, int newElementCount) where T : struct
where T : struct
{ {
return (Marshal.ReAllocHGlobal(new IntPtr(oldPointer), return (Marshal.ReAllocHGlobal(new IntPtr(oldPointer),
new IntPtr(Marshal.SizeOf(typeof(T)) * newElementCount))).ToPointer(); new IntPtr(Marshal.SizeOf(typeof(T)) * newElementCount))).ToPointer();

10
src/Utils/Extensions.cs Normal file
View File

@ -0,0 +1,10 @@
namespace DCFApixels.DragonECS
{
public static class Extensions
{
public static entlong ToEntityLong(this int self, EcsWorld world)
{
return world.GetEntityLong(self);
}
}
}