Skip to content

Commit c490392

Browse files
committed
Squashed commit of the following:
commit a230aa0 Author: zqy <vdergow@hotmail.com> Date: Fri Aug 12 14:06:28 2022 +0800 feat: improve performance commit f421152 Author: zqy <vdergow@hotmail.com> Date: Thu Aug 11 21:16:42 2022 +0800 feat: improve node layout commit d0a147c Author: zqy <vdergow@hotmail.com> Date: Thu Aug 11 17:52:40 2022 +0800 feat: improve node layout commit daa1363 Author: zqy <vdergow@hotmail.com> Date: Thu Aug 11 16:46:49 2022 +0800 feat: auto calculate node tree layout commit 8a9a1c9 Author: zqy <vdergow@hotmail.com> Date: Thu Aug 11 12:49:45 2022 +0800 feat: bug fix & sorting code commit c5a7b40 Author: zqy <vdergow@hotmail.com> Date: Wed Aug 10 22:01:21 2022 +0800 feat: draw nodes commit 6a9ea80 Author: zqy <vdergow@hotmail.com> Date: Wed Aug 10 21:47:08 2022 +0800 feat: playable graph view and nodes
1 parent 1baed78 commit c490392

20 files changed

Lines changed: 859 additions & 209 deletions

Editor/Scripts/GraphView.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
using GBG.PlayableGraphMonitor.Editor.Node;
2+
using System.Collections.Generic;
3+
using UnityEditor.Experimental.GraphView;
4+
using UnityEngine;
5+
using UnityEngine.Playables;
6+
using UnityEngine.UIElements;
7+
using UGraphView = UnityEditor.Experimental.GraphView.GraphView;
8+
9+
namespace GBG.PlayableGraphMonitor.Editor.GraphView
10+
{
11+
public class PlayableGraphView : UGraphView
12+
{
13+
private PlayableGraph _playableGraph;
14+
15+
private readonly List<PlayableOutputNode> _rootOutputNodes = new List<PlayableOutputNode>();
16+
17+
18+
public PlayableGraphView()
19+
{
20+
this.AddManipulator(new ContentDragger());
21+
//this.AddManipulator(new SelectionDragger());
22+
//this.AddManipulator(new RectangleSelector());
23+
SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale);
24+
}
25+
26+
public PlayableGraph GetPlayableGraph()
27+
{
28+
return _playableGraph;
29+
}
30+
31+
public void Update(PlayableGraph playableGraph)
32+
{
33+
if (!_playableGraph.IsValid())
34+
{
35+
ClearView();
36+
}
37+
38+
if (IsEqual(ref _playableGraph, ref playableGraph))
39+
{
40+
DiffOutputNodes();
41+
}
42+
else
43+
{
44+
// playable graph changed
45+
_playableGraph = playableGraph;
46+
47+
PopulateView();
48+
}
49+
50+
CalculateLayout();
51+
}
52+
53+
54+
private void ClearView()
55+
{
56+
foreach (var playableOutputNode in _rootOutputNodes)
57+
{
58+
playableOutputNode.RemoveFromContainer();
59+
}
60+
61+
_rootOutputNodes.Clear();
62+
}
63+
64+
private void PopulateView()
65+
{
66+
if (!_playableGraph.IsValid())
67+
{
68+
return;
69+
}
70+
71+
// create nodes
72+
for (int i = 0; i < _playableGraph.GetOutputCount(); i++)
73+
{
74+
var playableOutput = _playableGraph.GetOutput(i);
75+
var playableOutputNode = PlayableOutputNodeFactory.CreateNode(playableOutput);
76+
playableOutputNode.AddToContainer(this);
77+
78+
_rootOutputNodes.Add(playableOutputNode);
79+
}
80+
81+
for (int i = 0; i < _rootOutputNodes.Count; i++)
82+
{
83+
//_rootOutputNodes[i].CreateAndConnectInputNodes();
84+
_rootOutputNodes[i].Update();
85+
}
86+
}
87+
88+
private void DiffOutputNodes()
89+
{
90+
if (!_playableGraph.IsValid())
91+
{
92+
return;
93+
}
94+
95+
// mark all root nodes inactive
96+
for (int i = 0; i < _rootOutputNodes.Count; i++)
97+
{
98+
_rootOutputNodes[i].RemoveFlag(NodeFlag.Active);
99+
}
100+
101+
// diff nodes
102+
for (int i = 0; i < _playableGraph.GetOutputCount(); i++)
103+
{
104+
var playableOutput = _playableGraph.GetOutput(i);
105+
var rootOutputNodeIndex = FindRootOutputNode(playableOutput);
106+
if (rootOutputNodeIndex >= 0)
107+
{
108+
_rootOutputNodes[i].AddFlag(NodeFlag.Active);
109+
continue;
110+
}
111+
112+
// create new node
113+
var playableOutputNode = PlayableOutputNodeFactory.CreateNode(playableOutput);
114+
playableOutputNode.AddToContainer(this);
115+
playableOutputNode.AddFlag(NodeFlag.Active);
116+
117+
_rootOutputNodes.Add(playableOutputNode);
118+
}
119+
120+
for (int i = _rootOutputNodes.Count - 1; i >= 0; i--)
121+
{
122+
var rootOutputNode = _rootOutputNodes[i];
123+
if (!rootOutputNode.CheckFlag(NodeFlag.Active))
124+
{
125+
rootOutputNode.RemoveFromContainer();
126+
127+
_rootOutputNodes.RemoveAt(i);
128+
continue;
129+
}
130+
131+
rootOutputNode.Update();
132+
}
133+
}
134+
135+
private int FindRootOutputNode(PlayableOutput playableOutput)
136+
{
137+
for (int i = 0; i < _rootOutputNodes.Count; i++)
138+
{
139+
if (_rootOutputNodes[i].PlayableOutput.Equals(playableOutput))
140+
{
141+
return i;
142+
}
143+
}
144+
145+
return -1;
146+
}
147+
148+
private void CalculateLayout()
149+
{
150+
var origin = Vector2.zero;
151+
for (int i = 0; i < _rootOutputNodes.Count; i++)
152+
{
153+
var outputNode = _rootOutputNodes[i];
154+
var treeSize = outputNode.GetHierarchySize();
155+
156+
outputNode.CalculateLayout(origin);
157+
158+
origin.y += treeSize.y + NodeLayoutInfo.VerticalSpace;
159+
}
160+
}
161+
162+
163+
private static bool IsEqual(ref PlayableGraph a, ref PlayableGraph b)
164+
{
165+
if (!a.IsValid())
166+
{
167+
return !b.IsValid();
168+
}
169+
170+
if (!b.IsValid())
171+
{
172+
return false;
173+
}
174+
175+
var nameA = a.GetEditorName();
176+
var nameB = b.GetEditorName();
177+
178+
return nameA.Equals(nameB);
179+
}
180+
}
181+
}

Editor/Scripts/GraphView/PlayableGraphView.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Editor/Scripts/Node.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
using System.Collections.Generic;
2+
using UnityEditor.Experimental.GraphView;
3+
using UnityEngine;
4+
using UEdge = UnityEditor.Experimental.GraphView.Edge;
5+
using UGraphView = UnityEditor.Experimental.GraphView.GraphView;
6+
using UNode = UnityEditor.Experimental.GraphView.Node;
7+
8+
namespace GBG.PlayableGraphMonitor.Editor.Node
9+
{
10+
public enum NodeFlag : uint
11+
{
12+
None = 0,
13+
Active = 1 << 0,
14+
Dirty = 1 << 1,
15+
}
16+
17+
public readonly struct NodeInput
18+
{
19+
public UEdge Edge { get; }
20+
21+
public GraphViewNode Node { get; }
22+
23+
24+
public NodeInput(UEdge edge, GraphViewNode node)
25+
{
26+
Edge = edge;
27+
Node = node;
28+
}
29+
}
30+
31+
public abstract class GraphViewNode : UNode
32+
{
33+
public IReadOnlyList<Port> InputPorts => InternalInputPorts;
34+
35+
protected List<Port> InternalInputPorts { get; } = new List<Port>();
36+
37+
public IReadOnlyList<Port> OutputPorts => InternalOutputPorts;
38+
39+
protected List<Port> InternalOutputPorts { get; } = new List<Port>();
40+
41+
protected UGraphView Container { get; set; }
42+
43+
public IReadOnlyList<NodeInput> Inputs => InternalInputs;
44+
45+
protected List<NodeInput> InternalInputs { get; } = new List<NodeInput>();
46+
47+
protected GraphViewNode Parent { get; private set; }
48+
49+
50+
public virtual void Update() { }
51+
52+
53+
#region Hierarchy
54+
55+
public virtual void AddToContainer(UGraphView container)
56+
{
57+
Container = container;
58+
Container.AddElement(this);
59+
}
60+
61+
public virtual void RemoveFromContainer()
62+
{
63+
// self
64+
Container.RemoveElement(this);
65+
66+
// children
67+
for (int i = 0; i < InternalInputs.Count; i++)
68+
{
69+
var input = InternalInputs[i];
70+
Container.RemoveElement(input.Edge);
71+
input.Node.RemoveFromContainer();
72+
}
73+
74+
InternalInputs.Clear();
75+
76+
Container = null;
77+
}
78+
79+
80+
protected Port InstantiatePort<TPort>(Direction direction)
81+
{
82+
return InstantiatePort(Orientation.Horizontal, direction, Port.Capacity.Single, typeof(TPort));
83+
}
84+
85+
#endregion
86+
87+
88+
#region Layout
89+
90+
private Vector2? _hierarchySize;
91+
92+
93+
public Vector2 GetNodeSize()
94+
{
95+
return NodeLayoutInfo.StandardNodeSize;
96+
//return worldBound.size;
97+
}
98+
99+
public Vector2 GetHierarchySize()
100+
{
101+
if (_hierarchySize != null)
102+
{
103+
return _hierarchySize.Value;
104+
}
105+
106+
if (Inputs.Count == 0)
107+
{
108+
_hierarchySize = GetNodeSize();
109+
return _hierarchySize.Value;
110+
}
111+
112+
var subHierarchySize = Vector2.zero;
113+
for (int i = 0; i < Inputs.Count; i++)
114+
{
115+
var childSize = Inputs[i].Node.GetHierarchySize();
116+
subHierarchySize.x = Mathf.Max(subHierarchySize.x, childSize.x);
117+
subHierarchySize.y += childSize.y;
118+
}
119+
subHierarchySize.y += (Inputs.Count - 1) * NodeLayoutInfo.VerticalSpace;
120+
121+
var hierarchySize = GetNodeSize() + new Vector2(NodeLayoutInfo.HorizontalSpace, 0);
122+
hierarchySize.y = Mathf.Max(hierarchySize.y, subHierarchySize.y);
123+
_hierarchySize = hierarchySize;
124+
125+
return _hierarchySize.Value;
126+
}
127+
128+
public void CalculateLayout(Vector2 origin)
129+
{
130+
var subTreeSize = GetHierarchySize();
131+
var nodePos = CalculateSubTreeRootNodePosition(subTreeSize, origin);
132+
SetPosition(new Rect(nodePos, Vector2.zero));
133+
134+
origin.x -= GetNodeSize().x - NodeLayoutInfo.HorizontalSpace;
135+
for (int i = 0; i < Inputs.Count; i++)
136+
{
137+
var childNode = Inputs[i];
138+
var childHierarchySize = childNode.Node.GetHierarchySize();
139+
childNode.Node.CalculateLayout(origin);
140+
141+
origin.y += childHierarchySize.y;
142+
}
143+
}
144+
145+
public static Vector2 CalculateSubTreeRootNodePosition(Vector2 subTreeSize, Vector2 subTreeOrigin)
146+
{
147+
var subTreePos = subTreeOrigin;
148+
subTreePos.y += subTreeSize.y / 2;
149+
return subTreePos;
150+
}
151+
152+
#endregion
153+
154+
155+
#region Flags
156+
157+
private uint _flags = 0;
158+
159+
160+
public bool CheckFlag(NodeFlag flag)
161+
{
162+
return (_flags & (uint)flag) != 0;
163+
}
164+
165+
public void AddFlag(NodeFlag flag)
166+
{
167+
_flags |= (uint)flag;
168+
}
169+
170+
public void RemoveFlag(NodeFlag flag)
171+
{
172+
_flags &= ~(uint)flag;
173+
}
174+
175+
#endregion
176+
}
177+
}

Editor/Scripts/Node/GraphViewNode.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)