mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-19 04:24:35 +08:00
without matrix
This commit is contained in:
parent
f865989c2d
commit
d6c0a22221
@ -1,450 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using static DCFApixels.DragonECS.EcsGraph;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public readonly ref struct EcsReadonlyGraph
|
|
||||||
{
|
|
||||||
private readonly EcsGraph _source;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public bool IsNull => _source == null;
|
|
||||||
public EcsArc Arc
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.Arc; }
|
|
||||||
}
|
|
||||||
public EcsWorld StartWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.StartWorld; }
|
|
||||||
}
|
|
||||||
public EcsWorld EndWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.EndWorld; }
|
|
||||||
}
|
|
||||||
public EcsArcWorld ArcWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.ArcWorld; }
|
|
||||||
}
|
|
||||||
public int ArcWorldID
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.ArcWorldID; }
|
|
||||||
}
|
|
||||||
public bool IsLoopArc
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.IsLoopArc; }
|
|
||||||
}
|
|
||||||
public EnumerableRelEnd this[int startEntityID]
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source[startEntityID]; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public EcsReadonlyGraph(EcsGraph source) { _source = source; }
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool Has(int relEntityID) { return _source.Has(relEntityID); }
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool HasStart(int startEntityID) { return _source.HasStart(startEntityID); }
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool HasEnd(int endEntityID) { return _source.HasEnd(endEntityID); }
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public EnumerableRelEnd GetRelEnds(int startEntityID) { return _source.GetRelEnds(startEntityID); }
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Internal
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
internal EcsGraph GetSource_Internal() => _source;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Other
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _source != null ? _source.ToString() : "NULL";
|
|
||||||
}
|
|
||||||
#pragma warning disable CS0809 // Устаревший член переопределяет неустаревший член
|
|
||||||
[Obsolete("Equals() on EcsGroup will always throw an exception. Use the equality operator instead.")]
|
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
||||||
public override bool Equals(object obj) => throw new NotSupportedException();
|
|
||||||
[Obsolete("GetHashCode() on EcsGroup will always throw an exception.")]
|
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
||||||
public override int GetHashCode() => throw new NotSupportedException();
|
|
||||||
#pragma warning restore CS0809 // Устаревший член переопределяет неустаревший член
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
//[DebuggerTypeProxy(typeof(DebuggerProxy))]
|
|
||||||
public class EcsGraph
|
|
||||||
{
|
|
||||||
private readonly EcsArc _source;
|
|
||||||
private readonly bool _isLoop;
|
|
||||||
|
|
||||||
private readonly BasketList _startBaskets;
|
|
||||||
private readonly BasketList _endBaskets;
|
|
||||||
private RelNodesInfo[] _relNodesMapping;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public EcsReadonlyGraph Readonly
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return new EcsReadonlyGraph(this); }
|
|
||||||
}
|
|
||||||
public EcsArc Arc
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source; }
|
|
||||||
}
|
|
||||||
public EcsWorld StartWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.StartWorld; }
|
|
||||||
}
|
|
||||||
public EcsWorld EndWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.EndWorld; }
|
|
||||||
}
|
|
||||||
public EcsArcWorld ArcWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.ArcWorld; }
|
|
||||||
}
|
|
||||||
public int ArcWorldID
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _source.ArcWorldID; }
|
|
||||||
}
|
|
||||||
public bool IsLoopArc
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _isLoop; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumerableRelEnd this[int startEntityID]
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return GetRelEnds(startEntityID); }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
public EcsGraph(EcsArc arc)
|
|
||||||
{
|
|
||||||
_source = arc;
|
|
||||||
_isLoop = arc.IsLoop;
|
|
||||||
|
|
||||||
_startBaskets = new BasketList();
|
|
||||||
_endBaskets = new BasketList();
|
|
||||||
|
|
||||||
_relNodesMapping = new RelNodesInfo[arc.ArcWorld.Capacity];
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Add/Del
|
|
||||||
public void Add(int startEntityID, int endEntityID, int relEntityID)
|
|
||||||
{
|
|
||||||
_relNodesMapping[relEntityID] = new RelNodesInfo(
|
|
||||||
_startBaskets.AddToBasket(startEntityID, relEntityID),
|
|
||||||
_endBaskets.AddToBasket(endEntityID, relEntityID));
|
|
||||||
}
|
|
||||||
public void Add(int relEntityID)
|
|
||||||
{
|
|
||||||
var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID);
|
|
||||||
_relNodesMapping[relEntityID] = new RelNodesInfo(
|
|
||||||
_startBaskets.AddToBasket(startEntityID, relEntityID),
|
|
||||||
_endBaskets.AddToBasket(endEntityID, relEntityID));
|
|
||||||
}
|
|
||||||
public void Del(int relEntityID)
|
|
||||||
{
|
|
||||||
var (startEntityID, endEntityID) = _source.GetRelationInfo(relEntityID);
|
|
||||||
ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
|
|
||||||
_startBaskets.RemoveFromBasket(startEntityID, relInfo.startNodeIndex);
|
|
||||||
_endBaskets.RemoveFromBasket(endEntityID, relInfo.endNodeIndex);
|
|
||||||
}
|
|
||||||
public void DelStart(int startEntityID)
|
|
||||||
{
|
|
||||||
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
|
|
||||||
{
|
|
||||||
var endEntityID = _source.GetRelEnd(relEntityID);
|
|
||||||
ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
|
|
||||||
_endBaskets.RemoveFromBasket(endEntityID, relInfo.startNodeIndex);
|
|
||||||
}
|
|
||||||
_startBaskets.RemoveBasket(startEntityID);
|
|
||||||
}
|
|
||||||
public void DelEnd(int endEntityID)
|
|
||||||
{
|
|
||||||
foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID))
|
|
||||||
{
|
|
||||||
var startEntityID = _source.GetRelStart(relEntityID);
|
|
||||||
ref RelNodesInfo relInfo = ref _relNodesMapping[relEntityID];
|
|
||||||
_startBaskets.RemoveFromBasket(startEntityID, relInfo.endNodeIndex);
|
|
||||||
}
|
|
||||||
_endBaskets.RemoveBasket(endEntityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void DelStartAndDelRelEntities(int startEntityID, EcsArc arc)
|
|
||||||
{
|
|
||||||
|
|
||||||
foreach (var relEntityID in _startBaskets.GetBasketIterator(startEntityID))
|
|
||||||
{
|
|
||||||
arc.ArcWorld.TryDelEntity(relEntityID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
|
|
||||||
{
|
|
||||||
foreach (var relEntityID in _endBaskets.GetBasketIterator(endEntityID))
|
|
||||||
{
|
|
||||||
arc.ArcWorld.TryDelEntity(relEntityID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public struct FriendEcsArc
|
|
||||||
{
|
|
||||||
private EcsGraph _join;
|
|
||||||
public FriendEcsArc(EcsArc arc, EcsGraph join)
|
|
||||||
{
|
|
||||||
if (arc.IsInit_Internal != false)
|
|
||||||
{
|
|
||||||
Throw.UndefinedException();
|
|
||||||
}
|
|
||||||
_join = join;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void DelStartAndDelRelEntities(int startEntityID, EcsArc arc)
|
|
||||||
{
|
|
||||||
_join.DelStartAndDelRelEntities(startEntityID, arc);
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void DelEndAndDelRelEntities(int endEntityID, EcsArc arc)
|
|
||||||
{
|
|
||||||
_join.DelEndAndDelRelEntities(endEntityID, arc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Has
|
|
||||||
public bool Has(int relEntityID)
|
|
||||||
{
|
|
||||||
return _relNodesMapping[relEntityID] != RelNodesInfo.Empty;
|
|
||||||
}
|
|
||||||
public bool HasStart(int startEntityID)
|
|
||||||
{
|
|
||||||
return _startBaskets.GetBasketNodesCount(startEntityID) > 0;
|
|
||||||
}
|
|
||||||
public bool HasEnd(int endEntityID)
|
|
||||||
{
|
|
||||||
return _endBaskets.GetBasketNodesCount(endEntityID) > 0;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Clear
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_startBaskets.Clear();
|
|
||||||
if (!_isLoop)
|
|
||||||
{
|
|
||||||
_endBaskets.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region GetRelEnds
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public EnumerableRelEnd GetRelEnds(int startEntityID)
|
|
||||||
{
|
|
||||||
return new EnumerableRelEnd(_source, _startBaskets.GetBasketIterator(startEntityID).GetEnumerator());
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region EnumerableArcEnd
|
|
||||||
public readonly ref struct EnumerableRelEnd //: IEnumerable<RelEnd>
|
|
||||||
{
|
|
||||||
private readonly EcsArc _arc;
|
|
||||||
private readonly BasketList.BasketIterator.Enumerator _iterator;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
internal EnumerableRelEnd(EcsArc arc, BasketList.BasketIterator.Enumerator iterator)
|
|
||||||
{
|
|
||||||
_arc = arc;
|
|
||||||
_iterator = iterator;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Enumerator GetEnumerator() { return new Enumerator(_arc, _iterator); }
|
|
||||||
//IEnumerator<RelEnd> IEnumerable<RelEnd>.GetEnumerator() { return GetEnumerator(); }
|
|
||||||
//IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
|
||||||
public ref struct Enumerator //: IEnumerator<RelEnd>
|
|
||||||
{
|
|
||||||
private readonly EcsArc _arc;
|
|
||||||
private BasketList.BasketIterator.Enumerator _iterator;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
internal Enumerator(EcsArc arc, BasketList.BasketIterator.Enumerator iterator)
|
|
||||||
{
|
|
||||||
_arc = arc;
|
|
||||||
_iterator = iterator;
|
|
||||||
}
|
|
||||||
public RelEnd Current
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get
|
|
||||||
{
|
|
||||||
int currentArc = _iterator.Current;
|
|
||||||
return new RelEnd(currentArc, _arc.GetRelEnd(currentArc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//object IEnumerator.Current => Current;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool MoveNext() { return _iterator.MoveNext(); }
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//public void Reset() { }
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//public void Dispose() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ArcInfo
|
|
||||||
private struct RelNodesInfo : IEquatable<RelNodesInfo>
|
|
||||||
{
|
|
||||||
public readonly static RelNodesInfo Empty = default;
|
|
||||||
public int startNodeIndex;
|
|
||||||
public int endNodeIndex;
|
|
||||||
public RelNodesInfo(int startNodeIndex, int endNodeIndex)
|
|
||||||
{
|
|
||||||
this.startNodeIndex = startNodeIndex;
|
|
||||||
this.endNodeIndex = endNodeIndex;
|
|
||||||
}
|
|
||||||
#region Object
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
return obj is RelNodesInfo && Equals((RelNodesInfo)obj);
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool Equals(RelNodesInfo other)
|
|
||||||
{
|
|
||||||
return startNodeIndex == other.startNodeIndex &&
|
|
||||||
endNodeIndex == other.endNodeIndex;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return ~startNodeIndex ^ endNodeIndex;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region operators
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static bool operator ==(RelNodesInfo a, RelNodesInfo b) => a.startNodeIndex == b.startNodeIndex && a.endNodeIndex == b.endNodeIndex;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static bool operator !=(RelNodesInfo a, RelNodesInfo b) => a.startNodeIndex != b.startNodeIndex || a.endNodeIndex != b.endNodeIndex;
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Operators
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static implicit operator EcsReadonlyGraph(EcsGraph a) => a.Readonly;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region UpSize
|
|
||||||
public void UpArcSize(int minSize)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _relNodesMapping, minSize);
|
|
||||||
}
|
|
||||||
public void UpStartSize(int minSize)
|
|
||||||
{
|
|
||||||
_startBaskets.UpBasketsSize(minSize);
|
|
||||||
}
|
|
||||||
public void UpEndSize(int minSize)
|
|
||||||
{
|
|
||||||
_endBaskets.UpBasketsSize(minSize);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region DebuggerProxy
|
|
||||||
//internal class DebuggerProxy
|
|
||||||
//{
|
|
||||||
// private EcsJoinGroup _basket;
|
|
||||||
//
|
|
||||||
// public SpanDebugInfo[] HeadSpans => GetSpans(_basket._startList, _basket._startMapping);
|
|
||||||
// public SpanDebugInfo[] ValueSpans => GetSpans(_basket._endList, _basket._endMapping);
|
|
||||||
//
|
|
||||||
// private SpanDebugInfo[] GetSpans(IdsLinkedList list, SpanInfo[] mapping)
|
|
||||||
// {
|
|
||||||
// SpanDebugInfo[] result = new SpanDebugInfo[mapping.Length];
|
|
||||||
// for (int i = 0; i < mapping.Length; i++)
|
|
||||||
// result[i] = new SpanDebugInfo(list, mapping[i].nodeIndex, mapping[i].count);
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
// public DebuggerProxy(EcsJoinGroup basket)
|
|
||||||
// {
|
|
||||||
// _basket = basket;
|
|
||||||
// }
|
|
||||||
// public struct SpanDebugInfo
|
|
||||||
// {
|
|
||||||
// private IdsLinkedList _list;
|
|
||||||
// public int index;
|
|
||||||
// public int count;
|
|
||||||
// public NodeDebugInfo[] Nodes
|
|
||||||
// {
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// var result = new NodeDebugInfo[this.count];
|
|
||||||
// var nodes = _list.Nodes;
|
|
||||||
// int index;
|
|
||||||
// int count = this.count;
|
|
||||||
// int next = this.index;
|
|
||||||
// int i = 0;
|
|
||||||
// while (true)
|
|
||||||
// {
|
|
||||||
// index = next;
|
|
||||||
// next = nodes[next].next;
|
|
||||||
// if (!(index > 0 && count-- > 0))
|
|
||||||
// break;
|
|
||||||
// var node = nodes[index];
|
|
||||||
// result[i] = new NodeDebugInfo(index, node.prev, node.next, node.value);
|
|
||||||
// i++;
|
|
||||||
// }
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// public SpanDebugInfo(IdsLinkedList list, int index, int count)
|
|
||||||
// {
|
|
||||||
// _list = list;
|
|
||||||
// this.index = index;
|
|
||||||
// this.count = count;
|
|
||||||
// }
|
|
||||||
// public override string ToString() => $"[{index}] {count}";
|
|
||||||
// }
|
|
||||||
// public struct NodeDebugInfo
|
|
||||||
// {
|
|
||||||
// public int index;
|
|
||||||
// public int prev;
|
|
||||||
// public int next;
|
|
||||||
// public int value;
|
|
||||||
// public NodeDebugInfo(int index, int prev, int next, int value)
|
|
||||||
// {
|
|
||||||
// this.index = index;
|
|
||||||
// this.prev = prev;
|
|
||||||
// this.next = next;
|
|
||||||
// this.value = value;
|
|
||||||
// }
|
|
||||||
// public override string ToString() => $"[{index}] {prev}_{next} - {value}";
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
108
src/EcsArc.cs
108
src/EcsArc.cs
@ -1,8 +1,6 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
using DCFApixels.DragonECS.Relations.Internal;
|
||||||
using DCFApixels.DragonECS.Relations.Utils;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Xml;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
@ -21,11 +19,6 @@ namespace DCFApixels.DragonECS
|
|||||||
private readonly EndWorldHandler _endWorldHandler;
|
private readonly EndWorldHandler _endWorldHandler;
|
||||||
private readonly LoopWorldHandler _loopWorldHandler;
|
private readonly LoopWorldHandler _loopWorldHandler;
|
||||||
|
|
||||||
//private readonly SparseArray64<int> _relationsMatrix = new SparseArray64<int>();
|
|
||||||
|
|
||||||
private EcsGraph _entitiesGraph;
|
|
||||||
private EcsGraph.FriendEcsArc _entitiesGraphFriend;
|
|
||||||
|
|
||||||
private EcsGroup _relEntities;
|
private EcsGroup _relEntities;
|
||||||
private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2
|
private RelEntityInfo[] _relEntityInfos; //N * (N - 1) / 2
|
||||||
|
|
||||||
@ -63,11 +56,6 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _relEntities.Readonly; }
|
get { return _relEntities.Readonly; }
|
||||||
}
|
}
|
||||||
public EcsReadonlyGraph EntitiesGraph
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _entitiesGraph.Readonly; }
|
|
||||||
}
|
|
||||||
public bool IsLoop
|
public bool IsLoop
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -88,9 +76,6 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
|
|
||||||
_relEntities = EcsGroup.New(_arcWorld);
|
_relEntities = EcsGroup.New(_arcWorld);
|
||||||
_entitiesGraph = new EcsGraph(this);
|
|
||||||
|
|
||||||
_entitiesGraphFriend = new EcsGraph.FriendEcsArc(this, _entitiesGraph);
|
|
||||||
|
|
||||||
_arcWorldHandler = new ArcWorldHandler(this);
|
_arcWorldHandler = new ArcWorldHandler(this);
|
||||||
if (_isLoop)
|
if (_isLoop)
|
||||||
@ -124,30 +109,11 @@ namespace DCFApixels.DragonECS
|
|||||||
#region New/Del
|
#region New/Del
|
||||||
public int NewRelation(int startEntityID, int endEntityID)
|
public int NewRelation(int startEntityID, int endEntityID)
|
||||||
{
|
{
|
||||||
//if (HasRelation(startEntityID, endEntityID))
|
|
||||||
//{
|
|
||||||
// Throw.RelationAlreadyExists();
|
|
||||||
//}
|
|
||||||
|
|
||||||
int relEntity = _arcWorld.NewEntity();
|
int relEntity = _arcWorld.NewEntity();
|
||||||
//_relationsMatrix.Add(startEntityID, endEntityID, relEntity);
|
|
||||||
|
|
||||||
_relEntityInfos[relEntity] = new RelEntityInfo(startEntityID, endEntityID);
|
_relEntityInfos[relEntity] = new RelEntityInfo(startEntityID, endEntityID);
|
||||||
_relEntities.Add(relEntity);
|
_relEntities.Add(relEntity);
|
||||||
_entitiesGraph.Add(startEntityID, endEntityID, relEntity);
|
|
||||||
return relEntity;
|
return relEntity;
|
||||||
}
|
}
|
||||||
//public void DelRelation(int startEntityID, int endEntityID)
|
|
||||||
//{
|
|
||||||
// if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntityID))
|
|
||||||
// {
|
|
||||||
// _arcWorld.DelEntity(relEntityID);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// Throw.UndefinedRelationException();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public void DelRelation(int relEntityID)
|
public void DelRelation(int relEntityID)
|
||||||
{
|
{
|
||||||
@ -157,39 +123,8 @@ namespace DCFApixels.DragonECS
|
|||||||
public void ClearRelation_Internal(int relEntityID)
|
public void ClearRelation_Internal(int relEntityID)
|
||||||
{
|
{
|
||||||
_relEntities.Remove(relEntityID);
|
_relEntities.Remove(relEntityID);
|
||||||
_entitiesGraph.Del(relEntityID);
|
|
||||||
_relEntityInfos[relEntityID] = RelEntityInfo.Empty;
|
_relEntityInfos[relEntityID] = RelEntityInfo.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
//private void ClearRelation_Internal(int startEntityID, int endEntityID)
|
|
||||||
//{
|
|
||||||
// if (_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntityID))
|
|
||||||
// {
|
|
||||||
// _relEntities.Remove(relEntityID);
|
|
||||||
// _entitiesGraph.Del(relEntityID);
|
|
||||||
// _relationsMatrix.Remove(startEntityID, endEntityID);
|
|
||||||
// _relEntityInfos[relEntityID] = RelEntityInfo.Empty;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region GetRelation/HasRelation
|
|
||||||
//public bool HasRelation(int startEntityID, int endEntityID)
|
|
||||||
//{
|
|
||||||
// return _relationsMatrix.Contains(startEntityID, endEntityID);
|
|
||||||
//}
|
|
||||||
//public int GetRelation(int startEntityID, int endEntityID)
|
|
||||||
//{
|
|
||||||
// if (!_relationsMatrix.TryGetValue(startEntityID, endEntityID, out int relEntityID))
|
|
||||||
// {
|
|
||||||
// Throw.UndefinedRelationException();
|
|
||||||
// }
|
|
||||||
// return relEntityID;
|
|
||||||
//}
|
|
||||||
//public bool TryGetRelation(int startEntityID, int endEntityID, out int relEntityID)
|
|
||||||
//{
|
|
||||||
// return _relationsMatrix.TryGetValue(startEntityID, endEntityID, out relEntityID);
|
|
||||||
//}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ArcEntityInfo
|
#region ArcEntityInfo
|
||||||
@ -221,19 +156,6 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
return GetRelationInfo(relEntityID).end;
|
return GetRelationInfo(relEntityID).end;
|
||||||
}
|
}
|
||||||
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//public int GetInversedRelation(int relEntityID)
|
|
||||||
//{
|
|
||||||
// var (startEntityID, endEntityID) = GetRelationInfo(relEntityID);
|
|
||||||
// return GetRelation(endEntityID, startEntityID);
|
|
||||||
//}
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//public bool TryGetInversedRelation(int relEntityID, out int inversedRelEntityID)
|
|
||||||
//{
|
|
||||||
// var (startEntityID, endEntityID) = GetRelationInfo(relEntityID);
|
|
||||||
// return TryGetRelation(endEntityID, startEntityID, out inversedRelEntityID);
|
|
||||||
//}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
#region Other
|
||||||
@ -275,7 +197,6 @@ namespace DCFApixels.DragonECS
|
|||||||
public void OnWorldResize(int arcWorldNewSize)
|
public void OnWorldResize(int arcWorldNewSize)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize);
|
Array.Resize(ref _arc._relEntityInfos, arcWorldNewSize);
|
||||||
_arc._entitiesGraph.UpArcSize(arcWorldNewSize);
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@ -295,17 +216,10 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Callbacks
|
#region Callbacks
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
||||||
{
|
{
|
||||||
foreach (var startEntityID in startEntityBuffer)
|
|
||||||
{
|
|
||||||
_arc._entitiesGraphFriend.DelStartAndDelRelEntities(startEntityID, _arc);
|
|
||||||
}
|
|
||||||
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int startWorldNewSize)
|
public void OnWorldResize(int startWorldNewSize) { }
|
||||||
{
|
|
||||||
_arc._entitiesGraph.UpStartSize(startWorldNewSize);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
private class EndWorldHandler : IEcsWorldEventListener
|
private class EndWorldHandler : IEcsWorldEventListener
|
||||||
@ -324,17 +238,10 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Callbacks
|
#region Callbacks
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> endEntityBuffer)
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> endEntityBuffer)
|
||||||
{
|
{
|
||||||
foreach (var endEntityID in endEntityBuffer)
|
|
||||||
{
|
|
||||||
_arc._entitiesGraphFriend.DelEndAndDelRelEntities(endEntityID, _arc);
|
|
||||||
}
|
|
||||||
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int endWorldNewSize)
|
public void OnWorldResize(int endWorldNewSize) { }
|
||||||
{
|
|
||||||
_arc._entitiesGraph.UpEndSize(endWorldNewSize);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
private class LoopWorldHandler : IEcsWorldEventListener
|
private class LoopWorldHandler : IEcsWorldEventListener
|
||||||
@ -353,19 +260,10 @@ namespace DCFApixels.DragonECS
|
|||||||
#region Callbacks
|
#region Callbacks
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
||||||
{
|
{
|
||||||
foreach (var startEntityID in startEntityBuffer)
|
|
||||||
{
|
|
||||||
_arc._entitiesGraphFriend.DelStartAndDelRelEntities(startEntityID, _arc);
|
|
||||||
_arc._entitiesGraphFriend.DelEndAndDelRelEntities(startEntityID, _arc);
|
|
||||||
}
|
|
||||||
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int startWorldNewSize)
|
public void OnWorldResize(int startWorldNewSize) { }
|
||||||
{
|
|
||||||
_arc._entitiesGraph.UpStartSize(startWorldNewSize);
|
|
||||||
_arc._entitiesGraph.UpEndSize(startWorldNewSize);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System;
|
namespace DCFApixels.DragonECS
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
{
|
||||||
public static class EcsWorldConfigRelationsExtensions
|
public static class EcsWorldConfigRelationsExtensions
|
||||||
{
|
{
|
||||||
|
@ -1,438 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Relations.Internal;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
[DebuggerTypeProxy(typeof(DebuggerProxy))]
|
|
||||||
internal class BasketList
|
|
||||||
{
|
|
||||||
public const int NULL = 0;
|
|
||||||
|
|
||||||
private UnsafeArray<BasketInfo> _baskets = new UnsafeArray<BasketInfo>(64, true);
|
|
||||||
private UnsafeArray<Node> _nodes;
|
|
||||||
private int _recycledListHead = NULL;
|
|
||||||
|
|
||||||
#region Constructors/Destroy
|
|
||||||
public BasketList() : this(16) { }
|
|
||||||
public BasketList(int minCapacity)
|
|
||||||
{
|
|
||||||
Initialize(ArrayUtility.NormalizeSizeToPowerOfTwo(minCapacity));
|
|
||||||
}
|
|
||||||
//Dispose //GC.SuppressFinalize
|
|
||||||
~BasketList()
|
|
||||||
{
|
|
||||||
_baskets.Dispose();
|
|
||||||
_nodes.Dispose();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Clear
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < _nodes.Length; i++)
|
|
||||||
{
|
|
||||||
_nodes[i].next = 0;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < _baskets.Length; i++)
|
|
||||||
{
|
|
||||||
_baskets[i] = default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Other
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int GetBasketNodesCount(int basketIndex)
|
|
||||||
{
|
|
||||||
return _baskets[basketIndex].count;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Set(int nodeIndex, int value)
|
|
||||||
{
|
|
||||||
_nodes[nodeIndex].value = value;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int Get(int nodeIndex)
|
|
||||||
{
|
|
||||||
return _nodes[nodeIndex].value;
|
|
||||||
}
|
|
||||||
private Node GetNode(int nodeIndex)
|
|
||||||
{
|
|
||||||
return _nodes[nodeIndex];
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region AddToBasket/TakeRecycledNode
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private int TakeRecycledNode()
|
|
||||||
{
|
|
||||||
if (_recycledListHead == NULL)
|
|
||||||
{
|
|
||||||
ResizeNodes(_nodes.Length << 1);
|
|
||||||
}
|
|
||||||
int node = _recycledListHead;
|
|
||||||
_recycledListHead = _nodes[node].next;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int AddToBasket(int basketIndex, int value)
|
|
||||||
{
|
|
||||||
ref BasketInfo basketInfo = ref _baskets[basketIndex];
|
|
||||||
int newNodeIndex = TakeRecycledNode();
|
|
||||||
if (basketInfo.count == 0)
|
|
||||||
{
|
|
||||||
_nodes[newNodeIndex].SetValue_Prev(value, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int nodeIndex = basketInfo.nodeIndex;
|
|
||||||
ref int nextNode_Prev = ref _nodes[nodeIndex].prev;
|
|
||||||
|
|
||||||
_nodes[newNodeIndex].Set(value, nextNode_Prev, nodeIndex);
|
|
||||||
nextNode_Prev = newNodeIndex;
|
|
||||||
}
|
|
||||||
basketInfo.nodeIndex = newNodeIndex;
|
|
||||||
basketInfo.count++;
|
|
||||||
return newNodeIndex;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region RemoveFromBasket/RemoveBasket
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void RemoveFromBasket(int basketIndex, int nodeIndex)
|
|
||||||
{//нужно добавить ограничение на удаление повторяющейся ноды, иначе recycled ноды зацикливаются
|
|
||||||
#if DEBUG
|
|
||||||
if (nodeIndex <= 0)
|
|
||||||
{
|
|
||||||
//Throw.ArgumentOutOfRange();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ref BasketInfo basketInfo = ref _baskets[basketIndex];
|
|
||||||
|
|
||||||
ref var node = ref _nodes[nodeIndex];
|
|
||||||
int nextNode = node.next;
|
|
||||||
|
|
||||||
Link(node.prev, nextNode);
|
|
||||||
LinkToRecycled(nodeIndex, nodeIndex);
|
|
||||||
if (basketInfo.nodeIndex == nodeIndex)
|
|
||||||
{
|
|
||||||
basketInfo.nodeIndex = nextNode;
|
|
||||||
}
|
|
||||||
basketInfo.count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void RemoveBasket(int basketIndex)
|
|
||||||
{
|
|
||||||
ref BasketInfo basket = ref _baskets[basketIndex];
|
|
||||||
|
|
||||||
int startNodeIndex = basket.nodeIndex;
|
|
||||||
int endNodeIndex = startNodeIndex;
|
|
||||||
ref Node startNode = ref _nodes[startNodeIndex];
|
|
||||||
for (int i = 0, n = basket.count; i < n; i++)
|
|
||||||
{
|
|
||||||
endNodeIndex = _nodes[endNodeIndex].next;
|
|
||||||
}
|
|
||||||
ref Node endNode = ref _nodes[endNodeIndex];
|
|
||||||
|
|
||||||
LinkToRecycled(startNodeIndex, endNodeIndex);
|
|
||||||
Link(startNode.prev, endNode.next);
|
|
||||||
|
|
||||||
basket.count = 0;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Links
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//private void Separate(int leftNodeIndex, int rightNodeIndex)
|
|
||||||
//{
|
|
||||||
// _nodes[rightNodeIndex].prev = 0;
|
|
||||||
// _nodes[leftNodeIndex].next = 0;
|
|
||||||
//}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void Link(int leftNodeIndex, int rightNodeIndex)
|
|
||||||
{
|
|
||||||
_nodes[rightNodeIndex].prev = leftNodeIndex;
|
|
||||||
_nodes[leftNodeIndex].next = rightNodeIndex;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void LinkToRecycled(int startNodeIndex, int endNodeIndex)
|
|
||||||
{
|
|
||||||
if (_recycledListHead <= NULL)
|
|
||||||
{
|
|
||||||
_nodes[endNodeIndex].next = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Link(startNodeIndex, _recycledListHead);
|
|
||||||
}
|
|
||||||
_recycledListHead = startNodeIndex;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region UpSize/Resize/Initialize
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
private void ResizeNodes(int newSize)
|
|
||||||
{
|
|
||||||
int oldSize = _nodes.Length;
|
|
||||||
UnsafeArray.Resize(ref _nodes, newSize);
|
|
||||||
InitNewNodes(oldSize, newSize);
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
private void Initialize(int newSize)
|
|
||||||
{
|
|
||||||
_nodes = new UnsafeArray<Node>(newSize);
|
|
||||||
_nodes[0] = Node.Empty;
|
|
||||||
InitNewNodes(1, newSize);
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
||||||
private void InitNewNodes(int oldSize, int newSize)
|
|
||||||
{
|
|
||||||
int leftNode = NULL;
|
|
||||||
for (int i = oldSize; i < newSize; i++)
|
|
||||||
{
|
|
||||||
Link(leftNode, i);
|
|
||||||
leftNode = i;
|
|
||||||
}
|
|
||||||
LinkToRecycled(oldSize, newSize - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpNodesSize(int minSize)
|
|
||||||
{
|
|
||||||
if (minSize > _nodes.Length)
|
|
||||||
{
|
|
||||||
int newSize = ArrayUtility.NormalizeSizeToPowerOfTwo(minSize);
|
|
||||||
ResizeNodes(newSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void UpBasketsSize(int minSize)
|
|
||||||
{
|
|
||||||
if (minSize > _baskets.Length)
|
|
||||||
{
|
|
||||||
int newSize = ArrayUtility.NormalizeSizeToPowerOfTwo(minSize);
|
|
||||||
UnsafeArray.ResizeAndInit(ref _baskets, newSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Node
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
|
||||||
public struct Node
|
|
||||||
{
|
|
||||||
public static readonly Node Empty = new Node() { value = 0, next = NULL };
|
|
||||||
public int value;
|
|
||||||
/// <summary>next node index</summary>
|
|
||||||
public int next;
|
|
||||||
/// <summary>prev node index</summary>
|
|
||||||
public int prev;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Set(int value, int prev, int next)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.next = next;
|
|
||||||
this.prev = prev;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void SetValue_Prev(int value, int prev)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.prev = prev;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void SetPrev_Next(int prev, int next)
|
|
||||||
{
|
|
||||||
this.next = next;
|
|
||||||
this.prev = prev;
|
|
||||||
}
|
|
||||||
public override string ToString() => $"node({prev}<>{next} v:{value})";
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region BasketInfo
|
|
||||||
private struct BasketInfo
|
|
||||||
{
|
|
||||||
public static readonly BasketInfo Empty = new BasketInfo() { nodeIndex = 0, count = 0, };
|
|
||||||
public int nodeIndex;
|
|
||||||
public int count;
|
|
||||||
public override string ToString() => $"basket_info(i:{nodeIndex} c:{count})";
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Basket
|
|
||||||
public BasketIterator this[int basketIndex]
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => GetBasketIterator(basketIndex);
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public BasketIterator GetBasketIterator(int basketIndex)
|
|
||||||
{
|
|
||||||
return new BasketIterator(this, basketIndex);
|
|
||||||
}
|
|
||||||
public readonly struct BasketIterator : IEnumerable<int>
|
|
||||||
{
|
|
||||||
private readonly BasketList _basketList;
|
|
||||||
private readonly int _basketIndex;
|
|
||||||
public int Count
|
|
||||||
{
|
|
||||||
get { return _basketList._baskets[_basketIndex].count; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public BasketIterator(BasketList basketList, int basketIndex)
|
|
||||||
{
|
|
||||||
_basketList = basketList;
|
|
||||||
_basketIndex = basketIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Enumerator GetEnumerator() => new Enumerator(this);
|
|
||||||
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
||||||
public struct Enumerator : IEnumerator<int>
|
|
||||||
{
|
|
||||||
private readonly UnsafeArray<Node> _nodes;
|
|
||||||
private int _nodeIndex;
|
|
||||||
private int _nextNodeIndex;
|
|
||||||
private int _count;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Enumerator(BasketIterator iterator)
|
|
||||||
{
|
|
||||||
ref BasketInfo basketInfo = ref iterator._basketList._baskets[iterator._basketIndex];
|
|
||||||
_nodes = iterator._basketList._nodes;
|
|
||||||
_nodeIndex = -1;
|
|
||||||
_nextNodeIndex = basketInfo.nodeIndex;
|
|
||||||
_count = basketInfo.count;
|
|
||||||
}
|
|
||||||
public int Current
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => _nodes[_nodeIndex].value;
|
|
||||||
}
|
|
||||||
object IEnumerator.Current => Current;
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
_nodeIndex = _nextNodeIndex;
|
|
||||||
_nextNodeIndex = _nodes[_nextNodeIndex].next;
|
|
||||||
return _nodeIndex > 0 && _count-- > 0;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Reset() { }
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Dispose() { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region DebuggerProxy
|
|
||||||
private class DebuggerProxy
|
|
||||||
{
|
|
||||||
private BasketList _basketList;
|
|
||||||
public IEnumerable<BasketIteratorDebbugerProxy> Baskets
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<BasketIteratorDebbugerProxy> result = new List<BasketIteratorDebbugerProxy>();
|
|
||||||
for (int i = 0; i < _basketList._baskets.Length; i++)
|
|
||||||
{
|
|
||||||
if (_basketList._baskets[i].count > 0)
|
|
||||||
{
|
|
||||||
result.Add(new BasketIteratorDebbugerProxy(_basketList[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public IEnumerable<Node> Recycled
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<Node> result = new List<Node>();
|
|
||||||
Node curNode = new Node();
|
|
||||||
curNode.index = _basketList._recycledListHead;
|
|
||||||
|
|
||||||
for (int i = 0; i < _basketList._nodes.Length; i++)
|
|
||||||
{
|
|
||||||
if (curNode.index == NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BasketList.Node x = _basketList.GetNode(curNode.index);
|
|
||||||
curNode.prev = x.prev;
|
|
||||||
curNode.next = x.next;
|
|
||||||
|
|
||||||
result.Add(curNode);
|
|
||||||
|
|
||||||
curNode.index = curNode.next;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public IEnumerable<Node> AllNodes
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<Node> result = new List<Node>();
|
|
||||||
|
|
||||||
for (int i = 0; i < _basketList._nodes.Length; i++)
|
|
||||||
{
|
|
||||||
result.Add(new Node(_basketList._nodes[i].prev, i, _basketList._nodes[i].next));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public DebuggerProxy(BasketList basketList)
|
|
||||||
{
|
|
||||||
_basketList = basketList;
|
|
||||||
}
|
|
||||||
public struct Node
|
|
||||||
{
|
|
||||||
public int prev;
|
|
||||||
public int index;
|
|
||||||
public int next;
|
|
||||||
public Node(int prev, int index, int next)
|
|
||||||
{
|
|
||||||
this.prev = prev;
|
|
||||||
this.index = index;
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
public override string ToString() => $"node({prev}< {index} >{next})";
|
|
||||||
}
|
|
||||||
public struct BasketIteratorDebbugerProxy
|
|
||||||
{
|
|
||||||
private BasketIterator _iterrator;
|
|
||||||
public int Count => _iterrator.Count;
|
|
||||||
public IEnumerable<int> RelEntities
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
List<int> result = new List<int>();
|
|
||||||
foreach (var e in _iterrator)
|
|
||||||
{
|
|
||||||
result.Add(e);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public BasketIteratorDebbugerProxy(BasketIterator iterrator)
|
|
||||||
{
|
|
||||||
_iterrator = iterrator;
|
|
||||||
}
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"count: {_iterrator.Count}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Serialization;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Relations.Internal
|
namespace DCFApixels.DragonECS.Relations.Internal
|
||||||
{
|
{
|
||||||
@ -42,6 +41,5 @@ namespace DCFApixels.DragonECS
|
|||||||
public EcsRelationException() { }
|
public EcsRelationException() { }
|
||||||
public EcsRelationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
|
public EcsRelationException(string message) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message) { }
|
||||||
public EcsRelationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
|
public EcsRelationException(string message, Exception inner) : base(EcsConsts.EXCEPTION_MESSAGE_PREFIX + message, inner) { }
|
||||||
protected EcsRelationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user