This commit is contained in:
Mikhail 2024-01-26 21:56:03 +08:00
parent 3b3f009fa6
commit 7c85a69ab0
4 changed files with 161 additions and 50 deletions

View File

@ -120,11 +120,11 @@ namespace DCFApixels.DragonECS
#region Other #region Other
public EcsArc GetInversetArc() public EcsArc GetInversetArc()
{ {
return _endWorld.GetArcWith(_startWorld); return _endWorld.GetArc(_startWorld);
} }
public bool TryGetInversetArc(out EcsArc arc) public bool TryGetInversetArc(out EcsArc arc)
{ {
return _endWorld.TryGetArcWith(_startWorld, out arc); return _endWorld.TryGetArc(_startWorld, out arc);
} }
#endregion #endregion

47
src/Utils/Arc.cs Normal file
View File

@ -0,0 +1,47 @@
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
public readonly struct StartArcEnd
{
/// <summary>Start vertex entity ID.</summary>
public readonly int start;
/// <summary>Arc entity ID.</summary>
public readonly int arc;
/// <summary>End vertex entity ID.</summary>
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
{
/// <summary>Arc entity ID.</summary>
public readonly int arc;
/// <summary>End vertex entity ID.</summary>
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;
}
}
}

View File

@ -1,6 +1,19 @@
using System; using System;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization; 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 namespace DCFApixels.DragonECS
{ {
[Serializable] [Serializable]

View File

@ -2,97 +2,148 @@
using DCFApixels.DragonECS.Relations.Utils; using DCFApixels.DragonECS.Relations.Utils;
using System; using System;
namespace DCFApixels.DragonECS.Relations.Internal namespace DCFApixels.DragonECS
{ {
internal static class WorldGraph public static class WorldGraph
{ {
private static readonly SparseArray64<EcsArc> _matrix = new SparseArray64<EcsArc>(4); private static readonly SparseArray64<EcsArc> _matrix = new SparseArray64<EcsArc>(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 startWorldID = startWorld.id;
int endWorldID = endWorld.id; int endWorldID = endWorld.id;
int arcWorldID = arcWorld.id;
if(_arcsMapping.Length <= arcWorldID)
{
Array.Resize(ref _arcsMapping, arcWorldID + 4);
}
#if DEBUG #if DEBUG
if (_matrix.Contains(startWorldID, endWorldID)) if (_matrix.Contains(startWorldID, endWorldID))
{
throw new EcsFrameworkException(); throw new EcsFrameworkException();
#endif
EcsArc edge = new EcsArc(startWorld, endWorld, edgeWorld);
_matrix[startWorldID, endWorldID] = edge;
return edge;
} }
internal static void Unregister(EcsWorld startWorld, EcsWorld endWorld) #endif
EcsArc arc = new EcsArc(startWorld, endWorld, arcWorld);
_matrix[startWorldID, endWorldID] = arc;
_arcsMapping[arcWorldID] = arc;
return arc;
}
private static void Unregister(EcsWorld startWorld, EcsWorld endWorld)
{ {
int startWorldID = startWorld.id; int startWorldID = startWorld.id;
int endWorldID = endWorld.id; int endWorldID = endWorld.id;
EcsArc arc = _matrix[startWorldID, endWorldID];
_arcsMapping[arc.ArcWorld.id] = null;
_matrix.Remove(startWorldID, endWorldID); _matrix.Remove(startWorldID, endWorldID);
} }
internal static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld) private static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld)
{ {
#if DEBUG #if DEBUG
if (!_matrix.Contains(startWorld.id, otherWorld.id)) if (!_matrix.Contains(startWorld.id, otherWorld.id))
{
throw new EcsFrameworkException(); throw new EcsFrameworkException();
}
#endif #endif
return _matrix[startWorld.id, otherWorld.id]; return _matrix[startWorld.id, otherWorld.id];
} }
internal static bool HasArc(EcsWorld startWorld, EcsWorld endWorld) => HasArc(startWorld.id, endWorld.id); private static bool Has(EcsWorld startWorld, EcsWorld endWorld) => Has(startWorld.id, endWorld.id);
internal static bool HasArc(int startWorldID, int endWorldID) => _matrix.Contains(startWorldID, endWorldID); private static bool Has(int startWorldID, int endWorldID) => _matrix.Contains(startWorldID, endWorldID);
#region Extension
public static bool IsRegistered(this EcsArcWorld self)
{
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];
} }
namespace DCFApixels.DragonECS
public static EcsArc SetLoopArc(this EcsWorld self) => SetArc(self, self);
public static EcsArc SetArc(this EcsWorld start, EcsWorld end)
{ {
public static class WorldGraphExtensions if (start == null || end == null)
{ {
public static EcsArc SetLoopArc(this EcsWorld self) => SetArcWith(self, self); Throw.ArgumentNull();
public static EcsArc SetArcWith(this EcsWorld self, EcsWorld endWorld) }
{ return Register(start, end, new EcsArcWorld());
if (self == null || endWorld == null)
throw new ArgumentNullException();
return WorldGraph.Register(self, endWorld, new EcsArcWorld());
} }
public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld edgeWorld) => SetEdgeWith(self, self, edgeWorld); public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld arc) => SetArc(self, self, arc);
public static EcsArc SetEdgeWith(this EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld edgeWorld) public static EcsArc SetArc(this EcsWorld start, EcsWorld end, EcsArcWorld arc)
{ {
if (startWorld == null || endWorld == null || edgeWorld == null) if (start == null || end == null || arc == null)
throw new ArgumentNullException(); {
return WorldGraph.Register(startWorld, endWorld, edgeWorld); Throw.ArgumentNull();
}
return Register(start, end, arc);
} }
public static bool HasLoopArc(this EcsWorld self) => HasArcWith(self, self); public static bool HasLoopArc(this EcsWorld self) => HasArc(self, self);
public static bool HasArcWith(this EcsWorld startWorld, EcsWorld endWorld) public static bool HasArc(this EcsWorld start, EcsWorld end)
{ {
if (startWorld == null || endWorld == null) if (start == null || end == null)
throw new ArgumentNullException(); {
return WorldGraph.HasArc(startWorld, endWorld); Throw.ArgumentNull();
}
return Has(start, end);
} }
public static EcsArc GetLoopArc(this EcsWorld self) => GetArcWith(self, self); public static EcsArc GetLoopArc(this EcsWorld self) => GetArc(self, self);
public static EcsArc GetArcWith(this EcsWorld startWorld, EcsWorld endWorld) public static EcsArc GetArc(this EcsWorld start, EcsWorld end)
{ {
if (startWorld == null || endWorld == null) if (start == null || end == null)
throw new ArgumentNullException(); {
return WorldGraph.Get(startWorld, endWorld); Throw.ArgumentNull();
}
return Get(start, end);
} }
public static bool TryGetLoopArc(this EcsWorld self, out EcsArc arc) => TryGetArcWith(self, self, out arc); public static bool TryGetLoopArc(this EcsWorld self, out EcsArc arc) => TryGetArc(self, self, out arc);
public static bool TryGetArcWith(this EcsWorld startWorld, EcsWorld endWorld, out EcsArc arc) public static bool TryGetArc(this EcsWorld start, EcsWorld end, out EcsArc arc)
{ {
if (startWorld == null || endWorld == null) if (start == null || end == null)
throw new ArgumentNullException(); {
bool result = WorldGraph.HasArc(startWorld, endWorld); Throw.ArgumentNull();
arc = result ? WorldGraph.Get(startWorld, endWorld) : null; }
bool result = Has(start, end);
arc = result ? Get(start, end) : null;
return result; return result;
} }
public static void DestroyLoopArc(this EcsWorld self) => DestroyArcWith(self, self); 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) if (start == null || end == null)
throw new ArgumentNullException(); {
WorldGraph.Get(startWorld, endWorld).ArcWorld.Destroy(); Throw.ArgumentNull();
WorldGraph.Unregister(startWorld, endWorld); }
} Get(start, end).ArcWorld.Destroy();
Unregister(start, end);
}
#endregion
} }
} }