2023-12-25 08:59:00 +08:00
|
|
|
|
using DCFApixels.DragonECS.Relations.Utils;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS
|
|
|
|
|
{
|
|
|
|
|
//Edge world
|
|
|
|
|
//Relation entity
|
|
|
|
|
//Relation 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;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
|
|
|
|
|
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
|
|
|
|
|
2024-01-07 23:19:03 +08:00
|
|
|
|
private EcsGroup _arcEntities;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
private ArcEntityInfo[] _arkEntityInfos; //N * (N - 1) / 2
|
|
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
public EcsWorld StartWorld => _startWorld;
|
|
|
|
|
public EcsWorld EndWorld => _endWorld;
|
|
|
|
|
public EcsArcWorld ArcWorld => _arcWorld;
|
2024-01-07 23:19:03 +08:00
|
|
|
|
public EcsReadonlyGroup ArcEntities => _arcEntities.Readonly;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
public bool IsLoop => _startWorld == _endWorld;
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Constructors
|
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;
|
|
|
|
|
|
|
|
|
|
_arkEntityInfos = new ArcEntityInfo[arcWorld.Capacity];
|
|
|
|
|
|
2024-01-28 02:19:49 +08:00
|
|
|
|
_startWorldHandler = new StartWorldHandler(this, _startWorld);
|
|
|
|
|
_arcWorldHandler = new ArcWorldHandler(this);
|
|
|
|
|
_endWorldHandler = new EndWorldHandler(this, _endWorld);
|
2024-01-07 23:19:03 +08:00
|
|
|
|
|
|
|
|
|
_startWorld.AddListener(worldEventListener: _startWorldHandler);
|
|
|
|
|
_startWorld.AddListener(entityEventListener: _startWorldHandler);
|
2024-01-28 02:19:49 +08:00
|
|
|
|
_arcWorld.AddListener(worldEventListener: _arcWorldHandler);
|
|
|
|
|
_arcWorld.AddListener(entityEventListener: _arcWorldHandler);
|
|
|
|
|
_endWorld.AddListener(worldEventListener: _endWorldHandler);
|
|
|
|
|
_endWorld.AddListener(entityEventListener: _endWorldHandler);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region New/Del
|
|
|
|
|
public int New(int startEntityID, int endEntityID)
|
|
|
|
|
{
|
|
|
|
|
if (Has(startEntityID, endEntityID))
|
|
|
|
|
throw new EcsRelationException();
|
2024-01-07 23:19:03 +08:00
|
|
|
|
|
2023-12-25 08:59:00 +08:00
|
|
|
|
int arcEntity = _arcWorld.NewEntity();
|
|
|
|
|
_relationsMatrix.Add(startEntityID, endEntityID, arcEntity);
|
2024-01-07 23:19:03 +08:00
|
|
|
|
|
2023-12-25 08:59:00 +08:00
|
|
|
|
_arkEntityInfos[arcEntity] = new ArcEntityInfo(startEntityID, endEntityID);
|
2024-01-07 23:19:03 +08:00
|
|
|
|
_arcEntities.Add(arcEntity);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
return arcEntity;
|
|
|
|
|
}
|
|
|
|
|
public void Del(int startEntityID, int endEntityID)
|
|
|
|
|
{
|
2024-01-07 23:19:03 +08:00
|
|
|
|
if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int arcEntity))
|
2023-12-25 08:59:00 +08:00
|
|
|
|
throw new EcsRelationException();
|
2024-01-07 23:19:03 +08:00
|
|
|
|
|
2023-12-25 08:59:00 +08:00
|
|
|
|
_relationsMatrix.Remove(startEntityID, endEntityID);
|
2024-01-07 23:19:03 +08:00
|
|
|
|
_arcWorld.DelEntity(arcEntity);
|
|
|
|
|
|
|
|
|
|
_arkEntityInfos[arcEntity] = ArcEntityInfo.Empty;
|
|
|
|
|
_arcEntities.Remove(arcEntity);
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Get/Has
|
|
|
|
|
public bool Has(int startEntityID, int endEntityID)
|
|
|
|
|
{
|
|
|
|
|
return _relationsMatrix.Contains(startEntityID, endEntityID);
|
|
|
|
|
}
|
|
|
|
|
public int Get(int startEntityID, int endEntityID)
|
|
|
|
|
{
|
2024-01-07 23:19:03 +08:00
|
|
|
|
if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int arcEntityID))
|
2023-12-25 08:59:00 +08:00
|
|
|
|
throw new EcsRelationException();
|
2024-01-07 23:19:03 +08:00
|
|
|
|
return arcEntityID;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
public bool TryGet(int startEntityID, int endEntityID, out int arcEntityID)
|
|
|
|
|
{
|
|
|
|
|
return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out arcEntityID);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ArcEntityInfo
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public bool IsArc(int arcEntityID)
|
|
|
|
|
{
|
|
|
|
|
if (arcEntityID <= 0 || arcEntityID >= _arkEntityInfos.Length)
|
|
|
|
|
return false;
|
|
|
|
|
return !_arkEntityInfos[arcEntityID].IsEmpty;
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public ArcEntityInfo GetArcInfo(int arcEntityID)
|
|
|
|
|
{
|
|
|
|
|
if (arcEntityID <= 0 || arcEntityID >= _arkEntityInfos.Length)
|
|
|
|
|
throw new Exception();
|
|
|
|
|
return _arkEntityInfos[arcEntityID];
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public int GetArcStart(int arcEntityID)
|
|
|
|
|
{
|
|
|
|
|
return GetArcInfo(arcEntityID).start;
|
|
|
|
|
}
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public int GetArcEnd(int arcEntityID)
|
|
|
|
|
{
|
|
|
|
|
return GetArcInfo(arcEntityID).end;
|
|
|
|
|
}
|
|
|
|
|
#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
|
|
|
|
|
private class ArcWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Callbacks
|
|
|
|
|
public void OnDelEntity(int entityID)
|
|
|
|
|
{
|
|
|
|
|
ref ArcEntityInfo rel = ref _arc._arkEntityInfos[entityID];
|
|
|
|
|
if (_arc._relationsMatrix.Contains(rel.start, rel.end))
|
|
|
|
|
{
|
|
|
|
|
_arc.Del(rel.start, rel.end);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void OnNewEntity(int entityID)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
|
|
|
|
{
|
|
|
|
|
_arc._arcWorld.ReleaseDelEntityBuffer(buffer.Length);
|
|
|
|
|
}
|
|
|
|
|
public void OnWorldDestroy()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnWorldResize(int newSize)
|
|
|
|
|
{
|
|
|
|
|
Array.Resize(ref _arc._arkEntityInfos, newSize);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private class StartWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener
|
2024-01-07 23:19:03 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private readonly EcsArc _arc;
|
|
|
|
|
private readonly EcsWorld _start;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
|
2024-01-28 02:19:49 +08:00
|
|
|
|
public StartWorldHandler(EcsArc arc, EcsWorld world)
|
|
|
|
|
{
|
|
|
|
|
_arc = arc;
|
|
|
|
|
_start = world;
|
|
|
|
|
}
|
2023-12-25 08:59:00 +08:00
|
|
|
|
|
2024-01-28 02:19:49 +08:00
|
|
|
|
#region Callbacks
|
|
|
|
|
public void OnDelEntity(int entityID)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnNewEntity(int entityID)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnWorldDestroy()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnWorldResize(int newSize)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
private class EndWorldHandler : IEcsWorldEventListener, IEcsEntityEventListener
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
private readonly EcsArc _arc;
|
|
|
|
|
private readonly EcsWorld _end;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
|
2024-01-28 02:19:49 +08:00
|
|
|
|
public EndWorldHandler(EcsArc arc, EcsWorld world)
|
2023-12-25 08:59:00 +08:00
|
|
|
|
{
|
2024-01-28 02:19:49 +08:00
|
|
|
|
_arc = arc;
|
|
|
|
|
_end = world;
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-07 23:19:03 +08:00
|
|
|
|
#region Callbacks
|
2023-12-25 08:59:00 +08:00
|
|
|
|
public void OnDelEntity(int entityID)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnNewEntity(int entityID)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-01-07 23:19:03 +08:00
|
|
|
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnWorldDestroy()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
public void OnWorldResize(int newSize)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
2023-12-25 08:59:00 +08:00
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|