While we can't really add our own icons on the fly as easily, something we can do somewhat easily is use the existing Slate Icons!
Finding Icons To Use
To browse available icons, I recommend thee Slate Style Browser plugin available on FAB:
We can launch this plugin's tool from the Tools
dropdown menu:
The Slate Style Browse allows us to quickly scan through all available Slate Icons, providing the exact information we need for our Python menu classes:
The key thing we want to add to our class' init is the following line:
Copy self.data.icon = unreal.ScriptSlateIcon(
"<Style Set>",
"<Property Name>"
)
That's all there is to it! Just find a Slate Icon we like and copy its Style Set and Property Name
Using the Details Button icon as an example, here's what our class now looks like:
Copy @unreal.uclass()
class PythonMenuTool(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
)
# Set the icon!
self.data.icon = unreal.ScriptSlateIcon(
"EditorStyle",
"WorldBrowser.DetailsButtonBrush"
)
menu.add_menu_entry_object(self)
And now our menu class has an icon:
Dynamic Icon
We can also make it dynamic, too!
Copy @unreal.ufunction(override=True)
def get_icon(self, context):
"""determine the icon to display"""
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
Note : The Icon does not refresh on Tick like the Label does, most menus only call this function once when the menu list is displayed
Full Class Code
Copy @unreal.uclass()
class PythonMenuTool(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