【Unity】【エディタ拡張】EditorWindowをモーダルやポップアップなどとして開く方法まとめ

Unityのエディタ拡張でEditorWindowをモーダルやポップアップなどとして開く方法についてまとめました。

Unity2020.1.17f1

はじめに

EditorWindowの派生クラスを作成して以下のように記述することで自作のエディタウィンドウを表示することができます。

using UnityEditor;
using UnityEngine;

public sealed class ExampleEditorWindow : EditorWindow
{
    [MenuItem("Window/Example/Window")]
    private static void Window()
    {
        var window = GetWindow<ExampleEditorWindow>();
        window.Show();
    }
}

EditorWindow

さてエディタウィンドウは、呼び出し方を変えることで、モーダルやポップアップなどとして表示することができます。

ポップアップの例

本記事ではこの方法についてまとめます。

一覧表

EditorWindowには自身を開くためのメソッドがいくつか定義されており、これにより上述の表示方法が変わります。
まず以下にそれらのメソッド名と簡単な説明をまとめ、次節以降で各メソッドについて細かくまとめます。

メソッド名 説明
ShowModal モーダルとして開く
閉じるまで他のエディタのインタラクションをブロック
ShowUtility ユーティリティとして開く
常に前面に表示される
ShowModalUtility モーダルユーティリティとして開く
モーダルと同じ?
ShowAuxWindow 補助ウィンドウとして開く
フォーカスが外れると閉じる
ShowAsDropDown ドロップダウンのように枠がなくドラッグ不可
フォーカスが外れると閉じる
ShowPopup ポップアップのように枠がなくドラッグ不可
フォーカスが外れても閉じない

ShowModal

ShowModal メソッドを使うとエディタウィンドウをモーダルとして開くことができます。

モーダルとは、最前面に表示され、自身以外のインタラクションをブロックするウィンドウのことです。
つまりこれを表示している時にはこのウィンドウ以外を操作することができなくなります。
さらに、表示中はスクリプトが更新されてもコンパイルが走らなくなります。
またアニメーション付きで開かれます。

モーダル

モーダルを開くコードの例は以下の通りです。
通常のエディタウィンドウを開く際にはGetWindow()を使いますが、以下ではCreateInstance()を使っている点に注意してください。

using UnityEditor;
using UnityEngine;

public sealed class ExampleEditorWindow : EditorWindow
{

    [MenuItem("Window/Example/Show Modal")]
    private static void Modal()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowModal();
    }
}

ShowUtility

ShowUtility メソッドを使うとエディタウィンドウをユーティリティウィンドウとして開くことができます。

ユーティリティウィンドウは、常に最前面に表示されますが、モーダルのようにインタラクションをブロックしません。
他のウィンドウにフォーカスが当たった時に後ろに回り込ませたくないものに使用します。

ユーティリティウィンドウ

ユーティリティウィンドウを開くコードの例は以下の通りです。

using UnityEditor;
using UnityEngine;

public sealed class ExampleEditorWindow : EditorWindow
{

    [MenuItem("Window/Example/Show Utility")]
    private static void Utility()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowUtility();
    }
}

ShowModalUtility

ShowModalUtility メソッドはユーティリティウィンドウをモーダルとして開きます。
...とのことですが、ShowModal との違いがいまいちわかりません。 (ユーティリティウィンドウの「常に最前面に表示」という性質はそもそもモーダルに包括されるものなので)

もしかしたら何か違いがあるのかもしれないので、わかったら追記します。

ShowAuxWindow

ShowAuxWindow メソッドを使うとエディタウィンドウを補助ウィンドウとして開くことができます。

補助ウィンドウは通常のウィンドウのように表示されますが、
補助ウィンドウ以外の箇所をクリックすると自動で閉じられます。
組み込みのカラーピッカー(ColorをInspectorからクリックすると開かれるウィンドウ)などに使用されています。

補助ウィンドウ

補助ウィンドウを開くコードの例は以下の通りです。

using UnityEditor;
using UnityEngine;

public sealed class ExampleEditorWindow : EditorWindow
{
    [MenuItem("Window/Example/Show Aux Window")]
    private static void AuxWindow()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowAuxWindow();
    }
}

ShowAsDropDown

ShowAsDropDown メソッドを使うとエディタウィンドウをドロップダウンのスタイルで開くことができます。

見た目としてはウィンドウの枠がなく、ドラッグすることはできません。 またフォーカスが外れると自動で閉じられます。
また、画面端などでウィンドウが隠れそうな場合にはよしなに位置を調整してくれます。

ドロップダウン

ドロップダウンを開くコードの例は後述のサンプルコードの節を参照してください。

Popup メソッドを使うとエディタウィンドウをポップアップのスタイルで開くことができます。

見た目としてはウィンドウの枠がなく、ドラッグすることはできません。
ドロップダウンとは違いフォーカスが外れても閉じられません。
また、画面端などでウィンドウが隠れそうな場合にはよしなに位置を調整してくれます。

ポップアップ

なおこれはあくまでポップアップ風のスタイルを適用するだけのものです。
本来ポップアップはフォーカスが外れたら閉じられたりする機能が必要です。
そのようにポップアップを実装したい場合には PopupWindow を使うべきです。

ポップアップを開くコードの例は後述のサンプルコードの節を参照してください。

サンプルコード

最後に今回紹介したウィンドウを一通り開けるようにしたサンプルコードを記載します。

using UnityEditor;
using UnityEngine;

public sealed class ExampleEditorWindow : EditorWindow
{
    private Rect _dropDownButtonRect;
    private Rect _popupButtonRect;

    private void OnGUI()
    {
        GUILayout.Label("Example Editor Window");

        if (GUILayout.Button("Close"))
            Close();

        // DropDown
        if (GUILayout.Button("Show As Dropdown"))
        {
            var popupPosition = GUIUtility.GUIToScreenPoint(_dropDownButtonRect.center);
            var window = CreateInstance<ExampleEditorWindow>();
            var windowSize = new Vector2(200, 100);
            window.ShowAsDropDown(new Rect(popupPosition, Vector2.zero), windowSize);
        }

        if (Event.current.type == EventType.Repaint) _dropDownButtonRect = GUILayoutUtility.GetLastRect();

        // Popup
        if (GUILayout.Button("Show Popup"))
        {
            // Stylingだけ
            var popupPosition = GUIUtility.GUIToScreenPoint(_popupButtonRect.center);
            var window = CreateInstance<ExampleEditorWindow>();
            window.position = new Rect(popupPosition, new Vector2(200, 100));
            window.ShowPopup();
        }

        if (Event.current.type == EventType.Repaint) _popupButtonRect = GUILayoutUtility.GetLastRect();
    }

    [MenuItem("Window/Example/Window")]
    private static void Window()
    {
        var window = GetWindow<ExampleEditorWindow>();
        window.Show();
    }

    [MenuItem("Window/Example/Show Modal")]
    private static void Modal()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowModal();
    }

    [MenuItem("Window/Example/Show Utility")]
    private static void Utility()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowUtility();
    }

    [MenuItem("Window/Example/Show Modal Utility")]
    private static void ModalUtility()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowModalUtility();
    }

    [MenuItem("Window/Example/Show Aux Window")]
    private static void AuxWindow()
    {
        var window = CreateInstance<ExampleEditorWindow>();
        window.ShowAuxWindow();
    }
}

参考

docs.unity3d.com

docs.unity3d.com

docs.unity3d.com

docs.unity3d.com

docs.unity3d.com