エンジニアっぽくなりたい

UnityやUnrealEngine 4などでなにか役に立ちそうなことを発信していく。

UE4シーケンサーのメニューに項目を追加したい(1)

目標


UE4シーケンサーのエディター拡張を行い、メニューの項目を追加してシーケンサーに対して独自の処理を行うための入り口を作りたい。
※エンジン改造はしません。
今回はシーケンサーツールバーにメニューを追加する方法になります。
具体的には以下の画像の箇所

f:id:naoxgames:20210214181503p:plain
シーケンサーツールバー


環境

・UE 4.26.1 (エンジンビルドはしていません)
・VisualStudio 2019 16.7.2

やってみる

作戦としてはシーケンサーツールバー部分のコードを参考に、似た処理を行うプラグインを作成していきます。

UIの拡張点の表示

まずはエディター拡張する部分の拡張点を知る必要があります。
UE4エディターの[編集]→[エディタの環境設定]をクリックし、以下の画像のように[UIの拡張点の表示]にチェックを入れます。

f:id:naoxgames:20210214184933p:plain
UIの拡張点の表示

その後エディターを再起動します。
すると、エディターの各所に緑色の文字が表示されるようになっていると思います。
今回対応したいシーケンサーツールバーでは以下のように表示されています。
f:id:naoxgames:20210214185901p:plain
ツールバー拡張点

「Level Sequence Separator」ということがわかりました。

エンジンから類似処理を探す

「Level Sequence Separator」でエンジンのコードを検索すると、SSequencer.cppで使われていることがわかります。
その直後に処理されているものが名前からしシーケンサーツールバーメニューのようですので、そのあたりを参考に対応してみます。(正確に確認したい場合はエンジンでこの部分を変更してみると変化が確認できます。)
※エンジン改造で問題ない場合はこのまま他のメニュー処理と同様の処理を記述することで対応できます。

プラグインでメニュー追加

今回はエンジン改造ではなくプラグインで対応をしてみます。
UE4エディターの[編集]→[プラグイン]→[新しいプラグイン]を選択してプラグインを作成します。
ひとまず今回の用途に近い「エディタツールバーのボタン」を元にして作成してみます。
当記事で説明するプラグイン名は「SequenceExtensionEd」とします。

モジュール設定

SequenceExtensionEd.Build.csに以下を追加します。
・Sequencer・・・・ISequencerModuleへのアクセス
・EditorStyle・・・・シーケンサーで使われている既存のアイコン使用のため(不要であれば削除)

~
        PrivateDependencyModuleNames.AddRange(
            new string[]
            {
                ~
                "Sequencer",
                "EditorStyle",
            }
            );
~


シーケンサーモジュールに拡張メニュー追加

エンジンから類似処理を探した際に処理を行っていたSSequencer::MakeToolBar()を見てみると、SequencerModuleを取得し、SequencerModule.GetToolBarExtensibilityManager()->GetAllExtenders()という処理で取得したものをツールバーに追加しています。
プラグインからも同様にSequencerModuleを取得してみると、GetToolBarExtensibilityManager()->AddExtenderという処理があります。ここに処理を追加できればツールバーに登録してくれそうです。

以下のようにStartupModuleでSequencerModuleを取得し、FExtenderのAddToolBarExtensionに追加するメニューを設定します。
今回は追加したメニューを選択したときにダイアログを表示する処理にしてみます。

SequenceExtensionEd.cpp

~
#include "Sequencer/Public/ISequencerModule.h"
~
void FSequencerExtensionEdModule::StartupModule()
{
    ~
    TSharedPtr<FUICommandList> ToolbarCommands = MakeShareable(new FUICommandList);
    ISequencerModule& SequencerModule = FModuleManager::GetModuleChecked<ISequencerModule>("Sequencer");
    ToolBarExtender = MakeShareable(new FExtender);
    ToolBarExtender->AddToolBarExtension(
        "Level Sequence Separator",
        EExtensionHook::After,
        ToolbarCommands,
        FToolBarExtensionDelegate::CreateRaw(this, &FSequencerExtensionEdModule::AddToolBarExtention)
    );
    SequencerModule.GetToolBarExtensibilityManager()->AddExtender(ToolBarExtender);
    ~
}

void FSequencerExtensionEdModule::AddToolBarExtention(FToolBarBuilder& ToolBarBuilder)
{
    ToolBarBuilder.AddComboButton(
        FUIAction(),
        FOnGetContent::CreateRaw(this, &FSequencerExtensionEdModule::MakeToolbarExtensionMenu),
        LOCTEXT("SequencerExtension", "ToolBarExtension"),
        LOCTEXT("SequencerExtension", "ToolBarExtension"),
        FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.Actions"),   //仮でアクションと同じアイコン
        false);
}

TSharedRef<class SWidget> FSequencerExtensionEdModule::MakeToolbarExtensionMenu()
{
    FMenuBuilder MenuBuilder(true, MakeShareable(new FUICommandList));
    MenuBuilder.BeginSection("SequencerToolBarExtension");

    MenuBuilder.AddMenuEntry(
        LOCTEXT("SequencerExtension", "ToolBarMenu"),
        LOCTEXT("SequencerExtension", "ToolBarMenu"),
        FSlateIcon(FEditorStyle::GetStyleSetName(), "Sequencer.Actions"),
        FUIAction(FExecuteAction::CreateLambda(
            []()
            {
                FText DialogText = FText::FromString("ToolBarMenuExtension");
                FMessageDialog::Open(EAppMsgType::Ok, DialogText);  //メニューを選択したらダイアログを表示
            }
    )));

    MenuBuilder.EndSection();

    return MenuBuilder.MakeWidget();
}

SequenceExtensionEd.h

    void AddToolBarExtention(FToolBarBuilder& ToolBarBuilder);
    TSharedRef<class SWidget> MakeToolbarExtensionMenu();

    TSharedPtr<class FExtender> ToolBarExtender;


実行!!!!

f:id:naoxgames:20210214210134p:plain
拡張メニュー

f:id:naoxgames:20210214210029p:plain
ダイアログ

シーケンサーツールバーに項目が指定した名前・アイコンで追加され、ダイアログが表示されました。

思ったこと

UE4案件はなんだかエンジン改造しないとダメ的な空気感が強い印象がありますが、やりようによってはプラグインで吸収できる箇所もそこそこありそうですね。(どうしようもないことも多々ありますが!!!)
エディター拡張をする分には、エンジンのコードを参考にすればなんとかなるものが多いと思われます。


ここまでの内容は以下のリポジトリに上げてあります。 github.com

この記事の続き
naoxgames.hatenablog.jp

正しい対応方法やより良い方法があればご指摘お願いいたします!!!