如何为图形或树结构编写 GUI 编辑器

Posted

技术标签:

【中文标题】如何为图形或树结构编写 GUI 编辑器【英文标题】:How to write a GUI editor for Graph or Tree structures 【发布时间】:2013-07-11 12:14:13 【问题描述】:

Unity3DMecanim 动画系统有一个自定义的 EditorWindow,它允许通过 GUI 定义一棵树(在本例中为混合树)。

看起来像:

它提供了创建节点(状态)和连接它们(转换)的可能性。

现在,我正在开发一些图形和树结构,我想编写一个编辑器扩展,以便让我的游戏设计师填充这些结构。

我最想重新创建一个 EditorWindow,就像 Mecanim 动画师(上图)一样。

我的问题是:是否有任何可用的组件可用于此类任务?是否有用于绘图和连接框和箭头的内置类?或者我需要自己编写完整的 GUI 元素?

【问题讨论】:

我不知道这是否对您有很大帮助,但举个例子,here is a nice post 我曾经在我的编辑器窗口中做贝塞尔线。这是一个很好的例子。 @Jerdak:谢谢.. 非常有趣。我去看看。 @Jerdak 也感谢您的链接!出于兴趣,我正在看这个,因为我想要一些与我的状态机的 MechanimEditor 非常相似的东西。 我看到的只有线条、箭头和文本框。所以你有它们的集合,你需要写一些可以创建和存储这样一个集合的东西 @Jerdak:我找到了一种在编辑器中绘制贝塞尔线的更简单方法。如果您将 Handles.DrawBezier 与 Handles.BeginGUI/EndGUI 放在一起,您可以使用统一函数在编辑器窗口中绘图。我很快就会发布一个sn-p。 【参考方案1】:

我不是在问“寻找工具、库或最喜欢的场外资源”。我想知道如何使用Unity3D API 或引擎本身提供的一些可用组件重现Mecanim 之类的图形编辑器(对不起,如果问题不清楚)。

这是我的答案:

不,没有可用的组件可用于绘制这种图形,但编写自己的非常容易。这是一个带有简单示例的 sn-p,使用可拖动的 GUI.Window 表示节点,Handles.DrawBezier 绘制边缘:

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();
    

【讨论】:

感谢您的回答。你得到你想要的了吗?我也在尝试制作一些简单的状态机图,因此如果您可以分享它们,我对您的发现很感兴趣:) @vexe:不,我没有完成实现它。我正在从事几个不同的项目,不幸的是,这具有最低的优先级。如果您想合作实施它,请告诉我,我们最终可以一起做一些事情。 壮观!令人惊讶的是有多少教程只是纯粹的废话。我已经挖掘了几个小时,阅读了 200 多行长的帖子,这个简单的 30 行代码解决了我的问题。谢谢!【参考方案2】:

你错了,伙计。您在 UnityEditor 中看到的所有内容都必须在某处有代码。您的 MecanimEditor 位于命名空间 UnityEditor.Graphs.AnimationStateMachine。

扩展 UnityEditor.Graphs 中的 GraphGUI。该类负责绘制图形。

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

namespace ws.winx.editor.components

 public class GraphGUIEx:GraphGUI


 


创建新的编辑器窗口。

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

  GraphGUIEx stateMachineGraphGUI;

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

....

创建图形结构。它将包含节点和节点之间的边。

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;

画图。

void OnGUI ()
  

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


    stateMachineGraphGUI.EndGraphGUI ();

   
  

覆盖 NodeGUI 或 EdgeGUI 以获得更多样式和绘图控制。 从 UnityEditor.Graphs.AnimationStateMachine.GraphGUI 样式复制粘贴代码,在 NodeGUI 和 EdgeGUI 中完成。

【讨论】:

我会检查的。在提出这个问题时,Graphs api 并未公开。感谢您的信息。 令人印象深刻。谢谢! UnityEditor.Graphs.AnimationStateMachine 命名空间似乎不存在(unity 5.4)【参考方案3】:

这个话题相当复杂,但是如果你想要一个不错的启动脚本存储库,请查看 Unity 官方网站上的这个论坛帖子http://forum.unity3d.com/threads/simple-node-editor.189230/

*更新:有人发布了一个复杂的教程系列,详细说明了如何准确地创建您所描述的内容。享受https://www.youtube.com/watch?v=gHTJmGGH92w。

编辑:我在 GitHub 存储库中编写了一个功能齐全的 Unity 图形编辑器。主要集中在技能树上。它并不完美,但展示了功能齐全的图形编辑器的外观。源代码在以下链接中。

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

【讨论】:

【参考方案4】:

您可以尝试为每个树对象内部的数据创建一个对象。 然后您可以尝试使用 System.Drawing 创建自定义控件(图片中的方框),也可以使用 System.Drawing 为每个树对象创建这些箭头。确保每个 DataObject 都有 ID 和箭头应该指向的位置的信息。 如果您在创建自定义控件方面需要帮助,我过去曾在 YouTube 上使用过 this 教程。

【讨论】:

【参考方案5】:

我从Unity AssetStore找到了一个Unity UI FlowChart Asset,UI Graph,由Broken Machinery开发,免费使用!

【讨论】:

【参考方案6】:

我已经完成了一个使用 TreeViewer 和复选框创建自定义图形的界面。是基于“邻接表”的想法。如果您选中了“根”顶点的复选框,它会使其与另一个顶点相邻,如果您只想让几个顶点相邻,那么您可以单独选择每个顶点。我已经为 java 开发了这个,但我相信它也可以用于你的目的。这是一张我希望能阐明我的想法的图片。

http://i.stack.imgur.com/3PhT9.jpg

【讨论】:

以上是关于如何为图形或树结构编写 GUI 编辑器的主要内容,如果未能解决你的问题,请参考以下文章

如何用MATLAB GUI创建图形用户界面

怎么用matlab实现计算器功能

如何为python类中的私有属性编写getter-setter方法?

如何为 Xcode 6.x 的 plist 创建自定义结构定义?

Go,AppEngine:如何为应用程序构建模板

如何为gettext .po文件制作标题?