Curve and Expressioned Parameters

New in Katana 8.5

Introduction

One of the design goals of UsdSuperLayer is not just to express the result in USD, but also the user’s intent. When an artist sets a keyframed curve or writes an expression to drive a parameter value, that intent is captured, evaluated, and then expressed cleanly in USD without leaving Katana-specific data behind.

Overview

This workflow proceeds through three stages:

1. Setting

When a parameter is authored via the UI or Python, UsdSuperLayer writes metadata into the Content Layer using the FnKatNodeAPI schema. The definition of this schema resides in the FnUsdShim source code.

Schema fields:

Field

Description

valueMode

Always present. Specifies the type of authored value: constant, curve, or expression.

curve

Optional. Serialized Katana FCurve in XML format.

expression

Optional. Expression as a string.

Whenever the parameter value changes, the schema is updated to reflect the new mode:

  • Switching into curve or expression populates the corresponding field.

  • Switching out of curve or expression removes the FnKatNodeAPI data from the prim.

Katana parameters may still hold onto dormant values locally (for example, expressions or curves on enableable parameters), but these are not retained in the Content Layer. This mirrors Katana’s typical parameter behavior and ensures that when all parameters are reset to defaults, the prim is left in an unmodified state.

2. Evaluation

At evaluation time:

  • The Content Layer is duplicated to a temporary layer that will be serialized and sent to the node’s Engine.

  • If valueMode is constant, the authored value is used directly.

  • If valueMode is curve or expression, the parameter is evaluated at the current Graph State by re-querying NotifyParameterChange on the ParameterHandler plug-in responsible for the parameter.

This allows the ParameterHandler to update the Content Layer with the appropriate frame-specific values for the current evaluation Graph State.

3. Pruning

After evaluation, the FnKatNodeAPI schema is stripped from the Content Layer. Only resolved USD values remain, leaving a clean, portable USD stage with no Katana-specific metadata.

Tip

It’s possible to disable pruning (i.e. for debugging purposes) by unchecking the removeIntermediateData parameter on the internal _UsdLayerNode within the UsdSuperLayer super tool (press Ctrl+Enter to enter a supertool node and see its internal nodes).

Examples

The following example shows how to set an expression on a parameter from the USD side. This demonstrates how Katana not only drives USD stage content but can also react to changes recorded in the Content Layer.

import usg
import NodegraphAPI
from NodesUsdAPI.UsdSuperLayer import Utils

# Create a UsdSuperLayer node in the scene with a cylinderlight on it
node = NodegraphAPI.CreateNode("UsdSuperLayer", NodegraphAPI.GetRootNode())
controller = node.getStageSubtreeController()
controller.createPrim("cylinderlight", "CylinderLight")

node.syncLayerAndParameters()
node.buildParametersForPrimPath("/root/cylinderlight")
param = node.getParameter(
    "properties.cylinderlight.fnPropertiesGroup.PropertiesParametersHandlerPlugin.inputs.intensity.value"
)

# Get the equivalent USD data in the Content Layer attached to the node
primPath = controller.getBasePath().appendChild("cylinderlight")
prim = controller.getContentLayer().getPrimAtPath(primPath)

# Apply the FnKatNodeAPI schema to signal an expression on the intensity attribute
instanceName = Utils.FnKatNodeAPISchemaHolder.GetInstanceNameFromParameter(param)
schema = Utils.FnKatNodeAPISchemaHolder.Apply(prim, instanceName)

valueModeAttr = schema.getValueModeAttr() or schema.createValueModeAttr()
valueModeAttr.set(usg.Token(Utils.FnKatNodeAPISchemaHolder.VALUE_MODE.EXPRESSION))

expressionAttr = schema.getExpressionAttr() or schema.createExpressionAttr()
expressionAttr.set("frame")

# sync with Katana
node.syncLayerAndParameters()

This produces a Content Layer entry such as the following:

#usda 1.0

def "root"
{
    def CylinderLight "cylinderlight" (
        prepend apiSchemas = ["FnKatNodeAPI:PropertiesParametersHandlerPlugin:inputs:intensity:value"]
    )
    {
        uniform string fnKatNodeAPI:PropertiesParametersHandlerPlugin:inputs:intensity:value:expression = "frame"
        uniform token fnKatNodeAPI:PropertiesParametersHandlerPlugin:inputs:intensity:value:valueMode = "expression"
    }
}

When Katana evaluates the engine chain, the prims containing the FnKatNodeAPI schema are traversed and the parameters they relate to are requeried with the evaluation for the parameter value at the given Graph State. This round-trip ensures both user intent and final result are preserved.