diff --git a/src/Builtin/EcsJoinExecutor.cs b/src/Builtin/EcsJoinExecutor.cs new file mode 100644 index 0000000..9b0ad23 --- /dev/null +++ b/src/Builtin/EcsJoinExecutor.cs @@ -0,0 +1,124 @@ +/* +namespace DCFApixels.DragonECS +{ + public class EcsJoinExecutor : EcsQueryExecutor, IEcsWorldEventListener + where TAspect : EcsAspect + { + private TAspect _aspect; + //internal EcsGroup _filteredGroup; + + private IdsLinkedList _linkedBasket; + private int[] _mapping; + private int[] _counts; + + private long _executeVersion; + + private int _targetWorldCapacity = -1; + private EcsProfilerMarker _executeMarker = new EcsProfilerMarker("JoinAttach"); + + #region Properties + public TAspect Aspect => _aspect; + internal long ExecuteVersion => _executeVersion; + #endregion + + #region OnInitialize/OnDestroy + protected override void OnInitialize() + { + _linkedBasket = new IdsLinkedList(128); + World.AddListener(this); + _mapping = new int[World.Capacity]; + _counts = new int[World.Capacity]; + } + protected override void OnDestroy() + { + World.RemoveListener(this); + } + #endregion + + public void Clear() + { + _linkedBasket.Clear(); + ArrayUtility.Fill(_mapping, 0, 0, _mapping.Length); + ArrayUtility.Fill(_counts, 0, 0, _counts.Length); + } + + public IdsLinkedList.Span GetEntitiesFor(int entity) + { + ref var nodeIndex = ref _mapping[entity]; + if (nodeIndex <= 0) + return _linkedBasket.EmptySpan(); + else + return _linkedBasket.GetSpan(nodeIndex, _counts[entity]); + } + + #region Execute + public EcsJoinAttachResult Execute() => ExecuteFor(World.Entities); + public EcsJoinAttachResult ExecuteFor(EcsReadonlyGroup sourceGroup) + { + _executeMarker.Begin(); + var world = _aspect.World; +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + if (sourceGroup.IsNull) throw new ArgumentNullException();//TODO составить текст исключения. +#endif +#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS + else + if (World != sourceGroup.World) throw new ArgumentException();//TODO составить текст исключения. это проверка на то что пользователь использует правильный мир +#endif + + //Подготовка массивов + if (_targetWorldCapacity < World.Capacity) + { + _targetWorldCapacity = World.Capacity; + _mapping = new int[_targetWorldCapacity]; + _counts = new int[_targetWorldCapacity]; + } + else + { + ArrayUtility.Fill(_counts, 0); + ArrayUtility.Fill(_mapping, 0); + } + _linkedBasket.Clear(); + //Конец подготовки массивов + + EcsEdge edge = World.GetEdgeWithSelf(); + + var iterator = new EcsAspectIterator(_aspect, sourceGroup); + foreach (var arcEntityID in iterator) + { + var rel = edge.GetRelationTargets(arcEntityID); + + + int sorceEntityID = rel.entity; + //if (!CheckMaskInternal(targetWorldWhereQuery.query.mask, attachTargetID)) continue; //TODO проверить что все работает //исчключить все аттачи, цели которых не входят в targetWorldWhereQuery + + ref int nodeIndex = ref _mapping[sorceEntityID]; + if (nodeIndex <= 0) + nodeIndex = _linkedBasket.Add(arcEntityID); + else + _linkedBasket.InsertAfter(nodeIndex, arcEntityID); + _counts[sorceEntityID]++; + } + + _executeVersion++; + _executeMarker.End(); + + return new EcsJoinAttachResult(_aspect, this, _executeVersion); + } + #endregion + + #region IEcsWorldEventListener + void IEcsWorldEventListener.OnWorldResize(int newSize) + { + Array.Resize(ref _mapping, newSize); + Array.Resize(ref _counts, newSize); + } + void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) + { + } + void IEcsWorldEventListener.OnWorldDestroy() + { + } + #endregion + } +} +*/ diff --git a/src/EcsEdge.cs b/src/EcsEdge.cs index 89f3ed9..01605b8 100644 --- a/src/EcsEdge.cs +++ b/src/EcsEdge.cs @@ -1,5 +1,6 @@ using DCFApixels.DragonECS.Relations.Utils; using System; +using System.Collections.Generic; using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS @@ -13,68 +14,87 @@ namespace DCFApixels.DragonECS 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 _relationsMatrix = new SparseArray64(); - public readonly ForwardOrientation Forward; - public readonly ReverseOrientation Reverse; + private ArcTargets[] _arkTargets; //N * (N - 1) / 2 - private RelationTargets[] _relationTargets; + private List> _groups = new List>(); + private Stack _groupsPool = new Stack(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; - _relationTargets = new RelationTargets[edgeWorld.Capacity]; + _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); - - Forward = new ForwardOrientation(this); - Reverse = new ReverseOrientation(this); } + #endregion - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref readonly RelationTargets GetRelationTargets(int arcEntityID) + #region Join Groups Pool + internal void RegisterGroup(EcsJoinGroup group) { - return ref _relationTargets[arcEntityID]; + _groups.Add(new WeakReference(group)); } - - #region Methods + 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 - private int NewRelation(int entityID, int otherEntityID) + public int New(int entityID, int otherEntityID) { - - if (HasRelation(entityID, otherEntityID)) + if (Has(entityID, otherEntityID)) throw new EcsRelationException(); - int e = _edgeWorld.NewEmptyEntity(); + int arcEntity = _edgeWorld.NewEntity(); _basket.AddToHead(entityID, otherEntityID); _otherBasket.AddToHead(otherEntityID, entityID); - _relationsMatrix.Add(entityID, otherEntityID, e); - _relationTargets[e] = new RelationTargets(entityID, otherEntityID); - return e; + _relationsMatrix.Add(entityID, otherEntityID, arcEntity); + _arkTargets[arcEntity] = new ArcTargets(entityID, otherEntityID); + return arcEntity; } - 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) + public void Del(int entityID, int otherEntityID) { if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e)) throw new EcsRelationException(); @@ -82,28 +102,25 @@ namespace DCFApixels.DragonECS _basket.DelHead(entityID); _otherBasket.Del(entityID); _edgeWorld.DelEntity(e); - _relationTargets[e] = RelationTargets.Empty; + _arkTargets[e] = ArcTargets.Empty; } #endregion - #region Has - private bool HasRelation(int entityID, int otherEntityID) => _relationsMatrix.Contains(entityID, otherEntityID); + #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); //} - #endregion - - #region GetRelation - private int GetRelation(int entityID, int otherEntityID) + public int Get(int entityID, int otherEntityID) { if (!_relationsMatrix.TryGetValue(entityID, otherEntityID, out int e)) throw new EcsRelationException(); return e; } - private bool TryGetRelation(int entityID, int otherEntityID, out int entity) + private bool TryGet(int entityID, int otherEntityID, out int entity) { return _relationsMatrix.TryGetValue(entityID, otherEntityID, out entity); } @@ -111,9 +128,7 @@ namespace DCFApixels.DragonECS //{ // return _source._relationsMatrix.TryGetValue(entityID, otherEntityID, out entity) && subject.IsMatches(entity); //} - #endregion - #region GetRelations //#region GetRelations //private IdsLinkedList.Span GetRelations(int entityID) //{ @@ -129,12 +144,31 @@ namespace DCFApixels.DragonECS //#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 _relationTargets, newSize); + Array.Resize(ref _arkTargets, newSize); } void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan buffer) { } void IEcsWorldEventListener.OnWorldDestroy() { } @@ -142,100 +176,38 @@ namespace DCFApixels.DragonECS void IEcsEntityEventListener.OnNewEntity(int entityID) { } void IEcsEntityEventListener.OnDelEntity(int entityID) { - ref RelationTargets rel = ref _relationTargets[entityID]; - if (_relationsMatrix.Contains(rel.entity, rel.otherEntity)) - Forward.Del(rel.entity, rel.otherEntity); + ref ArcTargets rel = ref _arkTargets[entityID]; + if (_relationsMatrix.Contains(rel.start, rel.end)) + Del(rel.start, rel.end); } #endregion - #region Orientation - public readonly struct ForwardOrientation : IEcsEdgeOrientation + #region VertexWorldHandler + private class VertexWorldHandler : IEcsEntityEventListener { private readonly EcsEdge _source; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ForwardOrientation(EcsEdge source) => _source = source; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int New(int entityID, int otherEntityID) => _source.NewRelation(entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Bind(int arcEntityID, int entityID, int otherEntityID) => _source.BindRelation(arcEntityID, entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int entityID, int otherEntityID) => _source.HasRelation(entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Get(int entityID, int otherEntityID) => _source.GetRelation(entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGet(int entityID, int otherEntityID, out int arcEntityID) => _source.TryGetRelation(entityID, otherEntityID, out arcEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IdsLinkedList.Span Get(int entityID) => _source._basket.GetSpanFor(entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IdsLinkedList.LongSpan GetLongs(int entityID) => _source._basket.GetLongSpanFor(_source._world, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Del(int entityID, int otherEntityID) => _source.DelRelation(entityID, otherEntityID); - } - public readonly struct ReverseOrientation : IEcsEdgeOrientation - { - private readonly EcsEdge _source; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ReverseOrientation(EcsEdge source) => _source = source; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int New(int otherEntityID, int entityID) => _source.NewRelation(entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Bind(int arcEntityID, int entityID, int otherEntityID) => _source.BindRelation(arcEntityID, otherEntityID, entityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Has(int otherEntityID, int entityID) => _source.HasRelation(entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public int Get(int otherEntityID, int entityID) => _source.GetRelation(entityID, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGet(int otherEntityID, int entityID, out int arcEntityID) => _source.TryGetRelation(entityID, otherEntityID, out arcEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IdsLinkedList.Span Get(int otherEntityID) => _source._otherBasket.GetSpanFor(otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IdsLinkedList.LongSpan GetLongs(int otherEntityID) => _source._otherBasket.GetLongSpanFor(_source._otherWorld, otherEntityID); - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Del(int otherEntityID, int entityID) => _source.DelRelation(entityID, otherEntityID); - } + private readonly EcsWorld _world; + private readonly IdsBasket _basket; - //public readonly ref struct FilterIterator - //{ - // private readonly IdsLinkedList.Span _listSpan; - // private readonly EcsMask _mask; - // public FilterIterator(EcsWorld world, IdsLinkedList.Span listSpan, EcsMask mask) - // { - // _listSpan = listSpan; - // _mask = mask; - // } - // public Enumerator GetEnumerator() => new Enumerator(_listSpan, _mask); - // public ref struct Enumerator - // { - // private readonly IdsLinkedList.SpanEnumerator _listEnumerator; - // private readonly EcsMask _mask; - // public Enumerator(IdsLinkedList.Span listSpan, EcsMask mask) - // { - // _listEnumerator = listSpan.GetEnumerator(); - // _mask = mask; - // } - // public int Current => _listEnumerator.Current; - // public bool MoveNext() - // { - // while (_listEnumerator.MoveNext()) - // { - // int e = _listEnumerator.Current; - // ... - // } - // return false; - // } - // } - //} + 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 } - public interface IEcsEdgeOrientation - { - public int New(int entityID, int otherEntityID); - public void Bind(int arcEntityID, int entityID, int otherEntityID); - public bool Has(int entityID, int otherEntityID); - public int Get(int entityID, int otherEntityID); - public bool TryGet(int otherEntityID, int entityID, out int arcEntityID); - public IdsLinkedList.Span Get(int entityID); - public IdsLinkedList.LongSpan GetLongs(int entityID); - public void Del(int entityID, int otherEntityID); - } } \ No newline at end of file diff --git a/src/EcsJoinGroup.cs b/src/EcsJoinGroup.cs new file mode 100644 index 0000000..3922626 --- /dev/null +++ b/src/EcsJoinGroup.cs @@ -0,0 +1,69 @@ +using DCFApixels.DragonECS.Relations.Utils; +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS +{ + public class EcsJoinGroup + { + private EcsEdge _source; + + private int[] _mapping; + private int[] _counts; + private IdsLinkedList _linkedList; + internal bool _isReleased = true; + + #region Properites + public EcsEdge Edge => _source; + #endregion + + + #region Constrcutors/Dispose + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static EcsJoinGroup New(EcsEdge edge) + { + return edge.GetFreeGroup(); + } + internal EcsJoinGroup(EcsEdge edge, int denseCapacity = 64) + { + _source = edge; + _source.RegisterGroup(this); + int capacity = edge.World.Capacity; + + _mapping = new int[capacity]; + _counts = new int[capacity]; + } + public void Dispose() => _source.ReleaseGroup(this); + #endregion + + public void Add(int entityFrom, int entityTo) + { + ref int nodeIndex = ref _mapping[entityFrom]; + if (nodeIndex <= 0) + { + nodeIndex = _linkedList.Add(entityTo); + _counts[entityFrom] = 1; + } + else + { + _linkedList.InsertAfter(nodeIndex, entityTo); + _counts[entityFrom]++; + } + } + + public IdsLinkedList.Span GetEntitiesFor(int entity) + { + ref var nodeIndex = ref _mapping[entity]; + if (nodeIndex <= 0) + return _linkedList.EmptySpan(); + else + return _linkedList.GetSpan(nodeIndex, _counts[entity]); + } + + public void Clear() + { + _linkedList.Clear(); + for (int i = 0; i < _mapping.Length; i++) + _mapping[i] = 0; + } + } +} diff --git a/src/Utils/ArcTargets.cs b/src/Utils/ArcTargets.cs new file mode 100644 index 0000000..c90b65e --- /dev/null +++ b/src/Utils/ArcTargets.cs @@ -0,0 +1,49 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace DCFApixels.DragonECS +{ + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] + [Serializable] + public readonly struct ArcTargets : IEquatable + { + public static readonly ArcTargets Empty = new ArcTargets(); + + /// Start vertex entity ID. + public readonly int start; + /// End vertex entity ID. + public readonly int end; + + #region Properties + public bool IsEmpty + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => start == 0 && end == 0; + } + #endregion + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal ArcTargets(int startEntity, int endEntity) + { + start = startEntity; + end = endEntity; + } + + #region operators + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(ArcTargets a, ArcTargets b) => a.start == b.start && a.end == b.end; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(ArcTargets a, ArcTargets b) => a.start != b.start || a.end != b.end; + #endregion + + #region Other + public override bool Equals(object obj) => obj is ArcTargets targets && targets == this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(ArcTargets other) => this == other; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() => ~start ^ end; + public override string ToString() => $"arc({start} -> {end})"; + #endregion + } +} \ No newline at end of file diff --git a/src/Utils/ArrayUtility.cs b/src/Utils/ArrayUtility.cs index 90b3a04..7d15f07 100644 --- a/src/Utils/ArrayUtility.cs +++ b/src/Utils/ArrayUtility.cs @@ -1,4 +1,8 @@ -namespace DCFApixels.DragonECS.Relations.Utils +using System.Runtime.InteropServices; +using System; +using System.Runtime.CompilerServices; + +namespace DCFApixels.DragonECS.Relations.Utils { internal static class ArrayUtility { @@ -12,4 +16,4 @@ array[i] = value; } } -} +} \ No newline at end of file diff --git a/src/Utils/RelationTargets.cs b/src/Utils/RelationTargets.cs deleted file mode 100644 index 2e97f79..0000000 --- a/src/Utils/RelationTargets.cs +++ /dev/null @@ -1,83 +0,0 @@ -#pragma warning disable IDE1006 // Стили именования -using DCFApixels.DragonECS.Utils; -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace DCFApixels.DragonECS -{ - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] - [Serializable] - public readonly struct RelationTargets : IEquatable - { - public static readonly RelationTargets Empty = new RelationTargets(); - - public readonly int entity; - public readonly int otherEntity; - - #region Properties - public int left - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => IsInverted ? otherEntity : entity; - } - public int right - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => IsInverted ? entity : otherEntity; - } - - public bool IsInverted - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => entity > otherEntity; // направление всегда с меньшего к большему - } - public bool IsEmpty - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => entity == 0 && otherEntity == 0; - } - - public RelationTargets Inverted - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new RelationTargets(otherEntity, entity); - } - #endregion - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal RelationTargets(int entity, int otherEntity) - { - this.entity = entity; - this.otherEntity = otherEntity; - } - - #region operators - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static RelationTargets operator -(RelationTargets a) => a.Inverted; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(RelationTargets a, RelationTargets b) => a.entity == b.entity && a.otherEntity == b.otherEntity; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(RelationTargets a, RelationTargets b) => a.entity != b.entity || a.otherEntity != b.otherEntity;s - #endregion - - #region Other - public override bool Equals(object obj) - { - return obj is RelationTargets targets && - entity == targets.entity && - otherEntity == targets.otherEntity; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(RelationTargets other) => this == other; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override int GetHashCode() => ~entity ^ otherEntity; - public override string ToString() - { - return IsInverted ? - $"rel({entity} <- {otherEntity})" : - $"rel({entity} -> {otherEntity})"; - } - #endregion - } -} \ No newline at end of file diff --git a/src/WorldGraph.cs b/src/WorldGraph.cs index 2512539..fbdc572 100644 --- a/src/WorldGraph.cs +++ b/src/WorldGraph.cs @@ -1,6 +1,5 @@ using DCFApixels.DragonECS.Relations.Internal; using DCFApixels.DragonECS.Relations.Utils; -using Leopotam.EcsLite; using System; namespace DCFApixels.DragonECS.Relations.Internal @@ -45,7 +44,7 @@ namespace DCFApixels.DragonECS.Relations.Internal } namespace DCFApixels.DragonECS -{ +{ public static class WorldGraphExtensions { public static EcsEdge SetEdgeWithSelf(this EcsWorld self) => SetEdgeWith(self, self); @@ -63,12 +62,12 @@ namespace DCFApixels.DragonECS return WorldGraph.Register(self, otherWorld, edgeWorld); } - public static void HasEdgeWithSelf(this EcsWorld self) => HasEdgeWith(self, self); - public static void HasEdgeWith(this EcsWorld self, EcsWorld otherWorld) + public static bool HasEdgeWithSelf(this EcsWorld self) => HasEdgeWith(self, self); + public static bool HasEdgeWith(this EcsWorld self, EcsWorld otherWorld) { if (self == null || otherWorld == null) throw new ArgumentNullException(); - WorldGraph.HasEdge(self, otherWorld); + return WorldGraph.HasEdge(self, otherWorld); } public static EcsEdge GetEdgeWithSelf(this EcsWorld self) => GetEdgeWith(self, self);