🌄

【UE5】C++でコンテンツブラウザにあるEditorUtilityWidgetを読み込んで実行させる

2024/12/02に公開

概要

この記事は一人アドベントカレンダー by ダリアの2日目の記事です。

今回はC++でEditorUtilityWidgetを読み込んで表示と実行させるやり方をまとめたものです。
今回想定しているイメージとしては以下のように好きな場所(自分の場合はメニュー)から呼べるようにするのを想定してます。
https://x.com/daria_nicht/status/1855543820274061667

環境

UE5.4.4

やり方

モジュールにUMGEditorEditorScriptingUtilitiesBlutilityUnrealEdを追加します。

using UnrealBuildTool;

public class DebugSystemsEditor : ModuleRules
{
    public DebugSystemsEditor(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(
            new string[]
            {
                "Core",
            }
        );

        PrivateDependencyModuleNames.AddRange(
            new string[]
            {
                "CoreUObject",
                "Engine",
                "Slate",
                "SlateCore",
 +              "UMGEditor",
 +              "EditorScriptingUtilities",
 +              "Blutility",
 +              "UnrealEd"
            }
        );
    }
}

次に以下のような処理を書きます。

EditorUtilityWidget自体を表示してるのはSpawnAndRegisterTab関数にEditorUtilityWidgetを渡して表示するようにしてます。

+ #include "EditorAssetLibrary.h"
+ #include "EditorUtilitySubsystem.h"
+ #include "EditorUtilityWidgetBlueprint.h"

//省略
//...

{
+   UObject* Blueprint = UEditorAssetLibrary::LoadAsset(FString(TEXT("EditorUtilityWidgetのパス'")));
+   if (IsValid(Blueprint)) 
+   {
+       UEditorUtilityWidgetBlueprint* EditorWidget = Cast<UEditorUtilityWidgetBlueprint>(Blueprint);
+       if (IsValid(EditorWidget)) 
+       {
+           UEditorUtilitySubsystem* EditorUtilitySubsystem = GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>();
+           EditorUtilitySubsystem->SpawnAndRegisterTab(EditorWidget);
+       }
+   }
}

サンプルとして、自分は前回の記事で作ったメニューの中に入れて呼んでいます。

適宜呼ぶ場所は自分の呼びたい場所に変えていただければ幸いです。

ExampleToolMenusExtension.cpp
#include "ExampleToolMenusExtension.h"

#include "ToolMenus.h"
#include "ToolMenuSection.h"
+ #include "EditorAssetLibrary.h"
+ #include "EditorUtilitySubsystem.h"
+ #include "EditorUtilityWidgetBlueprint.h"

#define LOCTEXT_NAMESPACE "ExampleToolMenusExtensionModule"

void FExampleToolMenusExtensionModule::StartupModule()
{
    if (!IsRunningCommandlet() && !IsRunningGame() && FSlateApplication::IsInitialized())
    {
        UToolMenus::Get()->RegisterStartupCallback(FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &ExampleToolMenusExtensionModule::RegisterMenuExtension));
    }
}

void FExampleToolMenusExtensionModule::ShutdownModule()
{
    if (!IsRunningCommandlet() && !IsRunningGame() && !IsRunningDedicatedServer())
    {
        UToolMenus::UnregisterOwner(this);
    }
}

void FExampleToolMenusExtensionModule::RegisterMenuExtension()
{
   UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Tools");
   //専用の項目を作る
   FToolMenuSection& Section = Menu->AddSection("ExampleToolMenusExtension", LOCTEXT("ExampleToolMenusExtension", "ExampleToolMenusExtension"));
   //項目に対して要素を追加する
   Section.AddEntry(FToolMenuEntry::InitMenuEntry(
       "ValidateData",
       //項目名
       TAttribute<FText>::Create(&GetMenuTitle), 
       //ツールチップ
       LOCTEXT("", ""), 
       //アイコン
       FSlateIcon(FAppStyle::GetAppStyleSetName(), "DeveloperTools.MenuIcon"),
       //選択されたときのイベント
       FUIAction(FExecuteAction::CreateStatic(&ExampleToolMenusExtensionModule::ExecuteMenu))
   ));
}

FText FExampleToolMenusExtensionModule::GetMenuTitle()
{
	return LOCTEXT("ExampleToolMenusExtensionModule", "ExampleToolMenusExtension");
}

void FExampleToolMenusExtensionModule::ExecuteMenu()
{
+   UObject* Blueprint = UEditorAssetLibrary::LoadAsset(FString(TEXT("EditorUtilityWidgetのパス'")));
+   if (IsValid(Blueprint)) 
+   {
+       UEditorUtilityWidgetBlueprint* EditorWidget = Cast<UEditorUtilityWidgetBlueprint>(Blueprint);
+       if (IsValid(EditorWidget)) 
+       {
+           UEditorUtilitySubsystem* EditorUtilitySubsystem = GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>();
+           EditorUtilitySubsystem->SpawnAndRegisterTab(EditorWidget);
+       }
+   }
}

#undef LOCTEXT_NAMESPACE
    
IMPLEMENT_MODULE(FExampleToolMenusExtensionModule, ExampleToolMenusExtension)

参考

How to make an EditorUtilityWidget open/run via C++
【UE5】EUW最速Plugin化(ToolBarMenu)

Discussion