diff --git a/src/Builtin/EcsGraphWorld.cs b/src/Builtin/EcsGraphWorld.cs index 10ace88..82ae5a5 100644 --- a/src/Builtin/EcsGraphWorld.cs +++ b/src/Builtin/EcsGraphWorld.cs @@ -1,7 +1,6 @@ -using DCFApixels.DragonECS; -using System.Diagnostics; +using System.Diagnostics; -namespace DCFApixels.Assets.Plugins.DragonECS_Graphs.src.Builtin +namespace DCFApixels.DragonECS { /// EcsWrold for store regular game entities. [MetaColor(MetaColor.DragonRose)] diff --git a/src/EntityGraph.cs b/src/EntityGraph.cs index 47c0bd9..55a8f7b 100644 --- a/src/EntityGraph.cs +++ b/src/EntityGraph.cs @@ -236,10 +236,10 @@ namespace DCFApixels.DragonECS #region Callbacks public void OnReleaseDelEntityBuffer(ReadOnlySpan delEntities) { - EcsSubGraph subGraph; + SubGraphMap subGraph; EcsWorld graphWorld = _graph._graphWorld; - subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.All); + subGraph = graphWorld.Join(JoinMode.All); foreach (var sourceE in delEntities) { var relEs = subGraph.GetRelations(sourceE); diff --git a/src/EntityGraphExtensions.cs b/src/EntityGraphExtensions.cs index d764839..c4bad67 100644 --- a/src/EntityGraphExtensions.cs +++ b/src/EntityGraphExtensions.cs @@ -71,6 +71,15 @@ namespace DCFApixels.DragonECS Throw.UndefinedException(); 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) { diff --git a/src/Executors/GraphQueries.cs b/src/Executors/GraphQueries.cs index 95b393b..d6c494b 100644 --- a/src/Executors/GraphQueries.cs +++ b/src/Executors/GraphQueries.cs @@ -6,56 +6,56 @@ namespace DCFApixels.DragonECS public static class GraphQueriesExtensions { #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); } #endregion #region JoinToGraph Mask - public static EcsSubGraph JoinToSubGraph(this TCollection entities, IComponentMask mask, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) + public static SubGraphMap Join(this TCollection entities, IComponentMask mask, JoinMode mode = JoinMode.Start) where TCollection : IEntityStorage { if (ReferenceEquals(entities, entities.World)) { - var executor = entities.World.GetExecutorForMask(mask); + var executor = entities.World.GetExecutorForMask(mask); 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(mask); + var executor = span.World.GetExecutorForMask(mask); return executor.ExecuteFor(span, mode); } #endregion #region JoinToGraph - public static EcsSubGraph JoinToSubGraph(this TCollection entities, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) + public static SubGraphMap Join(this TCollection entities, out TAspect aspect, JoinMode mode = JoinMode.Start) where TAspect : EcsAspect, new() where TCollection : IEntityStorage { 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 entities.ToSpan().JoinToSubGraph(out aspect, mode); + return entities.ToSpan().Join(out aspect, mode); } - public static EcsSubGraph JoinToSubGraph(this EcsReadonlyGroup group, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) + public static SubGraphMap JoinSubGraph(this EcsReadonlyGroup group, out TAspect aspect, JoinMode mode = JoinMode.Start) where TAspect : EcsAspect, new() { - return group.ToSpan().JoinToSubGraph(out aspect, mode); + return group.ToSpan().Join(out aspect, mode); } - public static EcsSubGraph JoinToSubGraph(this EcsSpan span, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) + public static SubGraphMap Join(this EcsSpan span, out TAspect aspect, JoinMode mode = JoinMode.Start) 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); } #endregion diff --git a/src/Executors/JoinToSubGraphExecutor.cs b/src/Executors/JoinToSubGraphExecutor.cs index 876727c..7ad71b1 100644 --- a/src/Executors/JoinToSubGraphExecutor.cs +++ b/src/Executors/JoinToSubGraphExecutor.cs @@ -3,12 +3,13 @@ using DCFApixels.DragonECS.Graphs.Internal; using DCFApixels.DragonECS.UncheckedCore; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Runtime.CompilerServices; using LinkedList = DCFApixels.DragonECS.Graphs.Internal.OnlyAppendHeadLinkedList; namespace DCFApixels.DragonECS.Graphs.Internal { - internal sealed class JoinToSubGraphExecutor : MaskQueryExecutor, IEcsWorldEventListener + internal sealed class JoinExecutor : MaskQueryExecutor, IEcsWorldEventListener { private EntityGraph _graph; private EcsMaskIterator _iterator; @@ -62,6 +63,11 @@ namespace DCFApixels.DragonECS.Graphs.Internal #region OnInitialize/OnDestroy 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); _linkedList = new OnlyAppendHeadLinkedList(World.Capacity); _linkedListSourceHeads = new LinkedListHead[World.Capacity]; @@ -81,7 +87,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal #region Execute [MethodImpl(MethodImplOptions.AggressiveInlining)] - private EcsSubGraph Execute_Internal(EcsSubGraphMode mode) + private SubGraphMap Execute_Internal(JoinMode mode) { //_executeMarker.Begin(); @@ -121,14 +127,14 @@ namespace DCFApixels.DragonECS.Graphs.Internal _linkedList.Clear(); //Заполнение массивов - if ((mode & EcsSubGraphMode.StartToEnd) != 0) + if ((mode & JoinMode.Start) != 0) { for (int i = 0; i < _filteredAllEntitiesCount; i++) { AddStart(_filteredAllEntities[i]); } } - if ((mode & EcsSubGraphMode.EndToStart) != 0) + if ((mode & JoinMode.End) != 0) { for (int i = 0; i < _filteredAllEntitiesCount; i++) { @@ -140,10 +146,10 @@ namespace DCFApixels.DragonECS.Graphs.Internal _version++; //_executeMarker.End(); - return new EcsSubGraph(this); + return new SubGraphMap(this); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private EcsSubGraph ExecuteFor_Internal(EcsSpan span, EcsSubGraphMode mode) + private SubGraphMap ExecuteFor_Internal(EcsSpan span, JoinMode mode) { //_executeMarker.Begin(); #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS @@ -184,14 +190,14 @@ namespace DCFApixels.DragonECS.Graphs.Internal _linkedList.Clear(); //Заполнение массивов - if ((mode & EcsSubGraphMode.StartToEnd) != 0) + if ((mode & JoinMode.Start) != 0) { for (int i = 0; i < _filteredEntitiesCount; i++) { AddStart(_filteredEntities[i]); } } - if ((mode & EcsSubGraphMode.EndToStart) != 0) + if ((mode & JoinMode.End) != 0) { for (int i = 0; i < _filteredEntitiesCount; i++) { @@ -201,14 +207,14 @@ namespace DCFApixels.DragonECS.Graphs.Internal //_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); } - public EcsSubGraph ExecuteFor(EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd) + public SubGraphMap ExecuteFor(EcsSpan span, JoinMode mode = JoinMode.Start) { return ExecuteFor_Internal(span, mode); } @@ -246,10 +252,10 @@ namespace DCFApixels.DragonECS.Graphs.Internal #region Internal result methods [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal EcsSubGraphSpan GetRelations_Internal(int sourceEntityID) + internal SubGraphMap.NodeInfo GetRelations_Internal(int 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)] internal int GetRelation_Internal(int sourceEntityID) @@ -291,7 +297,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal #endregion #region GetEntites - internal EcsSpan GetSourceEntities() + internal EcsSpan GetNodeEntities() { return UncheckedCoreUtility.CreateSpan(WorldID, _sourceEntities, _sourceEntitiesCount); } @@ -305,114 +311,143 @@ namespace DCFApixels.DragonECS.Graphs.Internal namespace DCFApixels.DragonECS { - public enum EcsSubGraphMode : byte + public enum JoinMode : byte { NONE = 0, - StartToEnd = 1 << 0, - EndToStart = 1 << 1, - All = StartToEnd | EndToStart, + Start = 1 << 0, + End = 1 << 1, + All = Start | End, } - #region EcsSubGraphSpan/EcsSubGraph - public readonly ref struct EcsSubGraph + #region SubGraphMap + public readonly ref struct SubGraphMap { - private readonly JoinToSubGraphExecutor _executer; + private readonly JoinExecutor _executer; public EntityGraph Graph { get { return _executer.Graph; } } - internal EcsSubGraph(JoinToSubGraphExecutor executer) + internal SubGraphMap(JoinExecutor executer) { _executer = executer; } - public EcsSpan GetSourceEntities() + + public EcsSpan WhereNodes(out TAspect a) + where TAspect : EcsAspect, new() { - return _executer.GetSourceEntities(); + return _executer.GetNodeEntities().Where(out a); } - public EcsSpan GetAllRelEntities() + public EcsSpan WhereNodes(IComponentMask mask) + { + return _executer.GetNodeEntities().Where(mask); + } + public EcsSpan WhereNodes(out TAspect a, Comparison comparison) + where TAspect : EcsAspect, new() + { + return _executer.GetNodeEntities().Where(out a, comparison); + } + public EcsSpan WhereNodes(IComponentMask mask, Comparison comparison) + { + return _executer.GetNodeEntities().Where(mask, comparison); + } + + public EcsSpan GetNodes() + { + return _executer.GetNodeEntities(); + } + public EcsSpan GetAllRelations() { 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 static EcsSubGraphSpan Empty + public NodeInfo GetRelations(int nodeEntityID) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return new EcsSubGraphSpan(null, 0, 0); } + return _executer.GetRelations_Internal(nodeEntityID); } - private readonly LinkedList.Node[] _nodes; - private readonly LinkedList.NodeIndex _startNodeIndex; - private readonly int _count; - public int Count + public int GetRelation(int nodeEntityID) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return _count; } + return _executer.GetRelation_Internal(nodeEntityID); } - private IEnumerable E + public int GetRelationsCount(int nodeEntityID) { - get - { - List result = new List(); - foreach (var item in this) - { - result.Add(item); - } - return result; - } + return _executer.GetRelationsCount_Internal(nodeEntityID); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal EcsSubGraphSpan(LinkedList.Node[] nodes, LinkedList.NodeIndex startNodeIndex, int count) - { - _nodes = nodes; - _startNodeIndex = startNodeIndex; - _count = count; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() - { - return new Enumerator(_nodes, _startNodeIndex, _count); - } - public ref struct Enumerator + + [DebuggerTypeProxy(typeof(DebuggerProxy))] + public readonly ref struct NodeInfo { 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 + private readonly LinkedList.NodeIndex _startNodeIndex; + private readonly int _count; + public int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return _nodes[_index].entityID; } + get { return _count; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() + internal NodeInfo(LinkedList.Node[] nodes, LinkedList.NodeIndex startNodeIndex, int count) { - _index = _next; - _next = (int)_nodes[_next].next; - return _index > 0 && _count-- > 0; - //return _count-- > 0; + _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 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 Entities + { + get + { + List result = new List(); + 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; + } } } }