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-01-29 17:40:38 +08:00
|
|
|
|
//Arc
|
|
|
|
|
//Arc world
|
|
|
|
|
//Rel entity
|
|
|
|
|
//Component
|
2024-01-28 02:19:49 +08:00
|
|
|
|
public class EcsArc
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
|
|
|
|
private readonly EcsWorld _startWorld;
|
|
|
|
|
private readonly EcsWorld _endWorld;
|
|
|
|
|
private readonly EcsArcWorld _arcWorld;
|
|
|
|
|
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private readonly StartWorldHandler _startWorldHandler;
|
|
|
|
|
private readonly ArcWorldHandler _arcWorldHandler;
|
|
|
|
|
private readonly EndWorldHandler _endWorldHandler;
|
2024-02-01 01:17:06 +08:00
|
|
|
|
private readonly LoopWorldHandler _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
|
|
|
|
|
|
|
|
|
private bool _isLoop;
|
2024-01-31 04:25:48 +08:00
|
|
|
|
private bool _isInit = false;
|
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-01-29 17:40:38 +08:00
|
|
|
|
public EcsWorld StartWorld
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
get { return _startWorld; }
|
|
|
|
|
}
|
|
|
|
|
public EcsWorld EndWorld
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
get { return _endWorld; }
|
|
|
|
|
}
|
|
|
|
|
public EcsArcWorld ArcWorld
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
get { return _arcWorld; }
|
|
|
|
|
}
|
|
|
|
|
public int ArcWorldID
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
get { return _arcWorld.id; }
|
|
|
|
|
}
|
|
|
|
|
public bool IsLoop
|
|
|
|
|
{
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
get { return _isLoop; }
|
|
|
|
|
}
|
2023-12-25 08:59:00 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
2024-01-31 04:25:48 +08:00
|
|
|
|
#region Constructors/Destroy
|
2024-01-07 23:19:03 +08:00
|
|
|
|
internal EcsArc(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld)
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-07 23:19:03 +08:00
|
|
|
|
_startWorld = startWorld;
|
|
|
|
|
_endWorld = endWorld;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
_arcWorld = arcWorld;
|
|
|
|
|
|
2024-01-29 17:40:38 +08:00
|
|
|
|
_isLoop = startWorld == endWorld;
|
|
|
|
|
|
2024-03-16 14:13:43 +08:00
|
|
|
|
_relEntityInfos = new RelationInfo[arcWorld.Capacity];
|
2024-03-16 12:40:37 +08:00
|
|
|
|
_matrix = new SparseMatrix(arcWorld.Capacity);
|
2024-02-03 21:37:11 +08:00
|
|
|
|
|
|
|
|
|
_arcWorldHandler = new ArcWorldHandler(this);
|
2024-02-01 01:17:06 +08:00
|
|
|
|
if (_isLoop)
|
|
|
|
|
{
|
|
|
|
|
_loopWorldHandler = new LoopWorldHandler(this);
|
|
|
|
|
}
|
|
|
|
|
else
|
2024-01-29 17:40:38 +08:00
|
|
|
|
{
|
2024-02-01 01:17:06 +08:00
|
|
|
|
_startWorldHandler = new StartWorldHandler(this);
|
2024-01-29 17:40:38 +08:00
|
|
|
|
_endWorldHandler = new EndWorldHandler(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();
|
|
|
|
|
if (_isLoop)
|
|
|
|
|
{
|
|
|
|
|
_loopWorldHandler.Destroy();
|
|
|
|
|
}
|
|
|
|
|
else
|
2024-01-31 04:40:27 +08:00
|
|
|
|
{
|
2024-02-01 01:17:06 +08:00
|
|
|
|
_startWorldHandler.Destroy();
|
|
|
|
|
_endWorldHandler.Destroy();
|
2024-01-31 04:40:27 +08:00
|
|
|
|
}
|
2024-02-03 21:37:11 +08:00
|
|
|
|
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2024-03-16 12:40:37 +08:00
|
|
|
|
#region New
|
|
|
|
|
[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)
|
|
|
|
|
{
|
|
|
|
|
int relEntityID = _arcWorld.NewEntity();
|
|
|
|
|
_matrix.Add(startEntityID, endEntityID, relEntityID);
|
2024-03-16 14:13:43 +08:00
|
|
|
|
_relEntityInfos[relEntityID] = new RelationInfo(startEntityID, endEntityID);
|
2024-03-16 12:40:37 +08:00
|
|
|
|
return relEntityID;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Has
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public bool HasRelation(int startEntityID, int endEntityID)
|
|
|
|
|
{
|
|
|
|
|
return _matrix.HasKey(startEntityID, endEntityID);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
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-02-03 21:45:36 +08:00
|
|
|
|
_arcWorld.DelEntity(relEntityID);
|
2024-03-16 12:40:37 +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-02-03 21:45:36 +08:00
|
|
|
|
public 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-16 12:40:37 +08:00
|
|
|
|
_matrix.TryDel(info.start, info.end);
|
2024-03-16 14:13:43 +08:00
|
|
|
|
info = RelationInfo.Empty;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ArcEntityInfo
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
2024-01-31 04:25:48 +08:00
|
|
|
|
public bool IsRelation(int relEntityID)
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-31 04:25:48 +08:00
|
|
|
|
if (relEntityID <= 0 || relEntityID >= _relEntityInfos.Length)
|
|
|
|
|
{
|
2023-12-25 08:59:00 +08:00
|
|
|
|
return false;
|
2024-01-31 04:25:48 +08:00
|
|
|
|
}
|
2024-03-16 14:13:43 +08:00
|
|
|
|
return !_relEntityInfos[relEntityID].IsNull;
|
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
|
|
|
|
|
|
|
|
|
|
#region Other
|
|
|
|
|
public EcsArc GetInversetArc()
|
|
|
|
|
{
|
2024-01-26 21:56:03 +08:00
|
|
|
|
return _endWorld.GetArc(_startWorld);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
public bool TryGetInversetArc(out EcsArc arc)
|
|
|
|
|
{
|
2024-01-26 21:56:03 +08:00
|
|
|
|
return _endWorld.TryGetArc(_startWorld, out arc);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
2024-01-28 02:19:49 +08:00
|
|
|
|
|
|
|
|
|
#region VertexWorldHandler
|
2024-01-31 04:25:48 +08:00
|
|
|
|
private class ArcWorldHandler : IEcsWorldEventListener
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private readonly EcsArc _arc;
|
|
|
|
|
public ArcWorldHandler(EcsArc arc)
|
|
|
|
|
{
|
|
|
|
|
_arc = arc;
|
2024-01-31 04:25:48 +08:00
|
|
|
|
_arc.ArcWorld.AddListener(this);
|
|
|
|
|
}
|
|
|
|
|
public void Destroy()
|
|
|
|
|
{
|
|
|
|
|
_arc.ArcWorld.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-01-31 04:25:48 +08:00
|
|
|
|
private class StartWorldHandler : IEcsWorldEventListener
|
2024-01-07 23:19:03 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private readonly EcsArc _arc;
|
2024-01-29 17:40:38 +08:00
|
|
|
|
public StartWorldHandler(EcsArc arc)
|
2024-01-28 02:19:49 +08:00
|
|
|
|
{
|
|
|
|
|
_arc = arc;
|
2024-01-31 04:25:48 +08:00
|
|
|
|
_arc.StartWorld.AddListener(this);
|
2024-03-16 13:54:50 +08:00
|
|
|
|
//OnWorldResize(_arc.StartWorld.Capacity);
|
2024-01-31 04:25:48 +08:00
|
|
|
|
}
|
|
|
|
|
public void Destroy()
|
|
|
|
|
{
|
|
|
|
|
_arc.StartWorld.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-02-03 21:37:11 +08:00
|
|
|
|
_arc._arcWorld.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-01-31 04:25:48 +08:00
|
|
|
|
private class EndWorldHandler : IEcsWorldEventListener
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private readonly EcsArc _arc;
|
2024-01-29 17:40:38 +08:00
|
|
|
|
public EndWorldHandler(EcsArc arc)
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
_arc = arc;
|
2024-01-31 04:25:48 +08:00
|
|
|
|
_arc.EndWorld.AddListener(this);
|
2024-03-16 13:54:50 +08:00
|
|
|
|
//OnWorldResize(_arc.EndWorld.Capacity);
|
2024-01-31 04:25:48 +08:00
|
|
|
|
}
|
|
|
|
|
public void Destroy()
|
|
|
|
|
{
|
|
|
|
|
_arc.EndWorld.RemoveListener(this);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
2024-01-07 23:19:03 +08:00
|
|
|
|
#region Callbacks
|
2024-01-31 04:25:48 +08:00
|
|
|
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> endEntityBuffer)
|
2024-01-07 23:19:03 +08:00
|
|
|
|
{
|
2024-02-03 21:37:11 +08:00
|
|
|
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
2024-01-07 23:19:03 +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 endWorldNewSize) { }
|
2024-01-07 23:19:03 +08:00
|
|
|
|
#endregion
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
2024-02-01 01:17:06 +08:00
|
|
|
|
private class LoopWorldHandler : IEcsWorldEventListener
|
|
|
|
|
{
|
|
|
|
|
private readonly EcsArc _arc;
|
|
|
|
|
public LoopWorldHandler(EcsArc arc)
|
|
|
|
|
{
|
|
|
|
|
_arc = arc;
|
|
|
|
|
_arc.StartWorld.AddListener(this);
|
2024-03-16 13:54:50 +08:00
|
|
|
|
//OnWorldResize(_arc.StartWorld.Capacity);
|
2024-02-01 01:17:06 +08:00
|
|
|
|
}
|
|
|
|
|
public void Destroy()
|
|
|
|
|
{
|
|
|
|
|
_arc.StartWorld.RemoveListener(this);
|
|
|
|
|
}
|
|
|
|
|
#region Callbacks
|
|
|
|
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
|
|
|
|
{
|
2024-02-03 21:37:11 +08:00
|
|
|
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
2024-02-01 01:17:06 +08:00
|
|
|
|
}
|
|
|
|
|
public void OnWorldDestroy() { }
|
2024-02-22 17:12:28 +08:00
|
|
|
|
public void OnWorldResize(int startWorldNewSize) { }
|
2024-02-01 01:17:06 +08:00
|
|
|
|
#endregion
|
|
|
|
|
}
|
2023-12-25 08:59:00 +08:00
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|