# 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.
  
![](preview_window.png)

## Context creation

The first step we take is to check whether the named `UsdContext` exists, and if not, create it.
```python
# 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.

```python
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

```python
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()
```
