Stage Preview Window
In order to display the Renderer’s output, we’ll need to have an omni.ui.window
that will host our widget. We’re interested in this level primarily to demonstrate the
ability to create a ViewportWidget
that isn’t tied to the application’s main UsdContext
;
rather you can provide a usd_context_name string argument and the StagePreviewWindow
will
either reuse an existing UsdContext
with that name, or create a new one.
Keep in mind a ViewportWidget
is currently tied to exactly one UsdContext
for its lifetime.
If you wanted to change the UsdContext
you are viewing, you would need to hide and show a new ViewportWidget
based
on which context you want to be displayed.
Context creation
The first step we take is to check whether the named UsdContext
exists, and if not, create it.
# We may be given an already valid context, or we'll be creating and managing it ourselves
usd_context = omni.usd.get_context(usd_context_name)
if not usd_context:
self.__usd_context_name = usd_context_name
self.__usd_context = omni.usd.create_context(usd_context_name)
else:
self.__usd_context_name = None
self.__usd_context = None
Viewport creation
Once we know a valid context with usd_context_name exists, we create the omni.ui.Window
passing along
the window size and window flags. The omni.ui
documentation has more in depth description of what an omni.ui.Window
is and the arguments for it’s creation.
After the omni.ui.Window
has been created, we’ll finally be able to create the StagePreviewWidget
, passing along
the usd_context_name
. We do this within the context of the omni.ui.Window.frame
property, and forward any
additional arguments to the StagePreviewWidget
constructor.
super().__init__(title, width=window_width, height=window_height, flags=flags)
with self.frame:
self.__preview_viewport = StagePreviewWidget(usd_context_name, *vp_args, **vp_kw_args)
Full code
class StagePreviewWindow(ui.Window):
def __init__(self, title: str, usd_context_name: str = '', window_width: int = 1280, window_height: int = 720 + 20, flags: int = ui.WINDOW_FLAGS_NO_SCROLLBAR, *vp_args, **vp_kw_args):
"""StagePreviewWindow contructor
Args:
title (str): The name of the Window.
usd_context_name (str): The name of a UsdContext this Viewport will be viewing.
window_width(int): The width of the Window.
window_height(int): The height of the Window.
flags(int): ui.WINDOW flags to use for the Window.
*vp_args, **vp_kw_args: Additional arguments to pass to the StagePreviewWidget
"""
# We may be given an already valid context, or we'll be creating and managing it ourselves
usd_context = omni.usd.get_context(usd_context_name)
if not usd_context:
self.__usd_context_name = usd_context_name
self.__usd_context = omni.usd.create_context(usd_context_name)
else:
self.__usd_context_name = None
self.__usd_context = None
super().__init__(title, width=window_width, height=window_height, flags=flags)
with self.frame:
self.__preview_viewport = StagePreviewWidget(usd_context_name, *vp_args, **vp_kw_args)
def __del__(self):
self.destroy()
@property
def preview_viewport(self):
return self.__preview_viewport
def open_stage(self, file_path: str):
# Reach into the StagePreviewWidget and get the viewport where we can retrieve the usd_context or usd_context_name
self.__preview_viewport.viewport_api.usd_context.open_stage(file_path)
# the Viewport doesn't have any idea of omni.ui.scene so give the models a sync after open (camera may have changed)
self.__preview_viewport.sync_models()
def destroy(self):
if self.__preview_viewport:
self.__preview_viewport.destroy()
self.__preview_viewport = None
if self.__usd_context:
# We can't fully tear down everything yet, so just clear out any active stage
self.__usd_context.remove_all_hydra_engines()
# self.__usd_context = None
# omni.usd.destroy_context(self.__usd_context_name)
super().destroy()