This commit is contained in:
Mikhail 2023-07-04 05:10:37 +08:00
parent c873ff08d7
commit 06aa34149c
4 changed files with 147 additions and 63 deletions

View File

@ -1,11 +1,10 @@
using DCFApixels.DragonECS.Relations.Utils; using System;
using System;
using System.Diagnostics; using System.Diagnostics;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS.Relations.Utils
{ {
[DebuggerTypeProxy(typeof(DebuggerProxy))] [DebuggerTypeProxy(typeof(DebuggerProxy))]
public class IdsBasket internal class IdsBasket
{ {
private IdsLinkedList _headList = new IdsLinkedList(4); private IdsLinkedList _headList = new IdsLinkedList(4);
private IdsLinkedList _valueList = new IdsLinkedList(4); private IdsLinkedList _valueList = new IdsLinkedList(4);
@ -83,6 +82,14 @@ namespace DCFApixels.DragonECS
else else
return _headList.GetSpan(head.startNodeIndex, head.count); return _headList.GetSpan(head.startNodeIndex, head.count);
} }
public IdsLinkedList.LongSpan GetLongSpanFor(EcsWorld world, int value)
{
ref var head = ref _headMapping[value];
if (head.startNodeIndex <= 0)
return _headList.EmptyLongSpan(world);
else
return _headList.GetLongSpan(world, head.startNodeIndex, head.count);
}
private struct SpanInfo private struct SpanInfo
{ {

View File

@ -1,5 +1,7 @@
using DCFApixels.DragonECS.Relations.Utils; using DCFApixels.DragonECS.Relations.Utils;
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
@ -158,9 +160,10 @@ namespace DCFApixels.DragonECS
public void BindRelation(int relationEntityID, int entityID, int otherEntityID) => _source.BindRelation(relationEntityID, 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 IdsLinkedList.LongSpan GetLongRelations(int entityID) => _source._basket.GetLongSpanFor(_source._world, entityID);
public void DelRelation(int entityID, int otherEntityID) => _source.DelRelation(entityID, otherEntityID);
} }
public readonly struct ReverseOrientation public readonly struct ReverseOrientation
{ {
@ -170,16 +173,43 @@ namespace DCFApixels.DragonECS
public void BindRelation(int relationEntityID, int entityID, int otherEntityID) => _source.BindRelation(relationEntityID, otherEntityID, entityID); 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);
public IdsLinkedList.LongSpan GetLongRelations(int otherEntityID) => _source._otherBasket.GetLongSpanFor(_source._otherWorld, otherEntityID);
public void DelRelation(int otherEntityID, int entityID) => _source.DelRelation(entityID, otherEntityID);
} }
public struct RelationsSpan //public readonly ref struct FilterIterator
{ //{
private readonly IdsBasket _basket; // private readonly IdsLinkedList.Span _listSpan;
private readonly EcsAspect _aspect; // 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;
// }
// }
//}
#endregion #endregion
} }
} }

View File

@ -130,16 +130,107 @@ namespace DCFApixels.DragonECS.Relations.Utils
public int Add(int id) => InsertAfter(_lastNodeIndex, id); public int Add(int id) => InsertAfter(_lastNodeIndex, id);
public ref readonly Node GetNode(int nodeIndex) => ref _nodes[nodeIndex]; public ref readonly Node GetNode(int nodeIndex) => ref _nodes[nodeIndex];
#region Span/Enumerator
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public SpanEnumerator GetEnumerator() => new SpanEnumerator(_nodes, _nodes[Head].next, _count); public SpanEnumerator GetEnumerator() => new SpanEnumerator(_nodes, _nodes[Head].next, _count);
public Span GetSpan(int startNodeIndex, int count) => new Span(this, startNodeIndex, count); public Span GetSpan(int startNodeIndex, int count) => new Span(this, startNodeIndex, count);
public Span EmptySpan() => new Span(this, 0, 0); public Span EmptySpan() => new Span(this, 0, 0);
#region IEnumerable public LongSpan GetLongs(EcsWorld world) => new LongSpan(world, this, _nodes[Head].next, _count);
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator(); public LongSpan GetLongSpan(EcsWorld world, int startNodeIndex, int count) => new LongSpan(world, this, startNodeIndex, count);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public LongSpan EmptyLongSpan(EcsWorld world) => new LongSpan(world, this, 0, 0);
public readonly ref struct Span
{
private readonly IdsLinkedList _source;
private readonly int _startNodeIndex;
private readonly int _count;
public Span(IdsLinkedList source, int startNodeIndex, int count)
{
_source = source;
_startNodeIndex = startNodeIndex;
_count = count;
}
public SpanEnumerator GetEnumerator() => new SpanEnumerator(_source._nodes, _startNodeIndex, _count);
}
public struct SpanEnumerator : IEnumerator<int>
{
private readonly Node[] _nodes;
private int _count;
private int _index;
private int _next;
public SpanEnumerator(Node[] nodes, int startIndex, int count)
{
_nodes = nodes;
_index = -1;
_count = count;
_next = startIndex;
}
public int Current => _nodes[_index].value;
object IEnumerator.Current => Current;
public bool MoveNext()
{
_index = _next;
_next = _nodes[_next].next;
return _index > 0 && _count-- > 0;
}
void IDisposable.Dispose() { }
void IEnumerator.Reset()
{
_index = -1;
_next = Head;
}
}
public readonly ref struct LongSpan
{
private readonly EcsWorld _world;
private readonly IdsLinkedList _source;
private readonly int _startNodeIndex;
private readonly int _count;
public LongSpan(EcsWorld world, IdsLinkedList source, int startNodeIndex, int count)
{
_world = world;
_source = source;
_startNodeIndex = startNodeIndex;
_count = count;
}
public LongSpanEnumerator GetEnumerator() => new LongSpanEnumerator(_world, _source._nodes, _startNodeIndex, _count);
}
public struct LongSpanEnumerator : IEnumerator<entlong>
{
private EcsWorld _world;
private readonly Node[] _nodes;
private int _count;
private int _index;
private int _next;
public LongSpanEnumerator(EcsWorld world, Node[] nodes, int startIndex, int count)
{
_world = world;
_nodes = nodes;
_index = -1;
_count = count;
_next = startIndex;
}
public entlong Current => _world.GetEntityLong(_nodes[_index].value);
object IEnumerator.Current => Current;
public bool MoveNext()
{
_index = _next;
_next = _nodes[_next].next;
return _index > 0 && _count-- > 0;
}
void IDisposable.Dispose() { }
void IEnumerator.Reset()
{
_index = -1;
_next = Head;
}
}
#endregion #endregion
#region Utils Node/Enumerator/Span #region Node
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)] [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
public struct Node public struct Node
{ {
@ -157,52 +248,6 @@ namespace DCFApixels.DragonECS.Relations.Utils
} }
public override string ToString() => $"node({prev}<>{next} v:{value})"; public override string ToString() => $"node({prev}<>{next} v:{value})";
} }
#region Span/Enumerator
public readonly ref struct Span
{
private readonly IdsLinkedList _source;
private readonly int _startNodeIndex;
private readonly int _count;
public Span(IdsLinkedList source, int startNodeIndex, int count)
{
_source = source;
_startNodeIndex = startNodeIndex;
_count = count;
}
public SpanEnumerator GetEnumerator() => new SpanEnumerator(_source._nodes, _startNodeIndex, _count);
}
public struct SpanEnumerator : IEnumerator<int>
{
private readonly Node[] _nodes;
private int _index;
private int _count;
private int _next;
public SpanEnumerator(Node[] nodes, int startIndex, int count)
{
_nodes = nodes;
_index = -1;
_count = count;
_next = startIndex;
}
public int Current => _nodes[_index].value;
public bool MoveNext()
{
_index = _next;
_next = _nodes[_next].next;
return _index > 0 && _count-- > 0;
}
object IEnumerator.Current => Current;
void IDisposable.Dispose() { }
void IEnumerator.Reset()
{
_index = -1;
_next = Head;
}
}
#endregion
#endregion #endregion
#region Debug #region Debug

View File

@ -17,6 +17,7 @@ namespace DCFApixels.DragonECS
#endif #endif
EcsEdge edge = new EcsEdge(world, otherWorld, edgeWorld); EcsEdge edge = new EcsEdge(world, otherWorld, edgeWorld);
_matrix[worldID, otherWorldID] = edge; _matrix[worldID, otherWorldID] = edge;
_matrix[otherWorldID, worldID] = edge;
return edge; return edge;
} }
internal static void Unregister(EcsWorld world, EcsWorld otherWorld) internal static void Unregister(EcsWorld world, EcsWorld otherWorld)
@ -25,6 +26,7 @@ namespace DCFApixels.DragonECS
int otherWorldID = otherWorld.id; int otherWorldID = otherWorld.id;
//var manager = _matrix[worldID, otherWorldID]; //var manager = _matrix[worldID, otherWorldID];
_matrix.Remove(worldID, otherWorldID); _matrix.Remove(worldID, otherWorldID);
_matrix.Remove(otherWorldID, worldID);
} }
internal static EcsEdge Get(EcsWorld world, EcsWorld otherWorld) internal static EcsEdge Get(EcsWorld world, EcsWorld otherWorld)
@ -64,8 +66,8 @@ namespace DCFApixels.DragonECS
WorldGraph.HasEdge(self, otherWorld); WorldGraph.HasEdge(self, otherWorld);
} }
public static EcsEdge GetEdgeWithSelf(this EcsWorld self) => GetRelationWith(self, self); public static EcsEdge GetEdgeWithSelf(this EcsWorld self) => GetEdgeWith(self, self);
public static EcsEdge GetRelationWith(this EcsWorld self, EcsWorld otherWorld) public static EcsEdge GetEdgeWith(this EcsWorld self, EcsWorld otherWorld)
{ {
if (self == null || otherWorld == null) if (self == null || otherWorld == null)
throw new ArgumentNullException(); throw new ArgumentNullException();