In this document you learn how to create an Extension inside of Omniverse. Extensions are what make up Omniverse. This tutorial is ideal for those who are beginners to Omniverse Kit.
Omniverse is made up of all kinds of Extensions that were created by developers. In this section, you create an Extension and learn how the code gets reflected back in Omniverse.
With the Extension created, you can update the metadata in extension.toml. This is metadata is used in the Extension details of the Extensions Manager. It’s also used to inform other systems of the Application.
Currently, your window is called “My window”, and the button says, “Click Me”. In this step, you make some changes to better reflect the purpose of your Extension.
Navigate to omni/spawn/primitives/extension.py to find the following source code:
importomni.extimportomni.uiasui# Any class derived from `omni.ext.IExt` in top level module (defined in `python.modules` of `extension.toml`) will be# instantiated when extension gets enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled# on_shutdown() is called.classMyExtension(omni.ext.IExt):# ext_id is current extension id. It can be used with extension manager to query additional information, like where# this extension is located on filesystem.defon_startup(self,ext_id):print("[omni.example.spawn_prims] MyExtension startup")self._window=ui.Window("My Window",width=300,height=300)withself._window.frame:withui.VStack():ui.Label("Some Label")defon_click():print("clicked!")ui.Button("Click Me",clicked_fn=lambda:on_click())defon_shutdown(self):print("[omni.example.spawn_prims] MyExtension shutdown")
Next, change some values to better reflect what your Extension does.
After making the above changes, your code should read as follows:
importomni.extimportomni.uiasui# Any class derived from `omni.ext.IExt` in top level module (defined in `python.modules` of `extension.toml`) will be# instantiated when extension gets enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled# on_shutdown() is called.classMyExtension(omni.ext.IExt):# ext_id is current extension id. It can be used with extension manager to query additional information, like where# this extension is located on filesystem.defon_startup(self,ext_id):print("[omni.example.spawn_prims] MyExtension startup")self._window=ui.Window("Spawn Primitives",width=300,height=300)withself._window.frame:withui.VStack():defon_click():print("clicked!")ui.Button("Spawn Cube",clicked_fn=lambda:on_click())defon_shutdown(self):print("[omni.example.spawn_prims] MyExtension shutdown")
Save the file, and return to Omniverse Code. There, you’ll see your new
window with a large button saying “Spawn Cube”.
Commands are actions that take place inside of Omniverse. A simple command could be creating an object or changing a color. Commands are composed of a do and an undo feature.
Omniverse allows users and developers to see what commands are being executed as they work in the application. You can find this information in the Commands window:
You’ll use this window to quickly build out command-based functionality.
Now that you have the necessary tools, you learn how you can grab one of these commands and use it in the extension. Specifically, you use it create a cube. There are different ways you can create the cube, but for this example, you use Create menu in the top bar.
Paste the copied command into the bottom of the extension.py file. The whole file looks like this:
importomni.extimportomni.uiasui# Any class derived from `omni.ext.IExt` in top level module (defined in `python.modules` of `extension.toml`) will be# instantiated when extension gets enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled# on_shutdown() is called.classMyExtension(omni.ext.IExt):# ext_id is current extension id. It can be used with extension manager to query additional information, like where# this extension is located on filesystem.defon_startup(self,ext_id):print("[omni.example.spawn_prims] MyExtension startup")self._window=ui.Window("Spawn Primitives",width=300,height=300)withself._window.frame:withui.VStack():defon_click():print("clicked!")ui.Button("Spawn Cube",clicked_fn=lambda:on_click())defon_shutdown(self):print("[omni.example.spawn_prims] MyExtension shutdown")importomni.kit.commandsomni.kit.commands.execute('CreateMeshPrimWithDefaultXform',prim_type='Cube')
You added a new import and a command that creates a cube.
importomni.extimportomni.uiasuiimportomni.kit.commands# Any class derived from `omni.ext.IExt` in top level module (defined in `python.modules` of `extension.toml`) will be# instantiated when extension gets enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled# on_shutdown() is called.classMyExtension(omni.ext.IExt):# ext_id is current extension id. It can be used with extension manager to query additional information, like where# this extension is located on filesystem.defon_startup(self,ext_id):print("[omni.example.spawn_prims] MyExtension startup")self._window=ui.Window("Spawn Primitives",width=300,height=300)withself._window.frame:withui.VStack():defon_click():omni.kit.commands.execute('CreateMeshPrimWithDefaultXform',prim_type='Cube')print("clicked!")ui.Button("Spawn Cube",clicked_fn=lambda:on_click())defon_shutdown(self):print("[omni.example.spawn_prims] MyExtension shutdown")
In Omniverse Code, test your extension by clicking Spawn Cube. You should see that a new Cube prim is created with each button press.
Excellent, you now know how to spawn a cube using a function. What’s more, you didn’t have to reference anything as Omniverse Code was kind enough to deliver everything you needed.
Continuing on and via same methods, construct a second button that spawns a cone in the same interface.
Paste the command into extensions.py like you did before:
defon_click():#Create a Cubeomni.kit.commands.execute('CreateMeshPrimWithDefaultXform',prim_type='Cube')#Create a Coneomni.kit.commands.execute('CreateMeshPrimWithDefaultXform',prim_type='Cone')print("clicked!")
Notice the command is the same, and only the prim_type is different:
Great job! You’ve successfully created a second button that spawns a second mesh, all within the same Extension. This, of course, can be expanded upon.
Optional Challenge: Add a button for every mesh type on your own.
Below you can find a completed “cheat sheet” if you need help or just want to copy it for your own use.
Click to show the final code
importomni.extimportomni.uiasuiimportomni.kit.commands# Any class derived from `omni.ext.IExt` in top level module (defined in `python.modules` of `extension.toml`) will be# instantiated when extension gets enabled and `on_startup(ext_id)` will be called. Later when extension gets disabled# on_shutdown() is called.classMyExtension(omni.ext.IExt):# ext_id is current extension id. It can be used with extension manager to query additional information, like where# this extension is located on filesystem.defon_startup(self,ext_id):print("[omni.example.spawn_prims] MyExtension startup")self._window=ui.Window("Spawn Primitives",width=300,height=300)withself._window.frame:withui.VStack():defon_click(prim_type):omni.kit.commands.execute('CreateMeshPrimWithDefaultXform',prim_type=prim_type)print("clicked!")ui.Button("Spawn Cube",clicked_fn=lambda:on_click("Cube"))ui.Button("Spawn Cone",clicked_fn=lambda:on_click("Cone"))ui.Button("Spawn Cylinder",clicked_fn=lambda:on_click("Cylinder"))ui.Button("Spawn Disk",clicked_fn=lambda:on_click("Disk"))ui.Button("Spawn Plane",clicked_fn=lambda:on_click("Plane"))ui.Button("Spawn Sphere",clicked_fn=lambda:on_click("Sphere"))ui.Button("Spawn Torus",clicked_fn=lambda:on_click("Torus"))defon_shutdown(self):print("[omni.example.spawn_prims] MyExtension shutdown")