Part Three: Create Your Own Nodes#

In Part Three of this tutorial, you create a custom node to implement logic that’s similar to what you used in your Push Graph.

OmniGraph offers a framework for creating nodes called OmniGraph Nodes (OGN). This framework takes a high-level description of the node and generates most of its implementation. The implementation can be in Python, as you’ll see in this tutorial, or C++. Furthermore, it can even generate documentation and tests for the node.

In this tutorial, you create two nodes:

  • Negate Double

  • Add Double

Together, these replace the functionality of the Subtract Double node you used in Part Two.

Open the Node Description Editor#

In the Window menu, click Visual Scripting > Node Description Editor:

Numbered steps for opening the Node Description Editor.

This opens the OmniGraph Node Description Editor panel:

The Node Description Editor.

Create a Negate Double Node#

The first that node you create in this tutorial is Negate Double.

Assign the Node Properties#

In the Node Properties section of the Node Description Editor panel, set the following properties:

Property

Description

Value

Name

The name of the node as it appears in the graph.

NegateDouble

Description

A description of the node’s compute algorithm.

Accepts a double as input and negates it

UI Name

The name of the node as it appears in user interface (UI) elements.

Negate Double

Leave the other values as their defaults:

The filled-out node properties.

Caution

In case you poke around other parts of the editor, don’t change the Extension Location field from its default value. Omniverse USD Composer, or whatever App you use, only looks for Extensions in a fixed number of locations. The default Extension Location is included in this list.

Add a Node Input#

In the Input Attributes section, click the Add new attribute button, and set the following attribute properties:

Property

Description

Value

Name

The name of the attribute.

in_double

Description

A description of the information that the attribute holds.

Input double

Attribute Type

The data type that the attribute manages.

Properties:

  • Base Type: double

  • Tuple Count: 1

  • Array: False

UI Name

The name of the attribute as it appears in UI elements.

Input Double

Leave the other values as their defaults:

Numbered instructions for filling in the input double attribute.

Add a Node Output#

In the Output Attributes section, click the Add new attribute button, and set the following attribute properties:

Property

Description

Value

Name

The name of the attribute.

out_double

Description

A description of the information that the attribute holds.

Output double

Attribute Type

The data type that the attribute manages.

Properties:

  • Base Type: double

  • Tuple Count: 1

  • Array: False

UI Name

The name of the attribute as it appears in UI elements.

Output Double

Leave the other values as their defaults:

Numbered instructions for filling in the output double attribute.

Review the Raw OGN Data#

Read the raw data in the Raw .ogn Data section:

The auto-generated raw .ogn data.

This data describes what the node looks like from a high level. In the next steps, you’ll store this data in an .ogn file and instruct OGN to parse it and generate Python template code, documentation, and tests.

Populate Your Extension#

In the Extension Management section, click Populate Extension:

Numbered steps for saving your node properties and generating the code from them.

This establishes your extension within the OGN framework.

Note

Notice the red Clean Extension button next to Populate Extension. This ensures that the generated files in the OGN directory match the expected files for the Extension. It removes extra files that might have accumulated over time, throughout changes to your Extension. It’s a good idea to click it if things aren’t working as you expect, but make sure you verify that your nodes look correct, first!

Generate an OGN File#

In the Node Properties section, click Save Node:

Numbered steps for generating an .ogn file.

This generates the .ogn file within the Extension.

Generate an Empty Implementation#

In the Node Properties section, click Generate Blank Implementation:

Numbered steps for generating an empty implementation.

This generates a template for implementing your node’s algorithm.

Review Your Node Implementation Template#

In the Node Properties section, click Edit Node:

Numbered steps for opening your node implementation file.

This opens the template node file that you generated in the last step:

"""
This is the implementation of the OGN node defined in OgnNewNode.ogn
"""

# Array or tuple values are accessed as numpy arrays so you probably need this import
import numpy


class OgnNewNode:
    """
        Accepts a double as input and negates it
    """
    @staticmethod
    def compute(db) -> bool:
        """Compute the outputs from the current input"""

        try:
            # By putting the compute in a try block you can fail the compute by raising an exception
            pass
        except Exception as error:
            # If anything causes your compute to fail report the error and return False
            db.log_error(str(error))
            return False

        # Even if inputs were edge cases like empty arrays, correct outputs mean success
        return True

Here is the template for your node. In the next step, you implement its behavior.

Tip

If you accidentally close the Node Description Editor, you can find the file by reopening the Node Description Editor and clicking File > Open…. the file is named OgnNewNode.ogn

Warning

The directory that contains this code is considered a build directory, not source code. So, don’t check it in to your source code’s version control system.

Implement Your Node Logic#

Update compute() to negate in_double and save it in out_double:

"""
This is the implementation of the OGN node defined in OgnNewNode.ogn
"""

# Array or tuple values are accessed as numpy arrays so you probably need this import
import numpy


class OgnNewNode:
    """
        Accepts a double as input and negates it
    """
    @staticmethod
    def compute(db) -> bool:
        db.outputs.out_double = - db.inputs.in_double
        return True

If you save your code while your node is in a graph, it should work immediately without you restarting or refreshing the App. This “hot reloading” works in most versions of Omniverse Kit. When it doesn’t, delete your node and undo the delete. This should resolve any problems with the App not registering changes.

Use Your Negate Double Node#

Search for the Negate Double node, drag it into the editor, and wire it up to the output of Abs Double:

Numbered steps for using your node in the Push Graph.

Here, you pass the output of Abs Double, the absolute value of the x position of the sphere, to Negate Double. In the Property panel, the Output Double field shows the negated value.

Create an Add Double Node#

In this tutorial, you’re creating two nodes:

  • Negate Double

  • Add Double

Together, these will replace the Subtract Double node that you currently have in your Push Graph. Now that Negate Double is working, create your next node, Add Double.

Create a New Node#

From the Node Description Editor, click File > New Node:

Numbered steps for using your node in the Push Graph.

Assign the Node Properties#

In the Node Properties section of the Node Description Editor panel, set the following properties:

Property

Description

Value

Name

The name of the node as it appears in the graph.

AddDouble

Description

A description of the node’s compute algorithm.

Add two doubles

UI Name

The name of the node as it appears in user interface (UI) elements.

Add Double

Leave the other values as their defaults:

The filled-out node properties.

Add Two Node Inputs#

In the Input Attributes section, click the Add new attribute button, and set the following attribute properties:

Property

Description

Value

Name

The name of the attribute.

input_a

Description

A description of the information that the attribute holds.

First input

Attribute Type

The data type that the attribute manages.

Properties:

  • Base Type: double

  • Tuple Count: 1

  • Array: False

UI Name

The name of the attribute as it appears in UI elements.

Input A

Leave the other values as their defaults:

Numbered instructions for filling in the input double attribute.

Then, add another input attribute with the following properties:

Property

Description

Value

Name

The name of the attribute.

input_b

Description

A description of the information that the attribute holds.

Second input

Attribute Type

The data type that the attribute manages.

Properties:

  • Base Type: double

  • Tuple Count: 1

  • Array: False

UI Name

The name of the attribute as it appears in UI elements.

Input B

Leave the other values as their defaults:

Numbered instructions for filling in the input double attribute.

Add a Node Output#

In the Output Attributes section, click the Add new attribute button, and set the following attribute properties:

Property

Description

Value

Name

The name of the attribute.

sum

Description

A description of the information that the attribute holds.

Sum of A and B

Attribute Type

The data type that the attribute manages.

Properties:

  • Base Type: double

  • Tuple Count: 1

  • Array: False

UI Name

The name of the attribute as it appears in UI elements.

Sum

Leave the other values as their defaults:

Numbered instructions for filling in the output double attribute.

Generate an OGN File and Template#

In the Node Properties section, click Save Node, name the file “OgnAddDoubleNode.ogn”, and click Generate Blank Implementation:

Numbered steps for generating an .ogn file and an empty implementation.

For Negate Double, you also clicked Populate Extension, but you don’t here. One Extension can include multiple nodes. This is the case with the OmniGraph Python Examples Extension that you used in Part Two. This is also the case for the two nodes that you’ve created here. Because you created an Extension while building Negate Double, you don’t need to populate another one for Add Double. Just give the nodes distinct names so they can coexist in the Extension directory.

Implement Your Node Logic#

In the Node Properties section, click Edit Node. Then, update compute() to add input_a and input_b and save it in sum:

"""
This is the implementation of the OGN node defined in OgnAddDoubleNode.ogn
"""

# Array or tuple values are accessed as numpy arrays so you probably need this import
import numpy


class OgnAddDoubleNode:
    """
        Add two doubles
    """
    @staticmethod
    def compute(db) -> bool:
        """Compute the outputs from the current input"""
        db.outputs.sum = db.inputs.input_a + db.inputs.input_b
        return True

Use Your Add Double Node#

Search for the Add Double node, drag it into the editor:

Numbered steps for using your node in the Push Graph.

Wire up the Negate Double node’s Output Double pin to the Add Double node’s Input B pin and the Add Double node’s Sum pin to the Clamp Double node’s Num pin:

Pointer showing the wired-up node in the Push Graph.

Right click and disconnect the Subtract Double node from the Abs Double node:

Pointer showing the disconnect button.

Tip

Consider deleting the dangling Subtract Double node if you’re not going to use it any more.

In the Property panel for Add Double, set Input A to 3:

Numbered steps for setting your Input A value.

This is the same a value that you used in Subtract Double.

Review Your Extension#

In the Extension Manager, look up your new Extension, ensure it’s enabled, and enable autoload:

Numbered steps for enabling your custom extension.

Enabling the Extension ensures that the nodes are active. Autoload ensures that the Extension will be enabled in future sessions.

That’s it! Try moving the sphere around, the graph functions as it did before.