Examples#
Simplified submenu creation with build_submenu_dict#
- This creates a dictionary of lists from the - namepaths in MenuItemDescription, expanding the path and creating (multiple, if required) sub_menu lists. The last item on the path is assumed to be not a sub_menu item.
menu_dict = omni.kit.menu.utils.build_submenu_dict([ MenuItemDescription(name="File/Open"),
                                                     MenuItemDescription(name="Edit/Select/Select by kind/Group"),
                                                     MenuItemDescription(name="Window/Viewport/Viewport 1"),
                                                     MenuItemDescription(name="Help/About"),
                                                    ])
using add_menu_items#
for group in menu_dict:
    omni.kit.menu.utils.add_menu_items(menu_dict[group], group)
using remove_menu_items#
for group in menu_dict:
    omni.kit.menu.utils.remove_menu_items(menu_dict[group], group)
Another example: Adding a menu with submenu for your extension;#
from omni.kit.menu.utils import MenuItemDescription
import carb.input
def on_startup(self, ext_id):
    self._file_menu_list = [
        MenuItemDescription(
            name="Sub Menu Example",
            glyph="file.svg",
            sub_menu=[
                MenuItemDescription(
                    name="Menu Example 1",
                    onclick_action=("omni.kit.menuext.extension", "menu_example_1"),
                ),
                MenuItemDescription(
                    name="Menu Example 2",
                    onclick_action=("omni.kit.menuext.extension", "menu_example_2"),
                )],
            )]
    omni.kit.menu.utils.add_menu_items(self._file_menu_list, "File")
def on_shutdown(self):
    omni.kit.menu.utils.remove_menu_items(self._file_menu_list, "File")
Adding to create menu#
self._create_menu_list = [
    MenuItemDescription(
        name="Scope",
        glyph="menu_scope.svg",
        appear_after="Camera",
        onclick_action=("omni.kit.menu.create", "create_prim_scope"),
    )
]
omni.kit.menu.utils.add_menu_items(self._create_menu_list, "Create")
Menu example with ui.Window subclass#
This is an example of how create a window with menu, without any helpers. Full working show/hide and subclass of ui.Window. NOTE: This uses print only as an example allowing users to see how this works, and should be removed when used in real extension
Extension class#
import carb
import asyncio
import omni.ext
import omni.ui as ui
import omni.kit.menu.utils
from omni.kit.menu.utils import MenuItemDescription
from .window import ExampleWindow
class TestMenu(omni.ext.IExt):
"""The entry point for Example Extension"""
    WINDOW_NAME = "Example"
    MENU_DESCRIPTION = "Example Window"
    MENU_GROUP = "TEST"
    def on_startup(self):
        print(f"[{self.__class__.__name__}] on_startup")
        ui.Workspace.set_show_window_fn(TestMenu.WINDOW_NAME, lambda v: self.show_window(None, v))
        self._menu_entry = [MenuItemDescription(
            name=TestMenu.MENU_DESCRIPTION,
            ticked=True, # menu item is ticked
            ticked_fn=self._is_visible, # gets called when the menu needs to get the state of the ticked menu
            onclick_fn=self._toggle_window
            )]
        omni.kit.menu.utils.add_menu_items(self._menu_entry, name=TestMenu.MENU_GROUP)
        ui.Workspace.show_window(TestMenu.WINDOW_NAME)
    def on_shutdown(self):
        print(f"[{self.__class__.__name__}] on_shutdown")
        omni.kit.menu.utils.remove_menu_items(self._menu_entry, name=TestMenu.MENU_GROUP)
        self._menu_entry = None
        ui.Workspace.set_show_window_fn(TestMenu.WINDOW_NAME, None)
        if self._window:
            self._window.destroy()
            self._window = None
    async def _destroy_window_async(self):
        print(f"[{self.__class__.__name__}] _destroy_window_async")
        # wait one frame, this is due to the one frame defer
        # in Window::_moveToMainOSWindow()
        await omni.kit.app.get_app().next_update_async()
        if self._window:
            self._window.destroy()
            self._window = None
    def _is_visible(self) -> bool:
        print(f"[{self.__class__.__name__}] _is_visible returning {False if self._window is None else self._window.visible}")
        return False if self._window is None else self._window.visible
    def _show(self):
        print(f"[{self.__class__.__name__}] _show")
        if self._window is None:
            self.show_window(None, True)
        if self._window and not self._window.visible:
            self.show_window(None, True)
    def _hide(self):
        print(f"[{self.__class__.__name__}] _hide")
        if self._window is not None:
            self.show_window(None, False)
    def _toggle_window(self):
        print(f"[{self.__class__.__name__}] _toggle_window")
        if self._is_visible():
            self._hide()
        else:
            self._show()
    def _visiblity_changed_fn(self, visible):
        print(f"[{self.__class__.__name__}] _visiblity_changed_fn")
        if not visible:
            # Destroy the window, since we are creating new window
            # in show_window
            asyncio.ensure_future(self._destroy_window_async())
            # this only tags test menu to update when menu is opening, so it
            # doesn't matter that is called before window has been destroyed
            omni.kit.menu.utils.refresh_menu_items(TestMenu.MENU_GROUP)
    def show_window(self, menu, value):
        print(f"[{self.__class__.__name__}] show_window menu:{menu} value:{value}")
        if value:
            self._window = ExampleWindow()
            self._window.set_visibility_changed_listener(self._visiblity_changed_fn)
        elif self._window:
            self._window.visible = False
Window class#
import omni.ui as ui
class ExampleWindow(ui.Window):
"""The Example window"""
    def __init__(self, usd_context_name: str = ""):
        print(f"[{self.__class__.__name__}] __init__")
        super().__init__("Example Window", width=300, height=300)
        self._visiblity_changed_listener = None
        self.set_visibility_changed_fn(self._visibility_changed_fn)
def destroy(self):
    """
    Called by extension before destroying this object. It doesn't happen automatically.
    Without this hot reloading doesn't work.
    """
    print(f"[{self.__class__.__name__}] destroy")
    self._visiblity_changed_listener = None
    super().destroy()
    def _visibility_changed_fn(self, visible):
        print(f"[{self.__class__.__name__}] _visibility_changed_fn visible:{visible}")
        if self._visiblity_changed_listener:
            self._visiblity_changed_listener(visible)
    def set_visibility_changed_listener(self, listener):
        print(f"[{self.__class__.__name__}] set_visibility_changed_listener listener:{listener}")
        self._visiblity_changed_listener = listener
Radio Buttons#
from omni.kit.menu.utils import MenuItemDescription
import carb.input
import omni.kit.actions.core
def on_startup(self, ext_id):
    self._radio_one_value = 1
    self._radio_two_value = 0
    # register actions
    def radio_one_func(value):
        print(f">> radio button one clicked {value}")
        self._radio_one_value = value
    def radio_two_func(value):
        print(f">> radio button two clicked {value}")
        self._radio_two_value = value
    action_registry = omni.kit.actions.core.get_action_registry()
    for index in range(10):
        action_registry.register_action(
            "test.radio.buttons", f"clicked_one_{index}", lambda v=index: radio_one_func(v)
        )
        action_registry.register_action(
            "test.radio.buttons", f"clicked_two_{index}", lambda v=index: radio_two_func(v)
        )
    # create menu
    self.__radiomenu_list = [
        MenuItemDescription(
            name=f"Radio One {index}",
            radio_group="test1",
            onclick_action=("test.radio.buttons", f"clicked_one_{index}"),
            ticked_value=index == 1,
        )
        for index in range(10)
    ]
    self.__radiomenu_list += [MenuItemDescription()]
    self.__radiomenu_list += [
        MenuItemDescription(
            name=f"Radio Two {index}",
            radio_group="test2",
            onclick_action=("test.radio.buttons", f"clicked_two_{index}"),
            ticked_value=index == 0,
        )
        for index in range(10)
    ]
    omni.kit.menu.utils.add_menu_items(self.__radiomenu_list, "Edit", 99)
def on_shutdown(self):
    omni.kit.menu.utils.remove_menu_items(self.__radiomenu_list, "Edit", 99)
    # free actions
    action_registry = omni.kit.actions.core.get_action_registry()
    action_registry.deregister_all_actions_for_extension("test.radio.buttons")