diff --git a/src/Builtin/EcsArcWorld.cs b/src/Builtin/EcsArcWorld.cs index c4ce31b..090272c 100644 --- a/src/Builtin/EcsArcWorld.cs +++ b/src/Builtin/EcsArcWorld.cs @@ -1,4 +1,11 @@ namespace DCFApixels.DragonECS { - public sealed class EcsArcWorld : EcsWorld { } + public abstract class EcsArcWorld : EcsWorld { } + public sealed class EcsLoopArcWorld : EcsArcWorld + where TWorld : EcsWorld + { } + public sealed class EcsArcWorld : EcsArcWorld + where TStartWorld : EcsWorld + where TEndWorld : EcsWorld + { } } diff --git a/src/Collections/EcsJoin.cs b/src/Collections/EcsJoin.cs index 7ef68f7..2ccd33c 100644 --- a/src/Collections/EcsJoin.cs +++ b/src/Collections/EcsJoin.cs @@ -1,4 +1,5 @@ -using System; +using DCFApixels.DragonECS.Relations.Internal; +using System; using System.ComponentModel; using System.Runtime.CompilerServices; using static DCFApixels.DragonECS.Relations.Utils.EcsJoin; @@ -41,7 +42,7 @@ namespace DCFApixels.DragonECS.Relations.Utils [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _source.IsLoopArc; } } - public EnumerableArcEnd this[int startEntityID] + public EnumerableRelEnd this[int startEntityID] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _source[startEntityID]; } @@ -61,7 +62,7 @@ namespace DCFApixels.DragonECS.Relations.Utils [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool HasEnd(int endEntityID) { return _source.HasEnd(endEntityID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public EnumerableArcEnd GetRelEnds(int startEntityID) { return _source.GetRelEnds(startEntityID); } + public EnumerableRelEnd GetRelEnds(int startEntityID) { return _source.GetRelEnds(startEntityID); } #endregion #region Internal @@ -92,7 +93,7 @@ namespace DCFApixels.DragonECS.Relations.Utils private readonly BasketList _startBaskets; private readonly BasketList _endBaskets; - private readonly RelInfo[] _relMapping; + private readonly RelNodesInfo[] _relNodesMapping; #region Properties public EcsReadonlyJoin Readonly @@ -131,7 +132,7 @@ namespace DCFApixels.DragonECS.Relations.Utils get { return _isLoop; } } - public EnumerableArcEnd this[int startEntityID] + public EnumerableRelEnd this[int startEntityID] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return GetRelEnds(startEntityID); } @@ -145,60 +146,52 @@ namespace DCFApixels.DragonECS.Relations.Utils _isLoop = arc.IsLoop; _startBaskets = new BasketList(); - if (_isLoop) - { - _endBaskets = _startBaskets; - } - else - { - _endBaskets = new BasketList(); - } - _relMapping = new RelInfo[arc.ArcWorld.Capacity]; + //if (_isLoop) + //{ + // _endBaskets = _startBaskets; + //} + //else + //{ + // _endBaskets = new BasketList(); + //} + _endBaskets = new BasketList(); + + _relNodesMapping = new RelNodesInfo[arc.ArcWorld.Capacity]; } #endregion #region Add/Del public void Add(int relEntityID) { - var (startEntityID, endEntityID) = _source.GetRelInfo(relEntityID); - ref RelInfo arcInfo = ref _relMapping[relEntityID]; + var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID); + ref RelNodesInfo arcInfo = ref _relNodesMapping[relEntityID]; arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID); - if (_isLoop) - { - arcInfo.endNodeIndex = arcInfo.startNodeIndex; - } - else - { - arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID); - } - - //arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID); - //if (!_isLoop) + //if (_isLoop) //{ - // arcInfo.startNodeIndex = _startBaskets.AddToBasket(startEntityID, relEntityID); + // arcInfo.endNodeIndex = arcInfo.startNodeIndex; //} //else //{ - // arcInfo.startNodeIndex = arcInfo.endNodeIndex; + arcInfo.endNodeIndex = _endBaskets.AddToBasket(endEntityID, relEntityID); //} } public void Del(int relEntityID) { - var (startEntityID, endEntityID) = _source.GetRelInfo(relEntityID); - ref RelInfo relInfo = ref _relMapping[relEntityID]; + var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID); + ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID]; _startBaskets.RemoveFromBasket(startEntityID, relInfo.startNodeIndex); - if (!_isLoop) - { + //if (!_isLoop) + //{ _startBaskets.RemoveFromBasket(endEntityID, relInfo.endNodeIndex); - } + //} } public void DelStart(int startEntityID) { foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID)) { var endEntityID = _source.GetRelEnd(relEntityID); - ref RelInfo relInfo = ref _relMapping[relEntityID]; + ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID]; _endBaskets.RemoveFromBasket(endEntityID, relInfo.startNodeIndex); } _startBaskets.RemoveBasket(startEntityID); @@ -208,17 +201,75 @@ namespace DCFApixels.DragonECS.Relations.Utils foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID)) { var startEntityID = _source.GetRelStart(relEntityID); - ref RelInfo relInfo = ref _relMapping[relEntityID]; + ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID]; _startBaskets.RemoveFromBasket(startEntityID, relInfo.endNodeIndex); } _endBaskets.RemoveBasket(endEntityID); } + + + private void DelStartAndDelRelEntities(int startEntityID, EcsArc arc) + { + + foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID)) + { + int endEntityID = _source.GetRelEnd(relEntityID); + int endNodeIndex = _relNodesMapping[relEntityID].endNodeIndex; + int revereceRelEntitiy = _endBaskets.Get(endNodeIndex); + + //_endBaskets.RemoveFromBasket(endEntityID, endNodeIndex); + + arc.ArcWorld.DelEntity(relEntityID); + //if(!_isLoop) + arc.ArcWorld.DelEntity(revereceRelEntitiy); + } + //_startBaskets.RemoveBasket(startEntityID); + } + private void DelEndAndDelRelEntities(int endEntityID, EcsArc arc) + { + foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID)) + { + int startEntityID = _source.GetRelStart(relEntityID); + int startNodeIndex = _relNodesMapping[relEntityID].startNodeIndex; + int revereceRelEntitiy = _startBaskets.Get(startNodeIndex); + + //_startBaskets.RemoveFromBasket(startEntityID, startNodeIndex); + + arc.ArcWorld.DelEntity(relEntityID); + //if(!_isLoop) + arc.ArcWorld.DelEntity(revereceRelEntitiy); + } + //_endBaskets.RemoveBasket(endEntityID); + } + public struct FriendEcsArc + { + private EcsJoin _join; + public FriendEcsArc(EcsArc arc, EcsJoin join) + { + if (arc.IsInit_Internal != false) + { + Throw.UndefinedException(); + } + _join = join; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DelStartAndDelRelEntities(int startEntityID, EcsArc arc) + { + _join.DelStartAndDelRelEntities(startEntityID, arc); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DelEndAndDelRelEntities(int endEntityID, EcsArc arc) + { + _join.DelEndAndDelRelEntities(endEntityID, arc); + } + } #endregion #region Has public bool Has(int relEntityID) { - return _relMapping[relEntityID] != RelInfo.Empty; + return _relNodesMapping[relEntityID] != RelNodesInfo.Empty; } public bool HasStart(int startEntityID) { @@ -243,19 +294,19 @@ namespace DCFApixels.DragonECS.Relations.Utils #region GetRelEnds [MethodImpl(MethodImplOptions.AggressiveInlining)] - public EnumerableArcEnd GetRelEnds(int startEntityID) + public EnumerableRelEnd GetRelEnds(int startEntityID) { - return new EnumerableArcEnd(_source, _startBaskets.GetBasketIterator(startEntityID).GetEnumerator()); + return new EnumerableRelEnd(_source, _startBaskets.GetBasketIterator(startEntityID).GetEnumerator()); } #endregion #region EnumerableArcEnd - public readonly ref struct EnumerableArcEnd //: IEnumerable + public readonly ref struct EnumerableRelEnd //: IEnumerable { private readonly EcsArc _arc; private readonly BasketList.BasketIterator.Enumerator _iterator; [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal EnumerableArcEnd(EcsArc arc, BasketList.BasketIterator.Enumerator iterator) + internal EnumerableRelEnd(EcsArc arc, BasketList.BasketIterator.Enumerator iterator) { _arc = arc; _iterator = iterator; @@ -295,19 +346,19 @@ namespace DCFApixels.DragonECS.Relations.Utils #endregion #region ArcInfo - private struct RelInfo : IEquatable + private struct RelNodesInfo : IEquatable { - public readonly static RelInfo Empty = default; + public readonly static RelNodesInfo Empty = default; public int startNodeIndex; public int endNodeIndex; #region Object public override bool Equals(object obj) { - return obj is RelInfo && Equals((RelInfo)obj); + return obj is RelNodesInfo && Equals((RelNodesInfo)obj); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RelInfo other) + public bool Equals(RelNodesInfo other) { return startNodeIndex == other.startNodeIndex && endNodeIndex == other.endNodeIndex; @@ -321,9 +372,9 @@ namespace DCFApixels.DragonECS.Relations.Utils #region operators [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(RelInfo a, RelInfo b) => a.startNodeIndex == b.startNodeIndex && a.endNodeIndex == b.endNodeIndex; + public static bool operator ==(RelNodesInfo a, RelNodesInfo b) => a.startNodeIndex == b.startNodeIndex && a.endNodeIndex == b.endNodeIndex; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(RelInfo a, RelInfo b) => a.startNodeIndex != b.startNodeIndex || a.endNodeIndex != b.endNodeIndex; + public static bool operator !=(RelNodesInfo a, RelNodesInfo b) => a.startNodeIndex != b.startNodeIndex || a.endNodeIndex != b.endNodeIndex; #endregion } #endregion diff --git a/src/EcsArc.cs b/src/EcsArc.cs index a1206cf..7526e93 100644 --- a/src/EcsArc.cs +++ b/src/EcsArc.cs @@ -1,4 +1,5 @@ -using DCFApixels.DragonECS.Relations.Utils; +using DCFApixels.DragonECS.Relations.Internal; +using DCFApixels.DragonECS.Relations.Utils; using Leopotam.EcsLite; using System; using System.Runtime.CompilerServices; @@ -22,12 +23,20 @@ namespace DCFApixels.DragonECS private readonly SparseArray64 _relationsMatrix = new SparseArray64(); private EcsJoin _joinEntities; + private EcsJoin.FriendEcsArc _joinEntitiesFriend; + private EcsGroup _relEntities; private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2 private bool _isLoop; + private bool _isInit = false; #region Properties + internal bool IsInit_Internal + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _isInit; } + } public EcsWorld StartWorld { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -65,7 +74,7 @@ namespace DCFApixels.DragonECS } #endregion - #region Constructors + #region Constructors/Destroy internal EcsArc(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld) { _startWorld = startWorld; @@ -85,15 +94,27 @@ namespace DCFApixels.DragonECS _relEntities = EcsGroup.New(_arcWorld); _joinEntities = new EcsJoin(this); + + _joinEntitiesFriend = new EcsJoin.FriendEcsArc(this, _joinEntities); + _isInit = true; + } + public void Destroy() + { + _startWorldHandler.Destroy(); + _arcWorldHandler.Destroy(); + //if (!_isLoop) + //{ + _endWorldHandler.Destroy(); + //} } #endregion #region New/Del public int NewRelation(int startEntityID, int endEntityID) { - if (Has(startEntityID, endEntityID)) + if (HasRelation(startEntityID, endEntityID)) { - throw new EcsRelationException(); + Throw.UndefinedRelationException(); } int relEntity = _arcWorld.NewEntity(); @@ -106,61 +127,99 @@ namespace DCFApixels.DragonECS } public void DelRelation(int startEntityID, int endEntityID) { - if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity)) + if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity)) { - throw new EcsRelationException(); + _arcWorld.DelEntity(relEntity); } - _joinEntities.Del(relEntity); + else + { + Throw.UndefinedRelationException(); + } + //if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity)) + //{ + // Throw.UndefinedRelationException(); + //} + //_joinEntities.Del(relEntity); + // + //_relationsMatrix.Remove(startEntityID, endEntityID); + //_arcWorld.DelEntity(relEntity); + // + //_relEntityInfos[relEntity] = RelEntityInfo.Empty; + //_relEntities.Remove(relEntity); + } - _relationsMatrix.Remove(startEntityID, endEntityID); - _arcWorld.DelEntity(relEntity); - - _relEntityInfos[relEntity] = RelEntityInfo.Empty; - _relEntities.Remove(relEntity); + private void ClearRelation_Internal(int startEntityID, int endEntityID) + { + if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntity)) + { + _relEntities.Remove(relEntity); + _joinEntities.Del(relEntity); + _relationsMatrix.Remove(startEntityID, endEntityID); + _relEntityInfos[relEntity] = RelEntityInfo.Empty; + } } #endregion - #region Get/Has - public bool Has(int startEntityID, int endEntityID) + #region GetRelation/HasRelation + public bool HasRelation(int startEntityID, int endEntityID) { return _relationsMatrix.Contains(startEntityID, endEntityID); } - public int Get(int startEntityID, int endEntityID) + public int GetRelation(int startEntityID, int endEntityID) { - if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int arcEntityID)) - throw new EcsRelationException(); - return arcEntityID; + if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntityID)) + { + Throw.UndefinedRelationException(); + } + return relEntityID; } - public bool TryGet(int startEntityID, int endEntityID, out int arcEntityID) + public bool TryGetRelation(int startEntityID, int endEntityID, out int relEntityID) { - return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out arcEntityID); + return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out relEntityID); } #endregion #region ArcEntityInfo [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool IsRel(int arcEntityID) + public bool IsRelation(int relEntityID) { - if (arcEntityID <= 0 || arcEntityID >= _relEntityInfos.Length) + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) + { return false; - return !_relEntityInfos[arcEntityID].IsEmpty; + } + return !_relEntityInfos[relEntityID].IsEmpty; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RelEntityInfo GetRelInfo(int arcEntityID) + public RelEntityInfo GetRelationInfo(int relEntityID) { - if (arcEntityID <= 0 || arcEntityID >= _relEntityInfos.Length) - throw new Exception(); - return _relEntityInfos[arcEntityID]; + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) + { + Throw.UndefinedException(); + } + return _relEntityInfos[relEntityID]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetRelStart(int arcEntityID) + public int GetRelStart(int relEntityID) { - return GetRelInfo(arcEntityID).start; + return GetRelationInfo(relEntityID).start; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetRelEnd(int arcEntityID) + public int GetRelEnd(int relEntityID) { - return GetRelInfo(arcEntityID).end; + return GetRelationInfo(relEntityID).end; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetInversedRelation(int relEntityID) + { + var (startEntityID, endEntityID) = GetRelationInfo(relEntityID); + return GetRelation(endEntityID, startEntityID); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryGetInversedRelation(int relEntityID, out int inversedRelEntityID) + { + var (startEntityID, endEntityID) = GetRelationInfo(relEntityID); + return TryGetRelation(endEntityID, startEntityID, out inversedRelEntityID); } #endregion @@ -177,87 +236,84 @@ namespace DCFApixels.DragonECS #region VertexWorldHandler - private class ArcWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener + private class ArcWorldHandler : IEcsWorldEventListener { private readonly EcsArc _arc; public ArcWorldHandler(EcsArc arc) { _arc = arc; - EcsArcWorld arcWorld = arc.ArcWorld; - arcWorld.AddListener(worldEventListener: this); - arcWorld.AddListener(entityEventListener: this); + _arc.ArcWorld.AddListener(this); } - - #region Callbacks - public void OnDelEntity(int entityID) { } - public void OnNewEntity(int entityID) { } - public void OnReleaseDelEntityBuffer(ReadOnlySpan buffer) + public void Destroy() { - foreach (var relEntityID in buffer) + _arc.ArcWorld.RemoveListener(this); + } + #region Callbacks + public void OnReleaseDelEntityBuffer(ReadOnlySpan relEntityBuffer) + { + foreach (var relEntityID in relEntityBuffer) { - ref RelEntityInfo rel = ref _arc._relEntityInfos[relEntityID]; - if (_arc._relationsMatrix.Contains(rel.start, rel.end)) - { - _arc.DelRelation(rel.start, rel.end); - } + var (startEntityID, endEntityID) = _arc._relEntityInfos[relEntityID]; + _arc.ClearRelation_Internal(startEntityID, endEntityID); } - _arc._arcWorld.ReleaseDelEntityBuffer(buffer.Length); } public void OnWorldDestroy() { } - public void OnWorldResize(int newSize) + public void OnWorldResize(int arcWorldNewSize) { - Array.Resize(ref _arc._relEntityInfos, newSize); + Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize); } #endregion } - private class StartWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener + private class StartWorldHandler : IEcsWorldEventListener { private readonly EcsArc _arc; public StartWorldHandler(EcsArc arc) { _arc = arc; - EcsWorld startWorld = arc.StartWorld; - startWorld.AddListener(worldEventListener: this); - startWorld.AddListener(entityEventListener: this); + _arc.StartWorld.AddListener(this); } - - #region Callbacks - public void OnDelEntity(int startEntityID) { } - public void OnNewEntity(int startEntityID) { } - public void OnReleaseDelEntityBuffer(ReadOnlySpan buffer) + public void Destroy() { - foreach (var startEntityID in buffer) + _arc.StartWorld.RemoveListener(this); + } + #region Callbacks + public void OnReleaseDelEntityBuffer(ReadOnlySpan startEntityBuffer) + { + foreach (var startEntityID in startEntityBuffer) { - _arc._joinEntities.DelStart(startEntityID); + //_arc._joinEntities.DelStart(startEntityID); + _arc._joinEntitiesFriend.DelStartAndDelRelEntities(startEntityID, _arc); } + _arc._arcWorld.ReleaseDelEntityBuffer(startEntityBuffer.Length); } public void OnWorldDestroy() { } - public void OnWorldResize(int newSize) { } + public void OnWorldResize(int startWorldNewSize) { } #endregion } - private class EndWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener + private class EndWorldHandler : IEcsWorldEventListener { private readonly EcsArc _arc; public EndWorldHandler(EcsArc arc) { _arc = arc; - EcsWorld endWorld = arc.EndWorld; - endWorld.AddListener(worldEventListener: this); - endWorld.AddListener(entityEventListener: this); + _arc.EndWorld.AddListener(this); } - - #region Callbacks - public void OnDelEntity(int endEntityID) { } - public void OnNewEntity(int endEntityID) { } - public void OnReleaseDelEntityBuffer(ReadOnlySpan buffer) + public void Destroy() { - foreach (var endEntityID in buffer) + _arc.EndWorld.RemoveListener(this); + } + #region Callbacks + public void OnReleaseDelEntityBuffer(ReadOnlySpan endEntityBuffer) + { + foreach (var endEntityID in endEntityBuffer) { - _arc._joinEntities.DelEnd(endEntityID); + //_arc._joinEntities.DelEnd(endEntityID); + _arc._joinEntitiesFriend.DelEndAndDelRelEntities(endEntityID, _arc); } + _arc._arcWorld.ReleaseDelEntityBuffer(endEntityBuffer.Length); } public void OnWorldDestroy() { } - public void OnWorldResize(int newSize) { } + public void OnWorldResize(int endWorldNewSize) { } #endregion } #endregion diff --git a/src/EcsWorldGraph.cs b/src/EcsWorldGraph.cs index 1da01dc..8ec4186 100644 --- a/src/EcsWorldGraph.cs +++ b/src/EcsWorldGraph.cs @@ -16,7 +16,7 @@ namespace DCFApixels.DragonECS int endWorldID = endWorld.id; int arcWorldID = arcWorld.id; - if(_arcsMapping.Length <= arcWorldID) + if (_arcsMapping.Length <= arcWorldID) { Array.Resize(ref _arcsMapping, arcWorldID + 4); } @@ -32,6 +32,10 @@ namespace DCFApixels.DragonECS _arcsMapping[arcWorldID] = arc; return arc; } + public static bool IsRegistered(EcsArc arc) + { + return Has(arc.StartWorld.id, arc.EndWorld.id); + } private static void Unregister(EcsWorld startWorld, EcsWorld endWorld) { int startWorldID = startWorld.id; @@ -39,20 +43,21 @@ namespace DCFApixels.DragonECS EcsArc arc = _matrix[startWorldID, endWorldID]; _arcsMapping[arc.ArcWorld.id] = null; _matrix.Remove(startWorldID, endWorldID); + arc.Destroy(); } #endregion #region Get/Has -// private static EcsArc GetOrRigister(EcsWorld startWorld, EcsWorld otherWorld) -// { -//#if DEBUG -// if (!_matrix.Contains(startWorld.id, otherWorld.id)) -// { -// return Register(); -// } -//#endif -// return _matrix[startWorld.id, otherWorld.id]; -// } + // private static EcsArc GetOrRigister(EcsWorld startWorld, EcsWorld otherWorld) + // { + //#if DEBUG + // if (!_matrix.Contains(startWorld.id, otherWorld.id)) + // { + // return Register(); + // } + //#endif + // return _matrix[startWorld.id, otherWorld.id]; + // } private static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld) { #if DEBUG @@ -63,8 +68,14 @@ namespace DCFApixels.DragonECS #endif return _matrix[startWorld.id, otherWorld.id]; } - private static bool Has(EcsWorld startWorld, EcsWorld endWorld) => Has(startWorld.id, endWorld.id); - private static bool Has(int startWorldID, int endWorldID) => _matrix.Contains(startWorldID, endWorldID); + private static bool Has(EcsWorld startWorld, EcsWorld endWorld) + { + return Has(startWorld.id, endWorld.id); + } + private static bool Has(int startWorldID, int endWorldID) + { + return _matrix.Contains(startWorldID, endWorldID); + } #endregion #region Extension @@ -84,7 +95,7 @@ namespace DCFApixels.DragonECS Throw.ArgumentNull(); } int id = self.id; - if(id < _arcsMapping.Length && _arcsMapping[self.id] == null) + if (id < _arcsMapping.Length && _arcsMapping[self.id] == null) { throw new Exception(); } @@ -92,15 +103,45 @@ namespace DCFApixels.DragonECS } - - public static EcsArc SetLoopArcAuto(this EcsWorld self) => SetArcAuto(self, self); - public static EcsArc SetArcAuto(this EcsWorld start, EcsWorld end) + public static EcsArc SetLoopArcAuto(this TWorld self, out EcsLoopArcWorld arcWorld) + where TWorld : EcsWorld + { + if (self == null) + { + Throw.ArgumentNull(); + } + if (typeof(TWorld) != self.GetType()) + { + EcsDebug.PrintWarning($"{nameof(TWorld)} is not {self.GetType().Name}"); + } + arcWorld = new EcsLoopArcWorld(); + return Register(self, self, arcWorld); + } + public static EcsArc SetArcAuto(this TStartWorld start, TEndWorld end, out EcsArcWorld arcWorld) + where TStartWorld : EcsWorld + where TEndWorld : EcsWorld { if (start == null || end == null) { Throw.ArgumentNull(); } - return Register(start, end, new EcsArcWorld()); + if (typeof(TStartWorld) == typeof(EcsWorld) && typeof(TEndWorld) == typeof(EcsWorld)) + { + EcsDebug.PrintWarning($"{nameof(TStartWorld)} is not {start.GetType().Name} or {nameof(TEndWorld)} is not {end.GetType().Name}"); + } + arcWorld = new EcsArcWorld(); + return Register(start, end, arcWorld); + } + public static EcsArc SetLoopArcAuto(this TWorld self) + where TWorld : EcsWorld + { + return SetLoopArcAuto(self, out _); + } + public static EcsArc SetArcAuto(this TStartWorld start, TEndWorld end) + where TStartWorld : EcsWorld + where TEndWorld : EcsWorld + { + return SetArcAuto(start, end, out _); } public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld arc) => SetArc(self, self, arc); diff --git a/src/Utils/BasketList.cs b/src/Utils/BasketList.cs index b9abbfa..2308bd0 100644 --- a/src/Utils/BasketList.cs +++ b/src/Utils/BasketList.cs @@ -1,4 +1,5 @@ -using System; +using DCFApixels.DragonECS.Relations.Internal; +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; @@ -42,16 +43,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.NoInlining)] private void Resize(int newSize) { - //int oldSize = _nodes.Length; - //Array.Resize(ref _nodes, newSize); - //int leftNode = newSize - 1; - //for (int i = newSize - 1, n = oldSize; i >= n; i--) - //{ - // Link(i, leftNode); - // leftNode = i; - //} - //LinkToRecycled(newSize - 1, oldSize); - int oldSize = _nodes.Length; Array.Resize(ref _nodes, newSize); int leftNode = newSize - 1; @@ -65,15 +56,6 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.NoInlining)] private void Initialize(int newSize) { - //_nodes = new Node[newSize]; - //int leftNode = newSize - 1; - //for (int i = newSize - 1, n = 1; i >= n; i--) - //{ - // Link(i, leftNode); - // leftNode = i; - //} - //LinkToRecycled(newSize - 1, 1); - _nodes = new Node[newSize]; int leftNode = newSize - 1; for (int i = 1; i < newSize; i++) @@ -101,13 +83,6 @@ namespace DCFApixels.DragonECS { return _nodes[nodeIndex].value; } - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public ref readonly Node GetNode(int nodeIndex) - //{ - // return ref _nodes[nodeIndex]; - //} - - [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -116,10 +91,15 @@ namespace DCFApixels.DragonECS #if DEBUG if (nodeIndex <= 0) { - throw new ArgumentOutOfRangeException(); + //Throw.ArgumentOutOfRange(); } #endif ref BasketInfo basketInfo = ref _baskets[basketIndex]; + + if (basketInfo.count <= 4) + { + + } ref var node = ref _nodes[nodeIndex]; int nextNode = node.next; @@ -208,20 +188,18 @@ namespace DCFApixels.DragonECS } ref Node endNode = ref _nodes[endNodeIndex]; - if (_recycledListLast != -1) - { - //_nodes[_recycledListLast].next = startNodeIndex; //link recycled nodes; - //startNode.prev = _recycledListLast; - //_recycledListLast = endNodeIndex; - Link(_recycledListLast, startNodeIndex); - } - _recycledListLast = endNodeIndex; - + LinkToRecycled(startNodeIndex, endNodeIndex); Link(startNode.prev, endNode.next); basket.count = 0; } + [MethodImpl(MethodImplOptions.NoInlining)] + private void UpBasketsSize(int minSize) + { + int newSize = GetHighBitNumber((uint)minSize) << 1; + Array.Resize(ref _baskets, newSize); + } private static int GetHighBitNumber(uint bits) { if (bits == 0) @@ -256,32 +234,6 @@ namespace DCFApixels.DragonECS return bit; } - //public int NewBasket() - //{ - // int newBasketIndex; - // if(_recycledBusketsCount > 0) - // { - // newBasketIndex = _recycledBuskets[--_recycledBusketsCount]; - // } - // else - // { - // newBasketIndex = _basketsCount; - // if(_basketsCount >= _baskets.Length) - // { - // Array.Resize(ref _baskets, _baskets.Length << 1); - // } - // } - // _basketsCount++; - // _baskets[newBasketIndex] = BasketInfo.Empty; - // return newBasketIndex; - //} - - public static void CreateCrossRef(int leftBasketIndex, int rightBasketIndex) - { - - } - - #region Node [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] public struct Node @@ -324,8 +276,7 @@ namespace DCFApixels.DragonECS { if (_baskets.Length <= basketIndex) { - int newSize = GetHighBitNumber((uint)basketIndex) << 1; - Array.Resize(ref _baskets, newSize); + UpBasketsSize(basketIndex); } return new BasketIterator(this, basketIndex); } diff --git a/src/Utils/Exceptions.cs b/src/Utils/Exceptions.cs index 9012c46..df7fe8e 100644 --- a/src/Utils/Exceptions.cs +++ b/src/Utils/Exceptions.cs @@ -11,6 +11,21 @@ namespace DCFApixels.DragonECS.Relations.Internal { throw new ArgumentNullException(); } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void UndefinedException() + { + throw new Exception(); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void ArgumentOutOfRange() + { + throw new ArgumentOutOfRangeException(); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void UndefinedRelationException() + { + throw new EcsRelationException(); + } } }