【UE5】EUW最速Plugin化(ToolBarMenu)

タイトルそのままですが、流れをサクッと確認したい人はとりあえず動画でどうぞ！
<iframe width="560" height="315" src="https://www.youtube.com/embed/4R-NiNlMIQc?si=hvY2w0cpy6M_8dnO" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 作成手順
※プラグイン名は仮にmyPluginとし、以降それに関連した命名規則によるものとなる。
※プロジェクト名とプラグイン名が同名だとプラグインが作成出来ないので注意。
## Unreal
1. プロジェクト作成(テンプレートは適当に) / プロジェクトのデフォルト : ***C++***
2. **メニュー > 編集 > プラグイン > 追加 > エディタツールバーボタン > プラグイン名入力 > プラグイン作成**
メニューバーにアイコンが追加されクリックでWindowが開く。

3. EUWをプラグインに含めるようにする
**メニュー > 編集 > プラグイン > Other > myPlugin > 編集 > Can Contain Content : True**
再起動するとコンテンツブラウザからPlugins/myPluginコンテンツフォルダが追加されてるのが確認出来る。

4. myPluginコンテンツ内にEUWを作成

## VisualStudio
プロジェクト作成時にVisualStudioが起動するのでこのタイミングで再読み込みを行い変更を反映させる。

※作業ディレクトリ: ***Unreal Projects\plugin_test\Plugins\test\Source\myPlugin***
各ファイルを以下のように変更する。
※***+*** は書き込まないように
### myPluginBuild.cs
```diff_cpp

		PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
+               "EditorScriptingUtilities"
				// ... add other public dependencies that you statically link with here ...
			}
			);

		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"Projects",
				"InputCore",
				"EditorFramework",
				"UnrealEd",
				"ToolMenus",
				"CoreUObject",
				"Engine",
				"Slate",
				"SlateCore",
+               "UMGEditor",
+				"Blutility",
+				"UMG"
				// ... add private dependencies that you statically link with here ...	
			}
			);
```
---
### Public\myPlugin.h
```diff_cpp
class FmyPluginModule : public IModuleInterface
{
public:

	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
+ 	virtual ~FmyPluginModule() {}
	
	/** This function will be bound to Command. */
	void PluginButtonClicked();
	
private:

	void RegisterMenus();
+ 	void RunEditorUtilityWidget();

private:
	TSharedPtr<class FUICommandList> PluginCommands;
};
```
---
### Private\myPlugin.cpp 
※ここでエラーが出ても後で解決するので気にしない。
```diff_cpp
#include "myPlugin.h"
#include "myPluginStyle.h"
#include "myPluginCommands.h"
#include "Misc/MessageDialog.h"
#include "ToolMenus.h"
+ #include "EditorAssetLibrary.h"
+ #include "Editor/Blutility/Public/EditorUtilitySubsystem.h"
+ #include "Editor/Blutility/Classes/EditorUtilityWidgetBlueprint.h"
+ #include "Editor/Blutility/Classes/EditorUtilityWidget.h"
```

```diff_cpp
void FmyPluginModule::PluginButtonClicked()
{
	// Put your "OnButtonClicked" stuff here
-	FText DialogText = FText::Format(

-							LOCTEXT("PluginButtonDialogText", "Add code to {0} in {1} to override this button's actions"),

-							FText::FromString(TEXT("FtestModule::PluginButtonClicked()")),

-							FText::FromString(TEXT("test.cpp"))

-					   );

-	FMessageDialog::Open(EAppMsgType::Ok, DialogText);
+	RunEditorUtilityWidget();
}
```
以下を追加
```diff_cpp
void FmyPluginModule::RunEditorUtilityWidget()
{
	UObject* Blueprint = UEditorAssetLibrary::LoadAsset(FString(TEXT("EUW_Path")));
	if (Blueprint)
	{
		UEditorUtilityWidgetBlueprint* EditorWidget =
			Cast<UEditorUtilityWidgetBlueprint>(Blueprint);

		if (EditorWidget)
		{
			UEditorUtilitySubsystem* EditorUtilitySubsystem =
				GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>();

			EditorUtilitySubsystem->SpawnAndRegisterTab(EditorWidget);
		}
	}
}
```
***EUW_Path***にはUnrealのコンテンツブラウザから***EUWのリファレンス***をコピーして置換

---
## Pluginのビルドとパッケージ
1. Unrealを閉じる
2. .uprojectを右クリックから ***Genalate Visual Studio project files***
3. VisualStudioで ***再読み込み > myPluginのビルド***
4. .uprojectを開き先ほど追加されたアイコンをクリックするとEUWが開く
5. ***メニュー > 編集 > プラグイン > Other > myPlugin > 編集 > 依存関係 > Plugins*** に ***EditorScriptingUtilities*** を追加
6. ***メニュー > 編集 > プラグイン > other > myPlugin > パッケージ***

以上

## あとがき
EUWで色々作ってたら他のプロジェクトで使うときにプラグイン化した方が楽なのでは？と思ったけど、ユーザビリティー的にPluginコンテンツまで行ってEUW開かせたりするのはよろしくないと思ってメインツールバーにアイコン表示させてそこから開かせるかたちに。

C++までは触りたくないいわゆるクリエーター的な立場だとEUWあたりで済ませたいんだけどこのあたりになるとやはりC++に手を出さないといけなくなるなぁ。
なかなかこの辺の参考になるものがなかったので備忘録的にまとめてみました。
(C++とかまったく触らないのでおかしいところ多々あるかも…)