diff --git a/Assets/Clients/GraphVisualizerClient.cs b/Assets/Clients/GraphVisualizerClient.cs
index 5e061d9..120619d 100644
--- a/Assets/Clients/GraphVisualizerClient.cs
+++ b/Assets/Clients/GraphVisualizerClient.cs
@@ -1,7 +1,7 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
-using UnityEngine.Experimental.Director;
+using UnityEngine.Playables;
// Bridge between runtime and editor code: the graph created in runtime code can call GraphVisualizerClient.Show(...)
// and the EditorWindow will register itself with the client to display any available graph.
diff --git a/Assets/Editor/GraphVisualizer/Graph/Renderer/DefaultGraphRenderer.cs b/Assets/Editor/GraphVisualizer/Graph/Renderer/DefaultGraphRenderer.cs
index 59ecf53..4e9af7d 100644
--- a/Assets/Editor/GraphVisualizer/Graph/Renderer/DefaultGraphRenderer.cs
+++ b/Assets/Editor/GraphVisualizer/Graph/Renderer/DefaultGraphRenderer.cs
@@ -5,7 +5,7 @@
using System.Linq;
using System.Text.RegularExpressions;
using GraphVisualizer;
-using UnityEngine.Experimental.Director;
+using UnityEngine.Playables;
public class DefaultGraphRenderer : IGraphRenderer
{
diff --git a/Assets/Editor/GraphVisualizer/PlayableGraphVisualizer.cs b/Assets/Editor/GraphVisualizer/PlayableGraphVisualizer.cs
index b027649..df2356a 100644
--- a/Assets/Editor/GraphVisualizer/PlayableGraphVisualizer.cs
+++ b/Assets/Editor/GraphVisualizer/PlayableGraphVisualizer.cs
@@ -2,27 +2,60 @@
using System.Collections.Generic;
using System.Text;
using GraphVisualizer;
-using UnityEngine.Experimental.Director;
+using UnityEngine.Playables;
-public class PlayableGraphNode : Node
+public class SharedPlayableNode : Node
{
- public PlayableGraphNode(PlayableHandle content, float weight = 1, bool active = false)
+ public SharedPlayableNode(object content, float weight = 1, bool active = false)
+ : base(content, weight, active)
+ {
+ }
+
+ protected static string InfoString(string key, double value)
+ {
+ return String.Format(
+ ((Math.Abs(value) < 100000.0) ? "{0}: {1:#.###}" : "{0}: {1:E4}"), key, value);
+ }
+
+ protected static string InfoString(string key, int value)
+ {
+ return String.Format("{0}: {1:D}", key, value);
+ }
+
+ protected static string InfoString(string key, object value)
+ {
+ return "" + key + ": " + (value ?? "(none)");
+ }
+
+ protected static string RemoveFromEnd(string str, string suffix)
+ {
+ if (str.EndsWith(suffix))
+ {
+ return str.Substring(0, str.Length - suffix.Length);
+ }
+ return str;
+ }
+}
+
+public class PlayableNode : SharedPlayableNode
+{
+ public PlayableNode(Playable content, float weight = 1, bool active = false)
: base(content, weight, active)
{
}
public override Type GetContentType()
{
- Playable p = null;
+ Playable p = Playable.Null;
try
{
- p = ((PlayableHandle)content).GetObject();
+ p = ((Playable)content);
}
catch
{
// Ignore.
}
- return p == null ? null : p.GetType();
+ return !p.IsValid() ? null : p.GetPlayableType();
}
public override string GetContentTypeShortName()
@@ -39,48 +72,66 @@ public override string ToString()
sb.AppendLine(InfoString("Handle", GetContentTypeShortName()));
- var h = (PlayableHandle)content;
+ var h = (Playable)content;
sb.AppendLine(InfoString("IsValid", h.IsValid()));
if (h.IsValid())
{
- sb.AppendLine(InfoString("IsDone", h.isDone));
- sb.AppendLine(InfoString("InputCount", h.inputCount));
- sb.AppendLine(InfoString("OutputCount", h.outputCount));
- sb.AppendLine(InfoString("PlayState", h.playState));
- sb.AppendLine(InfoString("Speed", h.speed));
- sb.AppendLine(InfoString("Duration", h.duration));
- sb.AppendLine(InfoString("Time", h.time));
+ sb.AppendLine(InfoString("IsDone", h.IsDone()));
+ sb.AppendLine(InfoString("InputCount", h.GetInputCount()));
+ sb.AppendLine(InfoString("OutputCount", h.GetOutputCount()));
+ sb.AppendLine(InfoString("PlayState", h.GetPlayState()));
+ sb.AppendLine(InfoString("Speed", h.GetSpeed()));
+ sb.AppendLine(InfoString("Duration", h.GetDuration()));
+ sb.AppendLine(InfoString("Time", h.GetTime()));
// sb.AppendLine(InfoString("Animation", h.animatedProperties));
}
return sb.ToString();
}
+}
- private static string InfoString(string key, double value)
+public class PlayableOutputNode : SharedPlayableNode
+{
+ public PlayableOutputNode(PlayableOutput content)
+ : base(content, content.GetWeight(), true)
{
- return String.Format(
- ((Math.Abs(value) < 100000.0) ? "{0}: {1:#.###}" : "{0}: {1:E4}") , key, value);
}
- private static string InfoString(string key, int value)
+ public override Type GetContentType()
{
- return String.Format("{0}: {1:D}", key, value);
+ PlayableOutput p = PlayableOutput.Null;
+ try
+ {
+ p = ((PlayableOutput)content);
+ }
+ catch
+ {
+ // Ignore.
+ }
+ return !p.IsOutputValid() ? null : p.GetPlayableOutputType();
}
- private static string InfoString(string key, object value)
+ public override string GetContentTypeShortName()
{
- return "" + key + ": " + (value ?? "(none)");
+ // Remove the extra Playable at the end of the Playable types.
+ string shortName = base.GetContentTypeShortName();
+ string cleanName = RemoveFromEnd(shortName, "PlayableOutput") + "Output";
+ return string.IsNullOrEmpty(cleanName) ? shortName : cleanName;
}
- private static string RemoveFromEnd(string str, string suffix)
+ public override string ToString()
{
- if (str.EndsWith(suffix))
- {
- return str.Substring(0, str.Length - suffix.Length);
- }
- return str;
+ var sb = new StringBuilder();
+
+ sb.AppendLine(InfoString("Handle", GetContentTypeShortName()));
+
+ var h = (PlayableOutput)content;
+
+ sb.AppendLine(InfoString("IsValid", h.IsOutputValid()));
+
+ return sb.ToString();
}
}
@@ -95,47 +146,81 @@ public PlayableGraphVisualizer(PlayableGraph playableGraph)
protected override void Populate()
{
- if (!m_PlayableGraph.IsValid()) return;
- int roots = m_PlayableGraph.rootPlayableCount;
- for (int i = 0; i < roots; i++)
+ if (!m_PlayableGraph.IsValid())
+ return;
+
+ int outputs = m_PlayableGraph.GetOutputCount();
+ for (int i = 0; i < outputs; i++)
{
- AddNodeHierarchy(CreateNodeFromPlayableHandle(m_PlayableGraph.GetRootPlayable(i), 1.0f));
+ var output = m_PlayableGraph.GetOutput(i);
+ if(output.IsOutputValid())
+ {
+ AddNodeHierarchy(CreateNodeFromPlayableOutput(output));
+ }
}
}
protected override IEnumerable GetChildren(Node node)
{
- // Children are the PlayableHandle Inputs.
- return GetInputsNode((PlayableHandle)node.content);
+ // Children are the Playable Inputs.
+ if(node is PlayableNode)
+ return GetInputsFromPlayableNode((Playable)node.content);
+ else if(node is PlayableOutputNode)
+ return GetInputsFromPlayableOutputNode((PlayableOutput)node.content);
+
+ return new List();
}
- private List GetInputsNode(PlayableHandle h)
+ private List GetInputsFromPlayableNode(Playable h)
{
var inputs = new List();
- for (int port = 0; port < h.inputCount; ++port)
+ if (h.IsValid())
{
- PlayableHandle playableHandle = h.GetInput(port);
- if (playableHandle.IsValid())
+ for (int port = 0; port < h.GetInputCount(); ++port)
+ {
+ Playable playable = h.GetInput(port);
+ if (playable.IsValid())
+ {
+ float weight = h.GetInputWeight(port);
+ Node node = CreateNodeFromPlayable(playable, weight);
+ inputs.Add(node);
+ }
+ }
+ }
+ return inputs;
+ }
+
+ private List GetInputsFromPlayableOutputNode(PlayableOutput h)
+ {
+ var inputs = new List();
+ if (h.IsOutputValid())
+ {
+ Playable playable = h.GetSourcePlayable();
+ if (playable.IsValid())
{
- float weight = h.GetInputWeight(port);
- Node node = CreateNodeFromPlayableHandle(playableHandle, weight);
+ Node node = CreateNodeFromPlayable(playable, 1);
inputs.Add(node);
}
}
return inputs;
}
- private PlayableGraphNode CreateNodeFromPlayableHandle(PlayableHandle h, float weight)
+ private PlayableNode CreateNodeFromPlayable(Playable h, float weight)
+ {
+ return new PlayableNode(h, weight, h.GetPlayState() == PlayState.Playing);
+ }
+
+ private PlayableOutputNode CreateNodeFromPlayableOutput(PlayableOutput h)
{
- return new PlayableGraphNode(h, weight, h.playState == PlayState.Playing);
+ return new PlayableOutputNode(h);
}
- private static bool HasValidOuputs(PlayableHandle h)
+ private static bool HasValidOuputs(Playable h)
{
- for (int port = 0; port < h.outputCount; ++port)
+ for (int port = 0; port < h.GetOutputCount(); ++port)
{
- PlayableHandle playableHandle = h.GetOutput(port);
- if (playableHandle.IsValid())
+ Playable playable = h.GetOutput(port);
+ if (playable.IsValid())
{
return true;
}
diff --git a/Assets/Editor/GraphVisualizer/PlayableGraphVisualizerWindow.cs b/Assets/Editor/GraphVisualizer/PlayableGraphVisualizerWindow.cs
index b9430a6..64b7669 100644
--- a/Assets/Editor/GraphVisualizer/PlayableGraphVisualizerWindow.cs
+++ b/Assets/Editor/GraphVisualizer/PlayableGraphVisualizerWindow.cs
@@ -3,7 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using GraphVisualizer;
-using UnityEngine.Experimental.Director;
+using UnityEngine.Playables;
using UnityEditor.Animations;
public class PlayableGraphVisualizerWindow : EditorWindow, IHasCustomMenu
@@ -67,12 +67,21 @@ private PlayableGraphInfo GetSelectedGraphInToolBar(IList gra
return selectedDirector;
}
- private void ShowMessage(string msg)
+ private static void ShowMessage(string msg)
{
- GUIStyle centeredStyle = GUI.skin.GetStyle("Label");
- centeredStyle.alignment = TextAnchor.UpperCenter;
- int width = 15 * msg.Length;
- GUI.Label(new Rect(0.5f * (Screen.width - width), 0.5f * (Screen.height - 50), width, 50), msg, centeredStyle);
+ GUILayout.BeginVertical();
+ GUILayout.FlexibleSpace();
+
+ GUILayout.BeginHorizontal();
+ GUILayout.FlexibleSpace();
+
+ GUILayout.Label(msg);
+
+ GUILayout.FlexibleSpace();
+ GUILayout.EndHorizontal();
+
+ GUILayout.FlexibleSpace();
+ GUILayout.EndVertical();
}
void Update()
@@ -100,7 +109,6 @@ void OnGUI()
// that are in the current scene.
if (m_AutoScanScene)
{
-#if PLAYABLE_DIRECTOR
// This code could be generalized, maybe if we added a IHasPlayableGraph Interface.
IList directors = FindObjectsOfType();
if (directors != null)
@@ -115,8 +123,7 @@ void OnGUI()
}
}
}
-#endif
-#if ANIMATOR_5_6
+
IList animators = FindObjectsOfType();
if (animators != null)
{
@@ -130,7 +137,6 @@ void OnGUI()
}
}
}
-#endif
}
if (GraphVisualizerClient.GetGraphs() != null)
diff --git a/README.md b/README.md
index 2f8157a..b20a2d3 100644
--- a/README.md
+++ b/README.md
@@ -3,11 +3,14 @@
The PlayableGraph Visualizer window can be used to display any *PlayableGraph*.
The tool can be used in both Play and Edit mode and will always reflect the current state of the graph.
Playable Handles in the graph are represented by colored nodes, varying according to their type. Wire color intensity indicates the local weight of the blending.
+## Setup ##
+- Download the release that matches your current Unity version, or the latest if there your Unity version is more recent than the latest release.
+- Copy the content of this repos Asset folder into a the Asset folder of an Unity Project. You will need to do this for every project.
+## Window ##
+- You can open the Timeline Visualizer in **Window > PlayableGraph Visualizer**.
## Usage ##
-- Copy the content of this repos into a Unity Project.
- Open any scene that contains at least one *PlayableGraph*.
- Register your *PlayableGraph* with the method GraphVisualizerClient.Show(PlayableGraph, string).
-- Open the Timeline Visualizer in **Window > PlayableGraph Visualizer**.
- Select the *PlayableGraph* to display in the top-left combo box.
- Click on a Node to display more information about the associated Playable Handle.
## Notes ##