编辑器菜单栏打开--浮动窗口¶
using UnityEditor;
public class TutorialWindow : EditorWindow
{
private static TutorialWindow window; //窗口实例对象,必须是一个static
[MenuItem("MyWindows/TutorialWindow")] //定义菜单栏位置
public static void OpenWindow() //打开窗口函数,必须是static
{
window = GetWindow<TutorialWindow>(false, "TutorialWindow", true); //实例化窗口
window.Show(); //显示窗口
}
/// <summary>
/// 窗口内显示的GUI面板
/// </summary>
private void OnGUI()
{
}
}
TreeView重要的类和方法¶
1. TreeViewItem¶
为了处理 TreeView 的渲染,需要确定一个扩展项(称为行)列表,用于在Editor中构建树结构的表示。每一行代表一个 TreeViewItem
。
+ 每个 TreeViewItem
都包含父子信息,此信息可供 TreeView 用来处理导航(按键和鼠标输入)。
+ 每个 TreeViewItem
必须以唯一的整数 ID(在 TreeView 中的所有项中是唯一的)进行构造,用于:
+ 查找项
+ 选择状态
+ 展开状态
+ 导航
+ 如果树表示 Unity 对象,应为每个对象使用 GetInstanceID 作为 TreeViewItem
的 ID
+ depth属性:表示视觉缩进
2.TreeViewState状态信息¶
包含交互时的状态信息,唯一可序列化: + 选择状态 + 展开状态 + 导航状态 + 滚动状态
3.BuildRoot¶
TreeView的单个抽象方法,必须实现该方法才能创建TreeView。 + 使用此方法发可以创建树的根项 + 每次Reload都会调用该方法 对于小型树,每次重新加载可以直接创建整个TreeViewItems
4.BuildRows¶
虚拟方法,此方法默认基于BuildRoot中创建的完整树来构建行列表。可以重写此方法来处理展开的行
Tree的创建¶
初始化TreeView¶
要创建TreeView,需要创建一个扩展TreeView的类,并实现抽象方法 BuildRoot
class SimpleTreeView : TreeView{
}
1. 调用基类构造,并实现自己的构造¶
public SimpleTreeView(TreeViewState treeViewState) : base(treeViewState) {
Reload();
}
2.实现BuildRoot重载¶
- ID应该唯一。
- 根项深度必须为-1,其余的深度在此基础上递增
方法一:使用了深度信息构建
方法二:使用AddChild直接设置父项和子项
protected override TreeViewItem BuildRoot() { var root = new TreeViewItem { id = 0, depth = -1, displayName = "Root" }; var allItems = new List<TreeViewItem> { new TreeViewItem {id = 1, depth = 0, displayName = "Animals"}, new TreeViewItem {id = 2, depth = 1, displayName = "Mammals"}, new TreeViewItem {id = 3, depth = 2, displayName = "Tiger"}, new TreeViewItem {id = 4, depth = 2, displayName = "Elephant"}, new TreeViewItem {id = 5, depth = 2, displayName = "Okapi"}, new TreeViewItem {id = 6, depth = 2, displayName = "Armadillo"}, new TreeViewItem {id = 7, depth = 1, displayName = "Reptiles"}, new TreeViewItem {id = 8, depth = 2, displayName = "Crocodile"}, new TreeViewItem {id = 9, depth = 2, displayName = "Lizard"}, }; // 用于初始化所有项的 TreeViewItem.children 和 .parent 的实用方法。 SetupParentsAndChildrenFromDepths(root, allItems); //返回树的根 return root; }
protected override TreeViewItem BuildRoot() { var root = new TreeViewItem { id = 0, depth = -1, displayName = "Root" }; var animals = new TreeViewItem { id = 1, displayName = "Animals" }; var mammals = new TreeViewItem { id = 2, displayName = "Mammals" }; var tiger = new TreeViewItem { id = 3, displayName = "Tiger" }; var elephant = new TreeViewItem { id = 4, displayName = "Elephant" }; var okapi = new TreeViewItem { id = 5, displayName = "Okapi" }; var armadillo = new TreeViewItem { id = 6, displayName = "Armadillo" }; var reptiles = new TreeViewItem { id = 7, displayName = "Reptiles" }; var croco = new TreeViewItem { id = 8, displayName = "Crocodile" }; var lizard = new TreeViewItem { id = 9, displayName = "Lizard" }; root.AddChild(animals); animals.AddChild(mammals); animals.AddChild(reptiles); mammals.AddChild(tiger); mammals.AddChild(elephant); mammals.AddChild(okapi); mammals.AddChild(armadillo); reptiles.AddChild(croco); reptiles.AddChild(lizard); SetupDepthsFromParentsAndChildren(root); return root; }
TreeViewWindow : EditorWindow实现方法¶
- 序列化TreeViewState
- 实现重载的树结构
- 检查是否已经存在序列化视图状态
- OnGUI展示树结构
- 添加到菜单栏
class SimpleTreeViewWindow : EditorWindow { // SerializeField 用于确保将视图状态写入窗口 // 布局文件。这意味着只要窗口未关闭,即使重新启动 Unity,也会保持 // 状态。如果省略该属性,仍然会序列化/反序列化状态。 [SerializeField] TreeViewState m_TreeViewState; //TreeView 不可序列化,因此应该通过树数据对其进行重建。 SimpleTreeView m_SimpleTreeView; void OnEnable() { //检查是否已存在序列化视图状态(在程序集重新加载后 // 仍然存在的状态) if (m_TreeViewState == null) m_TreeViewState = new TreeViewState(); m_SimpleTreeView = new SimpleTreeView(m_TreeViewState); } void OnGUI() { m_SimpleTreeView.OnGUI(new Rect(0, 0, position.width, position.height)); } // 将名为 "My Window" 的菜单添加到 Window 菜单 [MenuItem("TreeView Examples/Simple Tree Window")] static void ShowWindow() { // 获取现有打开的窗口;如果没有,则新建一个窗口: var window = GetWindow<SimpleTreeViewWindow>(); window.titleContent = new GUIContent("My Window"); window.Show(); } }