Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a GUI editor for Graph or Tree structures

Tags:

c#

unity3d

Unity3D's Mecanim animations system has a custom EditorWindow that allows to define a tree (a blend tree in this case) thorough GUI.

It looks like:

enter image description here

It offers the possibility of creating nodes (states) and connect them (transitions).

Now, I'm developing some graph and and tree structure and I would like to write an editor extension in order to allow my game designer to populate those structures.

I want pretty most recreate exactly an EditorWindow like the one of Mecanim animator (figure above).

My question is: are there any available components that I can use for such a task? Is there any builtin class used for the drawing and connecting boxes and arrow? Or I need to write completely the GUI elements by my own?

like image 408
Heisenbug Avatar asked Jul 11 '13 12:07

Heisenbug


3 Answers

I was not asking "for a find a tool, library or favorite off-site resource". I would like to know how reproduce a Mecanim like graph editor using Unity3D API or some available components provided by the engine itself (sorry if the question wasn't clear).

Here's my answer:

No, there's isn't an available component usable as is to draw that kind of graph, but it's quite easy to write your own. Here's a snippet with a simple example using draggable GUI.Window to represent nodes and Handles.DrawBezier to draw the edges:

public class GraphEditorWindow : EditorWindow
{
    Rect windowRect = new Rect (100 + 100, 100, 100, 100);
    Rect windowRect2 = new Rect (100, 100, 100, 100);


    [MenuItem ("Window/Graph Editor Window")]
    static void Init () {
        EditorWindow.GetWindow (typeof (GraphEditorWindow));
    }

    private void OnGUI()
    {
        Handles.BeginGUI();
        Handles.DrawBezier(windowRect.center, windowRect2.center, new Vector2(windowRect.xMax + 50f,windowRect.center.y), new Vector2(windowRect2.xMin - 50f,windowRect2.center.y),Color.red,null,5f);
        Handles.EndGUI();

        BeginWindows();
        windowRect = GUI.Window (0, windowRect, WindowFunction, "Box1");
        windowRect2 = GUI.Window (1, windowRect2, WindowFunction, "Box2");

        EndWindows();

    }
    void WindowFunction (int windowID) 
    {
        GUI.DragWindow();
    }
}
like image 155
Heisenbug Avatar answered Nov 20 '22 13:11

Heisenbug


You are wrong dude. Everything you see in UnityEditor must have code somewhere. Your MecanimEditor is in namespace UnityEditor.Graphs.AnimationStateMachine.

Extend GraphGUI found in UnityEditor.Graphs. This class is responsible for drawing graph.

using System;
using UnityEditor;
using UnityEngine;
using UnityEditor.Graphs;
using System.Collections.Generic;

namespace ws.winx.editor.components
{
 public class GraphGUIEx:GraphGUI{


 }

}

Create new EditorWindow.

public class GraphEditorWindow : EditorWindow
 { 
  static GraphEditorWindow graphEditorWindow;
  Graph stateMachineGraph;

  GraphGUIEx stateMachineGraphGUI;

  [MenuItem("Window/Example")]
  static void Do ()
  {
   graphEditorWindow = GetWindow<grapheditorwindow> ();
  }

....

Create Graph structure. It will contains nodes and edges between nodes.

stateMachineGraph = ScriptableObject.CreateInstance<Graph> ();
    stateMachineGraph.hideFlags = HideFlags.HideAndDontSave;

                 //create new node
    Node node=ScriptableObject.CreateInstance<Node>();
    node.title="mile2";
    node.position=new Rect(400,34,300,200);


    node.AddInputSlot("input");
    start=node.AddOutputSlot("output");
    node.AddProperty(new Property(typeof(System.Int32),"integer"));
    stateMachineGraph.AddNode(node);

//create new node
    Node node=ScriptableObject.CreateInstance<Node>();
    node.title="mile";
    node.position=new Rect(0,0,300,200);

    Slot end=node.AddInputSlot("input");
    node.AddOutputSlot("output");
    node.AddProperty(new Property(typeof(System.Int32),"integer"));
    stateMachineGraph.AddNode(node);

//create edge
    stateMachineGraph.Connect(start,end);

graphGUI = ScriptableObject.CreateInstance<GraphGUIEx>();
graphGUI.graph = graph;

Draw Graph.

void OnGUI ()
  {

   if (graphEditorWindow && stateMachineGraphGUI != null) {
    stateMachineGraphGUI.BeginGraphGUI (graphEditorWindow, new Rect (0, 0, graphEditorWindow.position.width, graphEditorWindow.position.height));
               stateMachineGraphGUI.OnGraphGUI ();


    stateMachineGraphGUI.EndGraphGUI ();

   }
  }

Override NodeGUI or EdgeGUI for more styling and drawing control. Copy paste code from UnityEditor.Graphs.AnimationStateMachine.GraphGUI styling done in NodeGUI and EdgeGUI.

like image 39
user999913 Avatar answered Nov 20 '22 13:11

user999913


This topic is quite complicated, but if you want a nice repository of starter scripts check out this forum thread on Unity's official site http://forum.unity3d.com/threads/simple-node-editor.189230/

*Update: Someone has posted a complex tutorial series, heavily detailing how to create exactly what you've described. Enjoy https://www.youtube.com/watch?v=gHTJmGGH92w.

Edit: I've written a fully functioning Unity graph editor in a GitHub repo. Primarily focused on skill trees. It isn't perfect, but demonstrates what a fully functioning graph editor could look like. Source code in the following link.

https://github.com/ashblue/unity-skill-tree-editor

like image 6
Ash Blue Avatar answered Nov 20 '22 14:11

Ash Blue