### Use Gradient Image Examples Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/docs/README.md Examples demonstrating the usage of the build_gradient_image function to create gradient backgrounds for UI elements. ```python colors = cls_color_gradient = [cl("#fa0405"), cl("#95668C"), cl("#4b53B4"), cl("#33C287"), cl("#9fE521"), cl("#ff0200")] byte_provider = build_gradient_image(colors, 8, "gradient_slider") cls_button_gradient = [cl("#232323"), cl("#656565")] button_background_gradient = build_gradient_image(cls_button_gradient, 22, "button_background_gradient") ``` -------------------------------- ### Clone UI Window Tutorial Repository Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Clone the starter branch of the kit-extension-sample-ui-window repository to begin the tutorial. This command fetches the necessary starting code. ```shell git clone -b ui-window-tutorial-start https://github.com/NVIDIA-Omniverse/kit-extension-sample-ui-window.git ``` -------------------------------- ### Explicitly Show Window on Startup Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Ensure the custom window is displayed when the extension starts up by calling `ui.Workspace.show_window()`. This uses the previously registered callback. ```python def on_startup(self): # The ability to show the window if the system requires it. # You use it in QuickLayout. ui.Workspace.set_show_window_fn(ExampleWindowExtension.WINDOW_NAME, partial(self.show_window, None)) # Add a Menu Item for the window editor_menu = omni.kit.ui.get_editor_menu() if editor_menu: self._menu = editor_menu.add_item( ExampleWindowExtension.MENU_PATH, self.show_window, toggle=True, value=True ) # Show the window through the 'set_show_window_fn' you wired up above # It will call `self.show_window` ui.Workspace.show_window(ExampleWindowExtension.WINDOW_NAME) ``` -------------------------------- ### Custom Path Button Widget Instantiation Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Example of how to instantiate the CustomPathButtonWidget with specific labels, an initial path, and a callback function. ```python CustomPathButtonWidget( label="Export Path", path=".../export/mesh1.usd", btn_label="Export", btn_callback=self.on_export_btn_click, ) ``` -------------------------------- ### Link Omniverse App by Path (Windows) Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/README.md On Windows, you can explicitly provide the path to your Omniverse Kit app installation when creating the folder link. ```bash > link_app.bat --path "C:/Users/bob/AppData/Local/ov/pkg/create-2022.1.3" ``` -------------------------------- ### Create Custom Window Class Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Derive a custom window from `ui.Window`. The UI can be defined directly in `__init__` or lazily via `set_build_fn`. This example uses `set_build_fn` and applies a custom style. ```python class PropertyWindowExample(ui.Window): """The class that represents the window""" def __init__(self, title: str, delegate=None, **kwargs): self.__label_width = LABEL_WIDTH super().__init__(title, **kwargs) # Apply the style to all the widgets of this window self.frame.style = julia_modeler_style # Set the function that is called to build widgets when the window is visible self.frame.set_build_fn(self._build_fn) ``` -------------------------------- ### Link Omniverse App (Windows) Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/README.md Use this script to create a folder link to your Omniverse Kit app installation on Windows. This is recommended for a better developer experience. ```bash > link_app.bat ``` -------------------------------- ### Link Omniverse App (Linux) Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/README.md Use this script to create a folder link to your Omniverse Kit app installation on Linux. This is recommended for a better developer experience. ```bash > link_app.sh ``` -------------------------------- ### Implementing Custom Widget Body Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Example of a child class implementing the _build_body() method to create a custom widget body, including a boolean image that reflects a default value. ```python def _build_body(self): with ui.HStack(): with ui.VStack(): ui.Spacer(height=2) self.__bool_image = ui.Image( name="checked" if self.__default_val else "unchecked", fill_policy=ui.FillPolicy.PRESERVE_ASPECT_FIT, height=16, width=16, checked=self.__default_val ) ui.Spacer() self.__bool_image.set_mouse_pressed_fn( lambda x, y, b, m: self._on_value_changed()) ``` -------------------------------- ### Custom Compound Widget Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/docs/README.md Create custom widgets by defining classes or functions that assemble sub-widgets. This example shows a compound widget for color input. ```python class ColorWidget: """The compound widget for color input""" def __init__(self, *args, model=None, **kwargs): self.__defaults: List[Union[float, int]] = args self.__model: Optional[ui.AbstractItemModel] = kwargs.pop("model", None) self.__multifield: Optional[ui.MultiFloatDragField] = None self.__colorpicker: Optional[ui.ColorWidget] = None self.__frame = ui.Frame() with self.__frame: self._build_fn() ``` -------------------------------- ### Modify Color Constants in style.py Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md This section shows how to change predefined color constants in `style.py` to customize gradient colors. For example, changing `cl_attribute_red` to a pink hex value. ```python # Pre-defined constants. It's possible to change them runtime. fl_attr_hspacing = 10 fl_attr_spacing = 1 fl_group_spacing = 5 cl_attribute_dark = cl("#202324") cl_attribute_red = cl("#fc03be") # previously was cl("#ac6060") cl_attribute_green = cl("#60ab7c") cl_attribute_blue = cl("#35889e") cl_line = cl("#404040") cl_text_blue = cl("#5eb3ff") cl_text_gray = cl("#707070") cl_text = cl("#a1a1a1") cl_text_hovered = cl("#ffffff") cl_field_text = cl("#5f5f5f") cl_widget_background = cl("#1f2123") cl_attribute_default = cl("#505050") cl_attribute_changed = cl("#55a5e2") cl_slider = cl("#383b3e") cl_combobox_background = cl("#252525") cl_main_background = cl("#2a2b2c") cls_temperature_gradient = [cl("#fe0a00"), cl("#f4f467"), cl("#a8b9ea"), cl("#2c4fac"), cl("#274483"), cl("#1f334e")] cls_color_gradient = [cl("#fa0405"), cl("#95668C"), cl("#4b53B4"), cl("#33C287"), cl("#9fE521"), cl("#ff0200")] cls_tint_gradient = [cl("#1D1D92"), cl("#7E7EC9"), cl("#FFFFFF")] cls_grey_gradient = [cl("#020202"), cl("#525252"), cl("#FFFFFF")] cls_button_gradient = [cl("#232323"), cl("#656565")] ``` -------------------------------- ### Startup Function for Julia Modeler Extension Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md The `on_startup` function initializes the extension by registering a show function, adding a menu item, and displaying the main window. This is a common pattern for window-based extensions. ```Python def on_startup(self): # The ability to show the window if the system requires it. We use it # in QuickLayout. ui.Workspace.set_show_window_fn(JuliaModelerExtension.WINDOW_NAME, partial(self.show_window, None)) # Add the new menu editor_menu = omni.kit.ui.get_editor_menu() if editor_menu: self._menu = editor_menu.add_item( JuliaModelerExtension.MENU_PATH, self.show_window, toggle=True, value=True ) # Show the window. It will call `self.show_window` ui.Workspace.show_window(JuliaModelerExtension.WINDOW_NAME) ``` -------------------------------- ### Clone Gradient Tutorial Repository Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Clone the specified branch of the kit-extension-sample-ui-window repository to access tutorial assets. ```shell git clone -b gradient-tutorial-start https://github.com/NVIDIA-Omniverse/kit-extension-sample-ui-window.git ``` -------------------------------- ### Initialize Custom UI Window Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Initialize a custom UI window by inheriting from `ui.Window`. Set the window title, apply styles, and define the function to build UI widgets when the window becomes visible. ```python def __init__(self, title: str, delegate=None, **kwargs): self.__label_width = LABEL_WIDTH super().__init__(title, **kwargs) # Apply the style to all the widgets of this window self.frame.style = example_window_style # Set the function that is called to build widgets when the window is # visible self.frame.set_build_fn(self._build_fn) ``` -------------------------------- ### Initialize Gradient Color Function Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Sets up the gradient color function by defining the step size and step interval based on the provided colors. ```python def get_gradient_color(value, max, colors): step_size = len(colors) - 1 step = 1.0/float(step_size) ``` -------------------------------- ### Instantiate Custom Window Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Call the constructor for your custom window class within the `show_window` method. This creates the window instance and assigns it to the extension's internal variable. ```python def show_window(self, menu, value): #value is true if the window should be shown if value: #call our custom window constructor self._window = ExampleWindow(ExampleWindowExtension.WINDOW_NAME, width=300, height=365) #Handles the change in visibility of the window gracefuly self._window.set_visibility_changed_fn(self._visiblity_changed_fn) elif self._window: self._window.visible = False ``` -------------------------------- ### Initial function stubs in style.py Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md These are the initial function definitions in the style.py file that need to be implemented. Remember to replace 'pass' with actual code. ```python def hex_to_color(hex: int) -> tuple: # YOUR CODE HERE pass def generate_byte_data(colors): # YOUR CODE HERE pass def _interpolate_color(hex_min: int, hex_max: int, intep): # YOUR CODE HERE pass def get_gradient_color(value, max, colors): # YOUR CODE HERE pass def build_gradient_image(colors, height, style_name): # YOUR CODE HERE pass ``` -------------------------------- ### Register Window with Workspace Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/docs/README.md Register a function to show the window using `ui.Workspace.set_show_window_fn`. This allows Kit to save and load the window's layout. ```python ui.Workspace.set_show_window_fn(ExampleWindowExtension.WINDOW_NAME, partial(self.show_window, None)) ``` -------------------------------- ### Initial _build_light_1 Function Structure Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md This is the initial structure of the _build_light_1 function before adding specific UI elements. It serves as a placeholder for building the 'Light 1' group. ```python def _build_light_1(self): # Build the widgets of the "Light 1" group # A multi float drag field lets you control a group of floats # Notice what you use the same label width in all of the collapsable frames # This ensures that the entire UI has a consistent feel #Feel free to copy this color widget and use it in your own UIs # The custom compound widget #An example of a checkbox pass ``` -------------------------------- ### Register Window with omni.ui.Workspace Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Register a window with `omni.ui.Workspace` using `set_show_window_fn`. This is crucial for saving and loading the layout of Kit. This function is typically called during extension startup. ```python ui.Workspace.set_show_window_fn(JuliaModelerExtension.WINDOW_NAME, partial(self.show_window, None)) ``` -------------------------------- ### Sample Callback for Export Button Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Provides a sample callback function for the export button, which displays a MessageDialog with the path provided to the button. ```python def on_export_btn_click(self, path): """Sample callback that is used when the Export button is pressed.""" dialog = MessageDialog( title="Button Pressed Dialog", message=f"Export Button was clicked with path inside: {path}", disable_cancel_button=True, ok_handler=lambda dialog: dialog.hide() ) dialog.show() ``` -------------------------------- ### Clone Omniverse Extension Repository Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Clone the main branch of the kit-extension-sample-ui-window GitHub repository to access the tutorial's code. ```shell git clone https://github.com/NVIDIA-Omniverse/kit-extension-sample-ui-window.git ``` -------------------------------- ### Create Gradient Image with ImageWithProvider Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Complete the `build_gradient_image` function by using `omni.ui.ImageWithProvider` to transform the byte sequence into a UI image. The function returns the byte provider. ```python def build_gradient_image(colors, height, style_name): byte_provider = generate_byte_data(colors) ui.ImageWithProvider(byte_provider,fill_policy=omni.ui.IwpFillPolicy.IWP_STRETCH, height=height, name=style_name) return byte_provider ``` -------------------------------- ### Create ByteImageProvider with Gradient Data Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Generate byte data from a list of colors and set it using `ByteImageProvider`. This prepares the data for rendering an image, likely a gradient. ```python def generate_byte_data(colors): data = [] for color in colors: data += hex_to_color(color) _byte_provider = ui.ByteImageProvider() _byte_provider.set_bytes_data(data [len(colors), 1]) return _byte_provider ``` -------------------------------- ### Initial _build_parameters Function Structure Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md This is the initial structure of the _build_parameters function before adding any UI elements. It serves as a placeholder. ```python def _build_parameters(self): # Build the widgets of the "Parameters" group # A Float Slider is similar to an Int Slider # controls a 'float' which is a number with a decimal point (A Real number) # You can set the min and max of a float slider as well # Setting the labels all to the same width gives the UI a nice alignment # A few more examples of float sliders pass ``` -------------------------------- ### Initialize Byte Data Array Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Initialize an empty list to store color values. This is the first step in preparing data for image generation. ```python def generate_byte_data(colors): data = [] ``` -------------------------------- ### Add VStack and HStack for Layout Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Implements a VStack containing an HStack to demonstrate a common UI pattern for aligning labels with controls. ```python def _build_calculations(self): # Build the widgets of the "Calculations" group with ui.CollapsableFrame("Calculations", name="group", build_header_fn=self._build_collapsable_header): # A VStack is a vertical stack and aligns widgets vertically one after the other with ui.VStack(height=0, spacing=SPACING): # An HStack is a horizontal stack and aligns widgets horizontally one after the other with ui.HStack(): # A label displays text # An IntSlider allows a user choose an integer by sliding a bar back and forth pass # Pairing a label with a control is a common UI comb # The label makes the purpose of the control clear # You can set the min and max value on an IntSlider pass ``` -------------------------------- ### Register Window with UI Workspace Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/docs/README.md Register the window with `ui.Workspace.set_show_window_fn` to enable saving and loading its layout within Kit. This function is called when the system requires the window to be shown. ```python # The ability to show up the window if the system requires it. We use it # in QuickLayout. ui.Workspace.set_show_window_fn(ExampleWindowExtension.WINDOW_NAME, partial(self.show_window, None)) ``` -------------------------------- ### JuliaModelerWindow Constructor Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Initializes the JuliaModelerWindow, setting label width, calling the superclass constructor, applying styles, and registering the build function. ```python def __init__(self, title: str, delegate=None, **kwargs): self.__label_width = ATTR_LABEL_WIDTH super().__init__(title, **kwargs) # Apply the style to all the widgets of this window self.frame.style = julia_modeler_style # Set the function that is called to build widgets when the window is # visible self.frame.set_build_fn(self._build_fn) ``` -------------------------------- ### Define build_gradient_image Function Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md This is the initial structure of the `build_gradient_image` function in `style.py`. It serves as a placeholder before implementation. ```python def build_gradient_image(colors, height, style_name): # YOUR CODE HERE pass ``` -------------------------------- ### Register Window Show Callback Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Register a callback function to allow Omniverse to show the window when needed. This is essential for managing window visibility externally. ```python def on_startup(self): # The ability to show the window if the system requires it. We use it # in QuickLayout. ui.Workspace.set_show_window_fn(ExampleWindowExtension.WINDOW_NAME, partial(self.show_window, None)) # Add a Menu Item for the window # Show the window through the 'set_show_window_fn' you wired up above # It will call `self.show_window` ``` -------------------------------- ### Define a Custom UI Window Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/docs/README.md Derive from `ui.Window` to create a custom window. Styles are applied to the window's frame, and the UI build function is set using `set_build_fn`. ```python class PropertyWindowExample(ui.Window): """The class that represents the window""" def __init__(self, title: str, delegate=None, **kwargs): self.__label_width = LABEL_WIDTH super().__init__(title, **kwargs) # Apply the style to all the widgets of this window self.frame.style = example_window_style # Set the function that is called to build widgets when the window is visible self.frame.set_build_fn(self._build_fn) ``` -------------------------------- ### Build Calculations Group Stub Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md This is the initial structure for the '_build_calculations' function, serving as a placeholder before adding UI elements. ```python def _build_calculations(self): # Build the widgets of the "Calculations" group # A VStack is a vertical stack and aligns widgets vertically one after the other # An HStack is a horizontal stack and aligns widgets horizontally one after the other # A label displays text # An IntSlider lets a user choose an integer by sliding a bar back and forth # Pairing a label with a control is a common UI comb # The label makes the purpose of the control clear # You can set the min and max value on an IntSlider pass ``` -------------------------------- ### Create a Scrolling Frame for UI Content Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Implement the `_build_fn` to create a `ui.ScrollingFrame`. This provides a scrollable area for your UI content, ensuring all elements are accessible even when the window is resized to be smaller. ```python def _build_fn(self): # The method that is called to build all the UI once the window is visible. with ui.ScrollingFrame(): pass ``` -------------------------------- ### Custom Path & Button Widget Build Function Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Demonstrates the construction of a custom widget that combines a label, a string field for path input, and a button within a horizontal stack. ```python with ui.HStack(): ui.Label( self.__attr_label, name="attribute_name", width=ATTR_LABEL_WIDTH ) self.__pathfield = ui.StringField( name="path_field", height=BLOCK_HEIGHT, width=ui.Fraction(2), ) self.__pathfield.model.set_value(self.__path) self.__btn = ui.Button( self.__btn_label, name="tool_button", height=BLOCK_HEIGHT, width=ui.Fraction(1), clicked_fn=lambda path=self.get_path(): self.__callback(path), ) ``` -------------------------------- ### Define UI Widget Styles Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Set font sizes for various UI elements. It's recommended to keep style definitions in a single location like `styles.py` for better organization, even if it means using seemingly redundant constants. ```python fl.window_title_font_size = 18 fl.field_text_font_size = 14 fl.main_label_font_size = 14 fl.multi_attr_label_font_size = 14 fl.radio_group_font_size = 14 fl.collapsable_header_font_size = 13 fl.range_text_size = 10 ``` -------------------------------- ### Organize UI Elements with Separate Build Functions Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Break down the UI construction into separate functions called from `_build_fn` for better organization. This approach is recommended for complex user interfaces, making them more manageable and maintainable. ```python def _build_fn(self): # The method that is called to build all the UI once the window is visible. with ui.ScrollingFrame(): with ui.VStack(height=0): self._build_calculations() self._build_parameters() self._build_light_1() ``` -------------------------------- ### Build Parameters Section Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Constructs the 'Parameters' section of the UI, featuring a collapsable frame and a series of custom slider widgets with defined ranges and default values. ```python def _build_parameters(self): """Build the widgets of the "Parameters" group""" with ui.CollapsableFrame("Parameters".upper(), name="group", build_header_fn=self._build_collapsable_header): with ui.VStack(height=0, spacing=SPACING): ui.Spacer(height=6) CustomSliderWidget(min=-2, max=2, display_range=True, label="Iterations", default_val=0.75) CustomSliderWidget(min=0, max=2, display_range=True, label="i", default_val=0.65) CustomSliderWidget(min=0, max=2, display_range=True, label="j", default_val=0.25) CustomSliderWidget(min=0, max=2, display_range=True, label="k", default_val=0.55) CustomSliderWidget(min=0, max=3.14, display_range=True, label="Theta", default_val=1.25) ``` -------------------------------- ### Show Window Function for Julia Modeler Extension Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md The `show_window` function handles the visibility of the Julia Modeler extension window. It creates and configures the window when `value` is True, and hides it when `value` is False. ```Python def show_window(self, menu, value): if value: self._window = JuliaModelerWindow( JuliaModelerExtension.WINDOW_NAME, width=WIN_WIDTH, height=WIN_HEIGHT) self._window.set_visibility_changed_fn(self._visiblity_changed_fn) elif self._window: self._window.visible = False ``` -------------------------------- ### Build Gradient Image Widget Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/docs/README.md Encapsulates gradient image generation using ByteImageProvider. Useful for creating custom slider or field backgrounds. ```python def hex_to_color(hex: int) -> tuple: # convert Value from int red = hex & 255 green = (hex >> 8) & 255 blue = (hex >> 16) & 255 alpha = (hex >> 24) & 255 rgba_values = [red, green, blue, alpha] return rgba_values def generate_byte_data(colors): data = [] for color in colors: data += hex_to_color(color) _byte_provider = ui.ByteImageProvider() _byte_provider.set_bytes_data(data, [len(colors), 1]) return _byte_provider def build_gradient_image(colors, height, style_name): byte_provider = generate_byte_data(colors) ui.ImageWithProvider(byte_provider,fill_policy=omni.ui.IwpFillPolicy.IWP_STRETCH, height=height, name=style_name) return byte_provider ``` -------------------------------- ### Generate Byte Data for Gradient Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Implement the `build_gradient_image` function by calling `generate_byte_data` to create the byte sequence for the gradient. ```python def build_gradient_image(colors, height, style_name): byte_provider = generate_byte_data(colors) ``` -------------------------------- ### Build Light 1 UI Group Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md This Python code defines the UI elements for the 'Light 1' group, including labels and input controls like MultiFloatDragField, FloatSlider, ColorWidget, and CheckBox. It demonstrates how to maintain consistent UI alignment using shared label widths. ```python def _build_light_1(self): # Build the widgets of the "Light 1" group with ui.CollapsableFrame("Light 1", name="group", build_header_fn=self._build_collapsable_header): with ui.VStack(height=0, spacing=SPACING): with ui.HStack(): ui.Label("Orientation", name="attribute_name", width=self.label_width) # A multi float drag field lets you control a group of floats (Real numbers) ui.MultiFloatDragField(0.0, 0.0, 0.0, h_spacing=SPACING, name="attribute_vector") # Notice what you use the same label width in all of the collapsable frames # This ensures that the entire UI has a consistent feel with ui.HStack(): ui.Label("Intensity", name="attribute_name", width=self.label_width) ui.FloatSlider(name="attribute_float") #Feel free to copy this color widget and use it in your own UIs with ui.HStack(): ui.Label("Color", name="attribute_name", width=self.label_width) # The custom compound widget ColorWidget(0.25, 0.5, 0.75) #An example of a checkbox with ui.HStack(): ui.Label("Shadow", name="attribute_name", width=self.label_width) ui.CheckBox(name="attribute_bool") ``` -------------------------------- ### Custom Slider Widget Implementation Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Illustrates the combination of ui.FloatSlider/ui.IntSlider and ui.FloatField/ui.IntField to create a custom slider widget with advanced features like background textures and range display. ```python self.__color_sub = self.__colorpicker.model.subscribe_item_changed_fn( lambda m, _, children=color_model.get_item_children(): self.set_color_stringfield(m, children)) self.__strfield_sub = self.__strfield.model.subscribe_value_changed_fn( lambda m, children=color_model.get_item_children(): self.set_color_widget(m, children)) ``` -------------------------------- ### Utilize Gradient Images in UI Widgets Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md This snippet shows how `build_gradient_image` is used to create gradient backgrounds for UI elements like buttons in `color_widget.py`. It demonstrates creating red, green, and blue gradients. ```python self.color_button_gradient_R = build_gradient_image([cl_attribute_dark, cl_attribute_red], 22, "button_background_gradient") ui.Spacer(width=9) with ui.VStack(width=6): ui.Spacer(height=8) ui.Circle(name="group_circle", width=4, height=4) self.color_button_gradient_G = build_gradient_image([cl_attribute_dark, cl_attribute_green], 22, "button_background_gradient") ui.Spacer(width=9) with ui.VStack(width=6): ui.Spacer(height=8) ui.Circle(name="group_circle", width=4, height=4) self.color_button_gradient_B = build_gradient_image([cl_attribute_dark, cl_attribute_blue], 22, "button_background_gradient") ``` -------------------------------- ### Complete hex_to_color function Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md This is the complete solution for the hex_to_color function, including the implementation for blue and alpha components using bitwise operations. ```python def hex_to_color(hex: int) -> tuple: # convert Value from int red = hex & 255 green = (hex >> 8) & 255 blue = (hex >> 16) & 255 alpha = (hex >> 24) & 255 rgba_values = [red, green, blue, alpha] return rgba_values ``` -------------------------------- ### Custom Window Class Definition Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/docs/README.md Derive a custom window from `ui.Window` to define its UI. The UI can be built directly in the `__init__` method or in a separate callback function set by `self.frame.set_build_fn`. ```python class ExampleWindow(ui.Window): """The class that represents the window""" def __init__(self, title: str, delegate=None, **kwargs): self.__label_width = LABEL_WIDTH super().__init__(title, **kwargs) # Apply the style to all the widgets of this window self.frame.style = example_window_style # Set the function that is called to build widgets when the window is # visible self.frame.set_build_fn(self._build_fn) ``` -------------------------------- ### Add a Second Label/IntSlider Pair with Min/Max Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Add another Label and IntSlider pair to an HStack for consistent UI alignment. Configure the IntSlider with specific minimum and maximum values. ```python def _build_calculations(self): # Build the widgets of the "Calculations" group with ui.CollapsableFrame("Calculations", name="group", build_header_fn=self._build_collapsable_header): # A VStack is a vertical stack and aligns widgets vertically one after the other with ui.VStack(height=0, spacing=SPACING): # An HStack is a horizontal stack and aligns widgets horizontally one after the other with ui.HStack(): # A label displays text ui.Label("Precision", name="attribute_name", width=self.label_width) # An IntSlider allows a user choose an integer by sliding a bar back and forth ui.IntSlider(name="attribute_int") # Pairing a label with a control is a common UI comb with ui.HStack(): # The label makes the purpose of the control clear ui.Label("Iterations", name="attribute_name", width=self.label_width) # You can set the min and max value on an IntSlider ui.IntSlider(name="attribute_int", min=0, max=5) ``` -------------------------------- ### Add Custom Color Widget to UI Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Integrates a custom ColorWidget into the UI, allowing users to select colors. This demonstrates the extensibility of the UI system with custom compound widgets. ```python def _build_light_1(self): # Build the widgets of the "Light 1" group with ui.CollapsableFrame("Light 1", name="group", build_header_fn=self._build_collapsable_header): with ui.VStack(height=0, spacing=SPACING): with ui.HStack(): ui.Label("Orientation", name="attribute_name", width=self.label_width) # A multi float drag field lets you control a group of floats (Real numbers) ui.MultiFloatDragField(0.0, 0.0, 0.0, h_spacing=SPACING, name="attribute_vector") # Notice what you use the same label width in all of the collapsable frames # This ensures that the entire UI has a consistent feel with ui.HStack(): ui.Label("Intensity", name="attribute_name", width=self.label_width) ui.FloatSlider(name="attribute_float") #Feel free to copy this color widget and use it in your own UIs with ui.HStack(): ui.Label("Color", name="attribute_name", width=self.label_width) # The custom compound widget ColorWidget(0.25, 0.5, 0.75) #An example of a checkbox ``` -------------------------------- ### JuliaModelerWindow Build Function Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Defines the main UI structure for the JuliaModelerWindow by creating a scrolling frame and a vertical stack, then calling methods to build specific sections. ```python def _build_fn(self): """ The method that is called to build all the UI once the window is visible. """ with ui.ScrollingFrame(name="window_bg", horizontal_scrollbar_policy=ui.ScrollBarPolicy.SCROLLBAR_ALWAYS_OFF): with ui.VStack(height=0): self._build_title() self._build_calculations() self._build_parameters() self._build_light_1() self._build_scene() ``` -------------------------------- ### Calculate Gradient Percentage and Index Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Calculates the current percentage along the gradient and determines the index of the closest color. ```python def get_gradient_color(value, max, colors): step_size = len(colors) - 1 step = 1.0/float(step_size) percentage = value / float(max) idx = (int) (percentage / step) ``` -------------------------------- ### Link Specific Omniverse App (Windows) Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/README.md On Windows, you can specify which Omniverse app to link to by passing the app name as an argument to the link script. ```bash > link_app.bat --app code ``` -------------------------------- ### Create a FloatSlider Widget Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Adds a FloatSlider widget to the UI within a CollapsableFrame and VStack. Ensure labels have consistent width for alignment. ```python def _build_parameters(self): # Build the widgets of the "Parameters" group with ui.CollapsableFrame("Parameters", name="group", build_header_fn=self._build_collapsable_header): with ui.VStack(height=0, spacing=SPACING): with ui.HStack(): ui.Label("Value", name="attribute_name", width=self.label_width) # A Float Slider is similar to an Int Slider # controls a 'float' which is a number with a decimal point (A Real number) ui.FloatSlider(name="attribute_float") # You can set the min and max of a float slider as well # Setting the labels all to the same width gives the UI a nice alignment # A few more examples of float sliders ``` -------------------------------- ### Convert Hex Colors to Byte Data Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Loop through provided hex color strings, convert them to color values using `hex_to_color`, and append them to the data list. ```python def generate_byte_data(colors): data = [] for color in colors: data += hex_to_color(color) ``` -------------------------------- ### Implement Red conversion in hex_to_color Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Add the line to convert the hex value to its red component using a bitwise AND operation. ```python def hex_to_color(hex: int) -> tuple: # convert Value from int red = hex & 255 ``` -------------------------------- ### Add Window to Application Menu Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Add a menu item to the Omniverse application menu to allow users to toggle the visibility of your custom window. This ensures users can reopen the window if it's closed. ```python def on_startup(self): # The ability to show the window if the system requires it. # You use it in QuickLayout. ui.Workspace.set_show_window_fn(ExampleWindowExtension.WINDOW_NAME, partial(self.show_window, None)) # Add a Menu Item for the window editor_menu = omni.kit.ui.get_editor_menu() if editor_menu: self._menu = editor_menu.add_item( ExampleWindowExtension.MENU_PATH, self.show_window, toggle=True, value=True ) # Show the window through the 'set_show_window_fn' you wired up above # It will call `self.show_window` ``` -------------------------------- ### Build Widget Body in Python Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Provides the core content area for a custom widget. This method is intended to be overridden by subclasses to define specific widget behavior and UI elements. ```Python def _build_body(self): """Build the custom part of the widget. Most custom widgets will override this method, as it is where the meat of the custom widget is. """ ui.Spacer() ``` -------------------------------- ### Implement Green conversion in hex_to_color Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Add the line to convert the hex value to its green component using a bitwise right shift and AND operation. ```python def hex_to_color(hex: int) -> tuple: # convert Value from int red = hex & 255 green = (hex >> 8) & 255 ``` -------------------------------- ### Build Widget Tail in Python Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Constructs the right-most section of the widget, including a revert arrow button. This function ensures a consistent look and feel across all custom widgets by providing a standard way to reset values. ```Python def _build_tail(self): """Build the right-most piece of the widget line. In this case, we have a Revert Arrow button at the end of each widget line. """ with ui.HStack(width=0): ui.Spacer(width=5) with ui.VStack(height=0): ui.Spacer(height=3) self.revert_img = ui.Image( name="revert_arrow", fill_policy=ui.FillPolicy.PRESERVE_ASPECT_FIT, width=12, height=13, enabled=False, ) ui.Spacer(width=5) # call back for revert_img click, to restore the default value self.revert_img.set_mouse_pressed_fn( lambda x, y, b, m: self._restore_default()) ``` -------------------------------- ### Handle Gradient Index Boundary Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Ensures the index does not exceed the bounds of the color list, returning the last color if it does. ```python def get_gradient_color(value, max, colors): step_size = len(colors) - 1 step = 1.0/float(step_size) percentage = value / float(max) idx = (int) (percentage / step) if idx == step_size: color = colors[-1] ``` -------------------------------- ### Base Custom Widget Structure Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/docs/README.md Defines the structure for custom widgets with methods to build the head, body, and tail sections, and a method to assemble them. Child classes typically override _build_body(). ```python def _build_head(self): # The main attribute label ui.Label( self.__attr_label, name="attribute_name", width=ATTR_LABEL_WIDTH ) def _build_body(self): # Most custom widgets will override this method, # as it is where the meat of the custom widget is ui.Spacer() def _build_tail(self): # In this case, we have a Revert Arrow button # at the end of each widget line with ui.HStack(width=0): ui.Spacer(width=5) with ui.VStack(height=0): ui.Spacer(height=3) self.revert_img = ui.Image( name="revert_arrow", fill_policy=ui.FillPolicy.PRESERVE_ASPECT_FIT, width=12, height=13, enabled=False, ) ui.Spacer(width=5) # add call back to revert_img click to restore the default value self.revert_img.set_mouse_pressed_fn( lambda x, y, b, m: self._restore_default()) def _build_fn(self): # Put all the parts together with ui.HStack(): self._build_head() self._build_body() self._build_tail() ``` -------------------------------- ### Add Multiple FloatSliders with Min/Max Values Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Adds several FloatSlider widgets to the UI, demonstrating the use of min and max attributes for controlling the slider range. Consistent label widths are maintained for alignment. ```python def _build_parameters(self): # Build the widgets of the "Parameters" group with ui.CollapsableFrame("Parameters", name="group", build_header_fn=self._build_collapsable_header): with ui.VStack(height=0, spacing=SPACING): with ui.HStack(): ui.Label("Value", name="attribute_name", width=self.label_width) # A Float Slider is similar to an Int Slider # controls a 'float' which is a number with a decimal point (A Real number) ui.FloatSlider(name="attribute_float") with ui.HStack(): ui.Label("i", name="attribute_name", width=self.label_width) # You can set the min and max of a float slider as well ui.FloatSlider(name="attribute_float", min=-1, max=1) # Setting the labels all to the same width gives the UI a nice alignment with ui.HStack(): ui.Label("j", name="attribute_name", width=self.label_width) ui.FloatSlider(name="attribute_float", min=-1, max=1) # A few more examples of float sliders with ui.HStack(): ui.Label("k", name="attribute_name", width=self.label_width) ui.FloatSlider(name="attribute_float", min=-1, max=1) with ui.HStack(): ui.Label("Theta", name="attribute_name", width=self.label_width) ui.FloatSlider(name="attribute_float") ``` -------------------------------- ### Add CollapsableFrame to Calculations Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Introduces a CollapsableFrame to group UI elements. This control can be expanded or contracted by clicking its header. ```python def _build_calculations(self): # Build the widgets of the "Calculations" group with ui.CollapsableFrame("Calculations", name="group", build_header_fn=self._build_collapsable_header): # A VStack is a vertical stack and aligns widgets vertically one after the other # An HStack is a horizontal stack and aligns widgets horizontally one after the other # A label displays text # An IntSlider lets a user choose an integer by sliding a bar back and forth # Pairing a label with a control is a common UI comb # The label makes the purpose of the control clear # You can set the min and max value on an IntSlider pass ``` -------------------------------- ### Build Widget Head in Python Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Implements the left-most part of a custom widget, typically a label. This function is part of the base widget class and aligns labels across all custom controls. ```Python def _build_head(self): """Build the left-most piece of the widget line (label in this case)""" ui.Label( self.__attr_label, name="attribute_name", width=ATTR_LABEL_WIDTH ) ``` -------------------------------- ### Add a Label to an HStack Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_window/tutorial/tutorial.md Add a Label widget to an HStack for displaying text. Ensure consistent alignment by setting a fixed width for labels within their respective HStacks. ```python def _build_calculations(self): # Build the widgets of the "Calculations" group with ui.CollapsableFrame("Calculations", name="group", build_header_fn=self._build_collapsable_header): # A VStack is a vertical stack and aligns widgets vertically one after the other with ui.VStack(height=0, spacing=SPACING): # An HStack is a horizontal stack and aligns widgets horizontally one after the other with ui.HStack(): # A label displays text ui.Label("Precision", name="attribute_name", width=self.label_width) # An IntSlider allows a user choose an integer by sliding a bar back and forth # Pairing a label with a control is a common UI comb # The label makes the purpose of the control clear # You can set the min and max value on an IntSlider ``` -------------------------------- ### Define Color Interpolation Function Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Initializes the color interpolation function by defining the maximum and minimum colors based on hex values. ```python def _interpolate_color(hex_min: int, hex_max: int, intep): max_color = hex_to_color(hex_max) min_color = hex_to_color(hex_min) ``` -------------------------------- ### Build Custom Slider Widget Body Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md This function constructs the main UI elements for a custom slider widget, including an image background, a slider, and a number field. It uses nested stacks and conditional logic to adapt to float or integer types and display range information. ```Python def _build_body(self): """Main meat of the widget. Draw the Slider, display range text, Field, and set up callbacks to keep them updated. """ with ui.HStack(spacing=0): # the user provided a list of default values with ui.VStack(spacing=3, width=ui.Fraction(3)): with ui.ZStack(): # Put texture image here, with rounded corners, then make slider # bg be fully transparent, and fg be gray and partially transparent with ui.Frame(width=SLIDER_WIDTH, height=FIELD_HEIGHT, horizontal_clipping=True): # Spacing is negative because "tileable" texture wasn't # perfectly tileable, so that adds some overlap to line up better. with ui.HStack(spacing=-12): for i in range(50): # tiling the texture ui.Image(name=TEXTURE_NAME, fill_policy=ui.FillPolicy.PRESERVE_ASPECT_CROP, width=50,) slider_cls = ( ui.FloatSlider if self.__num_type == "float" else ui.IntSlider ) self.__slider = slider_cls( height=FIELD_HEIGHT, min=self.__min, max=self.__max, name="attr_slider" ) if self.__display_range: self._build_display_range() with ui.VStack(width=ui.Fraction(1)): model = self.__slider.model model.set_value(self.__default_val) field_cls = ( ui.FloatField if self.__num_type == "float" else ui.IntField ) # Note: This is a hack to allow for text to fill the Field space more, as there was a bug # with Field padding. It is fixed, and will be available in the next release of Kit. with ui.ZStack(): # height=FIELD_HEIGHT-1 to account for the border, so the field isn't # slightly taller than the slider ui.Rectangle( style_type_name_override="Field", name="attr_field", height=FIELD_HEIGHT - 1 ) with ui.HStack(height=0): ui.Spacer(width=2) self.__numberfield = field_cls( model, height=0, style={ "background_color": cl.transparent, "border_color": cl.transparent, "padding": 4, "font_size": fl.field_text_font_size, }, ) if self.__display_range: ui.Spacer() ``` -------------------------------- ### Return Interpolated Color as Integer Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_gradient_window/tutorial/tutorial.md Completes the color interpolation by calculating the final color value and returning it as an integer. ```python def _interpolate_color(hex_min: int, hex_max: int, intep): max_color = hex_to_color(hex_max) min_color = hex_to_color(hex_min) color = [int((max - min) * intep) + min for max, min in zip(max_color, min_color)] return (color[3] << 8 * 3) + (color[2] << 8 * 2) + (color[1] << 8 * 1) + color[0] ``` -------------------------------- ### CustomSliderWidget Inheritance Source: https://github.com/nvidia-omniverse/kit-extension-sample-ui-window/blob/main/exts/omni.example.ui_julia_modeler/tutorial/tutorial.md Demonstrates inheritance in Python, where CustomSliderWidget inherits from CustomBaseWidget, indicating a hierarchical class structure for custom UI elements. ```python class CustomSliderWidget(CustomBaseWidget): ```