mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 20:04:35 +08:00
update
This commit is contained in:
parent
2087573b6e
commit
3da9cb9065
9
src/Builtin/IsMissingRelationNode.cs
Normal file
9
src/Builtin/IsMissingRelationNode.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[System.Serializable]
|
||||||
|
[MetaColor(MetaColor.DragonRose)]
|
||||||
|
[MetaGroup(EcsGraphConsts.PACK_GROUP)]
|
||||||
|
[MetaDescription(EcsConsts.AUTHOR, "...")]
|
||||||
|
[MetaID("1C53321A9301DB70DB84A88611F6C36C")]
|
||||||
|
public struct IsMissingRelationNode : IEcsTagComponent { }
|
||||||
|
}
|
7
src/Consts.cs
Normal file
7
src/Consts.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public static class EcsGraphConsts
|
||||||
|
{
|
||||||
|
public const string PACK_GROUP = "_" + EcsConsts.FRAMEWORK_NAME + "/Graphs";
|
||||||
|
}
|
||||||
|
}
|
@ -5,45 +5,45 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public static class EcsGraphExtensions
|
public static class EcsGraphExtensions
|
||||||
{
|
{
|
||||||
private static EcsGraph[] _worldGraphs = new EcsGraph[4];
|
private static EntityGraph[] _worldGraphs = new EntityGraph[4];
|
||||||
|
|
||||||
public static EcsGraph CreateGraph(this EcsWorld self, EcsWorld graphWorld)
|
public static EntityGraph CreateGraph(this EcsWorld self, EcsWorld graphWorld)
|
||||||
{
|
{
|
||||||
int worldID = self.ID;
|
int worldID = self.ID;
|
||||||
if (_worldGraphs.Length <= worldID)
|
if (_worldGraphs.Length <= worldID)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _worldGraphs, worldID + 4);
|
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||||
}
|
}
|
||||||
ref EcsGraph graph = ref _worldGraphs[worldID];
|
ref EntityGraph graph = ref _worldGraphs[worldID];
|
||||||
if (graph != null)
|
if (graph != null)
|
||||||
{
|
{
|
||||||
Throw.UndefinedException();
|
Throw.UndefinedException();
|
||||||
}
|
}
|
||||||
graph = new EcsGraph(self, graphWorld);
|
graph = new EntityGraph(self, graphWorld);
|
||||||
new Destroyer(graph);
|
new Destroyer(graph);
|
||||||
_worldGraphs[graphWorld.ID] = graph;
|
_worldGraphs[graphWorld.ID] = graph;
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EcsGraph CreateOrGetGraph(this EcsWorld self, EcsWorld graphWorld)
|
public static EntityGraph CreateOrGetGraph(this EcsWorld self, EcsWorld graphWorld)
|
||||||
{
|
{
|
||||||
int worldID = self.ID;
|
int worldID = self.ID;
|
||||||
if (_worldGraphs.Length <= worldID)
|
if (_worldGraphs.Length <= worldID)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _worldGraphs, worldID + 4);
|
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||||
}
|
}
|
||||||
ref EcsGraph graph = ref _worldGraphs[worldID];
|
ref EntityGraph graph = ref _worldGraphs[worldID];
|
||||||
if (graph != null)
|
if (graph != null)
|
||||||
{
|
{
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
graph = new EcsGraph(self, graphWorld);
|
graph = new EntityGraph(self, graphWorld);
|
||||||
new Destroyer(graph);
|
new Destroyer(graph);
|
||||||
_worldGraphs[graphWorld.ID] = graph;
|
_worldGraphs[graphWorld.ID] = graph;
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryGetGraph(this EcsWorld self, out EcsGraph graph)
|
public static bool TryGetGraph(this EcsWorld self, out EntityGraph graph)
|
||||||
{
|
{
|
||||||
int worldID = self.ID;
|
int worldID = self.ID;
|
||||||
if (_worldGraphs.Length <= worldID)
|
if (_worldGraphs.Length <= worldID)
|
||||||
@ -54,9 +54,9 @@ namespace DCFApixels.DragonECS
|
|||||||
return graph != null;
|
return graph != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EcsGraph GetGraph(this EcsWorld self)
|
public static EntityGraph GetGraph(this EcsWorld self)
|
||||||
{
|
{
|
||||||
if (self.TryGetGraph(out EcsGraph graph))
|
if (self.TryGetGraph(out EntityGraph graph))
|
||||||
{
|
{
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
@ -66,14 +66,14 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
public static bool IsGraphWorld(this EcsWorld self)
|
public static bool IsGraphWorld(this EcsWorld self)
|
||||||
{
|
{
|
||||||
if (self.TryGetGraph(out EcsGraph graph))
|
if (self.TryGetGraph(out EntityGraph graph))
|
||||||
{
|
{
|
||||||
return graph.GraphWorld == self;
|
return graph.GraphWorld == self;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryDestroy(EcsGraph graph)
|
private static void TryDestroy(EntityGraph graph)
|
||||||
{
|
{
|
||||||
int worldID = graph.WorldID;
|
int worldID = graph.WorldID;
|
||||||
if (_worldGraphs.Length <= worldID)
|
if (_worldGraphs.Length <= worldID)
|
||||||
@ -90,8 +90,8 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
private class Destroyer : IEcsWorldEventListener
|
private class Destroyer : IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
private EcsGraph _graph;
|
private EntityGraph _graph;
|
||||||
public Destroyer(EcsGraph graph)
|
public Destroyer(EntityGraph graph)
|
||||||
{
|
{
|
||||||
_graph = graph;
|
_graph = graph;
|
||||||
graph.World.AddListener(this);
|
graph.World.AddListener(this);
|
||||||
|
@ -8,7 +8,7 @@ namespace DCFApixels.DragonECS
|
|||||||
//Graph world
|
//Graph world
|
||||||
//Rel entity
|
//Rel entity
|
||||||
//Component
|
//Component
|
||||||
public class EcsGraph
|
public class EntityGraph
|
||||||
{
|
{
|
||||||
private readonly EcsWorld _world;
|
private readonly EcsWorld _world;
|
||||||
private readonly EcsWorld _graphWorld;
|
private readonly EcsWorld _graphWorld;
|
||||||
@ -16,13 +16,13 @@ namespace DCFApixels.DragonECS
|
|||||||
private readonly GraphWorldHandler _arcWorldHandler;
|
private readonly GraphWorldHandler _arcWorldHandler;
|
||||||
private readonly WorldHandler _loopWorldHandler;
|
private readonly WorldHandler _loopWorldHandler;
|
||||||
|
|
||||||
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
|
|
||||||
private readonly SparseMatrix _matrix;
|
private readonly SparseMatrix _matrix;
|
||||||
|
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
|
||||||
private bool _isInit = false;
|
|
||||||
|
|
||||||
private int _count;
|
private int _count;
|
||||||
|
|
||||||
|
private bool _isInit = false;
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
internal bool IsInit_Internal
|
internal bool IsInit_Internal
|
||||||
{
|
{
|
||||||
@ -57,7 +57,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors/Destroy
|
#region Constructors/Destroy
|
||||||
internal EcsGraph(EcsWorld world, EcsWorld graphWorld)
|
internal EntityGraph(EcsWorld world, EcsWorld graphWorld)
|
||||||
{
|
{
|
||||||
_world = world;
|
_world = world;
|
||||||
_graphWorld = graphWorld;
|
_graphWorld = graphWorld;
|
||||||
@ -146,6 +146,23 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region MoveRelation
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void MoveRelation(int relEntityID, int newStartEntityID, int newEndEntityID)
|
||||||
|
{
|
||||||
|
var startEnd = GetRelationStartEnd(relEntityID);
|
||||||
|
|
||||||
|
//Тут будет не стабильное состояние если TryDel пройдет, а TryAdd - нет
|
||||||
|
if (_matrix.TryDel(startEnd.start, startEnd.end) == false ||
|
||||||
|
_matrix.TryAdd(newStartEntityID, newEndEntityID, relEntityID) == false)
|
||||||
|
{
|
||||||
|
Throw.UndefinedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
_relEntityInfos[relEntityID] = new RelationInfo(newStartEntityID, newEndEntityID);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Get
|
#region Get
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public int GetRelation(int startEntityID, int endEntityID)
|
public int GetRelation(int startEntityID, int endEntityID)
|
||||||
@ -179,7 +196,11 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ArcEntityInfo
|
#region Other
|
||||||
|
public static implicit operator EntityGraph(SingletonMarker marker) { return marker.Builder.World.GetGraph(); }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region RelEntityInfo
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public StartEnd GetRelationStartEnd(int relEntityID)
|
public StartEnd GetRelationStartEnd(int relEntityID)
|
||||||
@ -213,8 +234,8 @@ namespace DCFApixels.DragonECS
|
|||||||
#region GraphWorldHandler
|
#region GraphWorldHandler
|
||||||
private class GraphWorldHandler : IEcsWorldEventListener
|
private class GraphWorldHandler : IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
private readonly EcsGraph _arc;
|
private readonly EntityGraph _arc;
|
||||||
public GraphWorldHandler(EcsGraph arc)
|
public GraphWorldHandler(EntityGraph arc)
|
||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.GraphWorld.AddListener(this);
|
_arc.GraphWorld.AddListener(this);
|
||||||
@ -243,38 +264,51 @@ namespace DCFApixels.DragonECS
|
|||||||
#region WorldHandler
|
#region WorldHandler
|
||||||
private class WorldHandler : IEcsWorldEventListener
|
private class WorldHandler : IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
private readonly EcsGraph _arc;
|
private readonly EntityGraph _graph;
|
||||||
public WorldHandler(EcsGraph arc)
|
public WorldHandler(EntityGraph arc)
|
||||||
{
|
{
|
||||||
_arc = arc;
|
_graph = arc;
|
||||||
_arc.World.AddListener(this);
|
_graph.World.AddListener(this);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
_arc.World.RemoveListener(this);
|
_graph.World.RemoveListener(this);
|
||||||
}
|
}
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> delEntities)
|
||||||
{
|
{
|
||||||
var graph = _arc.GraphWorld.JoinToSubGraph(EcsSubGraphMode.All);
|
EcsSubGraph subGraph;
|
||||||
foreach (var e in startEntityBuffer)
|
EcsWorld graphWorld = _graph._graphWorld;
|
||||||
|
|
||||||
|
//subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.StartToEnd);
|
||||||
|
subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.All);
|
||||||
|
foreach (var sourceE in delEntities)
|
||||||
{
|
{
|
||||||
var span = graph.GetNodes(e);
|
var relEs = subGraph.GetRelations(sourceE);
|
||||||
foreach (var relE in span)
|
foreach (var relE in relEs)
|
||||||
{
|
{
|
||||||
_arc.DelRelation(relE);
|
//int missingE = graphWorld.NewEntity();
|
||||||
|
_graph.DelRelation(relE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_arc._graphWorld.ReleaseDelEntityBufferAll();
|
|
||||||
|
//subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.EndToStart);
|
||||||
|
//foreach (var sourceE in delEntities)
|
||||||
|
//{
|
||||||
|
// var relEs = subGraph.GetRelations(sourceE);
|
||||||
|
// foreach (var relE in relEs)
|
||||||
|
// {
|
||||||
|
// //int missingE = graphWorld.NewEntity();
|
||||||
|
// _graph.DelRelation(relE);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
graphWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int startWorldNewSize) { }
|
public void OnWorldResize(int startWorldNewSize) { }
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
|
||||||
public static implicit operator EcsGraph(SingletonMarker marker) { return marker.Builder.World.GetGraph(); }
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,45 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Core;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public class EcsJoinExecutor : MaskQueryExecutor, IEcsWorldEventListener
|
|
||||||
{
|
|
||||||
private long _lastWorldVersion;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public sealed override long Version
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => _lastWorldVersion;
|
|
||||||
}
|
|
||||||
public override bool IsCached
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
public override int LastCachedCount
|
|
||||||
{
|
|
||||||
get { return 0; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Callbacks
|
|
||||||
protected override void OnInitialize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
protected override void OnDestroy()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public void OnWorldResize(int newSize)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public void OnWorldDestroy()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2b337a549ff9db3488c9ae26a898f770
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -7,48 +7,61 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
|
using LinkedList = OnlyAppendHeadLinkedList;
|
||||||
public sealed class EcsJoinToSubGraphExecutor : MaskQueryExecutor, IEcsWorldEventListener
|
public sealed class EcsJoinToSubGraphExecutor : MaskQueryExecutor, IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
private EntityLinkedList _linkedList;
|
private EntityGraph _graph;
|
||||||
private Basket[] _baskets;
|
private EcsMaskIterator _iterator;
|
||||||
|
|
||||||
|
private int[] _filteredAllEntities = new int[32];
|
||||||
|
private int _filteredAllEntitiesCount = 0;
|
||||||
|
private int[] _filteredEntities = null;
|
||||||
|
private int _filteredEntitiesCount = 0;
|
||||||
|
|
||||||
|
private int[] _currentFilteredEntities = null;
|
||||||
|
private int _currentFilteredEntitiesCount = 0;
|
||||||
|
|
||||||
|
private long _version;
|
||||||
|
private WorldStateVersionsChecker _versionsChecker;
|
||||||
|
|
||||||
|
private LinkedList _linkedList;
|
||||||
|
private LinkedListHead[] _linkedListSourceHeads;
|
||||||
|
|
||||||
private int[] _startEntities;
|
private int[] _startEntities;
|
||||||
private int _startEntitiesCount;
|
private int _startEntitiesCount;
|
||||||
|
|
||||||
private EcsGraph _graph;
|
|
||||||
|
|
||||||
private long _lastWorldVersion;
|
|
||||||
|
|
||||||
private int _targetWorldCapacity = -1;
|
private int _targetWorldCapacity = -1;
|
||||||
private EcsProfilerMarker _executeMarker = new EcsProfilerMarker("JoinAttach");
|
private EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Join");
|
||||||
|
|
||||||
private EcsMaskIterator _iterator;
|
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
public sealed override long Version
|
public sealed override long Version
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _lastWorldVersion; }
|
get { return _version; }
|
||||||
}
|
}
|
||||||
public EcsGraph Graph
|
public EntityGraph Graph
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _graph; }
|
get { return _graph; }
|
||||||
}
|
}
|
||||||
public override bool IsCached
|
public sealed override bool IsCached
|
||||||
{
|
{
|
||||||
get { return false; }
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _versionsChecker.Check(); }
|
||||||
}
|
}
|
||||||
public override int LastCachedCount
|
public sealed override int LastCachedCount
|
||||||
{
|
{
|
||||||
get { return 0; }
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _filteredAllEntitiesCount; }
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region OnInitialize/OnDestroy
|
#region OnInitialize/OnDestroy
|
||||||
protected override void OnInitialize()
|
protected override void OnInitialize()
|
||||||
{
|
{
|
||||||
_linkedList = new EntityLinkedList(World.Capacity);
|
_versionsChecker = new WorldStateVersionsChecker(Mask);
|
||||||
_baskets = new Basket[World.Capacity];
|
_linkedList = new OnlyAppendHeadLinkedList(World.Capacity);
|
||||||
|
_linkedListSourceHeads = new LinkedListHead[World.Capacity];
|
||||||
World.AddListener(this);
|
World.AddListener(this);
|
||||||
_graph = World.GetGraph();
|
_graph = World.GetGraph();
|
||||||
_iterator = Mask.GetIterator();
|
_iterator = Mask.GetIterator();
|
||||||
@ -60,95 +73,188 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Execute
|
#region Execute
|
||||||
public EcsSubGraph Execute(EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
private EcsSubGraph Execute_Internal(EcsSubGraphMode mode)
|
||||||
{
|
{
|
||||||
return ExecuteFor(World.Entities, mode);
|
_executeMarker.Begin();
|
||||||
|
|
||||||
|
World.ReleaseDelEntityBufferAllAuto();
|
||||||
|
|
||||||
|
if (Mask.IsEmpty)
|
||||||
|
{
|
||||||
|
_filteredAllEntitiesCount = World.Entities.ToArray(ref _filteredAllEntities);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_versionsChecker.CheckAndNext() == false)
|
||||||
|
{
|
||||||
|
_filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities);
|
||||||
|
////Подготовка массивов
|
||||||
|
//if (_startEntities.Length < _filteredAllEntitiesCount * 2)
|
||||||
|
//{
|
||||||
|
// _startEntities = new int[_filteredAllEntitiesCount * 2];
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//установка текущего массива
|
||||||
|
_currentFilteredEntities = _filteredAllEntities;
|
||||||
|
_currentFilteredEntitiesCount = _filteredAllEntitiesCount;
|
||||||
|
|
||||||
|
//Подготовка массивов
|
||||||
|
if (_targetWorldCapacity < World.Capacity)
|
||||||
|
{
|
||||||
|
_targetWorldCapacity = World.Capacity;
|
||||||
|
_linkedListSourceHeads = new LinkedListHead[_targetWorldCapacity];
|
||||||
|
_startEntities = new int[_targetWorldCapacity];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ArrayUtility.Fill(_linkedListSourceHeads, default); //TODO оптимизировать, сделав не полную отчистку а только по элементов с прошлого раза
|
||||||
|
}
|
||||||
|
_startEntitiesCount = 0;
|
||||||
|
_linkedList.Clear();
|
||||||
|
|
||||||
|
//Заполнение массивов
|
||||||
|
if ((mode & EcsSubGraphMode.StartToEnd) != 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _filteredAllEntitiesCount; i++)
|
||||||
|
{
|
||||||
|
AddStart(_filteredAllEntities[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((mode & EcsSubGraphMode.EndToStart) != 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _filteredAllEntitiesCount; i++)
|
||||||
|
{
|
||||||
|
AddEnd(_filteredAllEntities[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_version++;
|
||||||
|
|
||||||
|
_executeMarker.End();
|
||||||
|
return new EcsSubGraph(this);
|
||||||
}
|
}
|
||||||
public EcsSubGraph ExecuteFor(EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
private EcsSubGraph ExecuteFor_Internal(EcsSpan span, EcsSubGraphMode mode)
|
||||||
{
|
{
|
||||||
_executeMarker.Begin();
|
_executeMarker.Begin();
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
if (span.IsNull) { Throw.ArgumentException(""); }//TODO составить текст исключения.
|
if (span.IsNull) { _executeMarker.End(); Throw.ArgumentNull(nameof(span)); }
|
||||||
else if (World != span.World) { Throw.ArgumentException(""); } //TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
if (span.WorldID != World.ID) { _executeMarker.End(); Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||||
#endif
|
#endif
|
||||||
|
if (_filteredEntities == null)
|
||||||
//if (_lastWorldVersion != World.Version)
|
|
||||||
{
|
{
|
||||||
//Подготовка массивов
|
_filteredEntities = new int[32];
|
||||||
if (_targetWorldCapacity < World.Capacity)
|
|
||||||
{
|
|
||||||
_targetWorldCapacity = World.Capacity;
|
|
||||||
_baskets = new Basket[_targetWorldCapacity];
|
|
||||||
_startEntities = new int[_targetWorldCapacity];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ArrayUtility.Fill(_baskets, default);
|
|
||||||
}
|
|
||||||
_startEntitiesCount = 0;
|
|
||||||
_linkedList.Clear();
|
|
||||||
//Конец подготовки массивов
|
|
||||||
|
|
||||||
if ((mode & EcsSubGraphMode.StartToEnd) != 0)
|
|
||||||
{
|
|
||||||
if (Mask.IsEmpty)
|
|
||||||
{
|
|
||||||
foreach (var relationEntityID in span) { AddStart(relationEntityID); }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var relationEntityID in _iterator.Iterate(span)) { AddStart(relationEntityID); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((mode & EcsSubGraphMode.EndToStart) != 0)
|
|
||||||
{
|
|
||||||
if (Mask.IsEmpty)
|
|
||||||
{
|
|
||||||
foreach (var relationEntityID in span) { AddEnd(relationEntityID); }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var relationEntityID in _iterator.Iterate(span)) { AddEnd(relationEntityID); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastWorldVersion = World.Version;
|
|
||||||
}
|
}
|
||||||
//else
|
_filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities);
|
||||||
//{
|
|
||||||
//
|
throw new NotImplementedException();
|
||||||
//}
|
|
||||||
|
|
||||||
_executeMarker.End();
|
_executeMarker.End();
|
||||||
return new EcsSubGraph(this, UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public EcsSubGraph Execute(EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
{
|
||||||
|
return Execute_Internal(mode);
|
||||||
|
}
|
||||||
|
public EcsSubGraph ExecuteFor(EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
{
|
||||||
|
return ExecuteFor_Internal(span, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region TMP
|
||||||
|
// public EcsSubGraph Execute(EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
// {
|
||||||
|
// return ExecuteFor(World.Entities, mode);
|
||||||
|
// }
|
||||||
|
// public EcsSubGraph ExecuteFor(EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
// {
|
||||||
|
// _executeMarker.Begin();
|
||||||
|
//#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
|
// if (span.IsNull) { Throw.ArgumentException(""); }//TODO составить текст исключения.
|
||||||
|
// else if (World != span.World) { Throw.ArgumentException(""); } //TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
||||||
|
//#endif
|
||||||
|
//
|
||||||
|
// //if (_lastWorldVersion != World.Version)
|
||||||
|
// {
|
||||||
|
// //Подготовка массивов
|
||||||
|
// if (_targetWorldCapacity < World.Capacity)
|
||||||
|
// {
|
||||||
|
// _targetWorldCapacity = World.Capacity;
|
||||||
|
// _baskets = new Basket[_targetWorldCapacity];
|
||||||
|
// _startEntities = new int[_targetWorldCapacity];
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// ArrayUtility.Fill(_baskets, default);
|
||||||
|
// }
|
||||||
|
// _startEntitiesCount = 0;
|
||||||
|
// _linkedList.Clear();
|
||||||
|
// //Конец подготовки массивов
|
||||||
|
//
|
||||||
|
// if ((mode & EcsSubGraphMode.StartToEnd) != 0)
|
||||||
|
// {
|
||||||
|
// if (Mask.IsEmpty)
|
||||||
|
// {
|
||||||
|
// foreach (var relationEntityID in span) { AddStart(relationEntityID); }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// foreach (var relationEntityID in _iterator.Iterate(span)) { AddStart(relationEntityID); }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if ((mode & EcsSubGraphMode.EndToStart) != 0)
|
||||||
|
// {
|
||||||
|
// if (Mask.IsEmpty)
|
||||||
|
// {
|
||||||
|
// foreach (var relationEntityID in span) { AddEnd(relationEntityID); }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// foreach (var relationEntityID in _iterator.Iterate(span)) { AddEnd(relationEntityID); }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// _lastWorldVersion = World.Version;
|
||||||
|
// }
|
||||||
|
// //else
|
||||||
|
// //{
|
||||||
|
// //
|
||||||
|
// //}
|
||||||
|
//
|
||||||
|
// _executeMarker.End();
|
||||||
|
// return new EcsSubGraph(this, UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount));
|
||||||
|
// }
|
||||||
|
#endregion
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void AddStart(int relationEntityID)
|
private void AddStart(int relationEntityID)
|
||||||
{
|
{
|
||||||
AddFrom(_graph.GetRelationStart(relationEntityID), relationEntityID);
|
AddSourceEntity(_graph.GetRelationStart(relationEntityID), relationEntityID);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void AddEnd(int relationEntityID)
|
private void AddEnd(int relationEntityID)
|
||||||
{
|
{
|
||||||
AddFrom(_graph.GetRelationEnd(relationEntityID), relationEntityID);
|
AddSourceEntity(_graph.GetRelationEnd(relationEntityID), relationEntityID);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void AddFrom(int fromEntityID, int relationEntityID)
|
private void AddSourceEntity(int sourceEntityID, int relationEntityID)
|
||||||
{
|
{
|
||||||
if (fromEntityID == 0)
|
if (sourceEntityID == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ref var basket = ref _baskets[fromEntityID];
|
ref var basket = ref _linkedListSourceHeads[sourceEntityID];
|
||||||
if (basket.index <= 0)
|
if (basket.head == 0)
|
||||||
{
|
{
|
||||||
_startEntities[_startEntitiesCount++] = fromEntityID;
|
_startEntities[_startEntitiesCount++] = sourceEntityID;
|
||||||
basket.index = _linkedList.Add(relationEntityID);
|
basket.head = _linkedList.NewHead(relationEntityID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
basket.index = _linkedList.InsertBefore(basket.index, relationEntityID);
|
_linkedList.InsertIntoHead(ref basket.head, relationEntityID);
|
||||||
}
|
}
|
||||||
basket.count++;
|
basket.count++;
|
||||||
}
|
}
|
||||||
@ -156,21 +262,21 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
#region Internal result methods
|
#region Internal result methods
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal EcsSubGraphSpan GetNodes_Internal(int startEntityID)
|
internal EcsSubGraphSpan GetRelations_Internal(int sourceEntityID)
|
||||||
{
|
{
|
||||||
Basket basket = _baskets[startEntityID];
|
LinkedListHead basket = _linkedListSourceHeads[sourceEntityID];
|
||||||
return new EcsSubGraphSpan(_linkedList._nodes, basket.index, basket.count);
|
return new EcsSubGraphSpan(_linkedList._nodes, basket.head, basket.count);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal int GetNode_Internal(int startEntityID)
|
internal int GetRelation_Internal(int sourceEntityID)
|
||||||
{
|
{
|
||||||
Basket basket = _baskets[startEntityID];
|
LinkedListHead basket = _linkedListSourceHeads[sourceEntityID];
|
||||||
return basket.count > 0 ? _linkedList.Get(basket.index) : 0;
|
return basket.count > 0 ? _linkedList.Get(basket.head) : 0;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal int GetNodesCount_Internal(int startEntityID)
|
internal int GetRelationsCount_Internal(int sourceEntityID)
|
||||||
{
|
{
|
||||||
return _baskets[startEntityID].count;
|
return _linkedListSourceHeads[sourceEntityID].count;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal int GetCount_Internal()
|
internal int GetCount_Internal()
|
||||||
@ -182,26 +288,37 @@ namespace DCFApixels.DragonECS
|
|||||||
#region IEcsWorldEventListener
|
#region IEcsWorldEventListener
|
||||||
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _baskets, newSize);
|
Array.Resize(ref _linkedListSourceHeads, newSize);
|
||||||
}
|
}
|
||||||
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
void IEcsWorldEventListener.OnWorldDestroy() { }
|
void IEcsWorldEventListener.OnWorldDestroy() { }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Basket
|
#region Basket
|
||||||
public struct Basket
|
private struct LinkedListHead
|
||||||
{
|
{
|
||||||
public int index;
|
public LinkedList.NodeIndex head;
|
||||||
public int count;
|
public int count;
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"i:{index} count:{count}";
|
return $"i:{head} count:{count}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region GetEntites
|
||||||
|
internal EcsSpan GetSourceEntities()
|
||||||
|
{
|
||||||
|
return UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount);
|
||||||
|
}
|
||||||
|
internal EcsSpan GetRelEntities()
|
||||||
|
{
|
||||||
|
return UncheckedCoreUtility.CreateSpan(WorldID, _currentFilteredEntities, _currentFilteredEntitiesCount);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EcsSubGraphMode
|
public enum EcsSubGraphMode : byte
|
||||||
{
|
{
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
StartToEnd = 1 << 0,
|
StartToEnd = 1 << 0,
|
||||||
@ -209,7 +326,40 @@ namespace DCFApixels.DragonECS
|
|||||||
All = StartToEnd | EndToStart,
|
All = StartToEnd | EndToStart,
|
||||||
}
|
}
|
||||||
|
|
||||||
#region EcsJoinedSpan/EcsJoined
|
#region EcsSubGraphSpan/EcsSubGraph
|
||||||
|
public readonly ref struct EcsSubGraph
|
||||||
|
{
|
||||||
|
private readonly EcsJoinToSubGraphExecutor _executer;
|
||||||
|
public EntityGraph Graph
|
||||||
|
{
|
||||||
|
get { return _executer.Graph; }
|
||||||
|
}
|
||||||
|
internal EcsSubGraph(EcsJoinToSubGraphExecutor executer)
|
||||||
|
{
|
||||||
|
_executer = executer;
|
||||||
|
}
|
||||||
|
public EcsSpan GetSourceEntities()
|
||||||
|
{
|
||||||
|
return _executer.GetSourceEntities();
|
||||||
|
}
|
||||||
|
public EcsSpan GetAllRelEntities()
|
||||||
|
{
|
||||||
|
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 readonly ref struct EcsSubGraphSpan
|
||||||
{
|
{
|
||||||
public static EcsSubGraphSpan Empty
|
public static EcsSubGraphSpan Empty
|
||||||
@ -218,8 +368,8 @@ namespace DCFApixels.DragonECS
|
|||||||
get { return new EcsSubGraphSpan(null, 0, 0); }
|
get { return new EcsSubGraphSpan(null, 0, 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly EntityLinkedList.Node[] _nodes;
|
private readonly LinkedList.Node[] _nodes;
|
||||||
private readonly int _startNodeIndex;
|
private readonly LinkedList.NodeIndex _startNodeIndex;
|
||||||
private readonly int _count;
|
private readonly int _count;
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
@ -239,7 +389,7 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal EcsSubGraphSpan(EntityLinkedList.Node[] nodes, int startNodeIndex, int count)
|
internal EcsSubGraphSpan(LinkedList.Node[] nodes, LinkedList.NodeIndex startNodeIndex, int count)
|
||||||
{
|
{
|
||||||
_nodes = nodes;
|
_nodes = nodes;
|
||||||
_startNodeIndex = startNodeIndex;
|
_startNodeIndex = startNodeIndex;
|
||||||
@ -252,17 +402,17 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
public ref struct Enumerator
|
public ref struct Enumerator
|
||||||
{
|
{
|
||||||
private readonly EntityLinkedList.Node[] _nodes;
|
private readonly LinkedList.Node[] _nodes;
|
||||||
private int _index;
|
private int _index;
|
||||||
private int _count;
|
private int _count;
|
||||||
private int _next;
|
private int _next;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal Enumerator(EntityLinkedList.Node[] nodes, int startIndex, int count)
|
internal Enumerator(LinkedList.Node[] nodes, LinkedList.NodeIndex startIndex, int count)
|
||||||
{
|
{
|
||||||
_nodes = nodes;
|
_nodes = nodes;
|
||||||
_index = -1;
|
_index = -1;
|
||||||
_count = count;
|
_count = count;
|
||||||
_next = startIndex;
|
_next = (int)startIndex;
|
||||||
}
|
}
|
||||||
public int Current
|
public int Current
|
||||||
{
|
{
|
||||||
@ -273,100 +423,11 @@ namespace DCFApixels.DragonECS
|
|||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
_index = _next;
|
_index = _next;
|
||||||
_next = _nodes[_next].next;
|
_next = (int)_nodes[_next].next;
|
||||||
return _index > 0 && _count-- > 0;
|
return _index > 0 && _count-- > 0;
|
||||||
|
//return _count-- > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly ref struct EcsSubGraph
|
|
||||||
{
|
|
||||||
private readonly EcsJoinToSubGraphExecutor _executer;
|
|
||||||
private readonly EcsSpan _startEntities;
|
|
||||||
public EcsSpan FromEntitiesSpan
|
|
||||||
{
|
|
||||||
get { return _startEntities; }
|
|
||||||
}
|
|
||||||
public EcsGraph Graph
|
|
||||||
{
|
|
||||||
get { return _executer.Graph; }
|
|
||||||
}
|
|
||||||
internal EcsSubGraph(EcsJoinToSubGraphExecutor executer, EcsSpan startEntites)
|
|
||||||
{
|
|
||||||
_executer = executer;
|
|
||||||
_startEntities = startEntites;
|
|
||||||
}
|
|
||||||
public EcsSubGraphSpan GetNodes(int startEntityID)
|
|
||||||
{
|
|
||||||
return _executer.GetNodes_Internal(startEntityID);
|
|
||||||
}
|
|
||||||
public int GetNode(int startEntityID)
|
|
||||||
{
|
|
||||||
return _executer.GetNode_Internal(startEntityID);
|
|
||||||
}
|
|
||||||
public int GetNodesCount(int startEntityID)
|
|
||||||
{
|
|
||||||
return _executer.GetNodesCount_Internal(startEntityID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static class GraphQueries
|
|
||||||
{
|
|
||||||
#region JoinToGraph Empty
|
|
||||||
public static EcsSubGraph JoinToSubGraph<TCollection>(this TCollection entities, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
|
||||||
where TCollection : IEntityStorage
|
|
||||||
{
|
|
||||||
return entities.ToSpan().JoinToSubGraph(mode);
|
|
||||||
}
|
|
||||||
public static EcsSubGraph JoinToSubGraph(this EcsReadonlyGroup group, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
|
||||||
{
|
|
||||||
return group.ToSpan().JoinToSubGraph(mode);
|
|
||||||
}
|
|
||||||
public static EcsSubGraph JoinToSubGraph(this EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
|
||||||
{
|
|
||||||
EcsWorld world = span.World;
|
|
||||||
if (world.IsEnableReleaseDelEntBuffer)
|
|
||||||
{
|
|
||||||
world.ReleaseDelEntityBufferAll();
|
|
||||||
}
|
|
||||||
world.GetQueryCache(out EcsJoinToSubGraphExecutor executor, out EmptyAspect _);
|
|
||||||
return executor.ExecuteFor(span, mode);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region JoinToGraph
|
|
||||||
public static EcsSubGraph JoinToSubGraph<TCollection, TAspect>(this TCollection entities, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
|
||||||
where TAspect : EcsAspect, new()
|
|
||||||
where TCollection : IEntityStorage
|
|
||||||
{
|
|
||||||
return entities.ToSpan().JoinToSubGraph(out aspect, mode);
|
|
||||||
}
|
|
||||||
public static EcsSubGraph JoinToSubGraph<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
|
||||||
where TAspect : EcsAspect, new()
|
|
||||||
{
|
|
||||||
return group.ToSpan().JoinToSubGraph(out aspect, mode);
|
|
||||||
}
|
|
||||||
public static EcsSubGraph JoinToSubGraph<TAspect>(this EcsSpan span, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
|
||||||
where TAspect : EcsAspect, new()
|
|
||||||
{
|
|
||||||
EcsWorld world = span.World;
|
|
||||||
if (world.IsEnableReleaseDelEntBuffer)
|
|
||||||
{
|
|
||||||
world.ReleaseDelEntityBufferAll();
|
|
||||||
}
|
|
||||||
world.GetQueryCache(out EcsJoinToSubGraphExecutor executor, out aspect);
|
|
||||||
return executor.ExecuteFor(span, mode);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
63
src/Executors/GraphQueries.cs
Normal file
63
src/Executors/GraphQueries.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public static class GraphQueries
|
||||||
|
{
|
||||||
|
#region JoinToGraph Empty
|
||||||
|
//public static EcsSubGraph JoinToSubGraph<TCollection>(this TCollection entities, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
// where TCollection : IEntityStorage
|
||||||
|
//{
|
||||||
|
// return entities.ToSpan().JoinToSubGraph(mode);
|
||||||
|
//}
|
||||||
|
//public static EcsSubGraph JoinToSubGraph(this EcsReadonlyGroup group, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
//{
|
||||||
|
// return group.ToSpan().JoinToSubGraph(mode);
|
||||||
|
//}
|
||||||
|
//public static EcsSubGraph JoinToSubGraph(this EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
//{
|
||||||
|
// EcsWorld world = span.World;
|
||||||
|
// if (world.IsEnableReleaseDelEntBuffer)
|
||||||
|
// {
|
||||||
|
// world.ReleaseDelEntityBufferAll();
|
||||||
|
// }
|
||||||
|
// world.GetQueryCache(out EcsJoinToSubGraphExecutor executor, out EmptyAspect _);
|
||||||
|
// return executor.ExecuteFor(span, mode);
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region JoinToGraph
|
||||||
|
public static EcsSubGraph JoinToSubGraph<TCollection>(this TCollection entities, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
where TCollection : IEntityStorage
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(entities, entities.World))
|
||||||
|
{
|
||||||
|
entities.World.GetQueryCache(out EcsJoinToSubGraphExecutor executor, out EmptyAspect _);
|
||||||
|
return executor.Execute(mode);
|
||||||
|
}
|
||||||
|
return entities.ToSpan().JoinToSubGraph(out EmptyAspect _, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EcsSubGraph JoinToSubGraph<TCollection, TAspect>(this TCollection entities, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
where TAspect : EcsAspect, new()
|
||||||
|
where TCollection : IEntityStorage
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(entities, entities.World))
|
||||||
|
{
|
||||||
|
entities.World.GetQueryCache(out EcsJoinToSubGraphExecutor executor, out aspect);
|
||||||
|
return executor.Execute();
|
||||||
|
}
|
||||||
|
return entities.ToSpan().JoinToSubGraph(out aspect, mode);
|
||||||
|
}
|
||||||
|
public static EcsSubGraph JoinToSubGraph<TAspect>(this EcsReadonlyGroup group, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
where TAspect : EcsAspect, new()
|
||||||
|
{
|
||||||
|
return group.ToSpan().JoinToSubGraph(out aspect, mode);
|
||||||
|
}
|
||||||
|
public static EcsSubGraph JoinToSubGraph<TAspect>(this EcsSpan span, out TAspect aspect, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
|
where TAspect : EcsAspect, new()
|
||||||
|
{
|
||||||
|
span.World.GetQueryCache(out EcsJoinToSubGraphExecutor executor, out aspect);
|
||||||
|
return executor.ExecuteFor(span, mode);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -1,145 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Graphs.Internal
|
|
||||||
{
|
|
||||||
internal class EntityLinkedList
|
|
||||||
{
|
|
||||||
public const int Enter = 0;
|
|
||||||
|
|
||||||
internal Node[] _nodes;
|
|
||||||
private int _count;
|
|
||||||
private int _lastNodeIndex;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public int Count => _count;
|
|
||||||
public int Capacity => _nodes.Length;
|
|
||||||
public int Last => _lastNodeIndex;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
public EntityLinkedList(int capacity)
|
|
||||||
{
|
|
||||||
_nodes = new Node[capacity * 2 + 10];
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Resize(int newCapacity)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _nodes, newCapacity * 2 + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < _nodes.Length; i++)
|
|
||||||
{
|
|
||||||
_nodes[i].next = 0;
|
|
||||||
}
|
|
||||||
_lastNodeIndex = Enter;
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Set(int nodeIndex, int entityID)
|
|
||||||
{
|
|
||||||
_nodes[nodeIndex].entityID = entityID;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int Get(int nodeIndex)
|
|
||||||
{
|
|
||||||
return _nodes[nodeIndex].entityID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int InsertBefore(int nodeIndex, int entityID)
|
|
||||||
{
|
|
||||||
_nodes[++_count].Set(entityID, nodeIndex);
|
|
||||||
return _count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary> Insert after</summary>
|
|
||||||
/// <returns> new node index</returns>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int InsertAfter(int nodeIndex, int entityID)
|
|
||||||
{
|
|
||||||
_nodes[++_count].Set(entityID, _nodes[nodeIndex].next);
|
|
||||||
_nodes[nodeIndex].next = _count;
|
|
||||||
_lastNodeIndex = nodeIndex + 1;
|
|
||||||
return _count;
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public int Add(int entityID)
|
|
||||||
{
|
|
||||||
int result = InsertAfter(_lastNodeIndex, entityID);
|
|
||||||
_lastNodeIndex = _count;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Enumerator GetEnumerator()
|
|
||||||
{
|
|
||||||
return new Enumerator(_nodes);
|
|
||||||
}
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//public EcsJoinedSpan GetSpan(int startNodeIndex, int count)
|
|
||||||
//{
|
|
||||||
// return new EcsJoinedSpan(_nodes, startNodeIndex, count);
|
|
||||||
//}
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
//public EcsJoinedSpan GetEmptySpan()
|
|
||||||
//{
|
|
||||||
// return new EcsJoinedSpan(_nodes, 0, 0);
|
|
||||||
//}
|
|
||||||
#region Utils
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
|
||||||
public struct Node
|
|
||||||
{
|
|
||||||
public static readonly Node Empty = new Node() { entityID = 0, next = -1 };
|
|
||||||
public int entityID;
|
|
||||||
/// <summary>next node index</summary>
|
|
||||||
public int next;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Set(int entityID, int next)
|
|
||||||
{
|
|
||||||
this.entityID = entityID;
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"e:{entityID} next:{next}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public struct Enumerator
|
|
||||||
{
|
|
||||||
private readonly Node[] _nodes;
|
|
||||||
private int _index;
|
|
||||||
private int _next;
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Enumerator(Node[] nodes)
|
|
||||||
{
|
|
||||||
_nodes = nodes;
|
|
||||||
_index = -1;
|
|
||||||
_next = Enter;
|
|
||||||
}
|
|
||||||
public int Current
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _nodes[_index].entityID; }
|
|
||||||
}
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
_index = _next;
|
|
||||||
_next = _nodes[_next].next;
|
|
||||||
return _index > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
180
src/Internal/OnlyAppendHeadLinkedList.cs
Normal file
180
src/Internal/OnlyAppendHeadLinkedList.cs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Graphs.Internal
|
||||||
|
{
|
||||||
|
internal class OnlyAppendHeadLinkedList
|
||||||
|
{
|
||||||
|
public const NodeIndex Enter = 0;
|
||||||
|
|
||||||
|
internal Node[] _nodes;
|
||||||
|
private int _count;
|
||||||
|
private NodeIndex _lastNodeIndex;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _count; }
|
||||||
|
}
|
||||||
|
public int Capacity
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _nodes.Length; }
|
||||||
|
}
|
||||||
|
public NodeIndex Last
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _lastNodeIndex; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public OnlyAppendHeadLinkedList(int capacity)
|
||||||
|
{
|
||||||
|
_nodes = new Node[capacity * 2 + 10];
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void InsertIntoHead(ref NodeIndex headIndex, int entityID)
|
||||||
|
{
|
||||||
|
_nodes[++_count].Set(entityID, headIndex);
|
||||||
|
headIndex = (NodeIndex)_count;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public NodeIndex NewHead(int entityID)
|
||||||
|
{
|
||||||
|
_nodes[++_count].Set(entityID, 0);
|
||||||
|
return (NodeIndex)_count;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int Get(NodeIndex nodeIndex)
|
||||||
|
{
|
||||||
|
return _nodes[(int)nodeIndex].entityID;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_lastNodeIndex = Enter;
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Enumerator GetEnumerator()
|
||||||
|
{
|
||||||
|
return new Enumerator(_nodes);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region TMP
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public void Resize(int newCapacity)
|
||||||
|
//{
|
||||||
|
// Array.Resize(ref _nodes, newCapacity * 2 + 10);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public void Set(HeadIndex nodeIndex, int entityID)
|
||||||
|
//{
|
||||||
|
// _nodes[(int)nodeIndex].entityID = entityID;
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// <returns> new node index</returns>
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public NodeID InsertBefore(NodeID nodeIndex, int entityID)
|
||||||
|
//{
|
||||||
|
// NodeID newNode = (NodeID)(++_count);
|
||||||
|
// _nodes[(int)newNode] = _nodes[(int)nodeIndex];
|
||||||
|
// _nodes[(int)newNode].Set(entityID, nodeIndex);
|
||||||
|
// return newNode;
|
||||||
|
//}
|
||||||
|
///// <returns> new node index</returns>
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public NodeID InsertAfter(NodeID nodeIndex, int entityID)
|
||||||
|
//{
|
||||||
|
// NodeID newNode = (NodeID)(++_count);
|
||||||
|
// _nodes[(int)nodeIndex].next = newNode;
|
||||||
|
// _nodes[(int)newNode].Set(entityID, _nodes[(int)nodeIndex].next);
|
||||||
|
// _lastNodeIndex = newNode;
|
||||||
|
// return newNode;
|
||||||
|
//
|
||||||
|
// //_nodes[++_count].Set(entityID, _nodes[(int)nodeIndex].next);
|
||||||
|
// //_nodes[(int)nodeIndex].next = (NodeID)_count;
|
||||||
|
// //_lastNodeIndex = (NodeID)((int)nodeIndex + 1);
|
||||||
|
// //return (NodeID)_count;
|
||||||
|
//}
|
||||||
|
/// <returns> new node index</returns>
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public NodeID Add(int entityID)
|
||||||
|
//{
|
||||||
|
// var result = InsertAfter(_lastNodeIndex, entityID);
|
||||||
|
// _lastNodeIndex = (NodeID)_count;
|
||||||
|
// return result;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public EcsJoinedSpan GetSpan(int startNodeIndex, int count)
|
||||||
|
//{
|
||||||
|
// return new EcsJoinedSpan(_nodes, startNodeIndex, count);
|
||||||
|
//}
|
||||||
|
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
//public EcsJoinedSpan GetEmptySpan()
|
||||||
|
//{
|
||||||
|
// return new EcsJoinedSpan(_nodes, 0, 0);
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Utils
|
||||||
|
public enum NodeIndex : int { }
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
|
public struct Node
|
||||||
|
{
|
||||||
|
public static readonly Node Empty = new Node() { entityID = 0, next = (int)Enter };
|
||||||
|
|
||||||
|
public int entityID;
|
||||||
|
public NodeIndex next;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Set(int entityID, NodeIndex next)
|
||||||
|
{
|
||||||
|
this.entityID = entityID;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"e:{entityID} next:{next}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public struct Enumerator
|
||||||
|
{
|
||||||
|
private readonly Node[] _nodes;
|
||||||
|
private int _index;
|
||||||
|
private int _next;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public Enumerator(Node[] nodes)
|
||||||
|
{
|
||||||
|
_nodes = nodes;
|
||||||
|
_index = -1;
|
||||||
|
_next = (int)Enter;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -19,9 +19,9 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void ArgumentNull()
|
internal static void ArgumentNull(string paramName)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException(paramName);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
internal static void ArgumentOutOfRange()
|
internal static void ArgumentOutOfRange()
|
||||||
@ -48,6 +48,13 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
{
|
{
|
||||||
throw new KeyNotFoundException();
|
throw new KeyNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
internal static void Quiery_ArgumentDifferentWorldsException()
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The groups belong to different worlds.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user