mirror of
https://github.com/DCFApixels/DragonECS-Graphs.git
synced 2025-09-17 19:24:36 +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
|
||||
{
|
||||
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;
|
||||
if (_worldGraphs.Length <= worldID)
|
||||
{
|
||||
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||
}
|
||||
ref EcsGraph graph = ref _worldGraphs[worldID];
|
||||
ref EntityGraph graph = ref _worldGraphs[worldID];
|
||||
if (graph != null)
|
||||
{
|
||||
Throw.UndefinedException();
|
||||
}
|
||||
graph = new EcsGraph(self, graphWorld);
|
||||
graph = new EntityGraph(self, graphWorld);
|
||||
new Destroyer(graph);
|
||||
_worldGraphs[graphWorld.ID] = 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;
|
||||
if (_worldGraphs.Length <= worldID)
|
||||
{
|
||||
Array.Resize(ref _worldGraphs, worldID + 4);
|
||||
}
|
||||
ref EcsGraph graph = ref _worldGraphs[worldID];
|
||||
ref EntityGraph graph = ref _worldGraphs[worldID];
|
||||
if (graph != null)
|
||||
{
|
||||
return graph;
|
||||
}
|
||||
graph = new EcsGraph(self, graphWorld);
|
||||
graph = new EntityGraph(self, graphWorld);
|
||||
new Destroyer(graph);
|
||||
_worldGraphs[graphWorld.ID] = 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;
|
||||
if (_worldGraphs.Length <= worldID)
|
||||
@ -54,9 +54,9 @@ namespace DCFApixels.DragonECS
|
||||
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;
|
||||
}
|
||||
@ -66,14 +66,14 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
public static bool IsGraphWorld(this EcsWorld self)
|
||||
{
|
||||
if (self.TryGetGraph(out EcsGraph graph))
|
||||
if (self.TryGetGraph(out EntityGraph graph))
|
||||
{
|
||||
return graph.GraphWorld == self;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void TryDestroy(EcsGraph graph)
|
||||
private static void TryDestroy(EntityGraph graph)
|
||||
{
|
||||
int worldID = graph.WorldID;
|
||||
if (_worldGraphs.Length <= worldID)
|
||||
@ -90,8 +90,8 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
private class Destroyer : IEcsWorldEventListener
|
||||
{
|
||||
private EcsGraph _graph;
|
||||
public Destroyer(EcsGraph graph)
|
||||
private EntityGraph _graph;
|
||||
public Destroyer(EntityGraph graph)
|
||||
{
|
||||
_graph = graph;
|
||||
graph.World.AddListener(this);
|
||||
|
@ -8,7 +8,7 @@ namespace DCFApixels.DragonECS
|
||||
//Graph world
|
||||
//Rel entity
|
||||
//Component
|
||||
public class EcsGraph
|
||||
public class EntityGraph
|
||||
{
|
||||
private readonly EcsWorld _world;
|
||||
private readonly EcsWorld _graphWorld;
|
||||
@ -16,13 +16,13 @@ namespace DCFApixels.DragonECS
|
||||
private readonly GraphWorldHandler _arcWorldHandler;
|
||||
private readonly WorldHandler _loopWorldHandler;
|
||||
|
||||
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
|
||||
private readonly SparseMatrix _matrix;
|
||||
|
||||
private bool _isInit = false;
|
||||
private RelationInfo[] _relEntityInfos; //N * (N - 1) / 2
|
||||
|
||||
private int _count;
|
||||
|
||||
private bool _isInit = false;
|
||||
|
||||
#region Properties
|
||||
internal bool IsInit_Internal
|
||||
{
|
||||
@ -57,7 +57,7 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#region Constructors/Destroy
|
||||
internal EcsGraph(EcsWorld world, EcsWorld graphWorld)
|
||||
internal EntityGraph(EcsWorld world, EcsWorld graphWorld)
|
||||
{
|
||||
_world = world;
|
||||
_graphWorld = graphWorld;
|
||||
@ -146,6 +146,23 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#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
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetRelation(int startEntityID, int endEntityID)
|
||||
@ -179,7 +196,11 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ArcEntityInfo
|
||||
#region Other
|
||||
public static implicit operator EntityGraph(SingletonMarker marker) { return marker.Builder.World.GetGraph(); }
|
||||
#endregion
|
||||
|
||||
#region RelEntityInfo
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public StartEnd GetRelationStartEnd(int relEntityID)
|
||||
@ -213,8 +234,8 @@ namespace DCFApixels.DragonECS
|
||||
#region GraphWorldHandler
|
||||
private class GraphWorldHandler : IEcsWorldEventListener
|
||||
{
|
||||
private readonly EcsGraph _arc;
|
||||
public GraphWorldHandler(EcsGraph arc)
|
||||
private readonly EntityGraph _arc;
|
||||
public GraphWorldHandler(EntityGraph arc)
|
||||
{
|
||||
_arc = arc;
|
||||
_arc.GraphWorld.AddListener(this);
|
||||
@ -243,38 +264,51 @@ namespace DCFApixels.DragonECS
|
||||
#region WorldHandler
|
||||
private class WorldHandler : IEcsWorldEventListener
|
||||
{
|
||||
private readonly EcsGraph _arc;
|
||||
public WorldHandler(EcsGraph arc)
|
||||
private readonly EntityGraph _graph;
|
||||
public WorldHandler(EntityGraph arc)
|
||||
{
|
||||
_arc = arc;
|
||||
_arc.World.AddListener(this);
|
||||
_graph = arc;
|
||||
_graph.World.AddListener(this);
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
_arc.World.RemoveListener(this);
|
||||
_graph.World.RemoveListener(this);
|
||||
}
|
||||
#region Callbacks
|
||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> startEntityBuffer)
|
||||
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> delEntities)
|
||||
{
|
||||
var graph = _arc.GraphWorld.JoinToSubGraph(EcsSubGraphMode.All);
|
||||
foreach (var e in startEntityBuffer)
|
||||
EcsSubGraph subGraph;
|
||||
EcsWorld graphWorld = _graph._graphWorld;
|
||||
|
||||
//subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.StartToEnd);
|
||||
subGraph = graphWorld.JoinToSubGraph(EcsSubGraphMode.All);
|
||||
foreach (var sourceE in delEntities)
|
||||
{
|
||||
var span = graph.GetNodes(e);
|
||||
foreach (var relE in span)
|
||||
var relEs = subGraph.GetRelations(sourceE);
|
||||
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 OnWorldResize(int startWorldNewSize) { }
|
||||
#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
|
||||
{
|
||||
using LinkedList = OnlyAppendHeadLinkedList;
|
||||
public sealed class EcsJoinToSubGraphExecutor : MaskQueryExecutor, IEcsWorldEventListener
|
||||
{
|
||||
private EntityLinkedList _linkedList;
|
||||
private Basket[] _baskets;
|
||||
private EntityGraph _graph;
|
||||
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 _startEntitiesCount;
|
||||
|
||||
private EcsGraph _graph;
|
||||
|
||||
private long _lastWorldVersion;
|
||||
|
||||
private int _targetWorldCapacity = -1;
|
||||
private EcsProfilerMarker _executeMarker = new EcsProfilerMarker("JoinAttach");
|
||||
|
||||
private EcsMaskIterator _iterator;
|
||||
private EcsProfilerMarker _executeMarker = new EcsProfilerMarker("Join");
|
||||
|
||||
#region Properties
|
||||
public sealed override long Version
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _lastWorldVersion; }
|
||||
get { return _version; }
|
||||
}
|
||||
public EcsGraph Graph
|
||||
public EntityGraph Graph
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
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
|
||||
|
||||
#region OnInitialize/OnDestroy
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
_linkedList = new EntityLinkedList(World.Capacity);
|
||||
_baskets = new Basket[World.Capacity];
|
||||
_versionsChecker = new WorldStateVersionsChecker(Mask);
|
||||
_linkedList = new OnlyAppendHeadLinkedList(World.Capacity);
|
||||
_linkedListSourceHeads = new LinkedListHead[World.Capacity];
|
||||
World.AddListener(this);
|
||||
_graph = World.GetGraph();
|
||||
_iterator = Mask.GetIterator();
|
||||
@ -60,95 +73,188 @@ namespace DCFApixels.DragonECS
|
||||
#endregion
|
||||
|
||||
#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();
|
||||
#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS
|
||||
if (span.IsNull) { Throw.ArgumentException(""); }//TODO составить текст исключения.
|
||||
else if (World != span.World) { Throw.ArgumentException(""); } //TODO составить текст исключения. это проверка на то что пользователь использует правильный мир
|
||||
if (span.IsNull) { _executeMarker.End(); Throw.ArgumentNull(nameof(span)); }
|
||||
if (span.WorldID != World.ID) { _executeMarker.End(); Throw.Quiery_ArgumentDifferentWorldsException(); }
|
||||
#endif
|
||||
|
||||
//if (_lastWorldVersion != World.Version)
|
||||
if (_filteredEntities == null)
|
||||
{
|
||||
//Подготовка массивов
|
||||
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;
|
||||
_filteredEntities = new int[32];
|
||||
}
|
||||
//else
|
||||
//{
|
||||
//
|
||||
//}
|
||||
_filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities);
|
||||
|
||||
throw new NotImplementedException();
|
||||
|
||||
_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)]
|
||||
private void AddStart(int relationEntityID)
|
||||
{
|
||||
AddFrom(_graph.GetRelationStart(relationEntityID), relationEntityID);
|
||||
AddSourceEntity(_graph.GetRelationStart(relationEntityID), relationEntityID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void AddEnd(int relationEntityID)
|
||||
{
|
||||
AddFrom(_graph.GetRelationEnd(relationEntityID), relationEntityID);
|
||||
AddSourceEntity(_graph.GetRelationEnd(relationEntityID), relationEntityID);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void AddFrom(int fromEntityID, int relationEntityID)
|
||||
private void AddSourceEntity(int sourceEntityID, int relationEntityID)
|
||||
{
|
||||
if (fromEntityID == 0)
|
||||
if (sourceEntityID == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
ref var basket = ref _baskets[fromEntityID];
|
||||
if (basket.index <= 0)
|
||||
ref var basket = ref _linkedListSourceHeads[sourceEntityID];
|
||||
if (basket.head == 0)
|
||||
{
|
||||
_startEntities[_startEntitiesCount++] = fromEntityID;
|
||||
basket.index = _linkedList.Add(relationEntityID);
|
||||
_startEntities[_startEntitiesCount++] = sourceEntityID;
|
||||
basket.head = _linkedList.NewHead(relationEntityID);
|
||||
}
|
||||
else
|
||||
{
|
||||
basket.index = _linkedList.InsertBefore(basket.index, relationEntityID);
|
||||
_linkedList.InsertIntoHead(ref basket.head, relationEntityID);
|
||||
}
|
||||
basket.count++;
|
||||
}
|
||||
@ -156,21 +262,21 @@ namespace DCFApixels.DragonECS
|
||||
|
||||
#region Internal result methods
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal EcsSubGraphSpan GetNodes_Internal(int startEntityID)
|
||||
internal EcsSubGraphSpan GetRelations_Internal(int sourceEntityID)
|
||||
{
|
||||
Basket basket = _baskets[startEntityID];
|
||||
return new EcsSubGraphSpan(_linkedList._nodes, basket.index, basket.count);
|
||||
LinkedListHead basket = _linkedListSourceHeads[sourceEntityID];
|
||||
return new EcsSubGraphSpan(_linkedList._nodes, basket.head, basket.count);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal int GetNode_Internal(int startEntityID)
|
||||
internal int GetRelation_Internal(int sourceEntityID)
|
||||
{
|
||||
Basket basket = _baskets[startEntityID];
|
||||
return basket.count > 0 ? _linkedList.Get(basket.index) : 0;
|
||||
LinkedListHead basket = _linkedListSourceHeads[sourceEntityID];
|
||||
return basket.count > 0 ? _linkedList.Get(basket.head) : 0;
|
||||
}
|
||||
[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)]
|
||||
internal int GetCount_Internal()
|
||||
@ -182,26 +288,37 @@ namespace DCFApixels.DragonECS
|
||||
#region IEcsWorldEventListener
|
||||
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
||||
{
|
||||
Array.Resize(ref _baskets, newSize);
|
||||
Array.Resize(ref _linkedListSourceHeads, newSize);
|
||||
}
|
||||
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||
void IEcsWorldEventListener.OnWorldDestroy() { }
|
||||
#endregion
|
||||
|
||||
#region Basket
|
||||
public struct Basket
|
||||
private struct LinkedListHead
|
||||
{
|
||||
public int index;
|
||||
public LinkedList.NodeIndex head;
|
||||
public int count;
|
||||
public override string ToString()
|
||||
{
|
||||
return $"i:{index} count:{count}";
|
||||
return $"i:{head} count:{count}";
|
||||
}
|
||||
}
|
||||
#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,
|
||||
StartToEnd = 1 << 0,
|
||||
@ -209,7 +326,40 @@ namespace DCFApixels.DragonECS
|
||||
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 static EcsSubGraphSpan Empty
|
||||
@ -218,8 +368,8 @@ namespace DCFApixels.DragonECS
|
||||
get { return new EcsSubGraphSpan(null, 0, 0); }
|
||||
}
|
||||
|
||||
private readonly EntityLinkedList.Node[] _nodes;
|
||||
private readonly int _startNodeIndex;
|
||||
private readonly LinkedList.Node[] _nodes;
|
||||
private readonly LinkedList.NodeIndex _startNodeIndex;
|
||||
private readonly int _count;
|
||||
public int Count
|
||||
{
|
||||
@ -239,7 +389,7 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal EcsSubGraphSpan(EntityLinkedList.Node[] nodes, int startNodeIndex, int count)
|
||||
internal EcsSubGraphSpan(LinkedList.Node[] nodes, LinkedList.NodeIndex startNodeIndex, int count)
|
||||
{
|
||||
_nodes = nodes;
|
||||
_startNodeIndex = startNodeIndex;
|
||||
@ -252,17 +402,17 @@ namespace DCFApixels.DragonECS
|
||||
}
|
||||
public ref struct Enumerator
|
||||
{
|
||||
private readonly EntityLinkedList.Node[] _nodes;
|
||||
private readonly LinkedList.Node[] _nodes;
|
||||
private int _index;
|
||||
private int _count;
|
||||
private int _next;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal Enumerator(EntityLinkedList.Node[] nodes, int startIndex, int count)
|
||||
internal Enumerator(LinkedList.Node[] nodes, LinkedList.NodeIndex startIndex, int count)
|
||||
{
|
||||
_nodes = nodes;
|
||||
_index = -1;
|
||||
_count = count;
|
||||
_next = startIndex;
|
||||
_next = (int)startIndex;
|
||||
}
|
||||
public int Current
|
||||
{
|
||||
@ -273,100 +423,11 @@ namespace DCFApixels.DragonECS
|
||||
public bool MoveNext()
|
||||
{
|
||||
_index = _next;
|
||||
_next = _nodes[_next].next;
|
||||
_next = (int)_nodes[_next].next;
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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)]
|
||||
internal static void ArgumentNull()
|
||||
internal static void ArgumentNull(string paramName)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal static void ArgumentOutOfRange()
|
||||
@ -48,6 +48,13 @@ namespace DCFApixels.DragonECS.Graphs.Internal
|
||||
{
|
||||
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