Unity

UnityEditorWindowでサムネイル付ボタンをタイル状に並べる

環境

Unity 2018.1.0f2

はじめに

複数のデザイナーさん向けにUnityEditorのツールを作る機会がありました。
機能の一部にキャラクターのポーズを切り替えるというものがあったのですが、ポーズを文言化しても共通認識しづらいね...となったのでサムネイルで表示することにしました。
また、ポーズの数が多く、今後も追加されることが予想されたので一覧をタイル状に並べて確認できるものが良いと考えました。
実装するにあたって下記が分からなかったので切り出してまとめておきます。
・ボタンにサムネイルを表示するには?
・ボタンをタイル状に並べるには?

先にまとめ

タイルボタン.gif

▽github - unityEditorTileArrangement
https://github.com/panti310/unityEditorTileArrangement
自由にいじっくてください!

解説

windowの作成とレイアウトに関して

そもそもeditorWindowの作り方を知らなかったので下記を参考にしました。
▽ケットシーウェア - 【エディタ拡張徹底解説】初級編①:ウィンドウを自作してみよう【Unity】
https://caitsithware.com/wordpress/archives/1377
Window作成からLayout全般まで丁寧に解説されています。

ボタンにサムネイルを貼る

サムネイルを読み込む

サムネイル画像は「Assets/Editor Default Resources」に配置し、EditorGUIUtility.Loadで読み込みます。
▽エディター拡張入門 - 第1章 エディター拡張で使用するフォルダー
https://anchan828.github.io/editor-manual/web/part2-beginner.html#h1-2
Editor用のリソースについて参考にしました。

毎フレーム読み込まないように、初期化のタイミングでキャッシュしておくと良いです。

    void Preload ()
    {
        m_default_tex = EditorGUIUtility.Load (Default_Icon_Path) as Texture2D;
        SetTexCacheDict (Sample_Icon_Root_Path, Sample_Icon_Extension, Button_Num);
    }

ボタンに貼る

GUILayout.Buttonに上記TextureをセットすればOKでした。
▽Unity - GUILayout.Button
https://docs.unity3d.com/ja/current/ScriptReference/GUILayout.Button.html

タイル状に並べる

まずは横に並べる

EditorGUILayout.BeginHorizontal ();
// この間に記載した要素が横に並ぶ
EditorGUILayout.EndHorizontal ();

スクリーンショット 2018-08-04 13.24.47.png

次に縦に並べる

EditorGUILayout.BeginVertical ();
// この間に記載した要素が縦に並ぶ
EditorGUILayout.EndVertical ();

スクリーンショット 2018-08-04 13.25.00.png

横の要素数をwindowの幅から計算する

windowの幅を超えない数分のボタンを描画し、それらをEditorGUILayoutのHorizontalで囲むという処理を作りました。
スクリーンショット 2018-08-04 13.25.13.png
以下に処理を抜粋しときます。

    void DrawThumbnailButtons (int itemNum, System.Action<int> onClick, string rootPath, string extension)
    {
        // 横の要素数求める
        float windowWidth = position.width;
        int horizontalMaxNumber = Mathf.FloorToInt (windowWidth / (m_buttonSize + Button_Margin));

        bool inHorizontalLayout = false;
        for (int i = 0; i < itemNum; i++) {
            if (i % horizontalMaxNumber == 0) {
                // 横レイアウト開始
                EditorGUILayout.BeginHorizontal ();
                inHorizontalLayout = true;
            }

            // ボタン作る処理とか

            if (i % horizontalMaxNumber == horizontalMaxNumber - 1) {
                // 横レイアウト終了
                EditorGUILayout.EndHorizontal ();
                inHorizontalLayout = false;
            }
        }

        if (inHorizontalLayout) {
            // horizontalMaxNumber ちょうどの数以外だと横レイアウト開きっぱなしになる
            // その際はここで横レイアウト終了
            EditorGUILayout.EndHorizontal ();
        }
    }

さいごに

言葉で表現しづらいものを大量にボタン化する際に是非使ってみて下さい。
タイル状レイアウトぐらいデフォルトであれば良いのになぁ...。

▽アイコン素材 - FLAT ICON DESIGN
http://flat-icon-design.com/
サンプルにもってこいなアイコンがたくさんあります。