mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 03:34:35 +08:00
tmp update
This commit is contained in:
parent
2f5c172c4e
commit
970f22510b
4
src/Builtin/EcsArcWorld.cs
Normal file
4
src/Builtin/EcsArcWorld.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public sealed class EcsArcWorld : EcsWorld { }
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public sealed class EcsEdgeWorld : EcsWorld { }
|
|
||||||
}
|
|
206
src/EcsArc.cs
Normal file
206
src/EcsArc.cs
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
using DCFApixels.DragonECS.Relations.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
//Edge world
|
||||||
|
//Relation entity
|
||||||
|
//Relation component
|
||||||
|
|
||||||
|
public class EcsEdge
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public class EcsArc : IEcsWorldEventListener, IEcsEntityEventListener
|
||||||
|
{
|
||||||
|
private readonly EcsWorld _startWorld;
|
||||||
|
private readonly EcsWorld _endWorld;
|
||||||
|
private readonly EcsArcWorld _arcWorld;
|
||||||
|
|
||||||
|
private readonly VertexWorldHandler _worldHandler;
|
||||||
|
|
||||||
|
private readonly IdsBasket _basket = new IdsBasket(256);
|
||||||
|
|
||||||
|
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
||||||
|
|
||||||
|
private ArcEntityInfo[] _arkEntityInfos; //N * (N - 1) / 2
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public EcsWorld StartWorld => _startWorld;
|
||||||
|
public EcsWorld EndWorld => _endWorld;
|
||||||
|
public EcsArcWorld ArcWorld => _arcWorld;
|
||||||
|
|
||||||
|
public bool IsLoop => _startWorld == _endWorld;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
internal EcsArc(EcsWorld world, EcsWorld otherWorld, EcsArcWorld arcWorld)
|
||||||
|
{
|
||||||
|
_arcWorld = arcWorld;
|
||||||
|
_startWorld = world;
|
||||||
|
_endWorld = otherWorld;
|
||||||
|
|
||||||
|
_worldHandler = new VertexWorldHandler(this, _startWorld, _basket);
|
||||||
|
_startWorld.AddListener(_worldHandler);
|
||||||
|
|
||||||
|
_arkEntityInfos = new ArcEntityInfo[arcWorld.Capacity];
|
||||||
|
|
||||||
|
_arcWorld.AddListener(worldEventListener: this);
|
||||||
|
_arcWorld.AddListener(entityEventListener: this);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region New/Del
|
||||||
|
public int New(int startEntityID, int endEntityID)
|
||||||
|
{
|
||||||
|
if (Has(startEntityID, endEntityID))
|
||||||
|
throw new EcsRelationException();
|
||||||
|
int arcEntity = _arcWorld.NewEntity();
|
||||||
|
_basket.AddToHead(startEntityID, endEntityID);
|
||||||
|
_relationsMatrix.Add(startEntityID, endEntityID, arcEntity);
|
||||||
|
_arkEntityInfos[arcEntity] = new ArcEntityInfo(startEntityID, endEntityID);
|
||||||
|
return arcEntity;
|
||||||
|
}
|
||||||
|
public void Del(int startEntityID, int endEntityID)
|
||||||
|
{
|
||||||
|
if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int e))
|
||||||
|
throw new EcsRelationException();
|
||||||
|
_relationsMatrix.Remove(startEntityID, endEntityID);
|
||||||
|
_basket.DelHead(startEntityID);
|
||||||
|
_arcWorld.DelEntity(e);
|
||||||
|
_arkEntityInfos[e] = ArcEntityInfo.Empty;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Get/Has
|
||||||
|
public bool Has(int startEntityID, int endEntityID)
|
||||||
|
{
|
||||||
|
return _relationsMatrix.Contains(startEntityID, endEntityID);
|
||||||
|
}
|
||||||
|
//public bool HasRelationWith(EcsSubject subject, int entityID, int otherEntityID)
|
||||||
|
//{
|
||||||
|
// if (subject.World != _relationWorld)
|
||||||
|
// throw new ArgumentException();
|
||||||
|
// return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out int entity) && subject.IsMatches(entity);
|
||||||
|
//}
|
||||||
|
public int Get(int startEntityID, int endEntityID)
|
||||||
|
{
|
||||||
|
if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int e))
|
||||||
|
throw new EcsRelationException();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
public bool TryGet(int startEntityID, int endEntityID, out int arcEntityID)
|
||||||
|
{
|
||||||
|
return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out arcEntityID);
|
||||||
|
}
|
||||||
|
//public bool TryGetRelation(EcsSubject subject, int entityID, int otherEntityID, out int entity)
|
||||||
|
//{
|
||||||
|
// return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out entity) && subject.IsMatches(entity);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//#region GetRelations
|
||||||
|
//private IdsLinkedList.Span GetRelations(int entityID)
|
||||||
|
//{
|
||||||
|
// return _basket.GetSpanFor(entityID);
|
||||||
|
//}
|
||||||
|
////ReadOnlySpan<int> временная заглушка, потому тут будет спан из линкедлиста
|
||||||
|
////public ReadOnlySpan<int> GetRelationsWith(EcsSubject subject, int entityID)
|
||||||
|
////{
|
||||||
|
//// if (subject.World != _relationWorld)
|
||||||
|
//// throw new ArgumentException();
|
||||||
|
//// throw new NotImplementedException();
|
||||||
|
////}
|
||||||
|
//#endregion
|
||||||
|
#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()
|
||||||
|
{
|
||||||
|
return _endWorld.GetArcWith(_startWorld);
|
||||||
|
}
|
||||||
|
public bool TryGetInversetArc(out EcsArc arc)
|
||||||
|
{
|
||||||
|
return _endWorld.TryGetArcWith(_startWorld, out arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IdsLinkedList.Span Get(int entityID) => _basket.GetSpanFor(entityID);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public IdsLinkedList.LongSpan GetLongs(int entityID) => _basket.GetLongSpanFor(_startWorld, entityID);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Callbacks
|
||||||
|
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _arkEntityInfos, newSize);
|
||||||
|
}
|
||||||
|
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
|
void IEcsWorldEventListener.OnWorldDestroy() { }
|
||||||
|
|
||||||
|
void IEcsEntityEventListener.OnNewEntity(int entityID) { }
|
||||||
|
void IEcsEntityEventListener.OnDelEntity(int entityID)
|
||||||
|
{
|
||||||
|
ref ArcEntityInfo rel = ref _arkEntityInfos[entityID];
|
||||||
|
if (_relationsMatrix.Contains(rel.start, rel.end))
|
||||||
|
Del(rel.start, rel.end);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region VertexWorldHandler
|
||||||
|
private class VertexWorldHandler : IEcsEntityEventListener
|
||||||
|
{
|
||||||
|
private readonly EcsArc _source;
|
||||||
|
private readonly EcsWorld _world;
|
||||||
|
private readonly IdsBasket _basket;
|
||||||
|
|
||||||
|
public VertexWorldHandler(EcsArc source, EcsWorld world, IdsBasket basket)
|
||||||
|
{
|
||||||
|
_source = source;
|
||||||
|
_world = world;
|
||||||
|
_basket = basket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDelEntity(int entityID)
|
||||||
|
{
|
||||||
|
var span = _basket.GetSpanFor(entityID);
|
||||||
|
foreach (var arcEntityID in span)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void OnNewEntity(int entityID)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
213
src/EcsEdge.cs
213
src/EcsEdge.cs
@ -1,213 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Utils;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
//Edge world
|
|
||||||
//Relation entity
|
|
||||||
//Relation component
|
|
||||||
public class EcsEdge : IEcsWorldEventListener, IEcsEntityEventListener
|
|
||||||
{
|
|
||||||
private readonly EcsWorld _world;
|
|
||||||
private readonly EcsWorld _otherWorld;
|
|
||||||
private readonly EcsEdgeWorld _edgeWorld;
|
|
||||||
|
|
||||||
private readonly VertexWorldHandler _worldHandler;
|
|
||||||
private readonly VertexWorldHandler _otherWorldHandler;
|
|
||||||
|
|
||||||
private readonly IdsBasket _basket = new IdsBasket(256);
|
|
||||||
private readonly IdsBasket _otherBasket = new IdsBasket(256);
|
|
||||||
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
|
||||||
|
|
||||||
private ArcTargets[] _arkTargets; //N * (N - 1) / 2
|
|
||||||
|
|
||||||
private List<WeakReference<EcsJoinGroup>> _groups = new List<WeakReference<EcsJoinGroup>>();
|
|
||||||
private Stack<EcsJoinGroup> _groupsPool = new Stack<EcsJoinGroup>(64);
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public EcsWorld World => _world;
|
|
||||||
public EcsWorld OtherWorld => _otherWorld;
|
|
||||||
public EcsEdgeWorld EdgeWorld => _edgeWorld;
|
|
||||||
|
|
||||||
public bool IsLoop => _world == _otherWorld;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
internal EcsEdge(EcsWorld world, EcsWorld otherWorld, EcsEdgeWorld edgeWorld)
|
|
||||||
{
|
|
||||||
_edgeWorld = edgeWorld;
|
|
||||||
_world = world;
|
|
||||||
_otherWorld = otherWorld;
|
|
||||||
|
|
||||||
_worldHandler = new VertexWorldHandler(this, _world, _basket);
|
|
||||||
_world.AddListener(_worldHandler);
|
|
||||||
if (IsLoop)
|
|
||||||
{
|
|
||||||
_otherWorldHandler = _worldHandler;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_otherWorldHandler = new VertexWorldHandler(this, _otherWorld, _otherBasket);
|
|
||||||
_world.AddListener(_otherWorldHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
_arkTargets = new ArcTargets[edgeWorld.Capacity];
|
|
||||||
|
|
||||||
_edgeWorld.AddListener(worldEventListener: this);
|
|
||||||
_edgeWorld.AddListener(entityEventListener: this);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Join Groups Pool
|
|
||||||
internal void RegisterGroup(EcsJoinGroup group)
|
|
||||||
{
|
|
||||||
_groups.Add(new WeakReference<EcsJoinGroup>(group));
|
|
||||||
}
|
|
||||||
internal EcsJoinGroup GetFreeGroup()
|
|
||||||
{
|
|
||||||
EcsJoinGroup result = _groupsPool.Count <= 0 ? new EcsJoinGroup(this) : _groupsPool.Pop();
|
|
||||||
result._isReleased = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
internal void ReleaseGroup(EcsJoinGroup group)
|
|
||||||
{
|
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS
|
|
||||||
if (group.Edge != this) throw new Exception();
|
|
||||||
#endif
|
|
||||||
group._isReleased = true;
|
|
||||||
group.Clear();
|
|
||||||
_groupsPool.Push(group);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region New/Del
|
|
||||||
public int New(int entityID, int otherEntityID)
|
|
||||||
{
|
|
||||||
if (Has(entityID, otherEntityID))
|
|
||||||
throw new EcsRelationException();
|
|
||||||
int arcEntity = _edgeWorld.NewEntity();
|
|
||||||
_basket.AddToHead(entityID, otherEntityID);
|
|
||||||
_otherBasket.AddToHead(otherEntityID, entityID);
|
|
||||||
_relationsMatrix.Add(entityID, otherEntityID, arcEntity);
|
|
||||||
_arkTargets[arcEntity] = new ArcTargets(entityID, otherEntityID);
|
|
||||||
return arcEntity;
|
|
||||||
}
|
|
||||||
public void Del(int entityID, int otherEntityID)
|
|
||||||
{
|
|
||||||
if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e))
|
|
||||||
throw new EcsRelationException();
|
|
||||||
_relationsMatrix.Remove(entityID, otherEntityID);
|
|
||||||
_basket.DelHead(entityID);
|
|
||||||
_otherBasket.Del(entityID);
|
|
||||||
_edgeWorld.DelEntity(e);
|
|
||||||
_arkTargets[e] = ArcTargets.Empty;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Get/Has
|
|
||||||
public bool Has(int entityID, int otherEntityID) => _relationsMatrix.Contains(entityID, otherEntityID);
|
|
||||||
//public bool HasRelationWith(EcsSubject subject, int entityID, int otherEntityID)
|
|
||||||
//{
|
|
||||||
// if (subject.World != _relationWorld)
|
|
||||||
// throw new ArgumentException();
|
|
||||||
// return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out int entity) && subject.IsMatches(entity);
|
|
||||||
//}
|
|
||||||
public int Get(int entityID, int otherEntityID)
|
|
||||||
{
|
|
||||||
if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e))
|
|
||||||
throw new EcsRelationException();
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
private bool TryGet(int entityID, int otherEntityID, out int entity)
|
|
||||||
{
|
|
||||||
return _relationsMatrix.TryGetValue(entityID, otherEntityID, out entity);
|
|
||||||
}
|
|
||||||
//public bool TryGetRelation(EcsSubject subject, int entityID, int otherEntityID, out int entity)
|
|
||||||
//{
|
|
||||||
// return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out entity) && subject.IsMatches(entity);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//#region GetRelations
|
|
||||||
//private IdsLinkedList.Span GetRelations(int entityID)
|
|
||||||
//{
|
|
||||||
// return _basket.GetSpanFor(entityID);
|
|
||||||
//}
|
|
||||||
////ReadOnlySpan<int> временная заглушка, потому тут будет спан из линкедлиста
|
|
||||||
////public ReadOnlySpan<int> GetRelationsWith(EcsSubject subject, int entityID)
|
|
||||||
////{
|
|
||||||
//// if (subject.World != _relationWorld)
|
|
||||||
//// throw new ArgumentException();
|
|
||||||
//// throw new NotImplementedException();
|
|
||||||
////}
|
|
||||||
//#endregion
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Other
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool IsArc(int arcEntityID)
|
|
||||||
{
|
|
||||||
if (arcEntityID <= 0 || arcEntityID >= _arkTargets.Length)
|
|
||||||
return false;
|
|
||||||
return !_arkTargets[arcEntityID].IsEmpty;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ArcTargets GetArcTargets(int arcEntityID)
|
|
||||||
{
|
|
||||||
if (arcEntityID <= 0 || arcEntityID >= _arkTargets.Length)
|
|
||||||
throw new Exception();
|
|
||||||
return _arkTargets[arcEntityID];
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public IdsLinkedList.Span Get(int entityID) => _basket.GetSpanFor(entityID);
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public IdsLinkedList.LongSpan GetLongs(int entityID) => _basket.GetLongSpanFor(_world, entityID);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Callbacks
|
|
||||||
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _arkTargets, newSize);
|
|
||||||
}
|
|
||||||
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
|
||||||
void IEcsWorldEventListener.OnWorldDestroy() { }
|
|
||||||
|
|
||||||
void IEcsEntityEventListener.OnNewEntity(int entityID) { }
|
|
||||||
void IEcsEntityEventListener.OnDelEntity(int entityID)
|
|
||||||
{
|
|
||||||
ref ArcTargets rel = ref _arkTargets[entityID];
|
|
||||||
if (_relationsMatrix.Contains(rel.start, rel.end))
|
|
||||||
Del(rel.start, rel.end);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region VertexWorldHandler
|
|
||||||
private class VertexWorldHandler : IEcsEntityEventListener
|
|
||||||
{
|
|
||||||
private readonly EcsEdge _source;
|
|
||||||
private readonly EcsWorld _world;
|
|
||||||
private readonly IdsBasket _basket;
|
|
||||||
|
|
||||||
public VertexWorldHandler(EcsEdge source, EcsWorld world, IdsBasket basket)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
_world = world;
|
|
||||||
_basket = basket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnDelEntity(int entityID)
|
|
||||||
{
|
|
||||||
var span = _basket.GetSpanFor(entityID);
|
|
||||||
foreach (var arcEntityID in span)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void OnNewEntity(int entityID)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public class EcsJoinGroup
|
public class EcsJoinGroup
|
||||||
{
|
{
|
||||||
private EcsEdge _source;
|
private EcsArc _source;
|
||||||
|
|
||||||
private int[] _mapping;
|
private int[] _mapping;
|
||||||
private int[] _counts;
|
private int[] _counts;
|
||||||
@ -13,26 +13,26 @@ namespace DCFApixels.DragonECS
|
|||||||
internal bool _isReleased = true;
|
internal bool _isReleased = true;
|
||||||
|
|
||||||
#region Properites
|
#region Properites
|
||||||
public EcsEdge Edge => _source;
|
public EcsArc Edge => _source;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Constrcutors/Dispose
|
#region Constrcutors/Dispose
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static EcsJoinGroup New(EcsEdge edge)
|
//public static EcsJoinGroup New(EcsArcController edge)
|
||||||
{
|
//{
|
||||||
return edge.GetFreeGroup();
|
// return edge.GetFreeGroup();
|
||||||
}
|
//}
|
||||||
internal EcsJoinGroup(EcsEdge edge, int denseCapacity = 64)
|
//internal EcsJoinGroup(EcsArcController edge, int denseCapacity = 64)
|
||||||
{
|
//{
|
||||||
_source = edge;
|
// _source = edge;
|
||||||
_source.RegisterGroup(this);
|
// _source.RegisterGroup(this);
|
||||||
int capacity = edge.World.Capacity;
|
// int capacity = edge.World.Capacity;
|
||||||
|
//
|
||||||
_mapping = new int[capacity];
|
// _mapping = new int[capacity];
|
||||||
_counts = new int[capacity];
|
// _counts = new int[capacity];
|
||||||
}
|
//}
|
||||||
public void Dispose() => _source.ReleaseGroup(this);
|
//public void Dispose() => _source.ReleaseGroup(this);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public void Add(int entityFrom, int entityTo)
|
public void Add(int entityFrom, int entityTo)
|
||||||
|
@ -6,9 +6,9 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public readonly struct ArcTargets : IEquatable<ArcTargets>
|
public readonly struct ArcEntityInfo : IEquatable<ArcEntityInfo>
|
||||||
{
|
{
|
||||||
public static readonly ArcTargets Empty = new ArcTargets();
|
public static readonly ArcEntityInfo Empty = new ArcEntityInfo();
|
||||||
|
|
||||||
/// <summary>Start vertex entity ID.</summary>
|
/// <summary>Start vertex entity ID.</summary>
|
||||||
public readonly int start;
|
public readonly int start;
|
||||||
@ -24,7 +24,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal ArcTargets(int startEntity, int endEntity)
|
internal ArcEntityInfo(int startEntity, int endEntity)
|
||||||
{
|
{
|
||||||
start = startEntity;
|
start = startEntity;
|
||||||
end = endEntity;
|
end = endEntity;
|
||||||
@ -32,15 +32,15 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
#region operators
|
#region operators
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool operator ==(ArcTargets a, ArcTargets b) => a.start == b.start && a.end == b.end;
|
public static bool operator ==(ArcEntityInfo a, ArcEntityInfo b) => a.start == b.start && a.end == b.end;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static bool operator !=(ArcTargets a, ArcTargets b) => a.start != b.start || a.end != b.end;
|
public static bool operator !=(ArcEntityInfo a, ArcEntityInfo b) => a.start != b.start || a.end != b.end;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
public override bool Equals(object obj) => obj is ArcTargets targets && targets == this;
|
public override bool Equals(object obj) => obj is ArcEntityInfo targets && targets == this;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public bool Equals(ArcTargets other) => this == other;
|
public bool Equals(ArcEntityInfo other) => this == other;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public override int GetHashCode() => ~start ^ end;
|
public override int GetHashCode() => ~start ^ end;
|
||||||
public override string ToString() => $"arc({start} -> {end})";
|
public override string ToString() => $"arc({start} -> {end})";
|
@ -6,40 +6,37 @@ namespace DCFApixels.DragonECS.Relations.Internal
|
|||||||
{
|
{
|
||||||
internal static class WorldGraph
|
internal static class WorldGraph
|
||||||
{
|
{
|
||||||
private static readonly SparseArray64<EcsEdge> _matrix = new SparseArray64<EcsEdge>(4);
|
private static readonly SparseArray64<EcsArc> _matrix = new SparseArray64<EcsArc>(4);
|
||||||
|
|
||||||
internal static EcsEdge Register(EcsWorld world, EcsWorld otherWorld, EcsEdgeWorld edgeWorld)
|
internal static EcsArc Register(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld edgeWorld)
|
||||||
{
|
{
|
||||||
int worldID = world.id;
|
int startWorldID = startWorld.id;
|
||||||
int otherWorldID = otherWorld.id;
|
int endWorldID = endWorld.id;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (_matrix.Contains(worldID, otherWorldID))
|
if (_matrix.Contains(startWorldID, endWorldID))
|
||||||
throw new EcsFrameworkException();
|
throw new EcsFrameworkException();
|
||||||
#endif
|
#endif
|
||||||
EcsEdge edge = new EcsEdge(world, otherWorld, edgeWorld);
|
EcsArc edge = new EcsArc(startWorld, endWorld, edgeWorld);
|
||||||
_matrix[worldID, otherWorldID] = edge;
|
_matrix[startWorldID, endWorldID] = edge;
|
||||||
_matrix[otherWorldID, worldID] = edge;
|
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
internal static void Unregister(EcsWorld world, EcsWorld otherWorld)
|
internal static void Unregister(EcsWorld startWorld, EcsWorld endWorld)
|
||||||
{
|
{
|
||||||
int worldID = world.id;
|
int startWorldID = startWorld.id;
|
||||||
int otherWorldID = otherWorld.id;
|
int endWorldID = endWorld.id;
|
||||||
//var manager = _matrix[worldID, otherWorldID];
|
_matrix.Remove(startWorldID, endWorldID);
|
||||||
_matrix.Remove(worldID, otherWorldID);
|
|
||||||
_matrix.Remove(otherWorldID, worldID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static EcsEdge Get(EcsWorld world, EcsWorld otherWorld)
|
internal static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (!_matrix.Contains(world.id, otherWorld.id))
|
if (!_matrix.Contains(startWorld.id, otherWorld.id))
|
||||||
throw new EcsFrameworkException();
|
throw new EcsFrameworkException();
|
||||||
#endif
|
#endif
|
||||||
return _matrix[world.id, otherWorld.id];
|
return _matrix[startWorld.id, otherWorld.id];
|
||||||
}
|
}
|
||||||
internal static bool HasEdge(EcsWorld world, EcsWorld otherWorld) => HasEdge(world.id, otherWorld.id);
|
internal static bool HasArc(EcsWorld startWorld, EcsWorld endWorld) => HasArc(startWorld.id, endWorld.id);
|
||||||
internal static bool HasEdge(int worldID, int otherWorldID) => _matrix.Contains(worldID, otherWorldID);
|
internal static bool HasArc(int startWorldID, int endWorldID) => _matrix.Contains(startWorldID, endWorldID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,44 +44,55 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public static class WorldGraphExtensions
|
public static class WorldGraphExtensions
|
||||||
{
|
{
|
||||||
public static EcsEdge SetEdgeWithSelf(this EcsWorld self) => SetEdgeWith(self, self);
|
public static EcsArc SetLoopArc(this EcsWorld self) => SetArcWith(self, self);
|
||||||
public static EcsEdge SetEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
public static EcsArc SetArcWith(this EcsWorld self, EcsWorld endWorld)
|
||||||
{
|
{
|
||||||
if (self == null || otherWorld == null)
|
if (self == null || endWorld == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
return WorldGraph.Register(self, otherWorld, new EcsEdgeWorld());
|
return WorldGraph.Register(self, endWorld, new EcsArcWorld());
|
||||||
}
|
|
||||||
public static EcsEdge SetEdgeWithSelf(this EcsWorld self, EcsEdgeWorld edgeWorld) => SetEdgeWith(self, self, edgeWorld);
|
|
||||||
public static EcsEdge SetEdgeWith(this EcsWorld self, EcsWorld otherWorld, EcsEdgeWorld edgeWorld)
|
|
||||||
{
|
|
||||||
if (self == null || otherWorld == null || edgeWorld == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
return WorldGraph.Register(self, otherWorld, edgeWorld);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasEdgeWithSelf(this EcsWorld self) => HasEdgeWith(self, self);
|
public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld edgeWorld) => SetEdgeWith(self, self, edgeWorld);
|
||||||
public static bool HasEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
public static EcsArc SetEdgeWith(this EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld edgeWorld)
|
||||||
{
|
{
|
||||||
if (self == null || otherWorld == null)
|
if (startWorld == null || endWorld == null || edgeWorld == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
return WorldGraph.HasEdge(self, otherWorld);
|
return WorldGraph.Register(startWorld, endWorld, edgeWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EcsEdge GetEdgeWithSelf(this EcsWorld self) => GetEdgeWith(self, self);
|
public static bool HasLoopArc(this EcsWorld self) => HasArcWith(self, self);
|
||||||
public static EcsEdge GetEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
public static bool HasArcWith(this EcsWorld startWorld, EcsWorld endWorld)
|
||||||
{
|
{
|
||||||
if (self == null || otherWorld == null)
|
if (startWorld == null || endWorld == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
return WorldGraph.Get(self, otherWorld);
|
return WorldGraph.HasArc(startWorld, endWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DestroyEdgeWithSelf(this EcsWorld self) => DestroyEdgeWith(self, self);
|
public static EcsArc GetLoopArc(this EcsWorld self) => GetArcWith(self, self);
|
||||||
public static void DestroyEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
public static EcsArc GetArcWith(this EcsWorld startWorld, EcsWorld endWorld)
|
||||||
{
|
{
|
||||||
if (self == null || otherWorld == null)
|
if (startWorld == null || endWorld == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
WorldGraph.Get(self, otherWorld).EdgeWorld.Destroy();
|
return WorldGraph.Get(startWorld, endWorld);
|
||||||
WorldGraph.Unregister(self, otherWorld);
|
}
|
||||||
|
|
||||||
|
public static bool TryGetLoopArc(this EcsWorld self, out EcsArc arc) => TryGetArcWith(self, self, out arc);
|
||||||
|
public static bool TryGetArcWith(this EcsWorld startWorld, EcsWorld endWorld, out EcsArc arc)
|
||||||
|
{
|
||||||
|
if (startWorld == null || endWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
bool result = WorldGraph.HasArc(startWorld, endWorld);
|
||||||
|
arc = result ? WorldGraph.Get(startWorld, endWorld) : null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DestroyLoopArc(this EcsWorld self) => DestroyArcWith(self, self);
|
||||||
|
public static void DestroyArcWith(this EcsWorld startWorld, EcsWorld endWorld)
|
||||||
|
{
|
||||||
|
if (startWorld == null || endWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
WorldGraph.Get(startWorld, endWorld).ArcWorld.Destroy();
|
||||||
|
WorldGraph.Unregister(startWorld, endWorld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user