Hello, so to quickly describe what I’m trying to make:
I have a uplugin which contains an EditorUtilityWidget, it is a little Unreal Engine tool I made to help with the use of my plugin, I want it so that when someone installs my plugin into their project, after activating it in the Plugins menu and being told to restart their Editor, after that first restart I want them to now have an extra button in the Tools menu that when they click, opens up my EditorUtilityWidget blueprint.
I understand that in order to auto-run the EditorUtilityWidget when the editor starts up, I have to add it to my projects DefaultEditorPerProjectUserSettings.ini
file in the Configs folder and in there I would add
[/Script/Blutility.EditorUtilitySubsystem]
+StartupObjects=/Path/To/My/UtilityWidget.UtilityWidget
So I’ve managed to automatically write to this config file in my StartupModule()
function of my plugin like so:
FString SectionName = TEXT("/Script/Blutility.EditorUtilitySubsystem");
FString Filename = TEXT("DefaultEditorPerProjectUserSettings.ini");
FString ConfigPath = FConfigCacheIni::NormalizeConfigIniPath(FPaths::ProjectConfigDir() + *Filename);
if (GConfig) {
FConfigSection* ConfigSection = GConfig->GetSectionPrivate(*SectionName, false, true, ConfigPath);
FConfigFile* ConfigFile = GConfig->FindConfigFile(*ConfigPath);
if (!ConfigFile->DoesSectionExist(*SectionName))
{
GConfig->EmptySection(*SectionName, ConfigPath);
}
GConfig->SetString(*SectionName, TEXT("+StartupObjects"), TEXT("/Path/To/My/UtilityWidget.UtilityWidget"), ConfigPath);
}
GConfig->Flush(true, ConfigPath);
And then I add a menu button to the Tools submenu in the main toolbar that would open my utility widget with a console command (more on this in a bit)
UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Tools");
FToolMenuSection& NewSection = Menu->AddSection("MyTool", FText::FromString("MyTool"));
NewSection.AddSeparator(FName("MyTool"));
NewSection.AddMenuEntry(
FName("MyTool"),
FText::FromString("MyTool"),
FText::FromString("Open MyTool"),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateRaw(this, &FMyPlugin::MenuCommand)
),
EUserInterfaceActionType::Button,
FName("MyTool Utilities"));
And the MenuCommand() function which is called when that button is pressed:
void MenuCommand()
{
FString Command = TEXT("KISMETEVENT UtilityWidget_C_0 OpenWidgetOptions");
FString Output;
UWorld* World = GEditor->GetEditorWorldContext().World();
if (World)
{
GEngine->Exec(World, *Command);
}
}
In the widget I have a function called OpenWidgetOptions which essentially just spawns and registers an instance of itself (the utility widget blueprint class) and keeps track of its tab ID so it can be toggled on and off. (Yes, this means that I have to first have an instance of my widget so I can launch another instance of my widget and register a tab ID for that second one, while the first instance toggles that tab on and off)
This works, but the problem is it requires 2 restarts of the Editor, the first would happen when the plugin is activated, and after that restart it would write to the DefaultEditorPerProjectUserSettings.ini
file and add the menu button in Tools, but this happens after the Editor has completed starting up and so the Editor won’t be aware of these changes until another restart, this means if I tried to click that menu button it would tell me something like that it couldn’t find an instance of my UtilityWidget running so it couldn’t run that OpenWidgetOptions function. But after the second restart it works fine because then an instance of that UtilityWidget would be running to receive the function call command from the console.
So I was wondering maybe I should find a way to just run this EditorUtilityWidget blueprint in C++ in my plugins StartupModule function, that way I can ensure it is actually running after the first restart and my menu button would work. I went deep into a rabbit hole to try and figure out how to do this but couldn’t manage to compile my solution due to a multitude of errors at every step.
Or maybe another possible solution is to find another way to execute a Blueprint function that would run an instance of my widget without needing to have an instance of a class, kind of like if it was in a BlueprintFunctionLibrary, but also have access to Editor Utility nodes.
This is all because I’m trying to avoid having developers restart their Unreal Editor twice before they can start using my plugin, any help on this would be greatly appreciated.