DragonECS-Graphs/src/EcsArc.cs

232 lines
7.5 KiB
C#
Raw Normal View History

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
}
}