Aetheria/Assets/Plugins/MSAGL/Layout/Layered/EdgePathsInserter.cs
Reinier Vens dbc522a224 Weapos Rejiggered
Modified weapon scripts to eliminate specialized projectile behavior - allows charged weapons to have projectiles and modify weapon stats when charged
Added machine gun weapon & VFX
Moved third party code to Plugins folder to improve compile times
2021-01-31 03:52:32 +00:00

196 lines
7 KiB
C#

using System.Collections.Generic;
using Microsoft.Msagl.Core.GraphAlgorithms;
using Microsoft.Msagl.Core.Layout;
namespace Microsoft.Msagl.Layout.Layered {
/// <summary>
/// This class is used in the case when there are multiple edges, but there is no need to dublicate layers.
/// We just insert dummy nodes for edge middles without distorting the order of vertices in the layers.
/// </summary>
internal class EdgePathsInserter {
Database database;
BasicGraph<Node, IntEdge> intGraph;
ProperLayeredGraph layeredGraph;
ProperLayeredGraph nLayeredGraph;
Dictionary<int, IntEdge> virtNodesToIntEdges = new Dictionary<int, IntEdge>();
internal ProperLayeredGraph NLayeredGraph {
get { return nLayeredGraph; }
}
LayerArrays la;
LayerArrays nla;
internal LayerArrays Nla {
get { return nla; }
}
int[] NLayering {
get {
return this.nla.Y;
}
}
static internal void InsertPaths(
ref ProperLayeredGraph layeredGraph, ref LayerArrays la,
Database db, BasicGraph<Node, IntEdge> intGraphP) {
EdgePathsInserter li = new EdgePathsInserter(layeredGraph, la, db, intGraphP);
li.InsertPaths();
layeredGraph = li.NLayeredGraph;
la = li.Nla;
}
EdgePathsInserter(
ProperLayeredGraph layeredGraph, LayerArrays la, Database database, BasicGraph<Node, IntEdge> intGraphP) {
this.la = la;
this.database = database;
this.layeredGraph = layeredGraph;
this.intGraph = intGraphP;
}
void InsertPaths() {
CreateFullLayeredGraph();
InitNewLayering();
MapVirtualNodesToEdges();
WidenOriginalLayers();
}
void WidenOriginalLayers() {
for (int i = 0; i < la.Layers.Length; i++) {
int[] layer = nla.Layers[i];
int offset = 0;
foreach (int v in la.Layers[i]) {
IntEdge e;
this.virtNodesToIntEdges.TryGetValue(v, out e);
if (e != null) {
int layerOffsetInTheEdge = NLayering[e.Source] - NLayering[v];
List<IntEdge> list = database.Multiedges[new IntPair(e.Source, e.Target)];
foreach (IntEdge ie in list) {
if (!EdgeIsFlat(ie)) {
if (ie != e) {
int u = ie.LayerEdges[layerOffsetInTheEdge].Source;
layer[offset] = u;
nla.X[u] = offset++;
} else {
layer[offset] = v;
nla.X[v] = offset++;
}
}
}
} else {
layer[offset] = v;
nla.X[v] = offset++;
}
}
}
}
private bool EdgeIsFlat(IntEdge ie) {
return la.Y[ie.Source] == la.Y[ie.Target];
}
void MapVirtualNodesToEdges() {
foreach (List<IntEdge> list in this.database.RegularMultiedges)
foreach (IntEdge e in list)
if (! EdgeIsFlat(e))//the edge is not flat
foreach (LayerEdge le in e.LayerEdges)
if (le.Target != e.Target)
this.virtNodesToIntEdges[le.Target] = e;
}
private void CreateFullLayeredGraph() {
int currentVV = this.layeredGraph.NodeCount;
foreach (KeyValuePair<IntPair, List<IntEdge>>
kv in database.Multiedges) {
if (kv.Key.x != kv.Key.y) { //not a self edge
List<IntEdge> list = kv.Value;
bool first = true;
int span = 0;
foreach (IntEdge e in list) {
if (first) {
first = false;
span = e.LayerSpan;
} else {
e.LayerEdges = new LayerEdge[span];
if (span == 1)
e.LayerEdges[0] = new LayerEdge(e.Source, e.Target, e.CrossingWeight);
else {
for (int i = 0; i < span; i++) {
int source = GetSource(ref currentVV, e, i);
int target = GetTarget(ref currentVV, e, i, span);
e.LayerEdges[i] = new LayerEdge(source, target, e.CrossingWeight);
}
}
}
LayerInserter.RegisterDontStepOnVertex(this.database, e);
}
}
}
this.nLayeredGraph = new ProperLayeredGraph(this.intGraph);
}
internal static int GetTarget(ref int currentVV, IntEdge e, int i, int span) {
if (i < span - 1)
return currentVV;
return e.Target;
}
internal static int GetSource(ref int currentVV, IntEdge e, int i) {
if (i == 0)
return e.Source;
return currentVV++;
}
void InitNewLayering() {
nla = new LayerArrays(new int[this.NLayeredGraph.NodeCount]);
for (int i = 0; i < layeredGraph.NodeCount; i++)
NLayering[i] = la.Y[i];
foreach (KeyValuePair<IntPair,List<IntEdge>> kv in database.Multiedges) {
if (kv.Key.First != kv.Key.Second && la.Y[kv.Key.First]!=la.Y[kv.Key.Second]) { //not a self edge and not a flat edge
int layer = 0;
bool first = true;
List<IntEdge> list = kv.Value;
foreach (IntEdge e in list) {
if (first) {
first = false;
layer = la.Y[e.Source];
}
int cl = layer - 1;
foreach (LayerEdge le in e.LayerEdges)
NLayering[le.Target] = cl--;
}
}
}
int[][] newLayers = new int[la.Layers.Length][];
//count new layer widths
int[] counts = new int[newLayers.Length];
foreach (int l in NLayering)
counts[l]++;
for (int i = 0; i < counts.Length; i++)
newLayers[i] = new int[counts[i]];
nla = new LayerArrays(NLayering);
nla.Layers = newLayers;
}
}
}