I have created an UMG editor widget utility blueprint and would like to open it at some point from my plugin C++ code. How can I achieve that?
I took a look into how in Blutility such an editor widget utility is run when you right click it and select “Run Editor utility Widget” in AssetTypeActions_EditorUtilityWidgetBlueprint.cpp". Unfortunately, this module does not export any of its symbols so I can’t link against it… Here was my attempt (inspired from FAssetTypeActions_EditorUtilityWidgetBlueprint::ExecuteRun):
void ULogListWidgetBase::OpenEditorUtilityWidgetWindow(UWidgetBlueprint* Blueprint)
{
if (Blueprint->GeneratedClass->IsChildOf(UEditorUtilityWidget::StaticClass()))
{
const UEditorUtilityWidget* CDO = Blueprint->GeneratedClass->GetDefaultObject<UEditorUtilityWidget>();
if (CDO->ShouldAutoRunDefaultAction())
{
// This is an instant-run blueprint, just execute it
UEditorUtilityWidget* Instance = NewObject<UEditorUtilityWidget>(GetTransientPackage(), Blueprint->GeneratedClass);
Instance->ExecuteDefaultAction();
}
else
{
FName RegistrationName = FName(*(Blueprint->GetPathName() + LOCTEXT("ActiveTabSuffix", "_ActiveTab").ToString()));
FText DisplayName = FText::FromString(Blueprint->GetName());
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>(TEXT("LevelEditor"));
TSharedPtr<FTabManager> LevelEditorTabManager = LevelEditorModule.GetLevelEditorTabManager();
if (!LevelEditorTabManager->CanSpawnTab(RegistrationName))
{
IBlutilityModule* BlutilityModule = FModuleManager::GetModulePtr<IBlutilityModule>("Blutility");
UEditorUtilityWidgetBlueprint* WidgetBlueprint = Cast<UEditorUtilityWidgetBlueprint>(Blueprint);
WidgetBlueprint->SetRegistrationName(RegistrationName);
LevelEditorTabManager->RegisterTabSpawner(RegistrationName, FOnSpawnTab::CreateUObject(WidgetBlueprint, &UEditorUtilityWidgetBlueprint::SpawnEditorUITab))
.SetDisplayName(DisplayName)
.SetGroup(BlutilityModule->GetMenuGroup().ToSharedRef());
BlutilityModule->AddLoadedScriptUI(WidgetBlueprint);
}
TSharedRef<SDockTab> NewDockTab = LevelEditorTabManager->InvokeTab(RegistrationName);
}
}
}
As I said, I can write this but even when I add Blutility to my list of dependencies, I get the following link errors:
error LNK2019: unresolved external symbol "private: static class UClass * __cdecl UEditorUtilityWidgetBlueprint::GetPrivateStaticClass(void)" (?GetPrivateStaticClass@UEditorUtilityWidgetBlueprint@@CAPEAVUClass@@XZ) referenced in function "public: static void __cdecl ULogListWidgetBase::OpenEditorUtilityWidgetWindow(class UWidgetBlueprint *)" (?OpenEditorUtilityWidgetWindow@ULogListWidgetBase@@SAXPEAVUWidgetBlueprint@@@Z)
error LNK2019: unresolved external symbol "public: class TSharedRef<class SDockTab,0> __cdecl UEditorUtilityWidgetBlueprint::SpawnEditorUITab(class FSpawnTabArgs const &)" (?SpawnEditorUITab@UEditorUtilityWidgetBlueprint@@QEAA?AV?$TSharedRef@VSDockTab@@$0A@@@AEBVFSpawnTabArgs@@@Z) referenced in function "public: static void __cdecl ULogListWidgetBase::OpenEditorUtilityWidgetWindow(class UWidgetBlueprint *)" (?OpenEditorUtilityWidgetWindow@ULogListWidgetBase@@SAXPEAVUWidgetBlueprint@@@Z)
Is it something impossible to do at the moment? Come on, opening the window of a custom editor widget utility… I must have missed something
I have been searching for this forever and I found this here. For some reason I cannot currently seem to get it to work. If you can find a way to get this to work, please let me know what you do.
The part where you find the path of your asset can be a bit tricky, fortunately, unreal editor provides an easy way to retrieve it using “Copy Reference” method:
Now you just have to CTRL+V your asset path in your IDE and here you go.
And last thing, do not forget to add a few dependencies in your module:
“Blutility”,
“UMG”,
“UMGEditor”,
Hope this helps!
PS: you might need a few other includes and a few other modules to declare for your own plugin to make everything compile but it works!
That’s awesome! Unfortunately this method will not work for me because I am trying to create a Marketplace contribution (meaning I can’t mess with the engine’s source) but that is still awesome that you were able to figure it out.
Here the first snipped is about how to register your tab, into the unreals tab"s manager, not sure if I need the first part of the code, but meh!
void UPipelineStatics::OpenWidgetBlueprint(UWidgetBlueprint* Blueprint)
{
if (!Blueprint) return;
if (Blueprint->GeneratedClass->IsChildOf(UEditorUtilityWidget::StaticClass()))
{
const UEditorUtilityWidget* CDO = Blueprint->GeneratedClass->GetDefaultObject<UEditorUtilityWidget>();
if (CDO->ShouldAutoRunDefaultAction())
{
// This is an instant-run blueprint, just execute it
UEditorUtilityWidget* Instance = NewObject<UEditorUtilityWidget>(GetTransientPackage(), Blueprint->GeneratedClass);
Instance->ExecuteDefaultAction();
}
else
{
FName RegistrationName = FName(*(Blueprint->GetPathName() + TEXT("_ActiveTab")));
FText DisplayName = FText::FromString(Blueprint->GetName());
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>(TEXT("LevelEditor"));
TSharedPtr<FTabManager> LevelEditorTabManager = LevelEditorModule.GetLevelEditorTabManager();
if (!LevelEditorTabManager->CanSpawnTab(RegistrationName))
{
//UEditorUtilityWidgetBlueprint* WidgetBlueprint = Cast<UEditorUtilityWidgetBlueprint>(Blueprint);
LevelEditorTabManager->RegisterTabSpawner(RegistrationName, FOnSpawnTab::CreateStatic(&UPipelineStatics::SpawnEditorUITab, Blueprint))
.SetDisplayName(DisplayName)
.SetMenuType(ETabSpawnerMenuType::Hidden);
}
TSharedRef<SDockTab> NewDockTab = LevelEditorTabManager->InvokeTab(RegistrationName);
}
}
}
and your will need this function to create your actual widget, looks like is possible create UMG widgets and bind that to any slate, check TakeWidget(); very straightforward
Hi, here’s updated solution for UE5.0.3 : Version: 5.0.3-20979098
In your .build.cs, find PrivateDependencyModuleNames.AddRange
and add these:
“Blutility”,
“UMG”,
“UMGEditor”,
If “private” dont work, then try public.
Delete VS solution and regenerate from the project .exe
include these:
include “EditorUtilityWidget.h” include “EditorUtilityWidgetBlueprint.h” include “EditorUtilitySubsystem.h”
Use this:
// get the path of the asset by R.Clicking on the asset and 'Copy Reference'
const FStringAssetReference widgetAssetPath("/LevelValidationTools/EUW_LevelValidator.EUW_LevelValidator");
UObject* widgetAssetLoaded = widgetAssetPath.TryLoad();
if (widgetAssetLoaded == nullptr) {
UE_LOG(LogTemp, Warning, TEXT("Missing Expected widget class at : /LevelValidationTools/EUW_LevelValidator.EUW_LevelValidator"));
return;
}
UEditorUtilityWidgetBlueprint* widget = Cast<UEditorUtilityWidgetBlueprint>(widgetAssetLoaded);
if (widget == nullptr) {
UE_LOG(LogTemp, Warning, TEXT("Couldnt cast /LevelValidationTools/EUW_LevelValidator.EUW_LevelValidator to UEditorUtilityWidgetBlueprint"));
return;
}
UEditorUtilitySubsystem* EditorUtilitySubsystem = GEditor->GetEditorSubsystem<UEditorUtilitySubsystem>();
EditorUtilitySubsystem->SpawnAndRegisterTab(widget);