mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 01:44:35 +08:00
Merge branch 'new_system_layers' into dev_new_layers
This commit is contained in:
commit
51ce4f5a5c
@ -1,12 +1,11 @@
|
|||||||
#if DISABLE_DEBUG
|
#if DISABLE_DEBUG
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
using DCFApixels.DragonECS.Core;
|
||||||
using DCFApixels.DragonECS.Internal;
|
using DCFApixels.DragonECS.Internal;
|
||||||
using DCFApixels.DragonECS.RunnersCore;
|
using DCFApixels.DragonECS.RunnersCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
@ -25,7 +24,7 @@ namespace DCFApixels.DragonECS
|
|||||||
|
|
||||||
public sealed partial class EcsPipeline
|
public sealed partial class EcsPipeline
|
||||||
{
|
{
|
||||||
public class Builder : IEcsModule
|
public partial class Builder : IEcsModule
|
||||||
{
|
{
|
||||||
private SystemNode[] _systemNodes = new SystemNode[256];
|
private SystemNode[] _systemNodes = new SystemNode[256];
|
||||||
private int _startIndex = -1;
|
private int _startIndex = -1;
|
||||||
@ -37,7 +36,7 @@ namespace DCFApixels.DragonECS
|
|||||||
private readonly Dictionary<string, LayerSystemsList> _layerLists = new Dictionary<string, LayerSystemsList>(8);
|
private readonly Dictionary<string, LayerSystemsList> _layerLists = new Dictionary<string, LayerSystemsList>(8);
|
||||||
private readonly List<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(4);
|
private readonly List<InitDeclaredRunner> _initDeclaredRunners = new List<InitDeclaredRunner>(4);
|
||||||
|
|
||||||
public readonly LayerList Layers;
|
public readonly LayersMap Layers;
|
||||||
public readonly Injector.Builder Injector;
|
public readonly Injector.Builder Injector;
|
||||||
public readonly Configurator Configs;
|
public readonly Configurator Configs;
|
||||||
|
|
||||||
@ -64,7 +63,8 @@ namespace DCFApixels.DragonECS
|
|||||||
Injector.AddNode<EcsAspect>();
|
Injector.AddNode<EcsAspect>();
|
||||||
Injector.AddNode<EcsPipeline>();
|
Injector.AddNode<EcsPipeline>();
|
||||||
|
|
||||||
Layers = new LayerList(this, PRE_BEGIN_LAYER, BEGIN_LAYER, BASIC_LAYER, END_LAYER, POST_END_LAYER);
|
var graph = new DependencyGraph<string>(BASIC_LAYER);
|
||||||
|
Layers = new LayersMap(graph, this, PRE_BEGIN_LAYER, BEGIN_LAYER, BASIC_LAYER, END_LAYER, POST_END_LAYER);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -234,21 +234,22 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
private void MergeWith(Builder other)
|
private void MergeWith(Builder other)
|
||||||
{
|
{
|
||||||
Injector.Add(other.Injector);
|
throw new NotImplementedException();
|
||||||
foreach (var declaredRunners in other._initDeclaredRunners)
|
//Injector.Add(other.Injector);
|
||||||
{
|
//foreach (var declaredRunners in other._initDeclaredRunners)
|
||||||
_initDeclaredRunners.Add(declaredRunners);
|
//{
|
||||||
}
|
// _initDeclaredRunners.Add(declaredRunners);
|
||||||
foreach (var config in other.Configs.Instance.GetAllConfigs())
|
//}
|
||||||
{
|
//foreach (var config in other.Configs.Instance.GetAllConfigs())
|
||||||
Configs.Instance.Set(config.Key, config.Value);
|
//{
|
||||||
}
|
// Configs.Instance.Set(config.Key, config.Value);
|
||||||
Layers.MergeWith(other.Layers);
|
//}
|
||||||
|
//Layers.MergeWith(other.Layers);
|
||||||
foreach (ref readonly SystemNode otherRecord in new LinkedListIterator<SystemNode>(_systemNodes, _systemNodesCount, _startIndex))
|
//
|
||||||
{
|
//foreach (ref readonly SystemNode otherRecord in new LinkedListCountIterator<SystemNode>(_systemNodes, _systemNodesCount, _startIndex))
|
||||||
AddNode_Internal(otherRecord.system, otherRecord.layerName, otherRecord.sortOrder, otherRecord.isUnique);
|
//{
|
||||||
}
|
// AddNode_Internal(otherRecord.system, otherRecord.layerName, otherRecord.sortOrder, otherRecord.isUnique);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -309,7 +310,7 @@ namespace DCFApixels.DragonECS
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
_buildMarker.Begin();
|
_buildMarker.Begin();
|
||||||
#endif
|
#endif
|
||||||
var it = new LinkedListIterator<SystemNode>(_systemNodes, _systemNodesCount, _startIndex);
|
var it = new LinkedListCountIterator<SystemNode>(_systemNodes, _systemNodesCount, _startIndex);
|
||||||
|
|
||||||
LayerSystemsList basicLayerList;
|
LayerSystemsList basicLayerList;
|
||||||
if (_layerLists.TryGetValue(BASIC_LAYER, out basicLayerList) == false)
|
if (_layerLists.TryGetValue(BASIC_LAYER, out basicLayerList) == false)
|
||||||
@ -354,7 +355,7 @@ namespace DCFApixels.DragonECS
|
|||||||
IEcsProcess[] allSystems = new IEcsProcess[allSystemsLength];
|
IEcsProcess[] allSystems = new IEcsProcess[allSystemsLength];
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (var item in Layers)
|
foreach (var item in Layers.Build())
|
||||||
{
|
{
|
||||||
if (_layerLists.TryGetValue(item, out var list) && list.IsInit)
|
if (_layerLists.TryGetValue(item, out var list) && list.IsInit)
|
||||||
{
|
{
|
||||||
@ -413,217 +414,10 @@ namespace DCFApixels.DragonECS
|
|||||||
return _builder;
|
return _builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region LayerList
|
#region LayerSystemsList
|
||||||
public class LayerList : IEnumerable<string>
|
|
||||||
{
|
|
||||||
private Builder _source;
|
|
||||||
private List<string> _layers;
|
|
||||||
private string _basicLayerName;
|
|
||||||
private string _addLayerName;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public int Count { get { return _layers.Count; } }
|
|
||||||
public object this[int index] { get { return _layers[index]; } }
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
public LayerList(Builder source, string basicLayerName)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
_layers = new List<string>(16) { basicLayerName };
|
|
||||||
_basicLayerName = basicLayerName;
|
|
||||||
_addLayerName = _basicLayerName;
|
|
||||||
}
|
|
||||||
public LayerList(Builder source, string preBeginlayer, string beginlayer, string basicLayer, string endLayer, string postEndLayer)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
_layers = new List<string>(16) { preBeginlayer, beginlayer, basicLayer, endLayer, postEndLayer };
|
|
||||||
_basicLayerName = basicLayer;
|
|
||||||
_addLayerName = _basicLayerName;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Edit
|
|
||||||
|
|
||||||
#region Single
|
|
||||||
public Builder Add(string newLayer)
|
|
||||||
{
|
|
||||||
InsertAfter(_addLayerName, newLayer);
|
|
||||||
_addLayerName = newLayer;
|
|
||||||
return _source;
|
|
||||||
}
|
|
||||||
public Builder Insert(string targetLayer, string newLayer)
|
|
||||||
{
|
|
||||||
if (Contains(newLayer)) { return _source; }
|
|
||||||
|
|
||||||
int index = _layers.IndexOf(targetLayer);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Layer {targetLayer} not found");
|
|
||||||
}
|
|
||||||
_layers.Insert(index, newLayer);
|
|
||||||
return _source;
|
|
||||||
}
|
|
||||||
public Builder InsertAfter(string targetLayer, string newLayer)
|
|
||||||
{
|
|
||||||
if (Contains(newLayer)) { return _source; }
|
|
||||||
|
|
||||||
int index = _layers.IndexOf(targetLayer);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Layer {targetLayer} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
_layers.Insert(++index, newLayer);
|
|
||||||
return _source;
|
|
||||||
}
|
|
||||||
public Builder Move(string targetLayer, string movingLayer)
|
|
||||||
{
|
|
||||||
_layers.Remove(movingLayer);
|
|
||||||
return Insert(targetLayer, movingLayer);
|
|
||||||
}
|
|
||||||
public Builder MoveAfter(string targetLayer, string movingLayer)
|
|
||||||
{
|
|
||||||
_layers.Remove(movingLayer);
|
|
||||||
return InsertAfter(targetLayer, movingLayer);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Range
|
|
||||||
public Builder Add(params string[] newLayers)
|
|
||||||
{
|
|
||||||
InsertAfter(_addLayerName, newLayers);
|
|
||||||
_addLayerName = newLayers[newLayers.Length - 1];
|
|
||||||
return _source;
|
|
||||||
}
|
|
||||||
public Builder Insert(string targetLayer, params string[] newLayers)
|
|
||||||
{
|
|
||||||
int index = _layers.IndexOf(targetLayer);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Layer {targetLayer} not found");
|
|
||||||
}
|
|
||||||
_layers.InsertRange(index, newLayers.Where(o => !Contains(o)));
|
|
||||||
return _source;
|
|
||||||
}
|
|
||||||
public Builder InsertAfter(string targetLayer, params string[] newLayers)
|
|
||||||
{
|
|
||||||
int index = _layers.IndexOf(targetLayer);
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Layer {targetLayer} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
_layers.InsertRange(++index, newLayers.Where(o => !Contains(o)));
|
|
||||||
return _source;
|
|
||||||
}
|
|
||||||
public Builder Move(string targetLayer, params string[] movingLayers)
|
|
||||||
{
|
|
||||||
foreach (var movingLayer in movingLayers)
|
|
||||||
{
|
|
||||||
_layers.Remove(movingLayer);
|
|
||||||
}
|
|
||||||
return Insert(targetLayer, movingLayers);
|
|
||||||
}
|
|
||||||
public Builder MoveAfter(string targetLayer, params string[] movingLayers)
|
|
||||||
{
|
|
||||||
foreach (var movingLayer in movingLayers)
|
|
||||||
{
|
|
||||||
_layers.Remove(movingLayer);
|
|
||||||
}
|
|
||||||
return InsertAfter(targetLayer, movingLayers);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region MergeWith
|
|
||||||
private static bool CheckOverlapsOrder(List<string> listA, IReadOnlyList<string> listB)
|
|
||||||
{
|
|
||||||
int lastIndexof = 0;
|
|
||||||
for (int i = 0; i < listB.Count; i++)
|
|
||||||
{
|
|
||||||
var a = listB[i];
|
|
||||||
int indexof = listA.IndexOf(a);
|
|
||||||
|
|
||||||
if (indexof < 0) { continue; }
|
|
||||||
if (indexof < lastIndexof)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
lastIndexof = indexof;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public void MergeWith(IReadOnlyList<string> other)
|
|
||||||
{
|
|
||||||
List<string> listA = _layers;
|
|
||||||
IReadOnlyList<string> listB = other;
|
|
||||||
|
|
||||||
if (CheckOverlapsOrder(listA, listB) == false)
|
|
||||||
{
|
|
||||||
//Для слияния списков слоев, нужно чтобы в пересечении порядок записей совпадал
|
|
||||||
Throw.Exception("To merge layer lists, the names of the layers present in both lists must appear in the same order in both lists.");
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<string> seen = new HashSet<string>();
|
|
||||||
List<string> result = new List<string>();
|
|
||||||
|
|
||||||
foreach (string item in listA)
|
|
||||||
{
|
|
||||||
seen.Add(item);
|
|
||||||
}
|
|
||||||
foreach (string item in listB)
|
|
||||||
{
|
|
||||||
if (seen.Add(item) == false)
|
|
||||||
{
|
|
||||||
seen.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0, j = 0;
|
|
||||||
while (i < listA.Count || j < listB.Count)
|
|
||||||
{
|
|
||||||
while (i < listA.Count && seen.Contains(listA[i]))
|
|
||||||
{
|
|
||||||
result.Add(listA[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while (j < listB.Count && seen.Contains(listB[j]))
|
|
||||||
{
|
|
||||||
result.Add(listB[j]);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < listA.Count) { i++; }
|
|
||||||
if (j < listB.Count)
|
|
||||||
{
|
|
||||||
result.Add(listB[j]);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_layers = result;
|
|
||||||
}
|
|
||||||
public void MergeWith(LayerList other)
|
|
||||||
{
|
|
||||||
MergeWith(other._layers);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Other
|
|
||||||
public bool Contains(string layer) { return _layers.Contains(layer); }
|
|
||||||
|
|
||||||
public List<string>.Enumerator GetEnumerator() { return _layers.GetEnumerator(); }
|
|
||||||
IEnumerator<string> IEnumerable<string>.GetEnumerator() { return _layers.GetEnumerator(); }
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() { return _layers.GetEnumerator(); }
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region SystemsList
|
|
||||||
private class LayerSystemsList
|
private class LayerSystemsList
|
||||||
{
|
{
|
||||||
public int lasyInitSystemsCount = 0;
|
public int lasyInitSystemsCount = 0;
|
||||||
@ -768,6 +562,18 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("Use LayersMap")]
|
||||||
|
public class LayerList : LayersMap
|
||||||
|
{
|
||||||
|
//public LayerList(Builder source, string basicLayerName) : base(source, basicLayerName) { }
|
||||||
|
//public LayerList(Builder source, string preBeginlayer, string beginlayer, string basicLayer, string endLayer, string postEndLayer) : base(source, preBeginlayer, beginlayer, basicLayer, endLayer, postEndLayer) { }
|
||||||
|
public LayerList(IDependencyGraph<string> graph, Builder pipelineBuilder) : base(graph, pipelineBuilder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
549
src/Utils/DependencyGraph.cs
Normal file
549
src/Utils/DependencyGraph.cs
Normal file
@ -0,0 +1,549 @@
|
|||||||
|
using DCFApixels.DragonECS.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Core
|
||||||
|
{
|
||||||
|
using VertexID = DependencyGraphVertextID;
|
||||||
|
public enum DependencyGraphVertextID : short { NULL = 0 }
|
||||||
|
public interface IDependencyGraph<T> : IReadOnlyCollection<T>
|
||||||
|
{
|
||||||
|
ReadonlyDependenciesCollection<T> Dependencies { get; }
|
||||||
|
VertexID AddVertex(T vertex, bool isLocked);
|
||||||
|
bool ContainsVertex(T vertex);
|
||||||
|
VertexID GetVertexID(T vertex);
|
||||||
|
T GetVertexFromID(VertexID vertexID);
|
||||||
|
bool RemoveVertex(T vertex);
|
||||||
|
void AddDependency(VertexID fromID, VertexID toID, bool moveToRight);
|
||||||
|
void MergeWith(IDependencyGraph<T> other);
|
||||||
|
T[] Sort();
|
||||||
|
}
|
||||||
|
public static class DependencyGraphExtensions
|
||||||
|
{
|
||||||
|
public static void AddDependency<T>(this IDependencyGraph<T> self, T from, T to, bool moveToRight)
|
||||||
|
{
|
||||||
|
self.AddDependency(self.GetVertexID(from), self.GetVertexID(to), moveToRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public struct ReadonlyDependenciesCollection<T> : IReadOnlyCollection<(T from, T to)>
|
||||||
|
{
|
||||||
|
private IDependencyGraph<T> _graph;
|
||||||
|
private IReadOnlyCollection<(VertexID from, VertexID to)> _source;
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _source.Count; }
|
||||||
|
}
|
||||||
|
public ReadonlyDependenciesCollection(IDependencyGraph<T> graph, IReadOnlyCollection<(VertexID from, VertexID to)> source)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_source = source;
|
||||||
|
}
|
||||||
|
public Enumerator GetEnumerator() { return new Enumerator(_graph, _source.GetEnumerator()); }
|
||||||
|
IEnumerator<(T from, T to)> IEnumerable<(T from, T to)>.GetEnumerator() { return GetEnumerator(); }
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||||
|
public struct Enumerator : IEnumerator<(T from, T to)>
|
||||||
|
{
|
||||||
|
private IDependencyGraph<T> _graph;
|
||||||
|
private IEnumerator<(VertexID from, VertexID to)> _source;
|
||||||
|
public Enumerator(IDependencyGraph<T> graph, IEnumerator<(VertexID from, VertexID to)> source)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_source = source;
|
||||||
|
}
|
||||||
|
public (T from, T to) Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var (from, to) = _source.Current;
|
||||||
|
return (_graph.GetVertexFromID(from), _graph.GetVertexFromID(to));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object IEnumerator.Current { get { return Current; } }
|
||||||
|
public bool MoveNext() { return _source.MoveNext(); }
|
||||||
|
public void Reset() { _source.Reset(); }
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public unsafe class DependencyGraph<T> : IDependencyGraph<T>
|
||||||
|
{
|
||||||
|
private readonly Dictionary<T, VertexID> _vertexIDs = new Dictionary<T, VertexID>(32);
|
||||||
|
private StructList<VertexInfo> _vertexInfos = new StructList<VertexInfo>(32);
|
||||||
|
|
||||||
|
private List<(VertexID from, VertexID to)> _dependencies = new List<(VertexID, VertexID)>(16);
|
||||||
|
private readonly VertexID _basicVertexID;
|
||||||
|
private int _increment = 1;
|
||||||
|
private int _count;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _count; }
|
||||||
|
}
|
||||||
|
public ReadonlyDependenciesCollection<T> Dependencies
|
||||||
|
{
|
||||||
|
get { return new ReadonlyDependenciesCollection<T>(this, _dependencies); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public DependencyGraph()
|
||||||
|
{
|
||||||
|
//GetVertexID("");
|
||||||
|
_vertexInfos.Add(default);
|
||||||
|
_basicVertexID = VertexID.NULL;
|
||||||
|
}
|
||||||
|
public DependencyGraph(T basicVertexName)
|
||||||
|
{
|
||||||
|
//GetVertexID("");
|
||||||
|
_vertexInfos.Add(default);
|
||||||
|
_basicVertexID = GetVertexID(basicVertexName);
|
||||||
|
LockVertex(basicVertexName);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
public VertexID GetVertexID(T vertext)
|
||||||
|
{
|
||||||
|
if (_vertexIDs.TryGetValue(vertext, out VertexID layerID) == false)
|
||||||
|
{
|
||||||
|
layerID = (VertexID)_vertexInfos.Count;
|
||||||
|
_vertexInfos.Add(default);
|
||||||
|
|
||||||
|
_vertexIDs[vertext] = layerID;
|
||||||
|
ref var layerInfo = ref GetVertexInfo(layerID);
|
||||||
|
layerInfo.value = vertext;
|
||||||
|
}
|
||||||
|
return layerID;
|
||||||
|
}
|
||||||
|
public T GetVertexFromID(VertexID vertexID)
|
||||||
|
{
|
||||||
|
return GetVertexInfo(vertexID).value;
|
||||||
|
}
|
||||||
|
private ref VertexInfo GetVertexInfo(VertexID vertexID)
|
||||||
|
{
|
||||||
|
return ref _vertexInfos._items[(int)vertexID];
|
||||||
|
}
|
||||||
|
private ref VertexInfo GetVertexInfo(int vertexID)
|
||||||
|
{
|
||||||
|
return ref _vertexInfos._items[(int)vertexID];
|
||||||
|
}
|
||||||
|
private int GetVertexInfosCount()
|
||||||
|
{
|
||||||
|
return _vertexInfos.Count;
|
||||||
|
}
|
||||||
|
public VertexID AddVertex(T vertex, bool isLocked)
|
||||||
|
{
|
||||||
|
var result = GetVertexID(vertex);
|
||||||
|
AddVertexByID(result);
|
||||||
|
if (isLocked)
|
||||||
|
{
|
||||||
|
LockVertex(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
private void LockVertex(T vertex)
|
||||||
|
{
|
||||||
|
LockVertex(GetVertexID(vertex));
|
||||||
|
}
|
||||||
|
private void LockVertex(VertexID vertexID)
|
||||||
|
{
|
||||||
|
GetVertexInfo(vertexID).isLocked = true;
|
||||||
|
}
|
||||||
|
private void AddVertexByID(VertexID id)
|
||||||
|
{
|
||||||
|
ref var info = ref GetVertexInfo(id);
|
||||||
|
if (info.isContained == false || info.isLocked == false)
|
||||||
|
{
|
||||||
|
_count++;
|
||||||
|
info.isContained = true;
|
||||||
|
}
|
||||||
|
info.insertionIndex = _increment++;
|
||||||
|
}
|
||||||
|
public bool RemoveVertex(T vertex)
|
||||||
|
{
|
||||||
|
var result = GetVertexID(vertex);
|
||||||
|
return RemoveVertexByID(result);
|
||||||
|
}
|
||||||
|
private bool RemoveVertexByID(VertexID id)
|
||||||
|
{
|
||||||
|
ref var info = ref GetVertexInfo(id);
|
||||||
|
bool result = false;
|
||||||
|
if (info.isLocked) { throw new Exception($"The {info.value} vertex cannot be removed"); }
|
||||||
|
if (info.isContained)
|
||||||
|
{
|
||||||
|
_count--;
|
||||||
|
info.isContained = false;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
info.insertionIndex = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public void AddDependency(VertexID fromVertexID, VertexID toVertexID, bool moveToRight)
|
||||||
|
{
|
||||||
|
ref var fromInfo = ref GetVertexInfo(fromVertexID);
|
||||||
|
ref var toInfo = ref GetVertexInfo(toVertexID);
|
||||||
|
fromInfo.hasAnyDependency = true;
|
||||||
|
toInfo.hasAnyDependency = true;
|
||||||
|
fromInfo.moveToRight = moveToRight;
|
||||||
|
_dependencies.Add((fromVertexID, toVertexID));
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MergeWith
|
||||||
|
public void MergeWith(IDependencyGraph<T> other)
|
||||||
|
{
|
||||||
|
if (other is DependencyGraph<T> graph)
|
||||||
|
{
|
||||||
|
foreach (var otherDependency in graph._dependencies)
|
||||||
|
{
|
||||||
|
this.AddDependency(graph.GetVertexFromID(otherDependency.from), graph.GetVertexFromID(otherDependency.to), false);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < graph.GetVertexInfosCount(); i++)
|
||||||
|
{
|
||||||
|
ref var otherLayerInfo = ref graph.GetVertexInfo(i);
|
||||||
|
AddVertexByID(GetVertexID(graph.GetVertexFromID((VertexID)i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var otherDependency in other.Dependencies)
|
||||||
|
{
|
||||||
|
this.AddDependency(otherDependency.from, otherDependency.to, false);
|
||||||
|
}
|
||||||
|
foreach (var vertex in other)
|
||||||
|
{
|
||||||
|
AddVertex(vertex, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Sort
|
||||||
|
public T[] Sort()
|
||||||
|
{
|
||||||
|
const int BUFFER_THRESHOLD = 256;
|
||||||
|
if (_count <= BUFFER_THRESHOLD)
|
||||||
|
{
|
||||||
|
var ptr = stackalloc VertexID[_count];
|
||||||
|
var buffer = UnsafeArray<VertexID>.Manual(ptr, _count);
|
||||||
|
TopoSorting(buffer);
|
||||||
|
ReoderInsertionIndexes(buffer);
|
||||||
|
TopoSorting(buffer);
|
||||||
|
return ConvertIdsToTsArray(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var ptr = TempBuffer<VertexID>.Get(_count);
|
||||||
|
var buffer = UnsafeArray<VertexID>.Manual(ptr, _count);
|
||||||
|
TopoSorting(buffer);
|
||||||
|
ReoderInsertionIndexes(buffer);
|
||||||
|
TopoSorting(buffer);
|
||||||
|
return ConvertIdsToTsArray(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void TopoSorting(UnsafeArray<VertexID> sortingBuffer)
|
||||||
|
{
|
||||||
|
VertexID[] nodes = new VertexID[_count];
|
||||||
|
var adjacency = new List<(VertexID To, int DependencyIndex)>[GetVertexInfosCount()];
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < GetVertexInfosCount(); i++)
|
||||||
|
{
|
||||||
|
VertexID layerID = (VertexID)i;
|
||||||
|
ref var info = ref GetVertexInfo(layerID);
|
||||||
|
adjacency[(int)layerID] = new List<(VertexID To, int DependencyIndex)>();
|
||||||
|
GetVertexInfo(layerID).inDegree = 0;
|
||||||
|
if (info.isContained)
|
||||||
|
{
|
||||||
|
nodes[j++] = layerID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _dependencies.Count; i++)
|
||||||
|
{
|
||||||
|
var (from, to) = _dependencies[i];
|
||||||
|
ref var fromInfo = ref GetVertexInfo(from);
|
||||||
|
ref var toInfo = ref GetVertexInfo(to);
|
||||||
|
|
||||||
|
if (fromInfo.isContained && toInfo.isContained)
|
||||||
|
{
|
||||||
|
adjacency[(int)from].Add((to, i));
|
||||||
|
toInfo.inDegree += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// добавление зависимостей для нод без зависимостей.
|
||||||
|
if (_basicVertexID != VertexID.NULL)
|
||||||
|
{
|
||||||
|
var basicLayerAdjacencyList = adjacency[(int)_basicVertexID];
|
||||||
|
int inserIndex = basicLayerAdjacencyList.Count;
|
||||||
|
for (int i = 0; i < GetVertexInfosCount(); i++)
|
||||||
|
{
|
||||||
|
var toID = (VertexID)i;
|
||||||
|
ref var toInfo = ref GetVertexInfo(i);
|
||||||
|
if (toInfo.isContained && toInfo.hasAnyDependency == false)
|
||||||
|
{
|
||||||
|
basicLayerAdjacencyList.Insert(inserIndex, (toID, toInfo.insertionIndex));
|
||||||
|
toInfo.inDegree += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<VertexID> zeroInDegree = new List<VertexID>(nodes.Length);
|
||||||
|
zeroInDegree.AddRange(nodes.Where(id => GetVertexInfo(id).inDegree == 0).OrderBy(id => GetVertexInfo(id).insertionIndex));
|
||||||
|
|
||||||
|
int resultCount = 0;
|
||||||
|
|
||||||
|
while (zeroInDegree.Count > 0)
|
||||||
|
{
|
||||||
|
var current = zeroInDegree[0];
|
||||||
|
zeroInDegree.RemoveAt(0);
|
||||||
|
|
||||||
|
GetVertexInfo(current).sortingIndex = resultCount;
|
||||||
|
sortingBuffer.ptr[resultCount++] = current;
|
||||||
|
|
||||||
|
var adjacencyList = adjacency[(int)current];
|
||||||
|
for (int i = 0; i < adjacencyList.Count; i++)
|
||||||
|
{
|
||||||
|
var (neighbor, _) = adjacencyList[i];
|
||||||
|
ref var neighborInfo = ref GetVertexInfo(neighbor);
|
||||||
|
neighborInfo.inDegree--;
|
||||||
|
if (neighborInfo.inDegree == 0)
|
||||||
|
{
|
||||||
|
var neighborInsertionIndex = neighborInfo.insertionIndex;
|
||||||
|
int insertIndex = zeroInDegree.FindIndex(id => GetVertexInfo(id).insertionIndex < neighborInsertionIndex);
|
||||||
|
insertIndex = insertIndex < 0 ? 0 : insertIndex;
|
||||||
|
zeroInDegree.Insert(insertIndex, neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resultCount != nodes.Length)
|
||||||
|
{
|
||||||
|
var cycle = FindCycle(adjacency, nodes);
|
||||||
|
string details = string.Empty;
|
||||||
|
if (cycle != null)
|
||||||
|
{
|
||||||
|
var cycleDependencies = GetCycleDependencies(cycle, adjacency);
|
||||||
|
details = $" Cycle edges path: {string.Join(", ", cycleDependencies)}";
|
||||||
|
}
|
||||||
|
throw new InvalidOperationException("Cyclic dependency detected." + details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void ReoderInsertionIndexes(UnsafeArray<VertexID> sortingBuffer)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < GetVertexInfosCount(); i++)
|
||||||
|
{
|
||||||
|
ref var info = ref GetVertexInfo(i);
|
||||||
|
if (info.isContained == false) { continue; }
|
||||||
|
info.leftBeforeIndex = info.moveToRight ? int.MaxValue : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var dependency in _dependencies)
|
||||||
|
{
|
||||||
|
ref var fromInfo = ref GetVertexInfo(dependency.from);
|
||||||
|
if (fromInfo.moveToRight)
|
||||||
|
{
|
||||||
|
ref var toInfo = ref GetVertexInfo(dependency.to);
|
||||||
|
fromInfo.leftBeforeIndex = Math.Min(toInfo.sortingIndex, fromInfo.leftBeforeIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = sortingBuffer.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var id = sortingBuffer.ptr[i];
|
||||||
|
ref var info = ref GetVertexInfo(id);
|
||||||
|
if (info.moveToRight)
|
||||||
|
{
|
||||||
|
if (info.leftBeforeIndex < sortingBuffer.Length)
|
||||||
|
{
|
||||||
|
MoveElement(ref sortingBuffer, i, info.leftBeforeIndex - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sortingBuffer.Length; i++)
|
||||||
|
{
|
||||||
|
ref var info = ref GetVertexInfo(sortingBuffer.ptr[i]);
|
||||||
|
info.insertionIndex = i;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void MoveElement<TValue>(ref UnsafeArray<TValue> array, int oldIndex, int newIndex) where TValue : unmanaged
|
||||||
|
{
|
||||||
|
if (oldIndex == newIndex) return;
|
||||||
|
|
||||||
|
var ptr = array.ptr;
|
||||||
|
TValue item = ptr[oldIndex];
|
||||||
|
|
||||||
|
int elementSize = sizeof(TValue);
|
||||||
|
int copyLength = Math.Abs(newIndex - oldIndex);
|
||||||
|
|
||||||
|
byte* source;
|
||||||
|
byte* destination;
|
||||||
|
long bytesToCopy = copyLength * elementSize;
|
||||||
|
|
||||||
|
if (oldIndex < newIndex)
|
||||||
|
{
|
||||||
|
// Сдвиг вправо: копируем блок [oldIndex+1 ... newIndex] в [oldIndex ... newIndex-1]
|
||||||
|
source = (byte*)(ptr + oldIndex + 1);
|
||||||
|
destination = (byte*)(ptr + oldIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Сдвиг влево: копируем блок [newIndex ... oldIndex-1] в [newIndex+1 ... oldIndex]
|
||||||
|
source = (byte*)(ptr + newIndex);
|
||||||
|
destination = (byte*)(ptr + newIndex + 1);
|
||||||
|
}
|
||||||
|
Buffer.MemoryCopy(source: source, destination: destination, destinationSizeInBytes: bytesToCopy, sourceBytesToCopy: bytesToCopy);
|
||||||
|
|
||||||
|
ptr[newIndex] = item;
|
||||||
|
}
|
||||||
|
private T[] ConvertIdsToTsArray(UnsafeArray<VertexID> buffer)
|
||||||
|
{
|
||||||
|
T[] result = new T[buffer.Length];
|
||||||
|
for (int i = 0; i < result.Length; i++)
|
||||||
|
{
|
||||||
|
result[i] = GetVertexInfo(buffer.ptr[i]).value;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region FindCycles
|
||||||
|
private List<VertexID> FindCycle(
|
||||||
|
List<(VertexID To, int DependencyIndex)>[] adjacency,
|
||||||
|
VertexID[] nodes)
|
||||||
|
{
|
||||||
|
var visited = new Dictionary<VertexID, bool>();
|
||||||
|
var recursionStack = new Stack<VertexID>();
|
||||||
|
|
||||||
|
foreach (var node in nodes)
|
||||||
|
{
|
||||||
|
if (FindCycleDFS(node, adjacency, visited, recursionStack))
|
||||||
|
{
|
||||||
|
return recursionStack.Reverse().ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private bool FindCycleDFS(
|
||||||
|
VertexID node,
|
||||||
|
List<(VertexID To, int DependencyIndex)>[] adjacency,
|
||||||
|
Dictionary<VertexID, bool> visited,
|
||||||
|
Stack<VertexID> recursionStack)
|
||||||
|
{
|
||||||
|
if (!visited.TryGetValue(node, out bool isVisited))
|
||||||
|
{
|
||||||
|
visited[node] = true;
|
||||||
|
recursionStack.Push(node);
|
||||||
|
|
||||||
|
foreach (var (neighbor, _) in adjacency[(int)node])
|
||||||
|
{
|
||||||
|
if (!visited.ContainsKey(neighbor) && FindCycleDFS(neighbor, adjacency, visited, recursionStack))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (recursionStack.Contains(neighbor))
|
||||||
|
{
|
||||||
|
recursionStack.Push(neighbor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recursionStack.Pop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return isVisited && recursionStack.Contains(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetCycleDependencies(
|
||||||
|
List<VertexID> cycle,
|
||||||
|
List<(VertexID To, int DependencyIndex)>[] adjacency)
|
||||||
|
{
|
||||||
|
var cycleEdges = new HashSet<(VertexID, VertexID)>();
|
||||||
|
for (int i = 0; i < cycle.Count - 1; i++)
|
||||||
|
{
|
||||||
|
cycleEdges.Add((cycle[i], cycle[i + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
var dependencies = new List<string>();
|
||||||
|
foreach (var from in cycle)
|
||||||
|
{
|
||||||
|
foreach (var (to, depIndex) in adjacency[(int)from])
|
||||||
|
{
|
||||||
|
if (cycleEdges.Contains((from, to)) && _dependencies.Count > depIndex)
|
||||||
|
{
|
||||||
|
var dep = _dependencies[depIndex];
|
||||||
|
dependencies.Add($"{GetVertexInfo(dep.from).value}->{GetVertexInfo(dep.to).value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dependencies.Distinct().ToArray();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Other
|
||||||
|
public bool ContainsVertex(T vertex)
|
||||||
|
{
|
||||||
|
return GetVertexInfo(GetVertexID(vertex)).isContained;
|
||||||
|
}
|
||||||
|
public Enumerator GetEnumerator() { return new Enumerator(this); }
|
||||||
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||||
|
public struct Enumerator : IEnumerator<T>
|
||||||
|
{
|
||||||
|
private DependencyGraph<T> _graph;
|
||||||
|
private int _index;
|
||||||
|
public Enumerator(DependencyGraph<T> graph)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
public T Current
|
||||||
|
{
|
||||||
|
get { return _graph.GetVertexInfo(_index).value; }
|
||||||
|
}
|
||||||
|
object IEnumerator.Current { get { return Current; } }
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (_index++ >= _graph.GetVertexInfosCount()) { return false; }
|
||||||
|
ref var info = ref _graph.GetVertexInfo(_index);
|
||||||
|
if (info.isContained == false)
|
||||||
|
{
|
||||||
|
return MoveNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Reset() { _index = -1; }
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region VertexInfo
|
||||||
|
[DebuggerDisplay("{value}")]
|
||||||
|
private struct VertexInfo
|
||||||
|
{
|
||||||
|
public T value;
|
||||||
|
public int insertionIndex;
|
||||||
|
public bool isLocked;
|
||||||
|
public bool isContained;
|
||||||
|
public bool moveToRight;
|
||||||
|
//build
|
||||||
|
public bool hasAnyDependency;
|
||||||
|
public int inDegree;
|
||||||
|
public int sortingIndex;
|
||||||
|
public int leftBeforeIndex;
|
||||||
|
public VertexInfo(T name) : this()
|
||||||
|
{
|
||||||
|
this.value = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
325
src/Utils/LayersMap.cs
Normal file
325
src/Utils/LayersMap.cs
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Core
|
||||||
|
{
|
||||||
|
using VertexID = DependencyGraphVertextID;
|
||||||
|
public class LayersMap : IDependencyGraph<string>
|
||||||
|
{
|
||||||
|
#region IDependencyGraph
|
||||||
|
VertexID IDependencyGraph<string>.AddVertex(string vertex, bool isLocked) { return _graph.AddVertex(vertex, isLocked); }
|
||||||
|
bool IDependencyGraph<string>.ContainsVertex(string vertex) { return _graph.ContainsVertex(vertex); }
|
||||||
|
VertexID IDependencyGraph<string>.GetVertexID(string vertex) { return _graph.GetVertexID(vertex); }
|
||||||
|
string IDependencyGraph<string>.GetVertexFromID(VertexID vertexID) { return _graph.GetVertexFromID(vertexID); }
|
||||||
|
bool IDependencyGraph<string>.RemoveVertex(string vertex) { return _graph.RemoveVertex(vertex); }
|
||||||
|
void IDependencyGraph<string>.AddDependency(VertexID fromID, VertexID toID, bool moveToRight) { _graph.AddDependency(fromID, toID, moveToRight); }
|
||||||
|
string[] IDependencyGraph<string>.Sort() { return _graph.Sort(); }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private readonly IDependencyGraph<string> _graph;
|
||||||
|
private readonly EcsPipeline.Builder _pipelineBuilder;
|
||||||
|
private readonly string _preBeginLayer;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public EcsPipeline.Builder Back
|
||||||
|
{
|
||||||
|
get { return _pipelineBuilder; }
|
||||||
|
}
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _graph.Count; }
|
||||||
|
}
|
||||||
|
public ReadonlyDependenciesCollection<string> Dependencies
|
||||||
|
{
|
||||||
|
get { return _graph.Dependencies; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public LayersMap(IDependencyGraph<string> graph, EcsPipeline.Builder pipelineBuilder)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_pipelineBuilder = pipelineBuilder;
|
||||||
|
}
|
||||||
|
public LayersMap(IDependencyGraph<string> graph, EcsPipeline.Builder pipelineBuilder, string preBeginlayer, string beginlayer, string basicLayer, string endLayer, string postEndLayer)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_pipelineBuilder = pipelineBuilder;
|
||||||
|
|
||||||
|
graph.AddVertex(preBeginlayer, true);
|
||||||
|
graph.AddVertex(beginlayer, true);
|
||||||
|
graph.AddVertex(basicLayer, true);
|
||||||
|
graph.AddVertex(endLayer, true);
|
||||||
|
graph.AddVertex(postEndLayer, true);
|
||||||
|
|
||||||
|
Move(preBeginlayer);
|
||||||
|
//.Before(beginlayer);
|
||||||
|
Move(beginlayer)
|
||||||
|
//.Before(basicLayer)
|
||||||
|
.After(preBeginlayer);
|
||||||
|
Move(basicLayer)
|
||||||
|
//.Before(endLayer)
|
||||||
|
.After(beginlayer);
|
||||||
|
Move(endLayer)
|
||||||
|
//.Before(postEndLayer)
|
||||||
|
.After(basicLayer);
|
||||||
|
Move(postEndLayer)
|
||||||
|
.After(endLayer);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Add
|
||||||
|
public MoveHandler Add(string layer)
|
||||||
|
{
|
||||||
|
VertexID id = _graph.AddVertex(layer, false);
|
||||||
|
return new MoveHandler(_graph, _pipelineBuilder, id);
|
||||||
|
}
|
||||||
|
public MoveHandler Add(params string[] layers)
|
||||||
|
{
|
||||||
|
return Add(layersRange: layers);
|
||||||
|
}
|
||||||
|
public MoveHandler Add(IEnumerable<string> layersRange)
|
||||||
|
{
|
||||||
|
foreach (var layer in layersRange)
|
||||||
|
{
|
||||||
|
Add(layer);
|
||||||
|
}
|
||||||
|
return new MoveHandler(_graph, _pipelineBuilder, layersRange);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Move
|
||||||
|
public MoveHandler Move(string layer)
|
||||||
|
{
|
||||||
|
VertexID id = _graph.GetVertexID(layer);
|
||||||
|
return new MoveHandler(_graph, _pipelineBuilder, id);
|
||||||
|
}
|
||||||
|
public MoveHandler Move(params string[] layers)
|
||||||
|
{
|
||||||
|
return new MoveHandler(_graph, _pipelineBuilder, layers);
|
||||||
|
}
|
||||||
|
public MoveHandler Move(IEnumerable<string> layersRange)
|
||||||
|
{
|
||||||
|
return new MoveHandler(_graph, _pipelineBuilder, layersRange);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MoveHandler
|
||||||
|
public struct MoveHandler
|
||||||
|
{
|
||||||
|
private readonly IDependencyGraph<string> _graph;
|
||||||
|
private readonly EcsPipeline.Builder _pipelineBuilder;
|
||||||
|
private readonly VertexID _layerID;
|
||||||
|
private readonly IEnumerable<string> _layersRange;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public EcsPipeline.Builder Back
|
||||||
|
{
|
||||||
|
get { return _pipelineBuilder; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public MoveHandler(IDependencyGraph<string> graph, EcsPipeline.Builder pipelineBuilder, VertexID id)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_pipelineBuilder = pipelineBuilder;
|
||||||
|
_layerID = id;
|
||||||
|
_layersRange = null;
|
||||||
|
}
|
||||||
|
public MoveHandler(IDependencyGraph<string> graph, EcsPipeline.Builder pipelineBuilder, IEnumerable<string> layersRange)
|
||||||
|
{
|
||||||
|
_graph = graph;
|
||||||
|
_pipelineBuilder = pipelineBuilder;
|
||||||
|
_layerID = VertexID.NULL;
|
||||||
|
_layersRange = layersRange;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Before
|
||||||
|
public MoveHandler Before(params string[] targets)
|
||||||
|
{
|
||||||
|
return Before(targetsRange: targets);
|
||||||
|
}
|
||||||
|
public MoveHandler Before(IEnumerable<string> targetsRange)
|
||||||
|
{
|
||||||
|
foreach (var target in targetsRange)
|
||||||
|
{
|
||||||
|
Before(target);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public MoveHandler Before(string targetLayer)
|
||||||
|
{
|
||||||
|
if (_layerID != VertexID.NULL)
|
||||||
|
{
|
||||||
|
_graph.AddDependency(_layerID, _graph.GetVertexID(targetLayer), true);
|
||||||
|
}
|
||||||
|
if (_layersRange != null)
|
||||||
|
{
|
||||||
|
foreach (var layer in _layersRange)
|
||||||
|
{
|
||||||
|
_graph.AddDependency(_graph.GetVertexID(layer), _graph.GetVertexID(targetLayer), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region After
|
||||||
|
public MoveHandler After(params string[] targets)
|
||||||
|
{
|
||||||
|
return After(targetsRange: targets);
|
||||||
|
}
|
||||||
|
public MoveHandler After(IEnumerable<string> targetsRange)
|
||||||
|
{
|
||||||
|
foreach (var target in targetsRange)
|
||||||
|
{
|
||||||
|
After(target);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public MoveHandler After(string targetLayer)
|
||||||
|
{
|
||||||
|
if (_layerID != VertexID.NULL)
|
||||||
|
{
|
||||||
|
_graph.AddDependency(_graph.GetVertexID(targetLayer), _layerID, false);
|
||||||
|
}
|
||||||
|
if (_layersRange != null)
|
||||||
|
{
|
||||||
|
foreach (var layer in _layersRange)
|
||||||
|
{
|
||||||
|
_graph.AddDependency(_graph.GetVertexID(targetLayer), _graph.GetVertexID(layer), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MergeWith
|
||||||
|
public void MergeWith(IDependencyGraph<string> other)
|
||||||
|
{
|
||||||
|
_graph.MergeWith(other);
|
||||||
|
}
|
||||||
|
//[Obsolete("Use MergeWith(LayersMap)")]
|
||||||
|
public void MergeWith(IReadOnlyList<string> other)
|
||||||
|
{
|
||||||
|
var enumerator = other.GetEnumerator();
|
||||||
|
string prev = null;
|
||||||
|
if (_preBeginLayer != null)
|
||||||
|
{
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
var layer = enumerator.Current;
|
||||||
|
if (layer == _preBeginLayer) { break; }
|
||||||
|
|
||||||
|
Add(layer);
|
||||||
|
if (prev != null)
|
||||||
|
{
|
||||||
|
Move(prev).Before(layer);
|
||||||
|
}
|
||||||
|
prev = layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
var layer = enumerator.Current;
|
||||||
|
Add(layer);
|
||||||
|
if (prev != null)
|
||||||
|
{
|
||||||
|
Move(layer).After(prev);
|
||||||
|
}
|
||||||
|
prev = layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion;
|
||||||
|
|
||||||
|
#region Other
|
||||||
|
public bool Contains(string layer)
|
||||||
|
{
|
||||||
|
return _graph.ContainsVertex(layer);
|
||||||
|
}
|
||||||
|
public IEnumerator<string> GetEnumerator() { return _graph.GetEnumerator(); }
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() { return _graph.GetEnumerator(); }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Build
|
||||||
|
public string[] Build()
|
||||||
|
{
|
||||||
|
return _graph.Sort();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Obsolete
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Add(layer).Before(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder Insert(string targetLayer, string newLayer)
|
||||||
|
{
|
||||||
|
Add(newLayer).Before(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Add(layer).After(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder InsertAfter(string targetLayer, string newLayer)
|
||||||
|
{
|
||||||
|
Add(newLayer).After(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Move(layer).Before(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder Move(string targetLayer, string newLayer)
|
||||||
|
{
|
||||||
|
Move(newLayer).Before(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Move(layer).After(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder MoveAfter(string targetLayer, string newLayer)
|
||||||
|
{
|
||||||
|
Move(newLayer).After(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Add(layers).Before(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder Insert(string targetLayer, params string[] newLayers)
|
||||||
|
{
|
||||||
|
Add(newLayers).Before(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Add(layers).After(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder InsertAfter(string targetLayer, params string[] newLayers)
|
||||||
|
{
|
||||||
|
Add(newLayers).After(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Move(layers).Before(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder Move(string targetLayer, params string[] movingLayers)
|
||||||
|
{
|
||||||
|
Move(movingLayers).Before(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
[Obsolete("Use " + nameof(LayersMap) + ".Move(layers).After(targetLayer).Back;")]
|
||||||
|
public EcsPipeline.Builder MoveAfter(string targetLayer, params string[] movingLayers)
|
||||||
|
{
|
||||||
|
Move(movingLayers).After(targetLayer);
|
||||||
|
return _pipelineBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
public object this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
foreach (var item in this)
|
||||||
|
{
|
||||||
|
if (i == index)
|
||||||
|
{
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user