How to make an EditorUtilityWidget open/run via C++

Hey,
I am working on a UE4 project for university and I am creating a small editor plugin to procedurally generate buildings.

Unfortunately I can not seem to find a way to start the editor utility widget by pressing the toolbar button/using C++.
I already tried to use CreateWidget, but it does not seem to work with EditorUtilityWidgets.

I realized that there is very little information to find for this problem.
Does anyone have an idea how to run an EditorUtilityWidget via C++?

Best regards

Hi,
In c++ you cas use this code for run editor utility widget

void YourClassName::RunEditorUtilityWidget(UEditorUtilityWidgetBlueprint* EditorWidget)
{
	if (EditorWidget)
	{
		UEditorUtilitySubsystem* EditorUtilitySubsystem = GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>();
		EditorUtilitySubsystem->SpawnAndRegisterTab(EditorWidget);
	}
}

Or in blueprint there are tutoriel on the Wiki

Ah thanks for the function!

Unfortunately I canā€™t get the reference to the Widget right.
Do you also know how to properly reference the EditorWidget, since I canā€™t seem to get it to work with ConstructorHelper::ClassFinder.

This is the code I want to use when pressing the toolbar button:

void FPlugiModule::PluginButtonClicked()
{

static ConstructorHelpers::FClassFinder<UEditorUtilityWidgetBlueprint> BBObj(TEXT("/Game/BB"));
if (BBObj.Succeeded()) {
	//MenuClass is TSubclassOf<class UEditorUtilityWidgetBlueprint> MenuClass;
	MenuClass = BBObj.Class;
}

//Does not work as it can't convert UClass to UEditorUtilityWidgetBlueprint
RunEditorUtilityWidget(MenuClass.Get());

}

I FINALLY GOT IT TO WORK!

If anyone is still wondering, since itā€™s hard to find the solution to this. I decided to share what I found.
I found this random chinese website, that posted like just a month ago and it shows a working way to open them via C++:

This is working for a Standalone Window Editor Plugin:

TSharedRef FVIR_ENVIRONMENTModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
{

// load UMG Of BP
UBlueprint* UMGBP = LoadObject<UBlueprint>(nullptr, L"/Game/yaksueEditorUtilityWidgetBlueprint"); //Reference to your EditorUtilityWidget

// Modelled on the  UEditorUtilityWidgetBlueprint::CreateUtilityWidget()  Do it again 
TSharedRef<SWidget> TabWidget = SNullWidget::NullWidget;
{

	UEditorUtilityWidget* CreatedUMGWidget = nullptr;// Created UMG Control 

	UClass* BlueprintClass = UMGBP->GeneratedClass;
	TSubclassOf<UEditorUtilityWidget> WidgetClass = BlueprintClass;
	UWorld* World = GEditor->GetEditorWorldContext().World();
	if (World)
	{

		if (CreatedUMGWidget)
		{

			CreatedUMGWidget->Rename(nullptr, GetTransientPackage());
		}
		CreatedUMGWidget = CreateWidget<UEditorUtilityWidget>(World, WidgetClass);
	}
	if (CreatedUMGWidget)
	{

		TabWidget = SNew(SVerticalBox)
			+ SVerticalBox::Slot()
			.HAlign(HAlign_Fill)
			[
				CreatedUMGWidget->TakeWidget()
			];
	}
}

Donā€™t forget to do this: #include ā€œEditor/Blutility/Classes/EditorUtilityWidget.hā€

Also add
ā€œUMGEditorā€,
ā€œBlutilityā€,
ā€œUMGā€

to your private dependencies in the Build.cs of the plugin.

All credits go to this post: Learn to use UMG as an editor control in the unreal engine

3 Likes

What does the header for this look like?

This is my current attempt to make this work

// Copyright Epic Games, Inc. All Rights Reserved.

#include "bplib.h"
#include "Editor/Blutility/Classes/EditorUtilityWidget.h"

#define LOCTEXT_NAMESPACE "FbplibModule"

void FbplibModule::StartupModule()
{
	// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
	
}

void FbplibModule::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.
	
}

void FbplibModule::PluginButtonClicked()
{
}

// Modelled on the  UEditorUtilityWidgetBlueprint::CreateUtilityWidget()  Do it again
TSharedRef FbplibModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
	{
	UBlueprint* UMGBP = LoadObject<UBlueprint>(nullptr, L"/Script/Blutility.EditorUtilityWidgetBlueprint'/bplib/bplib.bplib'"); //Reference to your EditorUtilityWidget

	TSharedRef<SWidget> TabWidget = SNullWidget::NullWidget;
	{

		UEditorUtilityWidget* CreatedUMGWidget = nullptr;// Created UMG Control 

		UClass* BlueprintClass = UMGBP->GeneratedClass;
		TSubclassOf<UEditorUtilityWidget> WidgetClass = BlueprintClass;
		UWorld* World = GEditor->GetEditorWorldContext().World();
		if (World)
		{

			if (CreatedUMGWidget)
			{

				CreatedUMGWidget->Rename(nullptr, GetTransientPackage());
			}
			CreatedUMGWidget = CreateWidget<UEditorUtilityWidget>(World, WidgetClass);
		}
		if (CreatedUMGWidget)
		{

			TabWidget = SNew(SVerticalBox)
				+ SVerticalBox::Slot()
				.HAlign(HAlign_Fill)
				[
					CreatedUMGWidget->TakeWidget()
				];
		}
	}
	
}

#undef LOCTEXT_NAMESPACE
	
IMPLEMENT_MODULE(FbplibModule, bplib)

header

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"

class FbplibModule : public IModuleInterface
{
public:

	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
	
	/** This function will be bound to Command (by default it will bring up plugin window) */
	void PluginButtonClicked();

	TSharedRef OnSpawnPluginTab();
	
};

edit: got it to work, report later

This post was great, but as written can cause crashes when the level changes. So I did it this way calling the UEditorUtilityWidgetBlueprint method rather than rebuilding it:

TSharedRef<SDockTab> FYourModule::OnSpawnPluginTab(const FSpawnTabArgs& SpawnTabArgs)
{

	// load YourWidget as BPClass
	UEditorUtilityWidgetBlueprint* UMGBP = LoadObject<UEditorUtilityWidgetBlueprint>(nullptr, L"/Game/YourEUWBP"); 

	TSharedRef<SDockTab> SpawnedTab = UMGBP->SpawnEditorUITab(SpawnTabArgs);

	return SpawnedTab;
	
}

This works for me as a Menu Tab

3 Likes

This code worked great for me, using UEditorUtilitySubsystem

void FAutomationModule::OnSpawnPluginTab()
{
    // Reference to your AutomationUtilityWidget
    UBlueprint* UMGBP = LoadObject<UBlueprint>(nullptr, L"/Script/Blutility.EditorUtilityWidgetBlueprint'/Automation/EUW_ConsoleCommand.EUW_ConsoleCommand'");

    UEditorUtilityWidgetBlueprint* EditorWidget = Cast<UEditorUtilityWidgetBlueprint>(UMGBP);

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

I got this working in UE5.4. If it helps anyone else, I made a plugin using the ā€œEditor toolbar buttonā€ template (NOT the standalone window one), then changed the ā€œ.Build.csā€ fileā€™s private dependencies to this:

		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"Projects",
				"InputCore",
				"EditorFramework",
				"UnrealEd",
				"ToolMenus",
				"CoreUObject",
				"Engine",
				"Slate",
				"SlateCore",
                "Blutility",
                "UMGEditor",
				"UMG",
                "EditorScriptingUtilities",
				// ... add private dependencies that you statically link with here ...	
			}
			);

And then for the actual code in the ā€œ.cppā€ file I did the following - but you need to:
(1) replace ā€˜MyPluginNameā€™ with yours, and
(2) the statement after TEXT should be your reference.

So, in content browser, find your Editor Utility Widget, right-click and choose REFERENCE. Then paste that in, replacing the one I have in there. (I had my widget inside ā€œCONTENT>Letsgoā€ and the widget itself was called ā€œLetsgoā€.)

void FMyPluginNameModule::PluginButtonClicked()
{
	UObject* Blueprint = UEditorAssetLibrary::LoadAsset(FString(TEXT("/Script/Blutility.EditorUtilityWidgetBlueprint'/Game/Letsgo/Letsgo.Letsgo'")));
	if (IsValid(Blueprint)) {
		UEditorUtilityWidgetBlueprint* EditorWidget = Cast<UEditorUtilityWidgetBlueprint>(Blueprint);
		if (IsValid(EditorWidget)) {
			UEditorUtilitySubsystem* EditorUtilitySubsystem = GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>();
			EditorUtilitySubsystem->SpawnAndRegisterTab(EditorWidget);
		}
	}

}

However the most IMPORTANT part is the top of the ā€˜.cppā€™ file, otherwise none of it will work:

// Copyright Epic Games, Inc. All Rights Reserved.

#include "AnimPalV2.h"
#include "AnimPalV2Style.h"
#include "AnimPalV2Commands.h"
#include "Misc/MessageDialog.h"
#include "ToolMenus.h"
#include "EditorUtilityWidgetBlueprint.h"
#include "EditorUtilitySubsystem.h"
#include "Editor/Blutility/Classes/EditorUtilityWidget.h"
#include "./../Plugins/Editor/EditorScriptingUtilities/Source/EditorScriptingUtilities/Public/EditorAssetLibrary.h"

There is an issue with UEditorAssetLibrary
image
Include look like this

#include "Misc/MessageDialog.h"
#include "ToolMenus.h"
//#include "WidgetBlueprint.h"
#include "Widgets/SWidget.h"
#include "SWidgetDrawer.h"
//Utility Widget
#include "EditorUtilitySubsystem.h"
#include "EditorUtilityWidget.h"
#include "EditorUtilityWidgetBlueprint.h"
#include "Editor/Blutility/Classes/EditorUtilityWidget.h"
#include "Widgets/SMainMenuWidget.h"
#include "Widgets/ByMovieUtility.h"
#include "./../Plugins/Editor/EditorScriptingUtilities/Source/EditorScriptingUtilities/Public/EditorAssetLibrary.h"

Edit. Fix this adding

#include "./../Plugins/Editor/EditorScriptingUtilities/Intermediate/Build/Win64/UnrealEditor/Inc/EditorScriptingUtilities/UHT/EditorAssetLibrary.generated.h"

into EditorAssetsLibrary.h
and delete:

#include "EditorAssetLibrary.generated.h"

Better fix like this:

	"Plugins": [
...
		{
			"Name": "EditorScriptingUtilities",
			"Enabled": true
		}
	]

and

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