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-03-18 02:45:25 +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-03-18 02:45:25 +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
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
}
|