拓展编辑器 4 - InspectorWindow

关键概念

  • [CustomEditor typeof(ComponentType)]: 修饰,指定派生自Editor 的类为 ComponentType 类型的编辑器控制类。
  • Editor : 派生改类,为 object 实现自定义的 Inspector 或 editor 界面。
  • Editor.OnInspectorGUI : 覆写 Inspector 绘制
  • GUILayout.Button : 创建按钮,与 GUI 相比,多了 Layout 功能。
  • GUI.enabled : 指定后面的 UI 是否可以交互。
  • Object.hideFlag : 位掩码,控制 Inspect 上 Object 的销毁,保存,可见性等。
  • 组件小齿轮菜单 : [MenuItem(“CONTEXT/Transform/XXX”)]。
  • UnityEditor.EditorApplication.delay : 下一帧调用
  • Object.DestroyImmediate(Objeect) : 立即删除一个对象,比如组件。

例子

using System;
using System.Reflection;
using UnityEngine;
using UnityEditor;

/// <summary>
/// 扩展 Camera 组件面板
/// </summary>
[CustomEditor(typeof(Camera))]
public class CameraInspectorExtend : Editor
{
    public override void OnInspectorGUI()
    {
        if(GUILayout.Button("My Button"))
        {
            Debug.Log("My Buffon");
        }
        base.OnInspectorGUI();
    }
}

/// <summary>
/// 利用反射扩展组件面板
/// Transform 的扩展不是必须用反射,这里仅是举例
/// </summary>
[CustomEditor(typeof(Transform))]
public class TransformView : Editor
{
    private Editor m_Editor;

    private void OnEnable()
    {
        // 利用反射从dll中拿到编辑面板类型,并创建
        Type transEditorType = Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.TransformInspector", true);
        m_Editor = Editor.CreateEditor(target, transEditorType);
    }

    public override void OnInspectorGUI()
    {
        if(GUILayout.Button("My Button"))
        {
            Debug.Log("Click my button");
        }

        m_Editor.OnInspectorGUI();
        //base.OnInspectorGUI();
    }
}


/// <summary>
/// 控制组件是否可以编辑
/// </summary>
[CustomEditor(typeof(MyBehaviourScript))]
public class MyBehaviourView : Editor
{
    public override void OnInspectorGUI()
    {
        MyBehaviourScript cmpt = target as MyBehaviourScript;
        cmpt.enableEdit = GUILayout.Toggle(cmpt.enableEdit, "可编辑");
        // 禁用组件编辑
        GUI.enabled = cmpt.enableEdit;
        base.OnInspectorGUI();
        // 启用组件编辑
        GUI.enabled = true;
        
        // 路径选择面板
        cmpt.folderGameObject = EditorGUILayout.ObjectField("Folder", cmpt.folderGameObject, typeof(Object));
        if(cmpt.folderGameObject)
            cmpt.folder = AssetDatabase.GetAssetPath(cmpt.folderGameObject);
    }
}

/// <summary>
/// 控制选中对象的可编辑开关
/// </summary>
public class InspectorEditableCtrl
{
    [MenuItem("GameObject/3D Object/Lock/Lock", false, 0)]
    static void Lock()
    {
        if(Selection.gameObjects != null)
        {
            foreach(GameObject go in Selection.gameObjects)
            {
                go.hideFlags = HideFlags.NotEditable;
            }
        }
    }

    [MenuItem("GameObject/3D Object/Lock/Unlock", false, 0)]
    static void Unlock()
    {
        if (Selection.gameObjects != null)
        {
            foreach (GameObject go in Selection.gameObjects)
            {
                go.hideFlags = HideFlags.None;
            }
        }
    }
}

/// <summary>
/// 扩展组件 小齿轮 菜单栏
/// CONTEXT 必须用大写
/// 格式:[MenuItem("CONTEXT/组件类名/XXX")]
/// </summary>
public class InspectorContextExtend
{
    /// <summary>
    /// 扩展 Transform
    /// </summary>
    /// <param name="cmd"></param>
    [MenuItem("CONTEXT/Transform/My 1")]
    static void MyTransfor1(MenuCommand cmd)
    {
        Debug.Log("Context: " + cmd.context.name);
    }

    /// <summary>
    /// 扩展 MyBehaviourScript
    /// </summary>
    /// <param name="cmd"></param>
    [MenuItem("CONTEXT/MyBehaviourScript/My 1")]
    static void MyTransfor2(MenuCommand cmd)
    {
        Debug.Log("Context: " + cmd.context.name);
    }
}

更复杂的绘制例子

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif


public class MyMono1 : MonoBehaviour
{
    public enum EType
    {
        A,
        B
    }

    public Vector2 mScrollPos;
    public int mID;
    public string mName;
    public GameObject mObject;
    public EType mEnum;
    public bool mToggleA;
    public bool mToggleB;
}

#if UNITY_EDITOR

[CustomEditor(typeof(MyMono1))]
public class MyMono1Editor : Editor
{
    private bool mEnableToggle;
    
    /// 添加小齿轮菜单
    [ContextMenu("Remove Component")]
    void RemoveComponent()
    {
        Debug.Log("Remove " + GetType().ToString());
        // 下一帧调用
        UnityEditor.EditorApplication.delayCall += ()=> 
        {
            DestroyImmediate(this);
        };
        
    }
    
    public override void OnInspectorGUI()
    {
        //base.OnInspectorGUI();

        MyMono1 sc = target as MyMono1;

        sc.mScrollPos = EditorGUILayout.BeginScrollView(sc.mScrollPos, false, true);

        sc.mName = EditorGUILayout.TextField("Name", sc.mName);
        sc.mID = EditorGUILayout.IntField("ID", sc.mID);
        sc.mObject = EditorGUILayout.ObjectField("Object", sc.mObject, typeof(GameObject), true) as GameObject;

        EditorGUILayout.BeginHorizontal();
        if(GUILayout.Button("A"))
        {
            Debug.Log("MyMono click A");
        }
        if (GUILayout.Button("B"))
        {
            Debug.Log("MyMono click B");
        }
        sc.mEnum = (MyMono1.EType)EditorGUILayout.EnumPopup("Enum", sc.mEnum);
        EditorGUILayout.EndHorizontal();

        mEnableToggle = EditorGUILayout.BeginToggleGroup("toggle", mEnableToggle);
        sc.mToggleA = EditorGUILayout.Toggle("A", sc.mToggleA);
        sc.mToggleB = EditorGUILayout.Toggle("B", sc.mToggleB);
        EditorGUILayout.EndToggleGroup();

        EditorGUILayout.EndScrollView();
    }
}

#endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章