Skip to content

Added Microsoft's open source graph layout engine #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions AssetDependencyGraph/AssetDependencyGraph-Editor.asmdef
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
{
"name": "AssetDependencyGraph-Editor",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
"overrideReferences": true,
"precompiledReferences": [
"AutomaticGraphLayout.dll"
],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
30 changes: 28 additions & 2 deletions AssetDependencyGraph/Editor/AssetDependencyGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#if UNITY_2019_1_OR_NEWER
using UnityEditor.Experimental.GraphView;
using UnityEngine.UIElements;
using UnityEditor.UIElements;
#else
using UnityEditor.Experimental.UIElements.GraphView;
using UnityEngine.Experimental.UIElements;
Expand Down Expand Up @@ -40,6 +41,7 @@ public class AssetDependencyGraph : EditorWindow
private const float kNodeWidth = 250.0f;

private GraphView m_GraphView;
private bool m_UseAutoLayout = true;

private readonly List<GraphElement> m_AssetElements = new List<GraphElement>();
private readonly Dictionary<string, Node> m_GUIDNodeLookup = new Dictionary<string, Node>();
Expand Down Expand Up @@ -88,6 +90,13 @@ public void OnEnable()
text = "Clear"
});

var toggle = new ToolbarToggle() {
text = "Auto Layout",
value = m_UseAutoLayout
};
toggle.RegisterValueChangedCallback(x => { m_UseAutoLayout = x.newValue; });
toolbar.Add(toggle);

#if !UNITY_2019_1_OR_NEWER
rootVisualElement = this.GetRootVisualContainer();
#endif
Expand Down Expand Up @@ -330,8 +339,10 @@ private void ClearGraph()
m_GUIDNodeLookup.Clear();
}

private void UpdateDependencyNodePlacement(GeometryChangedEvent e)
{
private void UpdateDependencyNodePlacement(GeometryChangedEvent e) {
var element = e.target as VisualElement;
element.UnregisterCallback<GeometryChangedEvent>(UpdateDependencyNodePlacement);

// The current y offset in per depth
var depthYOffset = new Dictionary<int, float>();

Expand Down Expand Up @@ -364,5 +375,20 @@ private void UpdateDependencyNodePlacement(GeometryChangedEvent e)
}

m_DependenciesForPlacement.Clear();

if(m_UseAutoLayout) {
// run graph improvements on top
var layouter = new GraphViewLayouter();
layouter.Adjust(m_GraphView);
}

element.RegisterCallback<GeometryChangedEvent>(FrameOnce);
}

private void FrameOnce(GeometryChangedEvent e) {
if (e.target is VisualElement element)
element.UnregisterCallback<GeometryChangedEvent>(FrameOnce);

m_GraphView.FrameAll();
}
}
Binary file not shown.
33 changes: 33 additions & 0 deletions AssetDependencyGraph/Editor/AutomaticGraphLayout.dll.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 58 additions & 0 deletions AssetDependencyGraph/Editor/GraphViewLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Microsoft.Msagl.Core.Geometry;
using Microsoft.Msagl.Core.Geometry.Curves;
using Microsoft.Msagl.Core.Layout;
using Microsoft.Msagl.Core.Routing;
using Microsoft.Msagl.Layout.Layered;

public class GraphViewLayouter
{
// https://www.microsoft.com/en-us/research/project/microsoft-automatic-graph-layout/#code-samples
public void Adjust(UnityEditor.Experimental.GraphView.GraphView graphView)
{
var elements = graphView.graphElements.ToList();
var nodes = elements.Where(x => x is UnityEditor.Experimental.GraphView.Node)
.Cast<UnityEditor.Experimental.GraphView.Node>();
var edges = elements.Where(x => x is UnityEditor.Experimental.GraphView.Edge)
.Cast<UnityEditor.Experimental.GraphView.Edge>();

GeometryGraph graph = new GeometryGraph();

Dictionary<UnityEditor.Experimental.GraphView.Node, Node> geomNodes =
new Dictionary<UnityEditor.Experimental.GraphView.Node, Node>();

foreach (var node in nodes) {
var nodeRect = node.GetPosition();
Node geometryNode = new Node(CurveFactory.CreateRectangle(nodeRect.width, nodeRect.height, new Point()), node);
graph.Nodes.Add(geometryNode);
geomNodes.Add(node, geometryNode);
}

foreach (var e in edges) {
// Exact edge end positions could be found with e.output.GetGlobalCenter()
Edge geometryEdge = new Edge(geomNodes[e.output.node], geomNodes[e.input.node]);
graph.Edges.Add(geometryEdge);
}

// settings found to look good (enough separation, not too much, clean layout) by experimentation
var settings = new SugiyamaLayoutSettings {
Transformation = PlaneTransformation.Rotation(Math.PI / 2),
EdgeRoutingSettings = {EdgeRoutingMode = EdgeRoutingMode.StraightLine},
// AspectRatio = 9.0 / 16.0, // allows adjusting aspect
LayerSeparation = 200,
GridSizeByX = 300,
GridSizeByY = 300,
SnapToGridByY = SnapToGridByY.Bottom
};
var layout = new LayeredLayout(graph, settings);
layout.Run();

foreach (var n in graph.Nodes) {
var unityNode = (UnityEditor.Experimental.GraphView.Node) n.UserData;
unityNode.SetPosition(new Rect((float) n.Center.X, (float) n.Center.Y, 0, 0));
}
}
}
11 changes: 11 additions & 0 deletions AssetDependencyGraph/Editor/GraphViewLayouter.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.