目录
需求描述
现在有这样一个需求:
- 在Hierarchy面板的对象上绘制按钮
- 点击按钮,弹出菜单
- 再点击菜单项目响应自定义操作
- 在这里的响应主要是复制对象层级路路径
看具体效果请看动图:
注:
- 核心是对EditorApplication.hierarchyWindowItemOnGUI委托的实现
- 其它需求,可参考实现
- 如是要要Project面板实现类似的功能:可以参考实现EditorApplication.hierarchyWindowItemOnGUI委托
上代码
csharp
/**********************************************
* @author: anyuanlzh
* @date: 2023-05-18
* @des: "Hierarchy面板"工具
***********************************************/
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class HierarchyTabTool
{
// 静态构造函数
static HierarchyTabTool()
{
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
}
private static void HierarchyWindowItemOnGUI(int instanceId, Rect selectionRect)
{
var obj = EditorUtility.InstanceIDToObject(instanceId) as GameObject;
if (obj == null)return;
GameObject selectedObjs = Selection.activeGameObject;
if(obj!=selectedObjs)return;
selectionRect.x += selectionRect.width - 60;
selectionRect.y += 0;
selectionRect.width = 60f;
GUIStyle fontStyle = new GUIStyle(GUI.skin.button);
fontStyle.alignment=TextAnchor.MiddleCenter;
fontStyle.fontSize=10;
fontStyle.normal.textColor=Color.yellow;
//点击事件
if (GUI.Button(selectionRect, "复制层级", fontStyle))
{
// Debug.Log($"click: {Selection.activeObject.name}");
// 弹出菜单
Vector2 mousePosition = Event.current.mousePosition;
Rect position = new Rect(mousePosition.x, mousePosition.y+7, 0, 0);
EditorUtility.DisplayPopupMenu(position, "GameObject/1_复制层级路径", null);
}
}
// 防止一次点击响应多次
private static float _last_call_time = 0;
private static float minInterval_time = 0.5f;
[MenuItem("GameObject/1_复制层级路径/A点~B点", false, 40)]
private static void GetHierarchyPath2()
{
if (Time.time - _last_call_time<minInterval_time)
{
return;
}
_last_call_time = Time.time;
GameObject[] selectedObjs = Selection.gameObjects;
//Debug.Log(selectedObjs.Length);
if (selectedObjs.Length == 1)
{
Copy_HierarchyPath_root2target();
return;
}
else if (selectedObjs.Length < 2)
{
Debug.Log("请选择一个或二个有包含关系对象");
return;
}
Transform first = selectedObjs[0].transform;
Transform last = selectedObjs[selectedObjs.Length-1].transform;
// Debug.Log($"first.name:{first.name} last.name:{last.name}");
Transform a = null;
Transform b = null;
if (EditorUtils.IsAncestor(first, last))
{
a = first;
b = last;
}
else if (EditorUtils.IsAncestor(last, first))
{
a = last;
b = first;
}
else
{
Debug.LogError("请选择有包含关系的二个对象");
return;
}
List<string> names = new List<string>();
while (b!=null)
{
if (a == b)
{
names.Insert(0,b.name);
break;
}
names.Insert(0, b.name);
b = b.parent;
}
string path = "";
for (int i = 0; i < names.Count-1; i++)
{
path += names[i] + "/";
}
path += names[^1];
GUIUtility.systemCopyBuffer = path;
Debug.Log("对象层次路径 A点到B点: " + path);
}
[MenuItem("GameObject/1_复制层级路径/根0~目标", false, 40)]
private static void Copy_HierarchyPath_root0target()
{
Copy_HierarchyPath_rootN2target(0);
}
[MenuItem("GameObject/1_复制层级路径/根1~目标", false, 40)]
private static void Copy_HierarchyPath_root1target()
{
Copy_HierarchyPath_rootN2target(1);
}
[MenuItem("GameObject/1_复制层级路径/根2~目标", false, 40)]
private static void Copy_HierarchyPath_root2target()
{
Copy_HierarchyPath_rootN2target(2);
}
[MenuItem("GameObject/1_复制层级路径/根3~目标", false, 40)]
private static void Copy_HierarchyPath_root3target()
{
Copy_HierarchyPath_rootN2target(3);
}
// 从根0的第N级到目标
// rootN从零开
static void Copy_HierarchyPath_rootN2target(int rootN)
{
if (Time.time - _last_call_time<minInterval_time)
{
return;
}
_last_call_time = Time.time;
if (Selection.count != 1)
{
Debug.LogError($"Copy_HierarchyPath_rootN2target: 请选择一个对象");
return;
}
Transform target = Selection.activeGameObject.transform;
List<string> names = new List<string>();
Transform parent = target.transform.parent;
while (target != null)
{
names.Insert(0, target.name);
target = target.parent;
}
if (names.Count - 1 < rootN)
{
Debug.LogError($"Copy_HierarchyPath_rootN2target: N:{rootN}大于目标对象的深度");
return;
}
string path = "";
for (int i = rootN; i < names.Count-1; i++)
{
path += names[i] + "/";
}
path += names[^1];
GUIUtility.systemCopyBuffer = path;
Debug.Log($"对象层次路径 root_{rootN}到target:" + path);
}
}