拓展編輯器 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

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