Converting Action Graph Nodes to IActionGraph

This document describes how to convert Action Graph nodes written using the legacy method of manipulating execution attributes to the currently recommended approach using omni::graph::action::IActionGraph_abi introduced in kit-sdk 105.1.

What Changed

The mechanism of writing and reading control information between nodes and the executor has changed. We now use the API to do this communication instead of reading and writing execution attributes. While the execution attributes are used to author the flow of execution of the graph, the value of these attributes is no longer relevant.

OGN Tests

Since the values of execution attributes are not relevant, the OGN tests can not usually be used to validate node behavior, instead unit tests should be used.

Add the extension dependency

The new API lives in omni.graph.action, so any extension that implements action graph nodes needs to depend on that.

[dependencies]
"omni.graph.action" = {}

Include the API

The omni::graph::action::IActionGraph_abi must be included in the node code, and a handle to API itself is acquired.

#include <omni/graph/action/IActionGraph.h>

// Acquire the API
auto iActionGraph = omni::graph::action::getInterface();
from omni.graph.action import get_interface

# Acquire the API
action_graph = get_interface()

Enabling an Execution Output

All execution outputs are automatically disabled before compute is called. An output can be enabled using the API call.

db.outputs.opened() = kExecutionAttributeStateEnabled;

// Becomes:
iActionGraph->setExecutionEnabled(outputs::opened.token(), db.getInstanceIndex());
db.outputs.opened = og.ExecutionState.ENABLED

# Becomes:
action_graph.set_execution_enabled("outputs:opened")

Reading an Execution Input

This is not needed for most nodes, but the state of input attributes should be read with the API call.

bool resetIsActive = (db.inputs.reset() != kExecutionAttributeStateDisabled);

// Becomes:
bool resetIsActive = iActionGraph->getExecutionEnabled(inputs::reset.token(), db.getInstanceIndex());
reset_is_active = (db.inputs.reset != db.ExecutionAttributeState.DISABLED)

# Becomes:
reset_in_is_active = action_graph.get_execution_enabled("inputs:reset")

Starting and Ending Latent State

This is not needed for most nodes, but the latent state should be controlled via the API.

if (starting)
    db.outputs.finished() = kExecutionAttributeStateLatentPush;
else
{
    db.outputs.finished() = kExecutionAttributeStateLatentFinish;
}

// Becomes:
if (starting)
    iActionGraph->startLatentState(db.getInstanceIndex());
else
{
    iActionGraph->endLatentState(db.getInstanceIndex());
    iActionGraph->setExecutionEnabled(outputs::finished.token(), db.getInstanceIndex());
}
if starting:
    db.outputs.finished = og.ExecutionAttributeState.LATENT_PUSH
else:
    db.outputs.finished = og.ExecutionAttributeState.LATENT_FINISH

# Becomes:
if starting:
    action_graph.start_latent_state()
else:
    action_graph.end_latent_state()
    action_graph.set_execution_enabled("outputs:finished")