Python Module Example

Menu Class examples as one big module-style example

import unreal

ToolMenus= unreal.ToolMenus.get()


@unreal.uclass()
class PythonMenuTool(unreal.ToolMenuEntryScript):
    name = "programatic_name"
    label = "display Name"
    tool_tip = "tool tip!"
 
    def __init__(self, menu, section=""):
        """
        given a menu object and a section name, 
        initialize this python tool and add it to the menu
        """
        super().__init__()
        
        if section:
            menu.add_section(section, section)

        # Initialize the entry data
        self.init_entry(
            owner_name="custom_owner",
            menu=menu.menu_name,
            section=section,
            name=self.name,
            label=self.label,
            tool_tip = self.tool_tip
        )

        # Add this tool to the desired menu
        menu.add_menu_entry_object(self)
        
    @unreal.ufunction(override=True)
    def execute(self, context):
        """The Python code to execute when pressed"""
        print(f"Provided context: {context}")
        
    @unreal.ufunction(override=True)
    def can_execute(self, context):
        """Can the user press this menu entry?"""
        is_ctrl_down = unreal.InputLibrary.modifier_keys_state_is_control_down(
            unreal.InputLibrary.get_modifier_keys_state()
        )
        return is_ctrl_down 
        
    @unreal.ufunction(override=True)
    def get_label(self, context):
        """Update the Display Name"""
        is_ctrl_down = unreal.InputLibrary.modifier_keys_state_is_control_down(
            unreal.InputLibrary.get_modifier_keys_state()
        )
        return "CTRL is GO!" if is_ctrl_down  else "Press CTRL to use"


@unreal.uclass()
class PythonMenuToolInsert(unreal.ToolMenuEntryScript):
    name = "inserted_menu"
    label = "Inserted Menu Class"
    tool_tip = "tool tip!"

    def __init__(self, menu, section="", insert_policy=None):
        """Initialize our entry for the given menu_object's section"""
        super().__init__()
        
        if section:
            menu.add_section(section, section)

        # Initialize the entry data
        self.init_entry(
            owner_name="custom_owner",
            menu=menu.menu_name,
            section=section,
            name=self.name,
            label=self.label,
            tool_tip=self.tool_tip
        )

        # if an insert policy was provided
        if insert_policy:
            # Build the entry insert object
            entry = unreal.ToolMenuEntry(
                name=self.name,
                type=self.data.advanced.entry_type,
                owner=unreal.ToolMenuOwner("custom_owner"),
                insert_position=insert_policy,
                script_object=self
            )

            # insert policy method
            menu.add_menu_entry(section, entry)

        else:
            # default method - add at the bottom of the menu
            menu.add_menu_entry_object(self)


@unreal.uclass()
class PythonMenuToolWithIcon(unreal.ToolMenuEntryScript):
    name = "icon_menu"
    label = "Menu Class w/ Icon"
    tool_tip = "tool tip!"

    def __init__(self, menu, section=""):
        """Initialize our entry for the given menu_object's section"""
        super().__init__()

        # Initialize the entry data
        self.init_entry(
            owner_name="custom_owner",
            menu=menu.menu_name,
            section=section,
            name=self.name,
            label=self.label,
            tool_tip=self.tool_tip
        )
        self.data.icon = unreal.ScriptSlateIcon(
            "EditorStyle", 
            "WorldBrowser.DetailsButtonBrush"
        )

        menu.add_menu_entry_object(self)

    @unreal.ufunction(override=True)
    def get_icon(self, context):
        """The Python code to execute when pressed"""
        is_ctrl_down = unreal.InputLibrary.modifier_keys_state_is_control_down(
            unreal.InputLibrary.get_modifier_keys_state()
        )
        active_icon = unreal.ScriptSlateIcon(
            "EditorStyle",
            "SourceControl.StatusIcon.On"
        )
        inactive_icon = unreal.ScriptSlateIcon(
            "EditorStyle",
            "SourceControl.StatusIcon.Error"
        )
        return active_icon if is_ctrl_down else inactive_icon


@unreal.uclass()
class EditorUtilityWidgetMenuTool(PythonMenuTool):
    """
    menu tool base class to launch specified Editor Utility Widgets
    """
    widget_path = "/Game/editor/utility/widget/path"

    @unreal.ufunction(override=True)
    def execute(self, context):
        """Open the EUW when pressed"""
        launch_editor_utility_widget(self.widget_path)

# Demo Code to Run

# Add a custom dropdown menu to the main menu bar at the top of the Editor:
menu = ToolMenus.find_menu("LevelEditor.MainMenu")
dropdown_menu = menu.add_sub_menu(
    owner="custom_owner", # this is used to delete menus later if needed
    section_name="",
    name="DemoTools",
    label="Demo Tools"
)

# Add the menu buttons to our dropdown
demo_menu = ToolMenus.find_menu("LevelEditor.MainMenu.DemoTools")
PythonMenuTool(demo_menu)
PythonMenuToolWithIcon(demo_menu)

# Insert the menu in the Edit dropdown after Paste
edit_menu = ToolMenus.find_menu("LevelEditor.MainMenu.Edit")
policy = unreal.ToolMenuInsert("Paste", unreal.ToolMenuInsertType.AFTER)
PythonMenuToolInsert(edit_menu, "EditMain", insert_policy = policy)

# Refresh the menus
ToolMenus.refresh_all_widgets()

Last updated