mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-18 03:34:35 +08:00
fixes
This commit is contained in:
parent
f16e5e353c
commit
285649c47c
@ -1,21 +0,0 @@
|
|||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public abstract class EcsArcWorld : EcsWorld
|
|
||||||
{
|
|
||||||
public EcsArcWorld(ConfigContainer config = null) : base(config) { }
|
|
||||||
public EcsArcWorld(IConfigContainer config = null) : base(config) { }
|
|
||||||
}
|
|
||||||
public sealed class EcsLoopArcWorld<TWorld> : EcsArcWorld
|
|
||||||
where TWorld : EcsWorld
|
|
||||||
{
|
|
||||||
public EcsLoopArcWorld(ConfigContainer config = null) : base(config) { }
|
|
||||||
public EcsLoopArcWorld(IConfigContainer config = null) : base(config) { }
|
|
||||||
}
|
|
||||||
public sealed class EcsArcWorld<TStartWorld, TEndWorld> : EcsArcWorld
|
|
||||||
where TStartWorld : EcsWorld
|
|
||||||
where TEndWorld : EcsWorld
|
|
||||||
{
|
|
||||||
public EcsArcWorld(ConfigContainer config = null) : base(config) { }
|
|
||||||
public EcsArcWorld(IConfigContainer config = null) : base(config) { }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 72248d53a53519847b5b360dd02c37c5
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,29 +1,24 @@
|
|||||||
using DCFApixels.DragonECS.Graphs.Internal;
|
using DCFApixels.DragonECS.Graphs.Internal;
|
||||||
using DCFApixels.DragonECS.UncheckedCore;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
//Arc
|
//Graph
|
||||||
//Arc world
|
//Graph world
|
||||||
//Rel entity
|
//Rel entity
|
||||||
//Component
|
//Component
|
||||||
public class EcsArc
|
public class EcsGraph
|
||||||
{
|
{
|
||||||
private readonly EcsWorld _startWorld;
|
private readonly EcsWorld _world;
|
||||||
private readonly EcsWorld _endWorld;
|
private readonly EcsWorld _graphWorld;
|
||||||
private readonly EcsArcWorld _arcWorld;
|
|
||||||
|
|
||||||
private readonly StartWorldHandler _startWorldHandler;
|
private readonly GraphWorldHandler _arcWorldHandler;
|
||||||
private readonly ArcWorldHandler _arcWorldHandler;
|
private readonly WorldHandler _loopWorldHandler;
|
||||||
private readonly EndWorldHandler _endWorldHandler;
|
|
||||||
private readonly LoopWorldHandler _loopWorldHandler;
|
|
||||||
|
|
||||||
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
|
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
|
||||||
private readonly SparseMatrix _matrix;
|
private readonly SparseMatrix _matrix;
|
||||||
|
|
||||||
private bool _isLoop;
|
|
||||||
private bool _isInit = false;
|
private bool _isInit = false;
|
||||||
|
|
||||||
private int _count;
|
private int _count;
|
||||||
@ -34,30 +29,25 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _isInit; }
|
get { return _isInit; }
|
||||||
}
|
}
|
||||||
public EcsWorld StartWorld
|
public EcsWorld World
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _startWorld; }
|
get { return _world; }
|
||||||
}
|
}
|
||||||
public EcsWorld EndWorld
|
public short WorldID
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _endWorld; }
|
get { return _world.id; }
|
||||||
}
|
}
|
||||||
public EcsArcWorld ArcWorld
|
public EcsWorld GraphWorld
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _arcWorld; }
|
get { return _graphWorld; }
|
||||||
}
|
}
|
||||||
public short ArcWorldID
|
public short GraphWorldID
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _arcWorld.id; }
|
get { return _graphWorld.id; }
|
||||||
}
|
|
||||||
public bool IsLoop
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _isLoop; }
|
|
||||||
}
|
}
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
@ -67,43 +57,23 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors/Destroy
|
#region Constructors/Destroy
|
||||||
internal EcsArc(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld)
|
internal EcsGraph(EcsWorld world, EcsWorld graphWorld)
|
||||||
{
|
{
|
||||||
_startWorld = startWorld;
|
_world = world;
|
||||||
_endWorld = endWorld;
|
_graphWorld = graphWorld;
|
||||||
_arcWorld = arcWorld;
|
|
||||||
|
|
||||||
_isLoop = startWorld == endWorld;
|
_relEntityInfos = new RelationInfo[_graphWorld.Capacity];
|
||||||
|
_matrix = new SparseMatrix(_graphWorld.Capacity);
|
||||||
|
|
||||||
_relEntityInfos = new RelationInfo[arcWorld.Capacity];
|
_arcWorldHandler = new GraphWorldHandler(this);
|
||||||
_matrix = new SparseMatrix(arcWorld.Capacity);
|
_loopWorldHandler = new WorldHandler(this);
|
||||||
|
|
||||||
_arcWorldHandler = new ArcWorldHandler(this);
|
|
||||||
if (_isLoop)
|
|
||||||
{
|
|
||||||
_loopWorldHandler = new LoopWorldHandler(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_startWorldHandler = new StartWorldHandler(this);
|
|
||||||
_endWorldHandler = new EndWorldHandler(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isInit = true;
|
_isInit = true;
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
_arcWorldHandler.Destroy();
|
_arcWorldHandler.Destroy();
|
||||||
if (_isLoop)
|
_loopWorldHandler.Destroy();
|
||||||
{
|
|
||||||
_loopWorldHandler.Destroy();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_startWorldHandler.Destroy();
|
|
||||||
_endWorldHandler.Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -125,7 +95,7 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private int NewRelationInternal(int startEntityID, int endEntityID)
|
private int NewRelationInternal(int startEntityID, int endEntityID)
|
||||||
{
|
{
|
||||||
int relEntityID = _arcWorld.NewEntity();
|
int relEntityID = _graphWorld.NewEntity();
|
||||||
_matrix.Add(startEntityID, endEntityID, relEntityID);
|
_matrix.Add(startEntityID, endEntityID, relEntityID);
|
||||||
_relEntityInfos[relEntityID] = new RelationInfo(startEntityID, endEntityID);
|
_relEntityInfos[relEntityID] = new RelationInfo(startEntityID, endEntityID);
|
||||||
_count++;
|
_count++;
|
||||||
@ -158,7 +128,7 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void DelRelation(int relEntityID)
|
public void DelRelation(int relEntityID)
|
||||||
{
|
{
|
||||||
_arcWorld.TryDelEntity(relEntityID);
|
_graphWorld.TryDelEntity(relEntityID);
|
||||||
//ClearRelation_Internal(relEntityID);
|
//ClearRelation_Internal(relEntityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,30 +183,18 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Other
|
#region GraphWorldHandler
|
||||||
public EcsArc GetInversetArc()
|
private class GraphWorldHandler : IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
return _endWorld.GetArc(_startWorld);
|
private readonly EcsGraph _arc;
|
||||||
}
|
public GraphWorldHandler(EcsGraph arc)
|
||||||
public bool TryGetInversetArc(out EcsArc arc)
|
|
||||||
{
|
|
||||||
return _endWorld.TryGetArc(_startWorld, out arc);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region VertexWorldHandler
|
|
||||||
private class ArcWorldHandler : IEcsWorldEventListener
|
|
||||||
{
|
|
||||||
private readonly EcsArc _arc;
|
|
||||||
public ArcWorldHandler(EcsArc arc)
|
|
||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.ArcWorld.AddListener(this);
|
_arc.GraphWorld.AddListener(this);
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
_arc.ArcWorld.RemoveListener(this);
|
_arc.GraphWorld.RemoveListener(this);
|
||||||
}
|
}
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> relEntityBuffer)
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> relEntityBuffer)
|
||||||
@ -253,25 +211,25 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Loop
|
#region WorldHandler
|
||||||
private class LoopWorldHandler : IEcsWorldEventListener
|
private class WorldHandler : IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
private readonly EcsArc _arc;
|
private readonly EcsGraph _arc;
|
||||||
public LoopWorldHandler(EcsArc arc)
|
public WorldHandler(EcsGraph arc)
|
||||||
{
|
{
|
||||||
_arc = arc;
|
_arc = arc;
|
||||||
_arc.StartWorld.AddListener(this);
|
_arc.World.AddListener(this);
|
||||||
//OnWorldResize(_arc.StartWorld.Capacity);
|
|
||||||
}
|
}
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
{
|
{
|
||||||
_arc.StartWorld.RemoveListener(this);
|
_arc.World.RemoveListener(this);
|
||||||
}
|
}
|
||||||
#region Callbacks
|
#region Callbacks
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
||||||
{
|
{
|
||||||
var graph = _arc.ArcWorld.GetExecutor<EcsJoinToGraphExecutor<EmptyAspect>>().Execute();
|
var graph = _arc.GraphWorld.JoinToSubGraph(EcsSubGraphMode.All);
|
||||||
foreach (var e in startEntityBuffer)
|
foreach (var e in startEntityBuffer)
|
||||||
{
|
{
|
||||||
var span = graph.GetNodes(e);
|
var span = graph.GetNodes(e);
|
||||||
@ -280,61 +238,12 @@ namespace DCFApixels.DragonECS
|
|||||||
_arc.DelRelation(relE);
|
_arc.DelRelation(relE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
_arc._graphWorld.ReleaseDelEntityBufferAll();
|
||||||
}
|
}
|
||||||
public void OnWorldDestroy() { }
|
public void OnWorldDestroy() { }
|
||||||
public void OnWorldResize(int startWorldNewSize) { }
|
public void OnWorldResize(int startWorldNewSize) { }
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region StartEnd
|
|
||||||
private class StartWorldHandler : IEcsWorldEventListener
|
|
||||||
{
|
|
||||||
private readonly EcsArc _arc;
|
|
||||||
public StartWorldHandler(EcsArc arc)
|
|
||||||
{
|
|
||||||
_arc = arc;
|
|
||||||
_arc.StartWorld.AddListener(this);
|
|
||||||
//OnWorldResize(_arc.StartWorld.Capacity);
|
|
||||||
}
|
|
||||||
public void Destroy()
|
|
||||||
{
|
|
||||||
_arc.StartWorld.RemoveListener(this);
|
|
||||||
}
|
|
||||||
#region Callbacks
|
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
|
||||||
{
|
|
||||||
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
|
||||||
}
|
|
||||||
public void OnWorldDestroy() { }
|
|
||||||
public void OnWorldResize(int startWorldNewSize) { }
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
private class EndWorldHandler : IEcsWorldEventListener
|
|
||||||
{
|
|
||||||
private readonly EcsArc _arc;
|
|
||||||
public EndWorldHandler(EcsArc arc)
|
|
||||||
{
|
|
||||||
_arc = arc;
|
|
||||||
_arc.EndWorld.AddListener(this);
|
|
||||||
//OnWorldResize(_arc.EndWorld.Capacity);
|
|
||||||
}
|
|
||||||
public void Destroy()
|
|
||||||
{
|
|
||||||
_arc.EndWorld.RemoveListener(this);
|
|
||||||
}
|
|
||||||
#region Callbacks
|
|
||||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> endEntityBuffer)
|
|
||||||
{
|
|
||||||
_arc._arcWorld.ReleaseDelEntityBufferAll();
|
|
||||||
}
|
|
||||||
public void OnWorldDestroy() { }
|
|
||||||
public void OnWorldResize(int endWorldNewSize) { }
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
108
src/EcsGraphExtensions.cs
Normal file
108
src/EcsGraphExtensions.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using DCFApixels.DragonECS.Graphs.Internal;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public static class EcsGraphExtensions
|
||||||
|
{
|
||||||
|
private static EcsGraph[] _worldGraphs = new EcsGraph[4];
|
||||||
|
|
||||||
|
public static EcsGraph CreateGraph(this EcsWorld self, EcsWorld graphWorld)
|
||||||
|
{
|
||||||
|
int worldID = self.id;
|
||||||
|
if (_worldGraphs.Length <= worldID)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||||
|
}
|
||||||
|
ref EcsGraph graph = ref _worldGraphs[worldID];
|
||||||
|
if (graph != null)
|
||||||
|
{
|
||||||
|
Throw.UndefinedException();
|
||||||
|
}
|
||||||
|
graph = new EcsGraph(self, graphWorld);
|
||||||
|
new Destroyer(graph);
|
||||||
|
_worldGraphs[graphWorld.id] = graph;
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EcsGraph CreateOrGetGraph(this EcsWorld self, EcsWorld graphWorld)
|
||||||
|
{
|
||||||
|
int worldID = self.id;
|
||||||
|
if (_worldGraphs.Length <= worldID)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||||
|
}
|
||||||
|
ref EcsGraph graph = ref _worldGraphs[worldID];
|
||||||
|
if (graph != null)
|
||||||
|
{
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
graph = new EcsGraph(self, graphWorld);
|
||||||
|
new Destroyer(graph);
|
||||||
|
_worldGraphs[graphWorld.id] = graph;
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetGraph(this EcsWorld self, out EcsGraph graph)
|
||||||
|
{
|
||||||
|
int worldID = self.id;
|
||||||
|
if (_worldGraphs.Length <= worldID)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||||
|
}
|
||||||
|
graph = _worldGraphs[worldID];
|
||||||
|
return graph != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EcsGraph GetGraph(this EcsWorld self)
|
||||||
|
{
|
||||||
|
if (self.TryGetGraph(out EcsGraph graph))
|
||||||
|
{
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
Throw.UndefinedException();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsGraphWorld(this EcsWorld self)
|
||||||
|
{
|
||||||
|
if (self.TryGetGraph(out EcsGraph graph))
|
||||||
|
{
|
||||||
|
return graph.GraphWorld == self;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryDestroy(EcsGraph graph)
|
||||||
|
{
|
||||||
|
int worldID = graph.WorldID;
|
||||||
|
if (_worldGraphs.Length <= worldID)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||||
|
}
|
||||||
|
int graphWorldID = graph.GraphWorldID;
|
||||||
|
if (_worldGraphs.Length <= graphWorldID)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _worldGraphs, graphWorldID + 4);
|
||||||
|
}
|
||||||
|
_worldGraphs[worldID] = null;
|
||||||
|
_worldGraphs[graphWorldID] = null;
|
||||||
|
}
|
||||||
|
private class Destroyer : IEcsWorldEventListener
|
||||||
|
{
|
||||||
|
private EcsGraph _graph;
|
||||||
|
public Destroyer(EcsGraph graph)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
graph.World.AddListener(this);
|
||||||
|
graph.GraphWorld.AddListener(this);
|
||||||
|
}
|
||||||
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
|
public void OnWorldDestroy()
|
||||||
|
{
|
||||||
|
TryDestroy(_graph);
|
||||||
|
}
|
||||||
|
public void OnWorldResize(int newSize) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,191 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Graphs.Internal;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public static class EcsWorldGraph
|
|
||||||
{
|
|
||||||
private static readonly SparseArray<EcsArc> _matrix = new SparseArray<EcsArc>(4);
|
|
||||||
private static EcsArc[] _arcsMapping = new EcsArc[4];
|
|
||||||
|
|
||||||
#region Register/Unregister
|
|
||||||
private static EcsArc Register(EcsWorld startWorld, EcsWorld endWorld, EcsArcWorld arcWorld)
|
|
||||||
{
|
|
||||||
int startWorldID = startWorld.id;
|
|
||||||
int endWorldID = endWorld.id;
|
|
||||||
int arcWorldID = arcWorld.id;
|
|
||||||
|
|
||||||
if (_arcsMapping.Length <= arcWorldID)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _arcsMapping, arcWorldID + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if (_matrix.Contains(startWorldID, endWorldID))
|
|
||||||
{
|
|
||||||
throw new EcsFrameworkException();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
EcsArc arc = new EcsArc(startWorld, endWorld, arcWorld);
|
|
||||||
_matrix[startWorldID, endWorldID] = arc;
|
|
||||||
_arcsMapping[arcWorldID] = arc;
|
|
||||||
return arc;
|
|
||||||
}
|
|
||||||
public static bool IsRegistered(EcsArc arc)
|
|
||||||
{
|
|
||||||
return Has(arc.StartWorld.id, arc.EndWorld.id);
|
|
||||||
}
|
|
||||||
private static void Unregister(EcsWorld startWorld, EcsWorld endWorld)
|
|
||||||
{
|
|
||||||
int startWorldID = startWorld.id;
|
|
||||||
int endWorldID = endWorld.id;
|
|
||||||
EcsArc arc = _matrix[startWorldID, endWorldID];
|
|
||||||
_arcsMapping[arc.ArcWorld.id] = null;
|
|
||||||
_matrix.Remove(startWorldID, endWorldID);
|
|
||||||
arc.Destroy();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Get/Has
|
|
||||||
// private static EcsArc GetOrRigister(EcsWorld startWorld, EcsWorld otherWorld)
|
|
||||||
// {
|
|
||||||
//#if DEBUG
|
|
||||||
// if (!_matrix.Contains(startWorld.id, otherWorld.id))
|
|
||||||
// {
|
|
||||||
// return Register();
|
|
||||||
// }
|
|
||||||
//#endif
|
|
||||||
// return _matrix[startWorld.id, otherWorld.id];
|
|
||||||
// }
|
|
||||||
private static EcsArc Get(EcsWorld startWorld, EcsWorld otherWorld)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
if (!_matrix.Contains(startWorld.id, otherWorld.id))
|
|
||||||
{
|
|
||||||
throw new EcsFrameworkException();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return _matrix[startWorld.id, otherWorld.id];
|
|
||||||
}
|
|
||||||
private static bool Has(EcsWorld startWorld, EcsWorld endWorld)
|
|
||||||
{
|
|
||||||
return Has(startWorld.id, endWorld.id);
|
|
||||||
}
|
|
||||||
private static bool Has(int startWorldID, int endWorldID)
|
|
||||||
{
|
|
||||||
return _matrix.Contains(startWorldID, endWorldID);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Extension
|
|
||||||
public static bool IsRegistered(this EcsArcWorld self)
|
|
||||||
{
|
|
||||||
if (self == null) { Throw.ArgumentNull(); }
|
|
||||||
int id = self.id;
|
|
||||||
return id < _arcsMapping.Length && _arcsMapping[self.id] != null;
|
|
||||||
}
|
|
||||||
public static EcsArc GetRegisteredArc(this EcsArcWorld self)
|
|
||||||
{
|
|
||||||
if (self == null) { Throw.ArgumentNull(); }
|
|
||||||
int id = self.id;
|
|
||||||
if (id < _arcsMapping.Length && _arcsMapping[self.id] == null)
|
|
||||||
{
|
|
||||||
Throw.UndefinedException();
|
|
||||||
}
|
|
||||||
return _arcsMapping[self.id];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self, out EcsLoopArcWorld<TWorld> arcWorld, IConfigContainer config = null)
|
|
||||||
where TWorld : EcsWorld
|
|
||||||
{
|
|
||||||
if (self == null) { Throw.ArgumentNull(); }
|
|
||||||
if (typeof(TWorld) != self.GetType())
|
|
||||||
{
|
|
||||||
EcsDebug.PrintWarning($"{nameof(TWorld)} is not {self.GetType().Name}");
|
|
||||||
}
|
|
||||||
arcWorld = new EcsLoopArcWorld<TWorld>(config);
|
|
||||||
return Register(self, self, arcWorld);
|
|
||||||
}
|
|
||||||
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end, out EcsArcWorld<TStartWorld, TEndWorld> arcWorld, IConfigContainer config = null)
|
|
||||||
where TStartWorld : EcsWorld
|
|
||||||
where TEndWorld : EcsWorld
|
|
||||||
{
|
|
||||||
if (start == null || end == null) { Throw.ArgumentNull(); }
|
|
||||||
if (typeof(TStartWorld) == typeof(EcsWorld) && typeof(TEndWorld) == typeof(EcsWorld))
|
|
||||||
{
|
|
||||||
EcsDebug.PrintWarning($"{nameof(TStartWorld)} is not {start.GetType().Name} or {nameof(TEndWorld)} is not {end.GetType().Name}");
|
|
||||||
}
|
|
||||||
arcWorld = new EcsArcWorld<TStartWorld, TEndWorld>(config);
|
|
||||||
return Register(start, end, arcWorld);
|
|
||||||
}
|
|
||||||
public static EcsArc SetLoopArcAuto<TWorld>(this TWorld self, IConfigContainer config = null)
|
|
||||||
where TWorld : EcsWorld
|
|
||||||
{
|
|
||||||
return SetLoopArcAuto(self, out _, config);
|
|
||||||
}
|
|
||||||
public static EcsArc SetArcAuto<TStartWorld, TEndWorld>(this TStartWorld start, TEndWorld end, IConfigContainer config = null)
|
|
||||||
where TStartWorld : EcsWorld
|
|
||||||
where TEndWorld : EcsWorld
|
|
||||||
{
|
|
||||||
return SetArcAuto(start, end, out _, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EcsArc SetLoopArc(this EcsWorld self, EcsArcWorld arc)
|
|
||||||
{
|
|
||||||
return SetArc(self, self, arc);
|
|
||||||
}
|
|
||||||
public static EcsArc SetArc(this EcsWorld start, EcsWorld end, EcsArcWorld arc)
|
|
||||||
{
|
|
||||||
if (start == null || end == null || arc == null) { Throw.ArgumentNull(); }
|
|
||||||
return Register(start, end, arc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasLoopArc(this EcsWorld self)
|
|
||||||
{
|
|
||||||
return HasArc(self, self);
|
|
||||||
}
|
|
||||||
public static bool HasArc(this EcsWorld start, EcsWorld end)
|
|
||||||
{
|
|
||||||
if (start == null || end == null) { Throw.ArgumentNull(); }
|
|
||||||
return Has(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static EcsArc GetLoopArc(this EcsWorld self)
|
|
||||||
{
|
|
||||||
return GetArc(self, self);
|
|
||||||
}
|
|
||||||
public static EcsArc GetArc(this EcsWorld start, EcsWorld end)
|
|
||||||
{
|
|
||||||
if (start == null || end == null) { Throw.ArgumentNull(); }
|
|
||||||
return Get(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryGetLoopArc(this EcsWorld self, out EcsArc arc)
|
|
||||||
{
|
|
||||||
return TryGetArc(self, self, out arc);
|
|
||||||
}
|
|
||||||
public static bool TryGetArc(this EcsWorld start, EcsWorld end, out EcsArc arc)
|
|
||||||
{
|
|
||||||
if (start == null || end == null) { Throw.ArgumentNull(); }
|
|
||||||
bool result = Has(start, end);
|
|
||||||
arc = result ? Get(start, end) : null;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DestroyLoopArc(this EcsWorld self)
|
|
||||||
{
|
|
||||||
DestroyArcWith(self, self);
|
|
||||||
}
|
|
||||||
public static void DestroyArcWith(this EcsWorld start, EcsWorld end)
|
|
||||||
{
|
|
||||||
if (start == null || end == null)
|
|
||||||
{
|
|
||||||
Throw.ArgumentNull();
|
|
||||||
}
|
|
||||||
Get(start, end).ArcWorld.Destroy();
|
|
||||||
Unregister(start, end);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,43 @@
|
|||||||
using DCFApixels.DragonECS.Graphs.Internal;
|
using DCFApixels.DragonECS.Graphs.Internal;
|
||||||
using DCFApixels.DragonECS.UncheckedCore;
|
using DCFApixels.DragonECS.UncheckedCore;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
public abstract class EcsJoinToGraphExecutor : EcsQueryExecutor, IEcsWorldEventListener
|
public sealed class EcsJoinToSubGraphExecutor<TAspect> : EcsJoinToSubGraphExecutor
|
||||||
|
where TAspect : EcsAspect
|
||||||
|
{
|
||||||
|
private TAspect _aspect;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public TAspect Aspect
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _aspect; }
|
||||||
|
}
|
||||||
|
protected override EcsAspect AspectRaw
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_aspect == null) { _aspect = World.GetAspect<TAspect>(); }
|
||||||
|
return _aspect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
public abstract class EcsJoinToSubGraphExecutor : EcsQueryExecutor, IEcsWorldEventListener
|
||||||
{
|
{
|
||||||
private EcsAspect _aspect;
|
private EcsAspect _aspect;
|
||||||
private EcsArcWorld _arcWorld;
|
|
||||||
|
|
||||||
private EntityLinkedList _linkedList;
|
private EntityLinkedList _linkedList;
|
||||||
private Basket[] _baskets;
|
private Basket[] _baskets;
|
||||||
private int[] _startEntities;
|
private int[] _startEntities;
|
||||||
private int _startEntitiesCount;
|
private int _startEntitiesCount;
|
||||||
|
|
||||||
|
private EcsGraph _graph;
|
||||||
|
|
||||||
private long _lastWorldVersion;
|
private long _lastWorldVersion;
|
||||||
|
|
||||||
private int _targetWorldCapacity = -1;
|
private int _targetWorldCapacity = -1;
|
||||||
@ -27,11 +50,6 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _lastWorldVersion; }
|
get { return _lastWorldVersion; }
|
||||||
}
|
}
|
||||||
public EcsArcWorld ArcWorld
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _arcWorld; }
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region OnInitialize/OnDestroy
|
#region OnInitialize/OnDestroy
|
||||||
@ -40,8 +58,8 @@ namespace DCFApixels.DragonECS
|
|||||||
_linkedList = new EntityLinkedList(World.Capacity);
|
_linkedList = new EntityLinkedList(World.Capacity);
|
||||||
_baskets = new Basket[World.Capacity];
|
_baskets = new Basket[World.Capacity];
|
||||||
World.AddListener(this);
|
World.AddListener(this);
|
||||||
_arcWorld = (EcsArcWorld)World;
|
|
||||||
_aspect = AspectRaw;
|
_aspect = AspectRaw;
|
||||||
|
_graph = World.GetGraph();
|
||||||
}
|
}
|
||||||
protected override void OnDestroy()
|
protected override void OnDestroy()
|
||||||
{
|
{
|
||||||
@ -50,11 +68,11 @@ namespace DCFApixels.DragonECS
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Execute
|
#region Execute
|
||||||
public EcsGraph Execute()
|
public EcsSubGraph Execute(EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
{
|
{
|
||||||
return ExecuteFor(World.Entities);
|
return ExecuteFor(World.Entities, mode);
|
||||||
}
|
}
|
||||||
public EcsGraph ExecuteFor(EcsSpan span)
|
public EcsSubGraph ExecuteFor(EcsSpan span, EcsSubGraphMode mode = EcsSubGraphMode.StartToEnd)
|
||||||
{
|
{
|
||||||
_executeMarker.Begin();
|
_executeMarker.Begin();
|
||||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||||
@ -62,7 +80,7 @@ namespace DCFApixels.DragonECS
|
|||||||
else if (World != span.World) { Throw.ArgumentException(""); } //TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
else if (World != span.World) { Throw.ArgumentException(""); } //TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_lastWorldVersion != World.Version)
|
//if (_lastWorldVersion != World.Version)
|
||||||
{
|
{
|
||||||
//Подготовка массивов
|
//Подготовка массивов
|
||||||
if (_targetWorldCapacity < World.Capacity)
|
if (_targetWorldCapacity < World.Capacity)
|
||||||
@ -79,50 +97,68 @@ namespace DCFApixels.DragonECS
|
|||||||
_linkedList.Clear();
|
_linkedList.Clear();
|
||||||
//Конец подготовки массивов
|
//Конец подготовки массивов
|
||||||
|
|
||||||
EcsArc arc = _arcWorld.GetRegisteredArc();
|
if ((mode & EcsSubGraphMode.StartToEnd) != 0)
|
||||||
|
|
||||||
if (_aspect.Mask.IsEmpty)
|
|
||||||
{
|
{
|
||||||
foreach (var relationEntityID in span)
|
if (_aspect.Mask.IsEmpty)
|
||||||
{
|
{
|
||||||
int startEntityID = arc.GetRelationStart(relationEntityID);
|
foreach (var relationEntityID in span) { AddStart(relationEntityID); }
|
||||||
if (startEntityID == 0) { continue; }
|
}
|
||||||
Add(startEntityID, relationEntityID);
|
else
|
||||||
|
{
|
||||||
|
var iterator = _aspect.GetIteratorFor(span);
|
||||||
|
foreach (var relationEntityID in iterator) { AddStart(relationEntityID); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if ((mode & EcsSubGraphMode.EndToStart) != 0)
|
||||||
{
|
{
|
||||||
var iterator = _aspect.GetIteratorFor(span);
|
if (_aspect.Mask.IsEmpty)
|
||||||
foreach (var relationEntityID in iterator)
|
|
||||||
{
|
{
|
||||||
int startEntityID = arc.GetRelationStart(relationEntityID);
|
foreach (var relationEntityID in span) { AddEnd(relationEntityID); }
|
||||||
if (startEntityID == 0) { continue; }
|
}
|
||||||
Add(startEntityID, relationEntityID);
|
else
|
||||||
|
{
|
||||||
|
var iterator = _aspect.GetIteratorFor(span);
|
||||||
|
foreach (var relationEntityID in iterator) { AddEnd(relationEntityID); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastWorldVersion = World.Version;
|
_lastWorldVersion = World.Version;
|
||||||
}
|
}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
|
||||||
_executeMarker.End();
|
_executeMarker.End();
|
||||||
return new EcsGraph(this, UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount));
|
return new EcsSubGraph(this, UncheckedCoreUtility.CreateSpan(WorldID, _startEntities, _startEntitiesCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Add(int startEntityID, int relationEntityID)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void AddStart(int relationEntityID)
|
||||||
{
|
{
|
||||||
_startEntities[_startEntitiesCount++] = startEntityID;
|
AddFrom(_graph.GetRelationStart(relationEntityID), relationEntityID);
|
||||||
ref var basket = ref _baskets[startEntityID];
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void AddEnd(int relationEntityID)
|
||||||
|
{
|
||||||
|
AddFrom(_graph.GetRelationEnd(relationEntityID), relationEntityID);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void AddFrom(int fromEntityID, int relationEntityID)
|
||||||
|
{
|
||||||
|
if (fromEntityID == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ref var basket = ref _baskets[fromEntityID];
|
||||||
if (basket.index <= 0)
|
if (basket.index <= 0)
|
||||||
{
|
{
|
||||||
|
_startEntities[_startEntitiesCount++] = fromEntityID;
|
||||||
basket.index = _linkedList.Add(relationEntityID);
|
basket.index = _linkedList.Add(relationEntityID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_linkedList.InsertAfter(basket.index, relationEntityID);
|
basket.index = _linkedList.InsertBefore(basket.index, relationEntityID);
|
||||||
}
|
}
|
||||||
basket.count++;
|
basket.count++;
|
||||||
}
|
}
|
||||||
@ -130,10 +166,10 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
#region Internal result methods
|
#region Internal result methods
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal EcsGraphSpan GetNodes_Internal(int startEntityID)
|
internal EcsSubGraphSpan GetNodes_Internal(int startEntityID)
|
||||||
{
|
{
|
||||||
Basket basket = _baskets[startEntityID];
|
Basket basket = _baskets[startEntityID];
|
||||||
return new EcsGraphSpan(_linkedList._nodes, basket.index, basket.count);
|
return new EcsSubGraphSpan(_linkedList._nodes, basket.index, basket.count);
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal int GetNode_Internal(int startEntityID)
|
internal int GetNode_Internal(int startEntityID)
|
||||||
@ -167,42 +203,29 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
public int index;
|
public int index;
|
||||||
public int count;
|
public int count;
|
||||||
}
|
public override string ToString()
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
public sealed class EcsJoinToGraphExecutor<TAspect> : EcsJoinToGraphExecutor
|
|
||||||
where TAspect : EcsAspect
|
|
||||||
{
|
|
||||||
private TAspect _aspect;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public TAspect Aspect
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get { return _aspect; }
|
|
||||||
}
|
|
||||||
protected override EcsAspect AspectRaw
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
{
|
||||||
if (_aspect == null)
|
return $"i:{index} count:{count}";
|
||||||
{
|
|
||||||
_aspect = World.GetAspect<TAspect>();
|
|
||||||
}
|
|
||||||
return _aspect;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum EcsSubGraphMode
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
StartToEnd = 1 << 0,
|
||||||
|
EndToStart = 1 << 1,
|
||||||
|
All = StartToEnd | EndToStart,
|
||||||
|
}
|
||||||
|
|
||||||
#region EcsJoinedSpan/EcsJoined
|
#region EcsJoinedSpan/EcsJoined
|
||||||
public readonly ref struct EcsGraphSpan
|
public readonly ref struct EcsSubGraphSpan
|
||||||
{
|
{
|
||||||
public static EcsGraphSpan Empty
|
public static EcsSubGraphSpan Empty
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return new EcsGraphSpan(null, 0, 0); }
|
get { return new EcsSubGraphSpan(null, 0, 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly EntityLinkedList.Node[] _nodes;
|
private readonly EntityLinkedList.Node[] _nodes;
|
||||||
@ -213,8 +236,20 @@ namespace DCFApixels.DragonECS
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get { return _count; }
|
get { return _count; }
|
||||||
}
|
}
|
||||||
|
private IEnumerable<int> E
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<int> result = new List<int>();
|
||||||
|
foreach (var item in this)
|
||||||
|
{
|
||||||
|
result.Add(item);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal EcsGraphSpan(EntityLinkedList.Node[] nodes, int startNodeIndex, int count)
|
internal EcsSubGraphSpan(EntityLinkedList.Node[] nodes, int startNodeIndex, int count)
|
||||||
{
|
{
|
||||||
_nodes = nodes;
|
_nodes = nodes;
|
||||||
_startNodeIndex = startNodeIndex;
|
_startNodeIndex = startNodeIndex;
|
||||||
@ -225,7 +260,7 @@ namespace DCFApixels.DragonECS
|
|||||||
{
|
{
|
||||||
return new Enumerator(_nodes, _startNodeIndex, _count);
|
return new Enumerator(_nodes, _startNodeIndex, _count);
|
||||||
}
|
}
|
||||||
public struct Enumerator
|
public ref struct Enumerator
|
||||||
{
|
{
|
||||||
private readonly EntityLinkedList.Node[] _nodes;
|
private readonly EntityLinkedList.Node[] _nodes;
|
||||||
private int _index;
|
private int _index;
|
||||||
@ -254,20 +289,20 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly ref struct EcsGraph
|
public readonly ref struct EcsSubGraph
|
||||||
{
|
{
|
||||||
private readonly EcsJoinToGraphExecutor _executer;
|
private readonly EcsJoinToSubGraphExecutor _executer;
|
||||||
private readonly EcsSpan _startEntities;
|
private readonly EcsSpan _startEntities;
|
||||||
public EcsSpan StartEntitiesSpan
|
public EcsSpan StartEntitiesSpan
|
||||||
{
|
{
|
||||||
get { return _startEntities; }
|
get { return _startEntities; }
|
||||||
}
|
}
|
||||||
internal EcsGraph(EcsJoinToGraphExecutor executer, EcsSpan startEntites)
|
internal EcsSubGraph(EcsJoinToSubGraphExecutor executer, EcsSpan startEntites)
|
||||||
{
|
{
|
||||||
_executer = executer;
|
_executer = executer;
|
||||||
_startEntities = startEntites;
|
_startEntities = startEntites;
|
||||||
}
|
}
|
||||||
public EcsGraphSpan GetNodes(int startEntityID)
|
public EcsSubGraphSpan GetNodes(int startEntityID)
|
||||||
{
|
{
|
||||||
return _executer.GetNodes_Internal(startEntityID);
|
return _executer.GetNodes_Internal(startEntityID);
|
||||||
}
|
}
|
||||||
@ -282,4 +317,64 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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();
|
||||||
|
}
|
||||||
|
var executor = world.GetExecutor<EcsJoinToSubGraphExecutor<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
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
EcsWorld world = span.World;
|
||||||
|
if (world.IsEnableReleaseDelEntBuffer)
|
||||||
|
{
|
||||||
|
world.ReleaseDelEntityBufferAll();
|
||||||
|
}
|
||||||
|
var executor = world.GetExecutor<EcsJoinToSubGraphExecutor<TAspect>>();
|
||||||
|
aspect = executor.Aspect;
|
||||||
|
return executor.ExecuteFor(span, mode);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
#region Constructors
|
#region Constructors
|
||||||
public EntityLinkedList(int capacity)
|
public EntityLinkedList(int capacity)
|
||||||
{
|
{
|
||||||
_nodes = new Node[capacity + 10];
|
_nodes = new Node[capacity * 2 + 10];
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -29,7 +29,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Resize(int newCapacity)
|
public void Resize(int newCapacity)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _nodes, newCapacity + 10);
|
Array.Resize(ref _nodes, newCapacity * 2 + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -54,6 +54,15 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
return _nodes[nodeIndex].entityID;
|
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>
|
/// <summary> Insert after</summary>
|
||||||
/// <returns> new node index</returns>
|
/// <returns> new node index</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -61,13 +70,15 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
{
|
{
|
||||||
_nodes[++_count].Set(entityID, _nodes[nodeIndex].next);
|
_nodes[++_count].Set(entityID, _nodes[nodeIndex].next);
|
||||||
_nodes[nodeIndex].next = _count;
|
_nodes[nodeIndex].next = _count;
|
||||||
_lastNodeIndex = _count;
|
_lastNodeIndex = nodeIndex + 1;
|
||||||
return _count;
|
return _count;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public int Add(int entityID)
|
public int Add(int entityID)
|
||||||
{
|
{
|
||||||
return InsertAfter(_lastNodeIndex, entityID);
|
int result = InsertAfter(_lastNodeIndex, entityID);
|
||||||
|
_lastNodeIndex = _count;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -99,6 +110,10 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
this.entityID = entityID;
|
this.entityID = entityID;
|
||||||
this.next = next;
|
this.next = next;
|
||||||
}
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"e:{entityID} next:{next}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public struct Enumerator
|
public struct Enumerator
|
||||||
{
|
{
|
||||||
|
@ -257,28 +257,30 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
_modBitMask = (newSize - 1) & 0x7FFFFFFF;
|
||||||
|
|
||||||
//newBuckets create and ini
|
//newBuckets create and ini
|
||||||
Basket* newBuckets = UnmanagedArrayUtility.New<Basket>(newSize);
|
//Basket* newBuckets = UnmanagedArrayUtility.New<Basket>(newSize);
|
||||||
|
UnsafeArray<Basket> newBuckets = new UnsafeArray<Basket>(newSize);
|
||||||
for (int i = 0; i < newSize; i++)
|
for (int i = 0; i < newSize; i++)
|
||||||
{
|
{
|
||||||
newBuckets[i] = Basket.Empty;
|
newBuckets[i] = Basket.Empty;
|
||||||
}
|
}
|
||||||
//END newBuckets create and ini
|
//END newBuckets create and ini
|
||||||
|
|
||||||
Entry* newEntries = UnmanagedArrayUtility.ResizeAndInit<Entry>(_entries.ptr, _capacity, newSize);
|
//Entry* newEntries = UnmanagedArrayUtility.ResizeAndInit<Entry>(_entries.ptr, _capacity, newSize);
|
||||||
|
UnsafeArray<Entry> newEntries = UnsafeArray<Entry>.Resize(_entries, newSize);
|
||||||
for (int i = 0; i < _count; i++)
|
for (int i = 0; i < _count; i++)
|
||||||
{
|
{
|
||||||
if (newEntries[i].key.yHash >= 0)
|
if (newEntries[i].key.x >= 0)
|
||||||
{
|
{
|
||||||
int targetBusket = newEntries[i].key.yHash % _capacity;
|
ref Entry entry = ref newEntries[i];
|
||||||
ref Basket basket = ref _buckets[targetBusket];
|
ref Basket basket = ref newBuckets[entry.key.yHash & _modBitMask];
|
||||||
newEntries[i].next = basket.index;
|
entry.next = basket.index;
|
||||||
basket.index = i;
|
basket.index = i;
|
||||||
basket.count++;
|
basket.count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_buckets = new UnsafeArray<Basket>(newBuckets, newSize);
|
_buckets = newBuckets;
|
||||||
_entries = new UnsafeArray<Entry>(newEntries, newSize);
|
_entries = newEntries;
|
||||||
|
|
||||||
_capacity = newSize;
|
_capacity = newSize;
|
||||||
}
|
}
|
||||||
@ -287,7 +289,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
private static int NormalizeCapacity(int capacity)
|
private static int NormalizeCapacity(int capacity)
|
||||||
{
|
{
|
||||||
int result = MIN_CAPACITY;
|
int result = MIN_CAPACITY;
|
||||||
while (result < capacity) result <<= 1;
|
while (result < capacity) { result <<= 1; }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -299,7 +301,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
public int next; // Index of next entry, -1 if last
|
public int next; // Index of next entry, -1 if last
|
||||||
public Key key;
|
public Key key;
|
||||||
public TValue value;
|
public TValue value;
|
||||||
public override string ToString() { return key.x == 0 ? "NULL" : value.ToString(); }
|
public override string ToString() { return key.x == 0 ? "NULL" : $"{key} {value}"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
@ -320,7 +322,7 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 8)]
|
||||||
public readonly struct Key : IEquatable<Key>
|
public readonly struct Key : IEquatable<Key>
|
||||||
{
|
{
|
||||||
public static readonly Key Null = new Key(-1, -1);
|
public static readonly Key Null = new Key(-1, 0);
|
||||||
public readonly int x;
|
public readonly int x;
|
||||||
public readonly int yHash;
|
public readonly int yHash;
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -330,12 +332,29 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
|||||||
this.yHash = yHash;
|
this.yHash = yHash;
|
||||||
}
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Key FromXY(int x, int y) { return new Key(x, x ^ y ^ BitsUtility.NextXorShiftState(y)); }
|
public static Key FromXY(int x, int y)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return new Key(x, x ^ y ^ XXX(y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static int XXX(int x)
|
||||||
|
{
|
||||||
|
x *= 3571;
|
||||||
|
x ^= x << 13;
|
||||||
|
x ^= x >> 17;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
public static bool operator ==(Key a, Key b) { return a.x == b.x && a.yHash == b.yHash; }
|
public static bool operator ==(Key a, Key b) { return a.x == b.x && a.yHash == b.yHash; }
|
||||||
public static bool operator !=(Key a, Key b) { return a.x != b.x || a.yHash != b.yHash; }
|
public static bool operator !=(Key a, Key b) { return a.x != b.x || a.yHash != b.yHash; }
|
||||||
public override int GetHashCode() { return yHash; }
|
public override int GetHashCode() { return yHash; }
|
||||||
public bool Equals(Key other) { return this == other; }
|
public bool Equals(Key other) { return this == other; }
|
||||||
public override bool Equals(object obj) { return obj is Key && Equals((Key)obj); }
|
public override bool Equals(object obj) { return obj is Key && Equals((Key)obj); }
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"({x}, {yHash})";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user