From 7c85a69ab0cea021396c3f2a21717bf8e8a6613b Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 26 Jan 2024 21:56:03 +0800 Subject: [PATCH] update --- src/EcsArc.cs | 4 +- src/Utils/Arc.cs | 47 +++++++++++++ src/Utils/Exceptions.cs | 13 ++++ src/WorldGraph.cs | 147 +++++++++++++++++++++++++++------------- 4 files changed, 161 insertions(+), 50 deletions(-) create mode 100644 src/Utils/Arc.cs diff --git a/src/EcsArc.cs b/src/EcsArc.cs index 996b3bc..e6e96fa 100644 --- a/src/EcsArc.cs +++ b/src/EcsArc.cs @@ -120,11 +120,11 @@ namespace DCFApixels.DragonECS #region Other public EcsArc GetInversetArc() { - return _endWorld.GetArcWith(_startWorld); + return _endWorld.GetArc(_startWorld); } public bool TryGetInversetArc(out EcsArc arc) { - return _endWorld.TryGetArcWith(_startWorld, out arc); + return _endWorld.TryGetArc(_startWorld, out arc); } #endregion diff --git a/src/Utils/Arc.cs b/src/Utils/Arc.cs new file mode 100644 index 0000000..321d04b --- /dev/null +++ b/src/Utils/Arc.cs @@ -0,0 +1,47 @@ +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS +{ + public readonly struct StartArcEnd + { + /// Start vertex entity ID. + public readonly int start; + /// Arc entity ID. + public readonly int arc; + /// End vertex entity ID. + public readonly int end; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public StartArcEnd(int start, int arc, int end) + { + this.start = start; + this.arc = arc; + this.end = end; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Deconstruct(out int start, out int arc, out int end) + { + start = this.start; + arc = this.arc; + end = this.end; + } + } + public readonly struct ArcEnd + { + /// Arc entity ID. + public readonly int arc; + /// End vertex entity ID. + public readonly int end; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ArcEnd(int arc, int end) + { + this.arc = arc; + this.end = end; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Deconstruct(out int arc, out int end) + { + arc = this.arc; + end = this.end; + } + } +} diff --git a/src/Utils/Exceptions.cs b/src/Utils/Exceptions.cs index ff38ead..9012c46 100644 --- a/src/Utils/Exceptions.cs +++ b/src/Utils/Exceptions.cs @@ -1,6 +1,19 @@ using System; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; +namespace DCFApixels.DragonECS.Relations.Internal +{ + internal static class Throw + { + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void ArgumentNull() + { + throw new ArgumentNullException(); + } + } +} + namespace DCFApixels.DragonECS { [Serializable] diff --git a/src/WorldGraph.cs b/src/WorldGraph.cs index 0172f1b..2867a3b 100644 --- a/src/WorldGraph.cs +++ b/src/WorldGraph.cs @@ -2,97 +2,148 @@ using DCFApixels.DragonECS.Relations.Utils; using System; -namespace DCFApixels.DragonECS.Relations.Internal +namespace DCFApixels.DragonECS { - internal static class WorldGraph + public static class WorldGraph { private static readonly SparseArray64 _matrix = new SparseArray64(4); + private static EcsArc[] _arcsMapping = new EcsArc[4]; - internal static EcsArc Register(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld edgeWorld) + private static EcsArc Register(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld) { int startWorldID = startWorld.id; int endWorldID = endWorld.id; + int arcWorldID = arcWorld.id; + + if(_arcsMapping.Length <= arcWorldID) + { + Array.Resize(ref _arcsMapping, arcWorldID + 4); + } + #if DEBUG if (_matrix.Contains(startWorldID, endWorldID)) + { throw new EcsFrameworkException(); + } #endif - EcsArc edge = new EcsArc(startWorld, endWorld, edgeWorld); - _matrix[startWorldID, endWorldID] = edge; - return edge; + EcsArc arc = new EcsArc(startWorld, endWorld, arcWorld); + _matrix[startWorldID, endWorldID] = arc; + _arcsMapping[arcWorldID] = arc; + return arc; } - internal static void Unregister(EcsWorld startWorld, EcsWorld endWorld) + private static void Unregister(EcsWorld startWorld, EcsWorld endWorld) { int startWorldID = startWorld.id; int endWorldID = endWorld.id; + EcsArc arc = _matrix[startWorldID, endWorldID]; + _arcsMapping[arc.ArcWorld.id] = null; _matrix.Remove(startWorldID, endWorldID); } - internal static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld) + private static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld) { #if DEBUG if (!_matrix.Contains(startWorld.id, otherWorld.id)) + { throw new EcsFrameworkException(); + } #endif return _matrix[startWorld.id, otherWorld.id]; } - internal static bool HasArc(EcsWorld startWorld, EcsWorld endWorld) => HasArc(startWorld.id, endWorld.id); - internal static bool HasArc(int startWorldID, int endWorldID) => _matrix.Contains(startWorldID, endWorldID); - } -} + 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); -namespace DCFApixels.DragonECS -{ - public static class WorldGraphExtensions - { - public static EcsArc SetLoopArc(this EcsWorld self) => SetArcWith(self, self); - public static EcsArc SetArcWith(this EcsWorld self, EcsWorld endWorld) + + + + #region Extension + public static bool IsRegistered(this EcsArcWorld self) { - if (self == null || endWorld == null) - throw new ArgumentNullException(); - return WorldGraph.Register(self, endWorld, new EcsArcWorld()); + if (self == null) + { + Throw.ArgumentNull(); + } + int id = self.id; + return id < _arcsMapping.Length && _arcsMapping[self.id] != null; + } + public static EcsArc GetRegisteredArc(this EcsArcWorld self) + { + if (self == null) + { + Throw.ArgumentNull(); + } + int id = self.id; + if(id < _arcsMapping.Length && _arcsMapping[self.id] == null) + { + throw new Exception(); + } + return _arcsMapping[self.id]; } - public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld edgeWorld) => SetEdgeWith(self, self, edgeWorld); - public static EcsArc SetEdgeWith(this EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld edgeWorld) + + + public static EcsArc SetLoopArc(this EcsWorld self) => SetArc(self, self); + public static EcsArc SetArc(this EcsWorld start, EcsWorld end) { - if (startWorld == null || endWorld == null || edgeWorld == null) - throw new ArgumentNullException(); - return WorldGraph.Register(startWorld, endWorld, edgeWorld); + if (start == null || end == null) + { + Throw.ArgumentNull(); + } + return Register(start, end, new EcsArcWorld()); } - public static bool HasLoopArc(this EcsWorld self) => HasArcWith(self, self); - public static bool HasArcWith(this EcsWorld startWorld, EcsWorld endWorld) + public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld arc) => SetArc(self, self, arc); + public static EcsArc SetArc(this EcsWorld start, EcsWorld end, EcsArcWorld arc) { - if (startWorld == null || endWorld == null) - throw new ArgumentNullException(); - return WorldGraph.HasArc(startWorld, endWorld); + if (start == null || end == null || arc == null) + { + Throw.ArgumentNull(); + } + return Register(start, end, arc); } - public static EcsArc GetLoopArc(this EcsWorld self) => GetArcWith(self, self); - public static EcsArc GetArcWith(this EcsWorld startWorld, EcsWorld endWorld) + public static bool HasLoopArc(this EcsWorld self) => HasArc(self, self); + public static bool HasArc(this EcsWorld start, EcsWorld end) { - if (startWorld == null || endWorld == null) - throw new ArgumentNullException(); - return WorldGraph.Get(startWorld, endWorld); + if (start == null || end == null) + { + Throw.ArgumentNull(); + } + return Has(start, end); } - public static bool TryGetLoopArc(this EcsWorld self, out EcsArc arc) => TryGetArcWith(self, self, out arc); - public static bool TryGetArcWith(this EcsWorld startWorld, EcsWorld endWorld, out EcsArc arc) + public static EcsArc GetLoopArc(this EcsWorld self) => GetArc(self, self); + public static EcsArc GetArc(this EcsWorld start, EcsWorld end) { - if (startWorld == null || endWorld == null) - throw new ArgumentNullException(); - bool result = WorldGraph.HasArc(startWorld, endWorld); - arc = result ? WorldGraph.Get(startWorld, endWorld) : null; + if (start == null || end == null) + { + Throw.ArgumentNull(); + } + return Get(start, end); + } + + public static bool TryGetLoopArc(this EcsWorld self, out EcsArc arc) => TryGetArc(self, self, out arc); + public static bool TryGetArc(this EcsWorld start, EcsWorld end, out EcsArc arc) + { + if (start == null || end == null) + { + Throw.ArgumentNull(); + } + bool result = Has(start, end); + arc = result ? Get(start, end) : null; return result; } public static void DestroyLoopArc(this EcsWorld self) => DestroyArcWith(self, self); - public static void DestroyArcWith(this EcsWorld startWorld, EcsWorld endWorld) + public static void DestroyArcWith(this EcsWorld start, EcsWorld end) { - if (startWorld == null || endWorld == null) - throw new ArgumentNullException(); - WorldGraph.Get(startWorld, endWorld).ArcWorld.Destroy(); - WorldGraph.Unregister(startWorld, endWorld); + if (start == null || end == null) + { + Throw.ArgumentNull(); + } + Get(start, end).ArcWorld.Destroy(); + Unregister(start, end); } + #endregion } -} +} \ No newline at end of file