diff --git a/src/EntityGraph.cs b/src/EntityGraph.cs index caa5fbd..f36c0a7 100644 --- a/src/EntityGraph.cs +++ b/src/EntityGraph.cs @@ -22,6 +22,7 @@ namespace DCFApixels.DragonECS private int _count; private bool _isInit = false; + private bool _isDestroyed = false; #region Properties internal bool IsInit_Internal @@ -77,12 +78,7 @@ namespace DCFApixels.DragonECS } #endregion - #region New/Convert - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int NewRelation(int startEntityID, int endEntityID) - { - return NewRelationInternal(startEntityID, endEntityID); - } + #region New [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetOrNewRelation(int startEntityID, int endEntityID) { @@ -92,40 +88,24 @@ namespace DCFApixels.DragonECS } return NewRelationInternal(startEntityID, endEntityID); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOrNewInverseRelation(int relEntityID) + { +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) { Throw.UndefinedException(); } +#endif + var info = _relEntityInfos[relEntityID]; + return GetOrNewRelation(info.end, info.start); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private int NewRelationInternal(int startEntityID, int endEntityID) { int relEntityID = _graphWorld.NewEntity(); - ConvertToRelationInternal(relEntityID, startEntityID, endEntityID); - return relEntityID; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ConvertToRelation(int entityID, int startEntityID, int endEntityID) - { - if (IsRelation(entityID)) - { - Throw.UndefinedException(); - } - ConvertToRelationInternal(entityID, startEntityID, endEntityID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ConvertToRelationInternal(int relEntityID, int startEntityID, int endEntityID) - { _matrix.Add(startEntityID, endEntityID, relEntityID); _relEntityInfos[relEntityID] = new RelationInfo(startEntityID, endEntityID); _count++; - } - #endregion - - #region Inverse - public int GetInverseRelation(int relEntityID) - { - if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) - { - Throw.UndefinedException(); - } - var x = _relEntityInfos[relEntityID]; - return GetOrNewRelation(x.end, x.start); + return relEntityID; } #endregion @@ -138,42 +118,27 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsRelation(int relEntityID) { - if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) - { - return false; - } - return !_relEntityInfos[relEntityID].IsNull; + return relEntityID > 0 && + relEntityID < _relEntityInfos.Length && + _relEntityInfos[relEntityID].IsNull == false; } #endregion - #region MoveRelation - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //private void MoveRelation(int relEntityID, int newStartEntityID, int newEndEntityID) - //{ - // var startEnd = GetRelationStartEnd(relEntityID); - // - // //Тут будет не стабильное состояние если TryDel пройдет, а TryAdd - нет - // if (_matrix.TryDel(startEnd.start, startEnd.end) == false || - // _matrix.TryAdd(newStartEntityID, newEndEntityID, relEntityID) == false) - // { - // Throw.UndefinedException(); - // } - // - // _relEntityInfos[relEntityID] = new RelationInfo(newStartEntityID, newEndEntityID); - //} - #endregion - #region Get [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int GetRelation(int startEntityID, int endEntityID) - { - return _matrix.GetValue(startEntityID, endEntityID); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetRelation(int startEntityID, int endEntityID, out int relEntityID) { return _matrix.TryGetValue(startEntityID, endEntityID, out relEntityID); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryGetInverseRelation(int relEntityID, out int inverseRelEntityID) + { +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) { Throw.UndefinedException(); } +#endif + var info = _relEntityInfos[relEntityID]; + return _matrix.TryGetValue(info.end, info.start, out inverseRelEntityID); + } #endregion #region Del @@ -196,42 +161,38 @@ namespace DCFApixels.DragonECS } #endregion - #region Other - public static implicit operator EntityGraph(SingletonMarker marker) { return marker.Builder.World.GetGraph(); } - #endregion - - #region RelEntityInfo - + #region GetRelInfo [MethodImpl(MethodImplOptions.AggressiveInlining)] public StartEnd GetRelationStartEnd(int relEntityID) { - if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) - { - Throw.UndefinedException(); - } +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) { Throw.UndefinedException(); } +#endif return new StartEnd(_relEntityInfos[relEntityID]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetRelationStart(int relEntityID) { - if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) - { - Throw.UndefinedException(); - } +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) { Throw.UndefinedException(); } +#endif return _relEntityInfos[relEntityID].start; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetRelationEnd(int relEntityID) { - if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) - { - Throw.UndefinedException(); - } +#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS + if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length) { Throw.UndefinedException(); } +#endif return _relEntityInfos[relEntityID].end; } #endregion - #region GraphWorldHandler + #region Other + public static implicit operator EntityGraph(SingletonMarker marker) { return marker.Builder.World.GetGraph(); } + #endregion + + #region WorldHandlers private class GraphWorldHandler : IEcsWorldEventListener { private readonly EntityGraph _arc; @@ -259,9 +220,6 @@ namespace DCFApixels.DragonECS } #endregion } - #endregion - - #region WorldHandler private class WorldHandler : IEcsWorldEventListener { private readonly EntityGraph _graph; diff --git a/src/EntityGraphExtensions.cs b/src/EntityGraphExtensions.cs index 31dbc33..d764839 100644 --- a/src/EntityGraphExtensions.cs +++ b/src/EntityGraphExtensions.cs @@ -7,6 +7,10 @@ namespace DCFApixels.DragonECS { private static EntityGraph[] _worldGraphs = new EntityGraph[4]; + public static EntityGraph CreateGraph(this EcsWorld self) + { + return self.CreateGraph(self); + } public static EntityGraph CreateGraph(this EcsWorld self, EcsWorld graphWorld) { int worldID = self.ID; @@ -25,6 +29,10 @@ namespace DCFApixels.DragonECS return graph; } + public static EntityGraph CreateOrGetGraph(this EcsWorld self) + { + return self.CreateGraph(self); + } public static EntityGraph CreateOrGetGraph(this EcsWorld self, EcsWorld graphWorld) { int worldID = self.ID; @@ -73,14 +81,15 @@ namespace DCFApixels.DragonECS return false; } - private static void TryDestroy(EntityGraph graph) + #region Internal Destroy + private static void TryDestroyGraph(EntityGraph graph) { - int worldID = graph.WorldID; + short worldID = graph.WorldID; if (_worldGraphs.Length <= worldID) { Array.Resize(ref _worldGraphs, worldID + 4); } - int graphWorldID = graph.GraphWorldID; + short graphWorldID = graph.GraphWorldID; if (_worldGraphs.Length <= graphWorldID) { Array.Resize(ref _worldGraphs, graphWorldID + 4); @@ -100,9 +109,10 @@ namespace DCFApixels.DragonECS public void OnReleaseDelEntityBuffer(ReadOnlySpan buffer) { } public void OnWorldDestroy() { - TryDestroy(_graph); + TryDestroyGraph(_graph); } public void OnWorldResize(int newSize) { } } + #endregion } } \ No newline at end of file diff --git a/src/Internal/SparseMatrix.cs b/src/Internal/SparseMatrix.cs index 97600bb..ca26849 100644 --- a/src/Internal/SparseMatrix.cs +++ b/src/Internal/SparseMatrix.cs @@ -96,7 +96,6 @@ namespace DCFApixels.DragonECS.Graphs.Internal // обновляем под новое значение _modBitMask targetBucket = hash & _modBitMask; } - //index = Interlocked.Increment(ref _count); index = _count++; } else @@ -281,7 +280,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal public override string ToString() { return key == 0 ? "NULL" : $"{key} {value}"; } } - public static class KeyUtility + private static class KeyUtility { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long FromXY(int x, int y) diff --git a/src/Utils/RelInfo.cs b/src/Utils/RelInfo.cs new file mode 100644 index 0000000..92b2e36 --- /dev/null +++ b/src/Utils/RelInfo.cs @@ -0,0 +1,66 @@ +using DCFApixels.DragonECS.Graphs.Internal; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace DCFApixels.DragonECS +{ + [Serializable] + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] + public readonly ref struct StartEnd + { + /// Start vertex entity ID. + public readonly int start; + /// End vertex entity ID. + public readonly int end; + + #region Properties + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return start == 0 && end == 0; } + } + public bool IsLoop + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return start == end; } + } + #endregion + + #region Constructor/Deconstruct + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal StartEnd(RelationInfo relInfo) + { + start = relInfo.start; + end = relInfo.end; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal StartEnd(int startEntity, int endEntity) + { + start = startEntity; + end = endEntity; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Deconstruct(out int start, out int end) + { + start = this.start; + end = this.end; + } + #endregion + + #region operators + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(StartEnd a, StartEnd b) { return a.start == b.start && a.end == b.end; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(StartEnd a, StartEnd b) { return a.start != b.start || a.end != b.end; } + #endregion + + #region Other + public override int GetHashCode() { throw new NotSupportedException(); } + public override bool Equals(object obj) { throw new NotSupportedException(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(StartEnd other) { return this == other; } + public override string ToString() { return $"arc({start} -> {end})"; } + #endregion + } +} \ No newline at end of file diff --git a/src/Utils/Rels.cs.meta b/src/Utils/RelInfo.cs.meta similarity index 100% rename from src/Utils/Rels.cs.meta rename to src/Utils/RelInfo.cs.meta diff --git a/src/Utils/Rels.cs b/src/Utils/Rels.cs deleted file mode 100644 index b2727cc..0000000 --- a/src/Utils/Rels.cs +++ /dev/null @@ -1,170 +0,0 @@ -using DCFApixels.DragonECS.Graphs.Internal; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS -{ - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] - [Serializable] - public readonly ref struct StartEnd - { - /// Start vertex entity ID. - public readonly int start; - /// End vertex entity ID. - public readonly int end; - - #region Properties - public bool IsNull - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return start == 0 && end == 0; } - } - public bool IsLoop - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return start == end; } - } - #endregion - - #region Constructor/Deconstruct - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal StartEnd(RelationInfo relInfo) - { - start = relInfo.start; - end = relInfo.end; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal StartEnd(int startEntity, int endEntity) - { - start = startEntity; - end = endEntity; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Deconstruct(out int start, out int end) - { - start = this.start; - end = this.end; - } - #endregion - - #region operators - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(StartEnd a, StartEnd b) { return a.start == b.start && a.end == b.end; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(StartEnd a, StartEnd b) { return a.start != b.start || a.end != b.end; } - #endregion - - #region Other - public override bool Equals(object obj) { throw new NotImplementedException(); } - public override int GetHashCode() { throw new NotImplementedException(); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(StartEnd other) { return this == other; } - public override string ToString() { return $"arc({start} -> {end})"; } - #endregion - } - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 12)] - [Serializable] - public readonly ref struct StartRelEnd - { - /// Start vertex entity ID. - public readonly int start; - /// Relation entity ID. - public readonly int rel; - /// End vertex entity ID. - public readonly int end; - - #region Properties - public bool IsNull - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return rel == 0 || (start == 0 && end == 0); } - } - public bool IsLoop - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return start == end; } - } - #endregion - - #region Constructor/Deconstruct - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public StartRelEnd(int start, int rel, int end) - { - this.start = start; - this.rel = rel; - this.end = end; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Deconstruct(out int start, out int rel, out int end) - { - start = this.start; - rel = this.rel; - end = this.end; - } - #endregion - - #region operators - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(StartRelEnd a, StartRelEnd b) { return a.start == b.start && a.rel == b.rel && a.end == b.end; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(StartRelEnd a, StartRelEnd b) { return a.start != b.start || a.rel != b.rel || a.end != b.end; } - #endregion - - #region Other - public override bool Equals(object obj) { throw new NotImplementedException(); } - public override int GetHashCode() { throw new NotImplementedException(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(StartRelEnd other) { return this == other; } - public override string ToString() { return $"arc({start} --({rel})-> {end})"; } - #endregion - } - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] - [Serializable] - public readonly ref struct RelEnd - { - /// Relation entity ID. - public readonly int rel; - /// End vertex entity ID. - public readonly int end; - - #region Properties - public bool IsNull - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return rel == 0; } - } - #endregion - - #region Constructor/Deconstruct - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public RelEnd(int rel, int end) - { - this.rel = rel; - this.end = end; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Deconstruct(out int rel, out int end) - { - rel = this.rel; - end = this.end; - } - #endregion - - #region operators - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(RelEnd a, RelEnd b) { return a.rel == b.rel && a.end == b.end; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(RelEnd a, RelEnd b) { return a.rel != b.rel || a.end != b.end; } - #endregion - - #region Other - public override bool Equals(object obj) { throw new NotImplementedException(); } - public override int GetHashCode() { throw new NotImplementedException(); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RelEnd other) { return this == other; } - public override string ToString() { return $"arc(--({rel})-> {end})"; } - #endregion - } -}