DragonECS-Graphs/src/EcsGraph.cs

280 lines
9.1 KiB
C#
Raw Normal View History

2024-03-16 13:54:50 +08:00
using DCFApixels.DragonECS.Graphs.Internal;
2023-12-25 08:59:00 +08:00
using System;
using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS
{
2024-03-18 02:45:25 +08:00
//Graph
//Graph world
2024-01-29 17:40:38 +08:00
//Rel entity
//Component
2024-03-18 02:45:25 +08:00
public class EcsGraph
2023-12-25 08:59:00 +08:00
{
2024-03-18 02:45:25 +08:00
private readonly EcsWorld _world;
private readonly EcsWorld _graphWorld;
2023-12-25 08:59:00 +08:00
2024-03-18 02:45:25 +08:00
private readonly GraphWorldHandler _arcWorldHandler;
private readonly WorldHandler _loopWorldHandler;
2023-12-25 08:59:00 +08:00
2024-03-16 14:13:43 +08:00
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
2024-03-16 12:40:37 +08:00
private readonly SparseMatrix _matrix;
2024-01-29 17:40:38 +08:00
2024-01-31 04:25:48 +08:00
private bool _isInit = false;
2023-12-25 08:59:00 +08:00
2024-03-17 13:43:15 +08:00
private int _count;
2023-12-25 08:59:00 +08:00
#region Properties
2024-01-31 04:25:48 +08:00
internal bool IsInit_Internal
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _isInit; }
}
2024-03-18 02:45:25 +08:00
public EcsWorld World
2024-01-29 17:40:38 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-18 02:45:25 +08:00
get { return _world; }
2024-01-29 17:40:38 +08:00
}
2024-03-18 02:45:25 +08:00
public short WorldID
2024-01-29 17:40:38 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-11-04 07:40:19 +08:00
get { return _world.ID; }
2024-01-29 17:40:38 +08:00
}
2024-03-18 02:45:25 +08:00
public EcsWorld GraphWorld
2024-01-29 17:40:38 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-18 02:45:25 +08:00
get { return _graphWorld; }
2024-01-29 17:40:38 +08:00
}
2024-03-18 02:45:25 +08:00
public short GraphWorldID
2024-01-29 17:40:38 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-11-04 07:40:19 +08:00
get { return _graphWorld.ID; }
2024-01-29 17:40:38 +08:00
}
2024-03-17 13:43:15 +08:00
public int Count
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _count; }
}
2023-12-25 08:59:00 +08:00
#endregion
2024-01-31 04:25:48 +08:00
#region Constructors/Destroy
2024-03-18 02:45:25 +08:00
internal EcsGraph(EcsWorld world, EcsWorld graphWorld)
2023-12-25 08:59:00 +08:00
{
2024-03-18 02:45:25 +08:00
_world = world;
_graphWorld = graphWorld;
2024-01-29 17:40:38 +08:00
2024-03-18 02:45:25 +08:00
_relEntityInfos = new RelationInfo[_graphWorld.Capacity];
_matrix = new SparseMatrix(_graphWorld.Capacity);
2024-02-03 21:37:11 +08:00
2024-03-18 02:45:25 +08:00
_arcWorldHandler = new GraphWorldHandler(this);
_loopWorldHandler = new WorldHandler(this);
2024-01-07 23:19:03 +08:00
2024-01-31 04:25:48 +08:00
_isInit = true;
}
public void Destroy()
{
2024-02-01 01:17:06 +08:00
_arcWorldHandler.Destroy();
2024-03-18 02:45:25 +08:00
_loopWorldHandler.Destroy();
2023-12-25 08:59:00 +08:00
}
#endregion
2024-04-03 13:48:28 +08:00
#region New/Convert
2024-03-16 12:40:37 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-01-29 17:40:38 +08:00
public int NewRelation(int startEntityID, int endEntityID)
2023-12-25 08:59:00 +08:00
{
2024-03-16 12:40:37 +08:00
return NewRelationInternal(startEntityID, endEntityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetOrNewRelation(int startEntityID, int endEntityID)
{
if (_matrix.TryGetValue(startEntityID, endEntityID, out int relEntityID))
{
return relEntityID;
}
return NewRelationInternal(startEntityID, endEntityID);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int NewRelationInternal(int startEntityID, int endEntityID)
{
2024-03-18 02:45:25 +08:00
int relEntityID = _graphWorld.NewEntity();
2024-04-03 13:48:28 +08:00
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)
{
2024-03-16 12:40:37 +08:00
_matrix.Add(startEntityID, endEntityID, relEntityID);
2024-03-16 14:13:43 +08:00
_relEntityInfos[relEntityID] = new RelationInfo(startEntityID, endEntityID);
2024-03-17 13:43:15 +08:00
_count++;
2024-03-16 12:40:37 +08:00
}
#endregion
2024-04-03 13:48:28 +08:00
#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);
}
#endregion
#region Has/Is
2024-03-16 12:40:37 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool HasRelation(int startEntityID, int endEntityID)
{
return _matrix.HasKey(startEntityID, endEntityID);
2023-12-25 08:59:00 +08:00
}
2024-04-03 13:48:28 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsRelation(int relEntityID)
{
if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
{
return false;
}
return !_relEntityInfos[relEntityID].IsNull;
}
2024-03-16 12:40:37 +08:00
#endregion
2024-02-03 21:45:36 +08:00
2024-03-16 12:40:37 +08:00
#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);
}
#endregion
#region Del
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-02-03 21:45:36 +08:00
public void DelRelation(int relEntityID)
2023-12-25 08:59:00 +08:00
{
2024-03-18 02:45:25 +08:00
_graphWorld.TryDelEntity(relEntityID);
2024-03-17 13:43:15 +08:00
//ClearRelation_Internal(relEntityID);
2024-01-31 04:25:48 +08:00
}
2024-01-07 23:19:03 +08:00
2024-03-16 12:40:37 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-04-03 13:48:28 +08:00
internal void ClearRelation_Internal(int relEntityID)
2024-01-31 04:25:48 +08:00
{
2024-03-16 14:13:43 +08:00
ref RelationInfo info = ref _relEntityInfos[relEntityID];
2024-03-17 13:43:15 +08:00
if (_matrix.TryDel(info.start, info.end))
{
_count--;
info = RelationInfo.Empty;
}
2023-12-25 08:59:00 +08:00
}
#endregion
#region ArcEntityInfo
2024-04-03 13:48:28 +08:00
2023-12-25 08:59:00 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-17 10:18:30 +08:00
public StartEnd GetRelationStartEnd(int relEntityID)
2023-12-25 08:59:00 +08:00
{
2024-01-31 04:25:48 +08:00
if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
{
Throw.UndefinedException();
}
2024-03-16 14:13:43 +08:00
return new StartEnd(_relEntityInfos[relEntityID]);
2024-01-31 04:25:48 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-17 10:18:30 +08:00
public int GetRelationStart(int relEntityID)
2024-01-31 04:25:48 +08:00
{
2024-03-17 10:18:30 +08:00
if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
{
Throw.UndefinedException();
}
return _relEntityInfos[relEntityID].start;
2023-12-25 08:59:00 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-17 10:18:30 +08:00
public int GetRelationEnd(int relEntityID)
2024-01-31 04:25:48 +08:00
{
2024-03-17 10:18:30 +08:00
if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
{
Throw.UndefinedException();
}
return _relEntityInfos[relEntityID].end;
2024-01-31 04:25:48 +08:00
}
2023-12-25 08:59:00 +08:00
#endregion
2024-03-18 02:45:25 +08:00
#region GraphWorldHandler
private class GraphWorldHandler : IEcsWorldEventListener
2023-12-25 08:59:00 +08:00
{
2024-03-18 02:45:25 +08:00
private readonly EcsGraph _arc;
public GraphWorldHandler(EcsGraph arc)
2024-01-28 02:19:49 +08:00
{
_arc = arc;
2024-03-18 02:45:25 +08:00
_arc.GraphWorld.AddListener(this);
2024-01-31 04:25:48 +08:00
}
public void Destroy()
{
2024-03-18 02:45:25 +08:00
_arc.GraphWorld.RemoveListener(this);
2024-01-28 02:19:49 +08:00
}
#region Callbacks
2024-01-31 04:25:48 +08:00
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> relEntityBuffer)
2024-01-28 02:19:49 +08:00
{
2024-01-31 04:25:48 +08:00
foreach (var relEntityID in relEntityBuffer)
2024-01-28 02:19:49 +08:00
{
2024-02-03 21:45:36 +08:00
_arc.ClearRelation_Internal(relEntityID);
2024-01-28 02:19:49 +08:00
}
}
2024-01-29 17:40:38 +08:00
public void OnWorldDestroy() { }
2024-01-31 04:25:48 +08:00
public void OnWorldResize(int arcWorldNewSize)
2024-01-28 02:19:49 +08:00
{
2024-01-31 04:25:48 +08:00
Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize);
2024-01-28 02:19:49 +08:00
}
#endregion
2023-12-25 08:59:00 +08:00
}
2024-03-18 02:45:25 +08:00
#endregion
2024-03-17 13:43:15 +08:00
2024-03-18 02:45:25 +08:00
#region WorldHandler
private class WorldHandler : IEcsWorldEventListener
2024-01-07 23:19:03 +08:00
{
2024-03-18 02:45:25 +08:00
private readonly EcsGraph _arc;
public WorldHandler(EcsGraph arc)
2024-01-28 02:19:49 +08:00
{
_arc = arc;
2024-03-18 02:45:25 +08:00
_arc.World.AddListener(this);
2024-01-31 04:25:48 +08:00
}
public void Destroy()
{
2024-03-18 02:45:25 +08:00
_arc.World.RemoveListener(this);
2024-01-28 02:19:49 +08:00
}
#region Callbacks
2024-01-31 04:25:48 +08:00
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
2024-01-28 02:19:49 +08:00
{
2024-03-18 02:45:25 +08:00
var graph = _arc.GraphWorld.JoinToSubGraph(EcsSubGraphMode.All);
2024-03-17 13:43:15 +08:00
foreach (var e in startEntityBuffer)
{
var span = graph.GetNodes(e);
foreach (var relE in span)
{
_arc.DelRelation(relE);
}
}
2024-03-18 02:45:25 +08:00
_arc._graphWorld.ReleaseDelEntityBufferAll();
2024-01-28 02:19:49 +08:00
}
2024-01-29 17:40:38 +08:00
public void OnWorldDestroy() { }
2024-02-22 17:12:28 +08:00
public void OnWorldResize(int startWorldNewSize) { }
2024-01-28 02:19:49 +08:00
#endregion
}
2024-03-17 13:43:15 +08:00
#endregion
2024-11-09 21:10:21 +08:00
#region Other
public static implicit operator EcsGraph(SingletonMarker marker) { return marker.Builder.World.GetGraph(); }
#endregion
2023-12-25 08:59:00 +08:00
}
}