This commit is contained in:
DCFApixels 2024-11-22 12:19:43 +08:00
commit 58f570c731
5 changed files with 154 additions and 111 deletions

View File

@ -1,7 +1,6 @@
using DCFApixels.DragonECS; using System.Diagnostics;
using System.Diagnostics;
namespace DCFApixels.Assets.Plugins.DragonECS_Graphs.src.Builtin namespace DCFApixels.DragonECS
{ {
/// <summary> EcsWrold for store regular game entities. </summary> /// <summary> EcsWrold for store regular game entities. </summary>
[MetaColor(MetaColor.DragonRose)] [MetaColor(MetaColor.DragonRose)]

View File

@ -236,10 +236,10 @@ namespace DCFApixels.DragonECS
#region Callbacks #region Callbacks
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> delEntities) public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> delEntities)
{ {
EcsSubGraph subGraph; SubGraphMap subGraph;
EcsWorld graphWorld = _graph._graphWorld; EcsWorld graphWorld = _graph._graphWorld;
subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.All); subGraph = graphWorld.Join(JoinMode.All);
foreach (var sourceE in delEntities) foreach (var sourceE in delEntities)
{ {
var relEs = subGraph.GetRelations(sourceE); var relEs = subGraph.GetRelations(sourceE);

View File

@ -71,6 +71,15 @@ namespace DCFApixels.DragonECS
Throw.UndefinedException(); Throw.UndefinedException();
return null; return null;
} }
public static EcsWorld GetGraphWorld(this EcsWorld self)
{
if (self.TryGetGraph(out EntityGraph graph))
{
return graph.GraphWorld;
}
Throw.UndefinedException();
return null;
}
public static bool IsGraphWorld(this EcsWorld self) public static bool IsGraphWorld(this EcsWorld self)
{ {

View File

@ -6,56 +6,56 @@ namespace DCFApixels.DragonECS
public static class GraphQueriesExtensions public static class GraphQueriesExtensions
{ {
#region JoinToGraph Empty #region JoinToGraph Empty
public static EcsSubGraph JoinToSubGraph(this EcsWorld entities, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap Join(this EcsWorld entities, JoinMode mode = JoinMode.Start)
{ {
entities.GetQueryCache(out JoinToSubGraphExecutor executor, out EmptyAspect _); entities.GetQueryCache(out JoinExecutor executor, out EmptyAspect _);
return executor.Execute(mode); return executor.Execute(mode);
} }
#endregion #endregion
#region JoinToGraph Mask #region JoinToGraph Mask
public static EcsSubGraph JoinToSubGraph<TCollection>(this TCollection entities, IComponentMask mask, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap Join<TCollection>(this TCollection entities, IComponentMask mask, JoinMode mode = JoinMode.Start)
where TCollection : IEntityStorage where TCollection : IEntityStorage
{ {
if (ReferenceEquals(entities, entities.World)) if (ReferenceEquals(entities, entities.World))
{ {
var executor = entities.World.GetExecutorForMask<JoinToSubGraphExecutor>(mask); var executor = entities.World.GetExecutorForMask<JoinExecutor>(mask);
return executor.Execute(); return executor.Execute();
} }
return entities.ToSpan().JoinToSubGraph(mask, mode); return entities.ToSpan().JoinSubGraph(mask, mode);
} }
public static EcsSubGraph JoinToSubGraph(this EcsReadonlyGroup group, IComponentMask mask, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap Join(this EcsReadonlyGroup group, IComponentMask mask, JoinMode mode = JoinMode.Start)
{ {
return group.ToSpan().JoinToSubGraph(mask, mode); return group.ToSpan().JoinSubGraph(mask, mode);
} }
public static EcsSubGraph JoinToSubGraph(this EcsSpan span, IComponentMask mask, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap JoinSubGraph(this EcsSpan span, IComponentMask mask, JoinMode mode = JoinMode.Start)
{ {
var executor = span.World.GetExecutorForMask<JoinToSubGraphExecutor>(mask); var executor = span.World.GetExecutorForMask<JoinExecutor>(mask);
return executor.ExecuteFor(span, mode); return executor.ExecuteFor(span, mode);
} }
#endregion #endregion
#region JoinToGraph #region JoinToGraph
public static EcsSubGraph JoinToSubGraph<TCollection, TAspect>(this TCollection entities, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap Join<TCollection, TAspect>(this TCollection entities, out TAspect aspect, JoinMode mode = JoinMode.Start)
where TAspect : EcsAspect, new() where TAspect : EcsAspect, new()
where TCollection : IEntityStorage where TCollection : IEntityStorage
{ {
if (ReferenceEquals(entities, entities.World)) if (ReferenceEquals(entities, entities.World))
{ {
entities.World.GetQueryCache(out JoinToSubGraphExecutor executor, out aspect); entities.World.GetQueryCache(out JoinExecutor executor, out aspect);
return executor.Execute(); return executor.Execute();
} }
return entities.ToSpan().JoinToSubGraph(out aspect, mode); return entities.ToSpan().Join(out aspect, mode);
} }
public static EcsSubGraph JoinToSubGraph<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap JoinSubGraph<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, JoinMode mode = JoinMode.Start)
where TAspect : EcsAspect, new() where TAspect : EcsAspect, new()
{ {
return group.ToSpan().JoinToSubGraph(out aspect, mode); return group.ToSpan().Join(out aspect, mode);
} }
public static EcsSubGraph JoinToSubGraph<TAspect>(this EcsSpan span, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public static SubGraphMap Join<TAspect>(this EcsSpan span, out TAspect aspect, JoinMode mode = JoinMode.Start)
where TAspect : EcsAspect, new() where TAspect : EcsAspect, new()
{ {
span.World.GetQueryCache(out JoinToSubGraphExecutor executor, out aspect); span.World.GetQueryCache(out JoinExecutor executor, out aspect);
return executor.ExecuteFor(span, mode); return executor.ExecuteFor(span, mode);
} }
#endregion #endregion

View File

@ -3,12 +3,13 @@ using DCFApixels.DragonECS.Graphs.Internal;
using DCFApixels.DragonECS.UncheckedCore; using DCFApixels.DragonECS.UncheckedCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using LinkedList = DCFApixels.DragonECS.Graphs.Internal.OnlyAppendHeadLinkedList; using LinkedList = DCFApixels.DragonECS.Graphs.Internal.OnlyAppendHeadLinkedList;
namespace DCFApixels.DragonECS.Graphs.Internal namespace DCFApixels.DragonECS.Graphs.Internal
{ {
internal sealed class JoinToSubGraphExecutor : MaskQueryExecutor, IEcsWorldEventListener internal sealed class JoinExecutor : MaskQueryExecutor, IEcsWorldEventListener
{ {
private EntityGraph _graph; private EntityGraph _graph;
private EcsMaskIterator _iterator; private EcsMaskIterator _iterator;
@ -62,6 +63,11 @@ namespace DCFApixels.DragonECS.Graphs.Internal
#region OnInitialize/OnDestroy #region OnInitialize/OnDestroy
protected override void OnInitialize() protected override void OnInitialize()
{ {
if (World.IsGraphWorld() == false)
{
Throw.Exception("The JounSubGraph query can only be used for EntityGraph.GraphWorld or a collection of that world.");
}
_versionsChecker = new WorldStateVersionsChecker(Mask); _versionsChecker = new WorldStateVersionsChecker(Mask);
_linkedList = new OnlyAppendHeadLinkedList(World.Capacity); _linkedList = new OnlyAppendHeadLinkedList(World.Capacity);
_linkedListSourceHeads = new LinkedListHead[World.Capacity]; _linkedListSourceHeads = new LinkedListHead[World.Capacity];
@ -81,7 +87,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
#region Execute #region Execute
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private EcsSubGraph Execute_Internal(EcsSubGraphMode mode) private SubGraphMap Execute_Internal(JoinMode mode)
{ {
//_executeMarker.Begin(); //_executeMarker.Begin();
@ -121,14 +127,14 @@ namespace DCFApixels.DragonECS.Graphs.Internal
_linkedList.Clear(); _linkedList.Clear();
//Заполнение массивов //Заполнение массивов
if ((mode & EcsSubGraphMode.StartToEnd) != 0) if ((mode & JoinMode.Start) != 0)
{ {
for (int i = 0; i < _filteredAllEntitiesCount; i++) for (int i = 0; i < _filteredAllEntitiesCount; i++)
{ {
AddStart(_filteredAllEntities[i]); AddStart(_filteredAllEntities[i]);
} }
} }
if ((mode & EcsSubGraphMode.EndToStart) != 0) if ((mode & JoinMode.End) != 0)
{ {
for (int i = 0; i < _filteredAllEntitiesCount; i++) for (int i = 0; i < _filteredAllEntitiesCount; i++)
{ {
@ -140,10 +146,10 @@ namespace DCFApixels.DragonECS.Graphs.Internal
_version++; _version++;
//_executeMarker.End(); //_executeMarker.End();
return new EcsSubGraph(this); return new SubGraphMap(this);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private EcsSubGraph ExecuteFor_Internal(EcsSpan span, EcsSubGraphMode mode) private SubGraphMap ExecuteFor_Internal(EcsSpan span, JoinMode mode)
{ {
//_executeMarker.Begin(); //_executeMarker.Begin();
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
@ -184,14 +190,14 @@ namespace DCFApixels.DragonECS.Graphs.Internal
_linkedList.Clear(); _linkedList.Clear();
//Заполнение массивов //Заполнение массивов
if ((mode & EcsSubGraphMode.StartToEnd) != 0) if ((mode & JoinMode.Start) != 0)
{ {
for (int i = 0; i < _filteredEntitiesCount; i++) for (int i = 0; i < _filteredEntitiesCount; i++)
{ {
AddStart(_filteredEntities[i]); AddStart(_filteredEntities[i]);
} }
} }
if ((mode & EcsSubGraphMode.EndToStart) != 0) if ((mode & JoinMode.End) != 0)
{ {
for (int i = 0; i < _filteredEntitiesCount; i++) for (int i = 0; i < _filteredEntitiesCount; i++)
{ {
@ -201,14 +207,14 @@ namespace DCFApixels.DragonECS.Graphs.Internal
//_executeMarker.End(); //_executeMarker.End();
return new EcsSubGraph(this); return new SubGraphMap(this);
} }
public EcsSubGraph Execute(EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public SubGraphMap Execute(JoinMode mode = JoinMode.Start)
{ {
return Execute_Internal(mode); return Execute_Internal(mode);
} }
public EcsSubGraph ExecuteFor(EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) public SubGraphMap ExecuteFor(EcsSpan span, JoinMode mode = JoinMode.Start)
{ {
return ExecuteFor_Internal(span, mode); return ExecuteFor_Internal(span, mode);
} }
@ -246,10 +252,10 @@ namespace DCFApixels.DragonECS.Graphs.Internal
#region Internal result methods #region Internal result methods
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsSubGraphSpan GetRelations_Internal(int sourceEntityID) internal SubGraphMap.NodeInfo GetRelations_Internal(int sourceEntityID)
{ {
LinkedListHead basket = _linkedListSourceHeads[sourceEntityID]; LinkedListHead basket = _linkedListSourceHeads[sourceEntityID];
return new EcsSubGraphSpan(_linkedList._nodes, basket.head, basket.count); return new SubGraphMap.NodeInfo(_linkedList._nodes, basket.head, basket.count);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal int GetRelation_Internal(int sourceEntityID) internal int GetRelation_Internal(int sourceEntityID)
@ -291,7 +297,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
#endregion #endregion
#region GetEntites #region GetEntites
internal EcsSpan GetSourceEntities() internal EcsSpan GetNodeEntities()
{ {
return UncheckedCoreUtility.CreateSpan(WorldID, _sourceEntities, _sourceEntitiesCount); return UncheckedCoreUtility.CreateSpan(WorldID, _sourceEntities, _sourceEntitiesCount);
} }
@ -305,114 +311,143 @@ namespace DCFApixels.DragonECS.Graphs.Internal
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public enum EcsSubGraphMode : byte public enum JoinMode : byte
{ {
NONE = 0, NONE = 0,
StartToEnd = 1 << 0, Start = 1 << 0,
EndToStart = 1 << 1, End = 1 << 1,
All = StartToEnd | EndToStart, All = Start | End,
} }
#region EcsSubGraphSpan/EcsSubGraph #region SubGraphMap
public readonly ref struct EcsSubGraph public readonly ref struct SubGraphMap
{ {
private readonly JoinToSubGraphExecutor _executer; private readonly JoinExecutor _executer;
public EntityGraph Graph public EntityGraph Graph
{ {
get { return _executer.Graph; } get { return _executer.Graph; }
} }
internal EcsSubGraph(JoinToSubGraphExecutor executer) internal SubGraphMap(JoinExecutor executer)
{ {
_executer = executer; _executer = executer;
} }
public EcsSpan GetSourceEntities()
public EcsSpan WhereNodes<TAspect>(out TAspect a)
where TAspect : EcsAspect, new()
{ {
return _executer.GetSourceEntities(); return _executer.GetNodeEntities().Where(out a);
} }
public EcsSpan GetAllRelEntities() public EcsSpan WhereNodes<TAspect>(IComponentMask mask)
{
return _executer.GetNodeEntities().Where(mask);
}
public EcsSpan WhereNodes<TAspect>(out TAspect a, Comparison<int> comparison)
where TAspect : EcsAspect, new()
{
return _executer.GetNodeEntities().Where(out a, comparison);
}
public EcsSpan WhereNodes<TAspect>(IComponentMask mask, Comparison<int> comparison)
{
return _executer.GetNodeEntities().Where(mask, comparison);
}
public EcsSpan GetNodes()
{
return _executer.GetNodeEntities();
}
public EcsSpan GetAllRelations()
{ {
return _executer.GetRelEntities(); return _executer.GetRelEntities();
} }
public EcsSubGraphSpan GetRelations(int startEntityID)
{
return _executer.GetRelations_Internal(startEntityID);
}
public int GetRelation(int startEntityID)
{
return _executer.GetRelation_Internal(startEntityID);
}
public int GetRelationsCount(int startEntityID)
{
return _executer.GetRelationsCount_Internal(startEntityID);
}
}
public readonly ref struct EcsSubGraphSpan public NodeInfo GetRelations(int nodeEntityID)
{
public static EcsSubGraphSpan Empty
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] return _executer.GetRelations_Internal(nodeEntityID);
get { return new EcsSubGraphSpan(null, 0, 0); }
} }
private readonly LinkedList.Node[] _nodes; public int GetRelation(int nodeEntityID)
private readonly LinkedList.NodeIndex _startNodeIndex;
private readonly int _count;
public int Count
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] return _executer.GetRelation_Internal(nodeEntityID);
get { return _count; }
} }
private IEnumerable<int> E public int GetRelationsCount(int nodeEntityID)
{ {
get return _executer.GetRelationsCount_Internal(nodeEntityID);
{
List<int> result = new List<int>();
foreach (var item in this)
{
result.Add(item);
}
return result;
}
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EcsSubGraphSpan(LinkedList.Node[] nodes, LinkedList.NodeIndex startNodeIndex, int count) [DebuggerTypeProxy(typeof(DebuggerProxy))]
{ public readonly ref struct NodeInfo
_nodes = nodes;
_startNodeIndex = startNodeIndex;
_count = count;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator()
{
return new Enumerator(_nodes, _startNodeIndex, _count);
}
public ref struct Enumerator
{ {
private readonly LinkedList.Node[] _nodes; private readonly LinkedList.Node[] _nodes;
private int _index; private readonly LinkedList.NodeIndex _startNodeIndex;
private int _count; private readonly int _count;
private int _next; public int Count
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Enumerator(LinkedList.Node[] nodes, LinkedList.NodeIndex startIndex, int count)
{
_nodes = nodes;
_index = -1;
_count = count;
_next = (int)startIndex;
}
public int Current
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _nodes[_index].entityID; } get { return _count; }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() internal NodeInfo(LinkedList.Node[] nodes, LinkedList.NodeIndex startNodeIndex, int count)
{ {
_index = _next; _nodes = nodes;
_next = (int)_nodes[_next].next; _startNodeIndex = startNodeIndex;
return _index > 0 && _count-- > 0; _count = count;
//return _count-- > 0; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator()
{
return new Enumerator(_nodes, _startNodeIndex, _count);
}
public ref struct Enumerator
{
private readonly LinkedList.Node[] _nodes;
private int _index;
private int _count;
private int _next;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Enumerator(LinkedList.Node[] nodes, LinkedList.NodeIndex startIndex, int count)
{
_nodes = nodes;
_index = -1;
_count = count;
_next = (int)startIndex;
}
public int Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get { return _nodes[_index].entityID; }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
_index = _next;
_next = (int)_nodes[_next].next;
return _index > 0 && _count-- > 0;
//return _count-- > 0;
}
}
private class DebuggerProxy
{
private readonly LinkedList.Node[] _nodes;
private readonly LinkedList.NodeIndex _startNodeIndex;
private readonly int _count;
private IEnumerable<int> Entities
{
get
{
List<int> result = new List<int>();
foreach (var item in new NodeInfo(_nodes, _startNodeIndex, _count))
{
result.Add(item);
}
return result;
}
}
public DebuggerProxy(NodeInfo node)
{
_nodes = node._nodes;
_startNodeIndex = node._startNodeIndex;
_count = node._count;
}
} }
} }
} }