mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 03:34:35 +08:00
update
This commit is contained in:
parent
4e10ec71e9
commit
9d9b7001e4
4
src/Common/EcsEdgeWorld.cs
Normal file
4
src/Common/EcsEdgeWorld.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public sealed class EcsEdgeWorld : EcsWorld { }
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public sealed class EcsRelationWorld : EcsWorld { }
|
|
||||||
}
|
|
@ -5,11 +5,26 @@
|
|||||||
public static readonly RelationTargets Empty = new RelationTargets();
|
public static readonly RelationTargets Empty = new RelationTargets();
|
||||||
public readonly int entity;
|
public readonly int entity;
|
||||||
public readonly int otherEntity;
|
public readonly int otherEntity;
|
||||||
|
|
||||||
|
public bool IsEmpty => entity == 0 && otherEntity == 0;
|
||||||
|
|
||||||
public RelationTargets(int entity, int otherEntity)
|
public RelationTargets(int entity, int otherEntity)
|
||||||
{
|
{
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.otherEntity = otherEntity;
|
this.otherEntity = otherEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is RelationTargets targets &&
|
||||||
|
entity == targets.entity &&
|
||||||
|
otherEntity == targets.otherEntity;
|
||||||
|
}
|
||||||
|
public override int GetHashCode() => ~entity ^ otherEntity;
|
||||||
public override string ToString() => $"rel({entity}, {otherEntity})";
|
public override string ToString() => $"rel({entity}, {otherEntity})";
|
||||||
|
|
||||||
|
|
||||||
|
public static bool operator ==(RelationTargets a, RelationTargets b) => (a.entity == b.entity && a.otherEntity == b.otherEntity);
|
||||||
|
public static bool operator !=(RelationTargets a, RelationTargets b) => a.entity != b.entity || a.otherEntity != b.otherEntity;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,29 +4,19 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
|
//Edge world
|
||||||
//Relation entity
|
//Relation entity
|
||||||
//Relation
|
//Relation
|
||||||
//Relation component
|
//Relation component
|
||||||
public readonly struct RelationData
|
public class EcsEdge : IEcsWorldEventListener, IEcsEntityEventListener
|
||||||
{
|
{
|
||||||
public readonly RelationManager manager;
|
private readonly EcsWorld _world;
|
||||||
public RelationData(RelationManager manager)
|
private readonly EcsWorld _otherWorld;
|
||||||
{
|
private readonly EcsEdgeWorld _edgeWorld;
|
||||||
this.manager = manager;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ref readonly RelationTargets GetRelationTargets(int relationEntityID) => ref manager.GetRelationTargets(relationEntityID);
|
|
||||||
}
|
|
||||||
public class RelationManager : IEcsWorldEventListener, IEcsEntityEventListener
|
|
||||||
{
|
|
||||||
private EcsRelationWorld _relationWorld;
|
|
||||||
|
|
||||||
private EcsWorld _world;
|
|
||||||
private EcsWorld _otherWorld;
|
|
||||||
|
|
||||||
private readonly IdsBasket _basket = new IdsBasket(256);
|
private readonly IdsBasket _basket = new IdsBasket(256);
|
||||||
private readonly IdsBasket _otherBasket = new IdsBasket(256);
|
private readonly IdsBasket _otherBasket = new IdsBasket(256);
|
||||||
private SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
||||||
|
|
||||||
public readonly ForwardOrientation Forward;
|
public readonly ForwardOrientation Forward;
|
||||||
public readonly ReverseOrientation Reverse;
|
public readonly ReverseOrientation Reverse;
|
||||||
@ -34,20 +24,21 @@ namespace DCFApixels.DragonECS
|
|||||||
private RelationTargets[] _relationTargets;
|
private RelationTargets[] _relationTargets;
|
||||||
|
|
||||||
public EcsWorld World => _world;
|
public EcsWorld World => _world;
|
||||||
public EcsWorld RelationWorld => _relationWorld;
|
|
||||||
public EcsWorld OtherWorld => _otherWorld;
|
public EcsWorld OtherWorld => _otherWorld;
|
||||||
|
public EcsEdgeWorld EdgeWorld => _edgeWorld;
|
||||||
|
|
||||||
public bool IsSolo => _world == _otherWorld;
|
public bool IsSolo => _world == _otherWorld;
|
||||||
|
|
||||||
internal RelationManager(EcsWorld world, EcsRelationWorld relationWorld, EcsWorld otherWorld)
|
internal EcsEdge(EcsWorld world, EcsWorld otherWorld, EcsEdgeWorld relationWorld)
|
||||||
{
|
{
|
||||||
_relationWorld = relationWorld;
|
_edgeWorld = relationWorld;
|
||||||
_world = world;
|
_world = world;
|
||||||
_otherWorld = otherWorld;
|
_otherWorld = otherWorld;
|
||||||
|
|
||||||
_relationTargets = new RelationTargets[relationWorld.Capacity];
|
_relationTargets = new RelationTargets[relationWorld.Capacity];
|
||||||
|
|
||||||
_relationWorld.AddListener(worldEventListener: this);
|
_edgeWorld.AddListener(worldEventListener: this);
|
||||||
_relationWorld.AddListener(entityEventListener: this);
|
_edgeWorld.AddListener(entityEventListener: this);
|
||||||
|
|
||||||
Forward = new ForwardOrientation(this);
|
Forward = new ForwardOrientation(this);
|
||||||
Reverse = new ReverseOrientation(this);
|
Reverse = new ReverseOrientation(this);
|
||||||
@ -67,13 +58,23 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
if (HasRelation(entityID, otherEntityID))
|
if (HasRelation(entityID, otherEntityID))
|
||||||
throw new EcsRelationException();
|
throw new EcsRelationException();
|
||||||
int e = _relationWorld.NewEmptyEntity();
|
int e = _edgeWorld.NewEmptyEntity();
|
||||||
_basket.AddToHead(entityID, otherEntityID);
|
_basket.AddToHead(entityID, otherEntityID);
|
||||||
_otherBasket.AddToHead(otherEntityID, entityID);
|
_otherBasket.AddToHead(otherEntityID, entityID);
|
||||||
_relationsMatrix.Add(entityID, otherEntityID, e);
|
_relationsMatrix.Add(entityID, otherEntityID, e);
|
||||||
_relationTargets[e] = new RelationTargets(entityID, otherEntityID);
|
_relationTargets[e] = new RelationTargets(entityID, otherEntityID);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
private void BindRelation(int relationEntityID, int entityID, int otherEntityID)
|
||||||
|
{
|
||||||
|
ref var rel = ref _relationTargets[relationEntityID];
|
||||||
|
if (HasRelation(entityID, otherEntityID) || rel.IsEmpty)
|
||||||
|
throw new EcsRelationException();
|
||||||
|
_basket.AddToHead(entityID, otherEntityID);
|
||||||
|
_otherBasket.AddToHead(otherEntityID, entityID);
|
||||||
|
_relationsMatrix.Add(entityID, otherEntityID, relationEntityID);
|
||||||
|
rel = new RelationTargets(entityID, otherEntityID);
|
||||||
|
}
|
||||||
private void DelRelation(int entityID, int otherEntityID)
|
private void DelRelation(int entityID, int otherEntityID)
|
||||||
{
|
{
|
||||||
if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e))
|
if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e))
|
||||||
@ -81,7 +82,7 @@ namespace DCFApixels.DragonECS
|
|||||||
_relationsMatrix.Remove(entityID, otherEntityID);
|
_relationsMatrix.Remove(entityID, otherEntityID);
|
||||||
_basket.DelHead(entityID);
|
_basket.DelHead(entityID);
|
||||||
_otherBasket.Del(entityID);
|
_otherBasket.Del(entityID);
|
||||||
_relationWorld.DelEntity(e);
|
_edgeWorld.DelEntity(e);
|
||||||
_relationTargets[e] = RelationTargets.Empty;
|
_relationTargets[e] = RelationTargets.Empty;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -113,6 +114,7 @@ namespace DCFApixels.DragonECS
|
|||||||
//}
|
//}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region GetRelations
|
||||||
//#region GetRelations
|
//#region GetRelations
|
||||||
//private IdsLinkedList.Span GetRelations(int entityID)
|
//private IdsLinkedList.Span GetRelations(int entityID)
|
||||||
//{
|
//{
|
||||||
@ -126,6 +128,7 @@ namespace DCFApixels.DragonECS
|
|||||||
//// throw new NotImplementedException();
|
//// throw new NotImplementedException();
|
||||||
////}
|
////}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -146,27 +149,28 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
#region Orientation
|
#region Orientation
|
||||||
public readonly struct ForwardOrientation
|
public readonly struct ForwardOrientation
|
||||||
{
|
{
|
||||||
private readonly RelationManager _source;
|
private readonly EcsEdge _source;
|
||||||
internal ForwardOrientation(RelationManager source) => _source = source;
|
internal ForwardOrientation(EcsEdge source) => _source = source;
|
||||||
public int NewRelation(int entityID, int otherEntityID) => _source.NewRelation(entityID, otherEntityID);
|
public int NewRelation(int entityID, int otherEntityID) => _source.NewRelation(entityID, otherEntityID);
|
||||||
public void DelRelation(int entityID, int otherEntityID) => _source.DelRelation(entityID, otherEntityID);
|
public void BindRelation(int relationEntityID, int entityID, int otherEntityID) => _source.BindRelation(relationEntityID, entityID, otherEntityID);
|
||||||
public bool HasRelation(int entityID, int otherEntityID) => _source.HasRelation(entityID, otherEntityID);
|
public bool HasRelation(int entityID, int otherEntityID) => _source.HasRelation(entityID, otherEntityID);
|
||||||
public int GetRelation(int entityID, int otherEntityID) => _source.GetRelation(entityID, otherEntityID);
|
public int GetRelation(int entityID, int otherEntityID) => _source.GetRelation(entityID, otherEntityID);
|
||||||
|
public void DelRelation(int entityID, int otherEntityID) => _source.DelRelation(entityID, otherEntityID);
|
||||||
public bool TryGetRelation(int entityID, int otherEntityID, out int relationEntityID) => _source.TryGetRelation(entityID, otherEntityID, out relationEntityID);
|
public bool TryGetRelation(int entityID, int otherEntityID, out int relationEntityID) => _source.TryGetRelation(entityID, otherEntityID, out relationEntityID);
|
||||||
public IdsLinkedList.Span GetRelations(int entityID) => _source._basket.GetSpanFor(entityID);
|
public IdsLinkedList.Span GetRelations(int entityID) => _source._basket.GetSpanFor(entityID);
|
||||||
}
|
}
|
||||||
public readonly struct ReverseOrientation
|
public readonly struct ReverseOrientation
|
||||||
{
|
{
|
||||||
private readonly RelationManager _source;
|
private readonly EcsEdge _source;
|
||||||
internal ReverseOrientation(RelationManager source) => _source = source;
|
internal ReverseOrientation(EcsEdge source) => _source = source;
|
||||||
public int NewRelation(int otherEntityID, int entityID) => _source.NewRelation(entityID, otherEntityID);
|
public int NewRelation(int otherEntityID, int entityID) => _source.NewRelation(entityID, otherEntityID);
|
||||||
public void DelRelation(int otherEntityID, int entityID) => _source.DelRelation(entityID, otherEntityID);
|
public void BindRelation(int relationEntityID, int entityID, int otherEntityID) => _source.BindRelation(relationEntityID, otherEntityID, entityID);
|
||||||
public bool HasRelation(int otherEntityID, int entityID) => _source.HasRelation(entityID, otherEntityID);
|
public bool HasRelation(int otherEntityID, int entityID) => _source.HasRelation(entityID, otherEntityID);
|
||||||
public int GetRelation(int otherEntityID, int entityID) => _source.GetRelation(entityID, otherEntityID);
|
public int GetRelation(int otherEntityID, int entityID) => _source.GetRelation(entityID, otherEntityID);
|
||||||
|
public void DelRelation(int otherEntityID, int entityID) => _source.DelRelation(entityID, otherEntityID);
|
||||||
public bool TryGetRelation(int otherEntityID, int entityID, out int relationEntityID) => _source.TryGetRelation(entityID, otherEntityID, out relationEntityID);
|
public bool TryGetRelation(int otherEntityID, int entityID, out int relationEntityID) => _source.TryGetRelation(entityID, otherEntityID, out relationEntityID);
|
||||||
public IdsLinkedList.Span GetRelations(int otherEntityID) => _source._otherBasket.GetSpanFor(otherEntityID);
|
public IdsLinkedList.Span GetRelations(int otherEntityID) => _source._otherBasket.GetSpanFor(otherEntityID);
|
||||||
}
|
}
|
||||||
@ -178,38 +182,4 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WorldRelationExtensions
|
|
||||||
{
|
|
||||||
public static void SetRelationWithSelf(this EcsWorld self) => SetRelationWith(self, self);
|
|
||||||
public static void SetRelationWith(this EcsWorld self, EcsWorld otherWorld)
|
|
||||||
{
|
|
||||||
if (self == null || otherWorld == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
WorldRelationsMatrix.Register(self, otherWorld, new EcsRelationWorld());
|
|
||||||
}
|
|
||||||
public static void SetRelationWithSelf(this EcsWorld self, EcsRelationWorld relationWorld) => SetRelationWith(self, relationWorld);
|
|
||||||
public static void SetRelationWith(this EcsWorld self, EcsWorld otherWorld, EcsRelationWorld relationWorld)
|
|
||||||
{
|
|
||||||
if (self == null || otherWorld == null || relationWorld == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
WorldRelationsMatrix.Register(self, otherWorld, relationWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DelRelationWithSelf(this EcsWorld self, EcsWorld otherWorld) => DelRelationWith(self, self);
|
|
||||||
public static void DelRelationWith(this EcsWorld self, EcsWorld otherWorld)
|
|
||||||
{
|
|
||||||
if (self == null || otherWorld == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
WorldRelationsMatrix.Unregister(self, otherWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RelationManager GetRelationWithSelf(this EcsWorld self) => GetRelationWith(self, self);
|
|
||||||
public static RelationManager GetRelationWith(this EcsWorld self, EcsWorld otherWorld)
|
|
||||||
{
|
|
||||||
if (self == null || otherWorld == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
return WorldRelationsMatrix.Get(self, otherWorld);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
83
src/WorldGraph.cs
Normal file
83
src/WorldGraph.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
using DCFApixels.DragonECS.Relations.Utils;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
internal static class WorldGraph
|
||||||
|
{
|
||||||
|
private static SparseArray64<EcsEdge> _matrix = new SparseArray64<EcsEdge>(4);
|
||||||
|
|
||||||
|
internal static EcsEdge Register(EcsWorld world, EcsWorld otherWorld, EcsEdgeWorld edgeWorld)
|
||||||
|
{
|
||||||
|
int worldID = world.id;
|
||||||
|
int otherWorldID = otherWorld.id;
|
||||||
|
#if DEBUG
|
||||||
|
if (_matrix.Contains(worldID, otherWorldID))
|
||||||
|
throw new EcsFrameworkException();
|
||||||
|
#endif
|
||||||
|
EcsEdge edge = new EcsEdge(world, otherWorld, edgeWorld);
|
||||||
|
_matrix[worldID, otherWorldID] = edge;
|
||||||
|
return edge;
|
||||||
|
}
|
||||||
|
internal static void Unregister(EcsWorld world, EcsWorld otherWorld)
|
||||||
|
{
|
||||||
|
int worldID = world.id;
|
||||||
|
int otherWorldID = otherWorld.id;
|
||||||
|
//var manager = _matrix[worldID, otherWorldID];
|
||||||
|
_matrix.Remove(worldID, otherWorldID);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static EcsEdge Get(EcsWorld world, EcsWorld otherWorld)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (!_matrix.Contains(world.id, otherWorld.id))
|
||||||
|
throw new EcsFrameworkException();
|
||||||
|
#endif
|
||||||
|
return _matrix[world.id, otherWorld.id];
|
||||||
|
}
|
||||||
|
internal static bool HasEdge(EcsWorld world, EcsWorld otherWorld) => HasEdge(world.id, otherWorld.id);
|
||||||
|
internal static bool HasEdge(int worldID, int otherWorldID) => _matrix.Contains(worldID, otherWorldID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WorldGraphExtensions
|
||||||
|
{
|
||||||
|
public static void SetEdgeWithSelf(this EcsWorld self) => SetEdgeWith(self, self);
|
||||||
|
public static void SetEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
||||||
|
{
|
||||||
|
if (self == null || otherWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
WorldGraph.Register(self, otherWorld, new EcsEdgeWorld());
|
||||||
|
}
|
||||||
|
public static void SetEdgeWithSelf(this EcsWorld self, EcsEdgeWorld relationWorld) => SetEdgeWith(self, self, relationWorld);
|
||||||
|
public static void SetEdgeWith(this EcsWorld self, EcsWorld otherWorld, EcsEdgeWorld edgeWorld)
|
||||||
|
{
|
||||||
|
if (self == null || otherWorld == null || edgeWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
WorldGraph.Register(self, otherWorld, edgeWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HasEdgeWithSelf(this EcsWorld self) => HasEdgeWith(self, self);
|
||||||
|
public static void HasEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
||||||
|
{
|
||||||
|
if (self == null || otherWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
WorldGraph.HasEdge(self, otherWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EcsEdge GetEdgeWithSelf(this EcsWorld self) => GetRelationWith(self, self);
|
||||||
|
public static EcsEdge GetRelationWith(this EcsWorld self, EcsWorld otherWorld)
|
||||||
|
{
|
||||||
|
if (self == null || otherWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
return WorldGraph.Get(self, otherWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DelEdgeWithSelf(this EcsWorld self) => DelEdgeWith(self, self);
|
||||||
|
public static void DelEdgeWith(this EcsWorld self, EcsWorld otherWorld)
|
||||||
|
{
|
||||||
|
if (self == null || otherWorld == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
WorldGraph.Unregister(self, otherWorld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,40 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Utils;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
internal static class WorldRelationsMatrix
|
|
||||||
{
|
|
||||||
private static SparseArray64<RelationManager> _matrix = new SparseArray64<RelationManager>(4);
|
|
||||||
|
|
||||||
internal static RelationManager Register(EcsWorld world, EcsWorld otherWorld, EcsRelationWorld relationWorld)
|
|
||||||
{
|
|
||||||
int worldID = world.id;
|
|
||||||
int otherWorldID = otherWorld.id;
|
|
||||||
#if DEBUG
|
|
||||||
if (_matrix.Contains(worldID, otherWorldID))
|
|
||||||
throw new EcsFrameworkException();
|
|
||||||
#endif
|
|
||||||
RelationManager manager = new RelationManager(world, relationWorld, otherWorld);
|
|
||||||
_matrix[worldID, otherWorldID] = manager;
|
|
||||||
return manager;
|
|
||||||
}
|
|
||||||
internal static void Unregister(EcsWorld world, EcsWorld otherWorld)
|
|
||||||
{
|
|
||||||
int worldID = world.id;
|
|
||||||
int otherWorldID = otherWorld.id;
|
|
||||||
//var manager = _matrix[worldID, otherWorldID];
|
|
||||||
_matrix.Remove(worldID, otherWorldID);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static RelationManager Get(EcsWorld world, EcsWorld otherWorld)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
if (!_matrix.Contains(world.id, otherWorld.id))
|
|
||||||
throw new EcsFrameworkException();
|
|
||||||
#endif
|
|
||||||
return _matrix[world.id, otherWorld.id];
|
|
||||||
}
|
|
||||||
internal static bool HasRelation(EcsWorld world, EcsWorld otherWorld) => HasRelation(world.id, otherWorld.id);
|
|
||||||
internal static bool HasRelation(int worldID, int otherWorldID) => _matrix.Contains(worldID, otherWorldID);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user