Is it possible to run an EditorUtilityWidget blueprint from C++ in a plugins StartupModule() function?

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.

1 Like

Editor blueprints generally need a World to exist, and I don’t think the World is loaded yet when Plugins/Modules first load.

My suggestion is to make it so that your plugin doesn’t need to reload when changing settings; instead make it Just Work. It’ll solve the problem you have now, and also be nicer to the end user :slight_smile:

Hey thanks for the response,

So couldn’t I just delegate the tool menu button to run an instance of that EditorUtilityBlueprint? That way it would ensure that it happens when the World is loaded.

I was trying to do this but had compile issues. The challenge was running a blueprint EditorUtilityWidget in C++ in a plugins StartupModule() function, I know that I couldn’t just execute it in that function but instead I want to set it up as a delegate for when a tool menu button is clicked.

I don’t understand what you mean by not needing to reload when changing settings. In the Plugins window, activating any plugin will tell the user that they need to restart their Editor for changes to take effect. And to actually have my widget running and available to users it needs to be added to the StartupObjects key in that config ini file, and if that ini file changes while Unreal is running, those changes won’t take effect until Unreal Editor is restarted. Unless there’s a way to refresh the editors cached ini config parameters while it’s open?

What is “Just Work”? I don’t really understand the solution you’re proposing lol

Why does it have to be in that key to run?

I’m probably missing something, though. Who is the user for whom you’re making this editor plugin? Generally, when something comes with source, you need to update the unreal build files to include that thing anyway. Can you update the ini file (or tell the user to update the ini file) at that time?

Is the use case “I want users to download this plugin, and then they have to enable it, and then they have to edit it in the startup objects file, and that makes installation harder to do?”
If so, can you ship a sample project that already has the appropriate enabled/edits made?

I saw the solution to add the widget to that ini here: 4.23: How to auto-start Editor Utility Widgets? (new feature)

This wasn’t something that was clear or that I had an easy time googling/finding out, but it did help in having my widget start up when I open my project.

Right now, my plugin and widget work, but a user that downloads and activates my plugin will have to restart twice before that can all work. Maybe I’m just being nitpicky and I can just tell them that they’ll have to restart twice, or maybe tell them to edit the ini file before the first restart so they wouldn’t have to do it twice, but I just thought it would be nice if I could just avoid all that and make it so it just works after first restart

Yeah, it looks like your plugin needs to do what it needs to do during startup using C++ if you want “enable plugin” to be the only necessary configuration.