Using tool menus for editor extension

This tutorial covers the use of tool menus to create a toolbar button in the level viewport. This button when clicked open up a Editor utility widget which you can use to make your own tool.

Updated 4 months ago Edit Page Revisions

Let's create a toolbar button that opens an Editor Widget. This button is created at the engine startup by using the Run function provided by EditorUtilityClasses. On click, the button runs a console command which calls a custom event. This event opens our Editor Widget.

Create a content plugin

First create a content plugin, this step is not required.

Creating a plugin is recommended for reuse of your tool.

On the Menubar select Edit then Plugin a window pop, click New plugin.

  • Finally select create plugin

Create the required Classes

Add a folder:

  • Right click the ContentBrowser

  • Select New Folder

  • Name it: "Tutorial"

Our Hook, our entry point

Right Click in the ContentBrowser then Select Editor Utility Blueprint like below

Then pick EditorUtilityObject

  • Call it BPU_TutoStartupHook

  • Right click on it and Copy Reference

Open Your project folder navigate to Config and edit DefaultEditorPerProjectUserSettings.ini and add:

[/Script/Blutility.EditorUtilitySubsystem]

StartupObjects="PasteYourReferenceHere"

Remove EditorUtilityBlueprint' from the pasted reference the final line should be like

StartupObjects="/MyToolTuto/Tutorial/BPU_TutoStartupHook.BPU_TutoStartupHook"

The widget

Create a Editor Utility Widget name it WBPU_ToolWidget

Blueprint setup

Create those variables names:

Now set the variables like below:

  • Menu

    • Type: Name

    • Value: LevelEditor.LevelEditorToolBar

  • Section

    • Type: Name

    • Value: MyTools

  • MenuEntry

    • Type: ToolMenuEntry

    • Value:

      • Name: Mytools

      • Type: ToolBarButton

      • UserInterfaceActionType: Button

  • Label

    • Type: Text

    • Value: MyTool

  • ToolTip

    • Type: Text

    • Value: Open MyTool

  • Icon

    • Type: ScriptSlateIcon
  • OptionWidget

    • Type: EditorUtilityWidgetBlueprint

    • Value: WBPU_ToolWidget

  • OptionWidgetID

    • Type: Name

Copy the following graph:

Add a space after KISMETEVENT

and before OpenWidgetOptions

Now you may try it: Close the editor and restart your project if a button appear like this:

Success if you can click the button and the widget window appear

If there is no button first verify DefaultEditorPerProjectUserSettings.ini add a print string node on the Event Run. Reload and search the OutputLog for the string. If you did not have to change the ini file to see the string the error may be one of the following in OutputLog:

  • "Hook menu not found" the variable menu value is wrong

  • "LogToolMenus: Warning: Toolbar 'LevelEditor.LevelEditorToolBar', item 'Mytools', type not currently supported: X" the variable MenuEntry is not setup correctly

If the button doesn't open the widget verify the append Node

  • If on click you see "Failed to find an object named 'BPU_TutoStartupHook_C_0OpenWidgetOptions'." You miss a space before OpenWidgetOptions

  • If the error is silent "Cmd: KISMETEVENTBPU_TutoStartupHook_C_0 BPUOpenWidgetOptions" You miss a space after KISMETEVENT

Further reading

Other menus

Now that you know how to create a toolbar button you can now do it for any kind of menu

e.g: You can add button in the main menu bar change the variable Menu to LevelEditor.MainMenu.Window and set accordingly MenuEntry Type to MenuEntry

you can search in the engine source for UToolMenus::Get()->RegisterMenu to find the available menus.

Specific Classes

  • This is a topic i do not master well.

  • A lot of the engine code is not exposed to blueprint

  • It may be change in future

You can create a button for a specific class to do that you need a context to find a matching class wich is provided by the ToolMenuEntryScript class you may subclass this and pass it to the MenuEntry ScriptObject variable.

Your ToolMenuEntryScript subclass has native event CanExecute and ConstructMenuEntry those provide the necessary context

Passing a scriptObject to the MenuEntry bypass the button creation from the node AddMenuEntry and as result it fire ConstructMenuEntry event.

  • Implement icon for the button

  • Support for other menus and specific classes

  • Support for Section

An Alternative Approach

Hi - thanks for the above information - but I believe there's an easier way.

I suggest you follow this example: https://twitter.com/MilkyEngineer/status/1379644300108029955

In summary:

  • You create an a Blueprint called Editor Utility Tool Menu Entry
  • You then set menu position and icon in the details of that new BP (the example also shows how to grab names for pre-existing icons in the Editor Style style set)
  • You then add a couple of events to the event graph of this BP, a custom event called Run (and add the same ini entry to add it to Startup Objects as identified above) and overide the Execute event to call Spawn and Register Tab

If working with UE 5.3:

  • In step 3 of the example, don't update the ini file, use the following Console Command: ToolMenus.Edit
  • If nothing shows up make sure you haven't messed up either the menu name or the section name, and in 5.3 the exact hierarchy/menu names seem to have changed around a bit. I used Menu = LevelEditor.LevelEditorToolBar.User and it worked (after having screwed it up and nothing showing up)

Same final results. Less code to add to your BP.

I hope this helps.