diff --git a/src/EcsArc.cs b/src/EcsArc.cs index 3feb3ab..ad79295 100644 --- a/src/EcsArc.cs +++ b/src/EcsArc.cs @@ -1,4 +1,5 @@ using DCFApixels.DragonECS.Graphs.Internal; +using DCFApixels.DragonECS.UncheckedCore; using System; using System.Runtime.CompilerServices; @@ -25,6 +26,8 @@ namespace DCFApixels.DragonECS private bool _isLoop; private bool _isInit = false; + private int _count; + #region Properties internal bool IsInit_Internal { @@ -46,7 +49,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _arcWorld; } } - public int ArcWorldID + public short ArcWorldID { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _arcWorld.id; } @@ -56,6 +59,11 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _isLoop; } } + public int Count + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _count; } + } #endregion #region Constructors/Destroy @@ -120,6 +128,7 @@ namespace DCFApixels.DragonECS int relEntityID = _arcWorld.NewEntity(); _matrix.Add(startEntityID, endEntityID, relEntityID); _relEntityInfos[relEntityID] = new RelationInfo(startEntityID, endEntityID); + _count++; return relEntityID; } #endregion @@ -149,16 +158,19 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DelRelation(int relEntityID) { - _arcWorld.DelEntity(relEntityID); - ClearRelation_Internal(relEntityID); + _arcWorld.TryDelEntity(relEntityID); + //ClearRelation_Internal(relEntityID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ClearRelation_Internal(int relEntityID) { ref RelationInfo info = ref _relEntityInfos[relEntityID]; - _matrix.TryDel(info.start, info.end); - info = RelationInfo.Empty; + if (_matrix.TryDel(info.start, info.end)) + { + _count--; + info = RelationInfo.Empty; + } } #endregion @@ -241,6 +253,42 @@ namespace DCFApixels.DragonECS } #endregion } + + #region Loop + private class LoopWorldHandler : IEcsWorldEventListener + { + private readonly EcsArc _arc; + public LoopWorldHandler(EcsArc arc) + { + _arc = arc; + _arc.StartWorld.AddListener(this); + //OnWorldResize(_arc.StartWorld.Capacity); + } + public void Destroy() + { + _arc.StartWorld.RemoveListener(this); + } + #region Callbacks + public void OnReleaseDelEntityBuffer(ReadOnlySpan startEntityBuffer) + { + var graph = _arc.ArcWorld.GetExecutor>().Execute(); + foreach (var e in startEntityBuffer) + { + var span = graph.GetNodes(e); + foreach (var relE in span) + { + _arc.DelRelation(relE); + } + } + _arc._arcWorld.ReleaseDelEntityBufferAll(); + } + public void OnWorldDestroy() { } + public void OnWorldResize(int startWorldNewSize) { } + #endregion + } + #endregion + + #region StartEnd private class StartWorldHandler : IEcsWorldEventListener { private readonly EcsArc _arc; @@ -285,28 +333,8 @@ namespace DCFApixels.DragonECS public void OnWorldResize(int endWorldNewSize) { } #endregion } - private class LoopWorldHandler : IEcsWorldEventListener - { - private readonly EcsArc _arc; - public LoopWorldHandler(EcsArc arc) - { - _arc = arc; - _arc.StartWorld.AddListener(this); - //OnWorldResize(_arc.StartWorld.Capacity); - } - public void Destroy() - { - _arc.StartWorld.RemoveListener(this); - } - #region Callbacks - public void OnReleaseDelEntityBuffer(ReadOnlySpan startEntityBuffer) - { - _arc._arcWorld.ReleaseDelEntityBufferAll(); - } - public void OnWorldDestroy() { } - public void OnWorldResize(int startWorldNewSize) { } - #endregion - } + #endregion + #endregion } } \ No newline at end of file diff --git a/src/Executors/EcsJoinExecutor.cs b/src/Executors/EcsJoinExecutor.cs index 8c4163f..193e1b2 100644 --- a/src/Executors/EcsJoinExecutor.cs +++ b/src/Executors/EcsJoinExecutor.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; namespace DCFApixels.DragonECS { diff --git a/src/Executors/EcsJoinToGraphExecutor.cs b/src/Executors/EcsJoinToGraphExecutor.cs index c68cd31..7cf63f7 100644 --- a/src/Executors/EcsJoinToGraphExecutor.cs +++ b/src/Executors/EcsJoinToGraphExecutor.cs @@ -41,6 +41,7 @@ namespace DCFApixels.DragonECS _baskets = new Basket[World.Capacity]; World.AddListener(this); _arcWorld = (EcsArcWorld)World; + _aspect = AspectRaw; } protected override void OnDestroy() { @@ -80,28 +81,26 @@ namespace DCFApixels.DragonECS EcsArc arc = _arcWorld.GetRegisteredArc(); - var iterator = _aspect.GetIteratorFor(span); - foreach (var relationEntityID in iterator) + if (_aspect.Mask.IsEmpty) { - int startEntityID = arc.GetRelationStart(relationEntityID); - if(startEntityID == 0) + foreach (var relationEntityID in span) { - continue; + int startEntityID = arc.GetRelationStart(relationEntityID); + if (startEntityID == 0) { continue; } + Add(startEntityID, relationEntityID); } - _startEntities[_startEntitiesCount++] = startEntityID; - - ref var basket = ref _baskets[startEntityID]; - if (basket.index <= 0) - { - basket.index = _linkedList.Add(relationEntityID); - } - else - { - _linkedList.InsertAfter(basket.index, relationEntityID); - } - basket.count++; } - + else + { + var iterator = _aspect.GetIteratorFor(span); + foreach (var relationEntityID in iterator) + { + int startEntityID = arc.GetRelationStart(relationEntityID); + if (startEntityID == 0) { continue; } + Add(startEntityID, relationEntityID); + } + } + _lastWorldVersion = World.Version; } else @@ -112,6 +111,21 @@ namespace DCFApixels.DragonECS _executeMarker.End(); return new EcsGraph(this, UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount)); } + + private void Add(int startEntityID, int relationEntityID) + { + _startEntities[_startEntitiesCount++] = startEntityID; + ref var basket = ref _baskets[startEntityID]; + if (basket.index <= 0) + { + basket.index = _linkedList.Add(relationEntityID); + } + else + { + _linkedList.InsertAfter(basket.index, relationEntityID); + } + basket.count++; + } #endregion #region Internal result methods @@ -156,7 +170,7 @@ namespace DCFApixels.DragonECS } #endregion } - public sealed class EcsJoinExecutor : EcsJoinToGraphExecutor + public sealed class EcsJoinToGraphExecutor : EcsJoinToGraphExecutor where TAspect : EcsAspect { private TAspect _aspect; @@ -169,7 +183,14 @@ namespace DCFApixels.DragonECS } protected override EcsAspect AspectRaw { - get { return _aspect; } + get + { + if (_aspect == null) + { + _aspect = World.GetAspect(); + } + return _aspect; + } } #endregion } diff --git a/src/Internal/SparseMatrix.cs b/src/Internal/SparseMatrix.cs index 872e2d4..4d2ba2e 100644 --- a/src/Internal/SparseMatrix.cs +++ b/src/Internal/SparseMatrix.cs @@ -13,8 +13,8 @@ namespace DCFApixels.DragonECS.Graphs.Internal private const int MAX_CHAIN_LENGTH = 5; - private Basket* _buckets; - private Entry* _entries; + private UnsafeArray _buckets; + private UnsafeArray _entries; private int _capacity; private int _count; @@ -42,12 +42,12 @@ namespace DCFApixels.DragonECS.Graphs.Internal public SparseMatrix(int minCapacity = MIN_CAPACITY) { minCapacity = NormalizeCapacity(minCapacity); - _buckets = UnmanagedArrayUtility.New(minCapacity); + _buckets = new UnsafeArray(minCapacity); for (int i = 0; i < minCapacity; i++) { _buckets[i] = Basket.Empty; } - _entries = UnmanagedArrayUtility.NewAndInit(minCapacity); + _entries = new UnsafeArray(minCapacity, true); _modBitMask = (minCapacity - 1) & 0x7FFFFFFF; _count = 0; @@ -256,26 +256,29 @@ namespace DCFApixels.DragonECS.Graphs.Internal int newSize = _capacity << 1; _modBitMask = (newSize - 1) & 0x7FFFFFFF; + //newBuckets create and ini Basket* newBuckets = UnmanagedArrayUtility.New(newSize); - for (int i = 0; i < _capacity; i++) + for (int i = 0; i < newSize; i++) { newBuckets[i] = Basket.Empty; } + //END newBuckets create and ini - Entry* newEntries = UnmanagedArrayUtility.ResizeAndInit(_entries, _capacity, newSize); + Entry* newEntries = UnmanagedArrayUtility.ResizeAndInit(_entries.ptr, _capacity, newSize); for (int i = 0; i < _count; i++) { if (newEntries[i].key.yHash >= 0) { - int targetBusket = newEntries[i].key.yHash % newSize; + int targetBusket = newEntries[i].key.yHash % _capacity; ref Basket basket = ref _buckets[targetBusket]; newEntries[i].next = basket.index; basket.index = i; basket.count++; } } - _buckets = newBuckets; - _entries = newEntries; + + _buckets = new UnsafeArray(newBuckets, newSize); + _entries = new UnsafeArray(newEntries, newSize); _capacity = newSize; } diff --git a/src/Internal/UnsafeArray.cs b/src/Internal/UnsafeArray.cs index a57800d..35eafe7 100644 --- a/src/Internal/UnsafeArray.cs +++ b/src/Internal/UnsafeArray.cs @@ -47,8 +47,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal get { #if DEBUG - if (index < 0 || index >= Length) - Throw.ArgumentOutOfRange(); + if (index < 0 || index >= Length) { Throw.ArgumentOutOfRange(); } #endif return ref ptr[index]; } @@ -67,7 +66,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal Length = length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private UnsafeArray(T* ptr, int length) + public UnsafeArray(T* ptr, int length) { this.ptr = ptr; Length = length;