【UE4】【C++】メモ:EditorUtilityWidgetをBlueprintから実行する方法 【★★★☆】

※この記事で使用しているUnrealのVersionは04.22.3 です。

※この記事のサンプルプロジェクトはございません。

※このブログは自分のメモ用なので、Twitterでの告知をしておりません。

BPからEditorUtilityWidgetを実行 レベル【★★★☆】

書かないとか言っておいて、メモしておきたくなったので、C++の記事を書きます。

今回はEditorUtilityWidgetをBlueprintから実行する方法についてです。

まずはC++プロジェクトを作成します。

次に新規でC++クラスを作成します。

親クラスは、「Blueprint Function Library」にします。

MyBlueprintFunctionLibrary.hの中身はこんな感じです

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Editor/Blutility/Classes/EditorUtilityWidget.h"
#include "MyBlueprintFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS(BlueprintType)
class KA_EUW_CALLBP_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable)
		static void RunEditorUtilityWidget(UWidgetBlueprint* Blueprint);
	
};

つづいて、MyBlueprintFunctionLibrary.cppの中身はこんな感じです。

// Fill out your copyright notice in the Description page of Project Settings.


#include "MyBlueprintFunctionLibrary.h"
#include "Editor/UMGEditor/Public/WidgetBlueprint.h"
#include "Editor/LevelEditor/Public/LevelEditor.h"
#include "Runtime/Core/Public/Modules/ModuleManager.h"
#include "Editor/Blutility/Public/IBlutilityModule.h"
#include "Editor/Blutility/Classes/EditorUtilityWidgetBlueprint.h"


//AssetTypeActions_EditorUtilityWidgetBlueprint.cpp内にある、ExecuteRun()を移植しただけ。

void UMyBlueprintFunctionLibrary::RunEditorUtilityWidget(UWidgetBlueprint* Blueprint)
{
	if (Blueprint->GeneratedClass->IsChildOf(UEditorUtilityWidget::StaticClass()))
	{
		const UEditorUtilityWidget* CDO = Blueprint->GeneratedClass->GetDefaultObject();
		if (CDO->ShouldAutoRunDefaultAction())
		{
			// This is an instant-run blueprint, just execute it
			UEditorUtilityWidget* Instance = NewObject(GetTransientPackage(), Blueprint->GeneratedClass);
			Instance->ExecuteDefaultAction();
		}
		else
		{
			FName RegistrationName = FName(*(Blueprint->GetPathName() + TEXT("_ActiveTab")));
			FText DisplayName = FText::FromString(Blueprint->GetName());
			FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked(TEXT("LevelEditor"));
			TSharedPtr LevelEditorTabManager = LevelEditorModule.GetLevelEditorTabManager();
			
			/*この部分を入れるとエラーが起きたので、とりあえず省いた。
			if (!LevelEditorTabManager->CanSpawnTab(RegistrationName))
			{
				IBlutilityModule* BlutilityModule = FModuleManager::GetModulePtr("Blutility");
				UEditorUtilityWidgetBlueprint* WidgetBlueprint = Cast(Blueprint);
				WidgetBlueprint->SetRegistrationName(RegistrationName);
				LevelEditorTabManager->RegisterTabSpawner(RegistrationName, FOnSpawnTab::CreateUObject(WidgetBlueprint, &UEditorUtilityWidgetBlueprint::SpawnEditorUITab))
					.SetDisplayName(DisplayName)
					.SetGroup(BlutilityModule->GetMenuGroup().ToSharedRef());
				BlutilityModule->AddLoadedScriptUI(WidgetBlueprint);
			}
			*/
			TSharedRef NewDockTab = LevelEditorTabManager->InvokeTab(RegistrationName);
		}
	}

}

さらに、Build.csファイル内の「PublicDependencyModuleNames.AddRange」に、
「”Slate”, “SlateCore”, “UnrealEd”, “Blutility”, “UMG”, “UMGEditor”」を追加します。

これで、コードを書くのは終わり。

エディターに戻ってコンパイルを押します。

次に、確認のためのEditorUtilityWidgetを作ります。

コンテンツブラウザ左上の「Add New」から「Editor Utilities」→「Editor Widget」を選択します。

中を開いたら、適当なWidgetを作っておきましょう。

次に、先ほどC++で作った関数を呼び出すための「Blutility」を作ります。

エディター左上の「Edit」→「Editor Preference」を選択します。

「General」→「Experimental」→「Tool」→「Editor Utility Blueprint (Blutility)」のチェックボックスにチェックを入れます。

できましたら、コンテンツブラウザ左上の「Add New」から「Editor Utilities」→「Blutility」を選択します。

親クラスは、今回は「GlobalEditor Utility Base」を選択します。

作ったアセットを右クリック「Edit Blueprint」を選択します。

開いたら以下のようにノードを組みます。

出来ましたら、あとはBlutilityアセットをダブルクリックして、作成したイベントのボタンを押すだけです。

※一度手動でEditorUtilityWidgetを起動しないと、↓のような画面になってしまいます。

おそらく移植したコードのコメントアウトした部分ですが、原因特定が面倒だったので解決できなかったです。

※この記事のサンプルプロジェクトはございません。