
目次
※この記事で使用しているUnrealのVersionは04.25.0 Preview6です。
※この記事のサンプルプロジェクトは以下URLにアップされています。
UE4.24からしれっとエディター上のメニューを作成できる機能を追加されているのに気が付きました。
エディターのメニューを追加したりするのは、「Slate使わないといけないんでしょ…」と自分もやろうと思っていませんでした。
エディター拡張において大変有効的な機能だと思いますので、是非皆さんも参考にしてみてください。
Blueprintだけで、Editor上にメニューを追加する レベル【★★★】
まずは、メニューを登録する処理を書くためのBlueprintを用意します。
今回は、「Editor Utility Bluepirnt」を使います。
Content Browser左上の「Add New」から「Editor Utilities」→「Editor Utility Blueprint」を選択してください。

そして、出てきたウィンドウから「Editor Utility Object」を選択し「Select」を押します。

作成したアセットは適当に名前を付けましょう。
そして、Editor Utility BlueprintをダブルクリックしてGraph Editorを開きます。
では、処理を書く前にメニューを作る際のポイントをご紹介します。
メニューを管理しているのは、「Tool Menus」というインスタンスです。
Tool Menusは、「Get」という関数で取得できます。

この関数で取得できるObjectには、Editor内の様々なMenuの情報が格納されています。
このObjectから「Extend Menu」という関数を呼び出すことで、メニューの名前を指定することで、各種の「Tool Menu」Objectを取得できます。
(Tool Menusとは別物です)

そして、メニューの名前ですが、Engineの実装を見るのが速いですが、ソース見るたりできない人でも、手っ取り早く調べる方法があります。
それは、「Editor Utility Widget」を作成し、「Details View」に↑のGet関数で取得したObjectを登録することで、そのObjectが保有している「Menus」という連想配列を確認できます。
①Editor Utility Widgetを作成

②Details Viewをウィジェットに配置

※その際、Details Viewを選択した状態で「Details」ウィンドウ内にある「Force Hidden Property Visible」にチェックを入れます。

③Details Viewに「Get」関数で取得したObjectを登録する

④Editor Utility Widget を起動する(Editor Utility Widgetを右クリック→Run Editor Utility Widget)

これで、Tools MenusにあるMenuの名前を確認するためのWindowができました。

まあ、わかったところで何がどのメニューなのかはいまいちわかりづらいので、
いくつかは以下に紹介しておきます。
名前 | 用途 |
ContentBrowser.AssetContextMenu | Content Browser上のアセットを右クリックした際に出てくるメニュー |
ContentBrowser.FolderContextMenu | Content Browser上のフォルダーを右クリックした際に出てくるメニュー |
LevelEditor.ActorContextMenu | レベル上のアクターを右クリックした際に出るメニュー |
LevelEditor.LevelEditorToolBar | Toolbar内のメニュー |
MainFrame.MainMenu.File | Editor左上の「File」内のメニュー |
GraphEditor.GraphContextMenu.Common | BlueprintGraphで、ノードを右クリックした際のメニュー |
などなど、他にもたくさんあります。
では、これらを踏まえてまずは
アセットを右クリックした際のメニューに独自のものを追加してみたいと思います。
先ほど作成したEditor Utility Blueprintをダブルクリックし、GraphEditorを開きましょう。
そして、以下のようにBlueprintを書いていきます。

さて、Extend Menu以降のノードを説明しますと、
「Construct Object from class」ノードは、あらかじめもう一つのEditor Utility Blueprintクラス(同じくParentはObject)を作成し、そのクラスを指定しています。
そのEditor Utility Blueprintの処理は以下になります。

単に、Runが実行されるとPrint Stringが呼ばれるだけのものとなっています。
次に「Init Menu Entry」という関数は、「Tool Menu Entry」構造体を生成するために使用します。パラメータの意味は以下になります。
Construct Object from Classで生成したObjectのPathをString
名前 | 用途 |
InOwner | 親となるTool Menuの名前を指定します。(特になくても問題ない) |
InName | 登録するメニューのプログラム上の名前を設定します。 |
InLabel | メニューとして表示される際の名前を指定します。 |
InToolTip | メニューにカーソルが合った際にポップするテキストを指定します。 |
CommandType | コマンドの種類を指定します。 Command=ConsoleCommandが走る Python=Pythonの命令が走る Custom=BP上では使っても意味がない(TypeをCustomCommandTypeで指定するようになる) |
CustomCommandType | CommandTypeがCustomの場合に、Name指定でCommandTypeを指定する。 |
CommandString | 実行する命令を書く |
今回は、CommandStringで実行するコマンドに「KE 」コマンドを使いました。KE [ObjectのPath] [Event名]で、 Object内に登録されているイベントを
名前指定で呼び出すことができます。
詳しくは 【UE4】ConsoleCommand「CE,KE」について【★★☆】 をご覧ください。
そして、「Add Menu Entry」ノードで、生成した構造体をTool Menuに登録します。
その際のSection Nameは特に必要ありませんが、メニューのボタンを配置する場所を変える際には、Sectionを指定してあげる必要があります(後述)
最後に「Refresh All Widget」ノードで、登録したメニューを表示するために初期化しています。
こんな感じで、少ないノード数ですが準備は整いました。
Content Browser上で、このEditor Utility Blueprintを右クリックして、「Run Editor Utility Blueprint」を選択すると、メニューが登録され独自のメニューが表示されるようになります。
すごいお手軽!!やったね!
さて、先ほどAdd Menu Entryの説明でも書きましたが、「Section Name」で任意のSectionを指定することで、Menuのボタンを表示する場所を変えることができたりします。
SectionNameはEngineの実装を見るのが速いですが、ひとまず今回はメニュー内の「Common」の羅列内にメニューを追加したいと思います。
先ほど実装したEditor Utility Blueprintを再び開いて、「Add Menu Entry」ノードの「Section Name」を「CommonAssetActions」としてみましょう。

そしてコンパイルしたら再び「Run Editor Utility Blueprint」を実行すると、以下のようにCommonの羅列にメニューを追加できたと思います。

また、SectionNameを「GetAssetActions」とすると、メニュー一上部に表示したりもできます。

さて、ここまで全部やっていると気づくかもしれませんが、
メニューは登録するたびに増えていきます。(3つに増えたExecute Test Script)

登録したMenuを消すには、Tool Menusから「Remove Menu Entry」という関数を呼び出します。

もしくはEditorを一度落とせばメニューはすべてなくなり、初期状態に戻ります。
もし、Editor起動した瞬間からメニューが登録されててほしい場合は、 DefaultEditorPerProjectUserSettings.ini のStartupObjectを使うといいかと思います。
参考ドキュメント:
エディタの起動時にブループリントを実行する
もしくは、PythonのStartupScriptを使用する手もあります。
参考ドキュメント:
Python を使用したエディタのスクリプティング
次に、もう少しだけ頑張って「Sub Menu」も作っちゃいたいと思います。
Sub Menuとは、「Asset Actions」など、メニューにカーソルを合わせた際に新たなメニューが出てきたりするようなメニューの事です。
↓みたいなやつ

Editor Utility Blueprintに少し処理を追加します。

追加したのは、「Add Sub Menu Script」というノードだけ。
Construct ObjectやAdd Menu Entryのターゲットを、Add Sub Menu Scriptで生成したTool Menu Objectに変えています。
設定する項目は、Command系のプロパティがないだけで、基本的にはInit Menu Entryと同じです。
これを実行すると、以下のようになります。

こんな感じで、メニューの中にメニューを作れました。
ちなみに、Addする先を「MainFrame.MainMenu」にすると以下のようになったりします。
このように、Tool Menusを使うとエディター上のメニューを独自に超簡単に作成できてしまいます(もうSlateなんて触らなくていいのです)
みなさん是非自分の開発しているプロジェクトで有効活用してください!
以上となります。
※この記事のサンプルプロジェクトは以下URLにアップされています。