Houdini 11 Houdini Object Model

Setting the Expression Language

Parameter expressions may be written using either the Hscript expression language or the Python expression language. You can mix and match the languages, so some parameters in a node may use Hscript expressions while other parameters in the same node use Python expressions.

In HOM terminology, a parameter can be in one of two states: animated or not animated. An animated parameter has a set of keyframes. Each keyframe contains a time and an expression (as well as other information discussed later). A keyframe is active from its time up to the next keyframe, or until the end of the time range if there is no next keyframe. When Houdini evaluates a parameter at a particular time, it looks up the keyframe corresponding to that time and evaluates the expression. So, when someone says a parameter has an expression, he or she typically means that it has a single keyframe at time=0, and they're referring that that keyframe’s expression. The convenience functions hou.Parm.expression and hou.Parm.setExpression provide easy access to that expression.

There are two ways to control a parameter’s language, depending on whether or not the parameter is already animated. If it is not animated and you write an expression in it, Houdini uses the node’s expression language. The parameter dialog displays the node’s language as either an H (for Hscript expressions) or the Python logo (for Python expressions). Changing the node’s language does not affect parameters that already have expressions; it simply determines the language for new expressions you write. If a parameter’s language is different from the node’s language, Houdini will highlight that parameter in pink to make you aware of that difference.

You can control the default expression language for newly created nodes with a preference in Houdini’s main preference dialog.

If the parameter is already animated, you can change its language by right-clicking on it and selecting “Expression → Change Language to Python” or “Change Lanuage to Hscript Expressions”. For most expressions, changing the language will generate an error because of syntactical and API differences between Hscript expressions and Python. However, certain functions, like ch and the animation functions (cubic, bezier, etc.) have been carefully designed to use the same syntax in both Hscript expressions and Python. For those expressions, you change change the language without generating errors or changing the output of those parameters.

Single and Multi Line Python Expressions

With Python parameter expressions, there is one simple rule you need to know: single lines are evaluated as standard expressions, and multiple lines are evaluated as function bodies. For example, 2+2 and ch("ty") + 2 are valid Python expressions, but x=3 and x=3; x are not. However, if you press Alt+e to bring up the multi-line editor, you can enter the following Python function body:

if ch("ty") == 0:
    return 0
if ch("ty") < 0:
    return ch("tx")
return ch("tz")
From a Python function body you can run arbitrary Python statements, giving you full access to Python’s standard library. Beware that Houdini may evaluate the parameter more often than you expect.

Python Expression Namespaces

Python expressions run in a different namespace than the global namespace provided by the Python shell. This way, you don’t have to worry about Python global variables created in the shell affecting the output of parameter expressions, and vice versa. Also, to reduce the length of your Python parameter expressions, Houdini implicitly runs from hou import * and from hou.session import * in the Python expression namespaces. This means you can drop the hou. prefix in your Python expressions, and you can call hou.session functions as though they were defined locally. For example, in a Python expression you can write ch("ty") instead of hou.ch("ty"). Similarly, Houdini imports the following functions from Python’s math module: acos, asin, atan, atan2, ceil, cos, cosh, degrees, exp, fabs, floor, log, log10, pow, radians, sin, sinh, sqrt, tan, tanh Because the expression operates in a different namespace, Houdini’s global Python namespace is not polluted by these imports.

Tip

If you really want to access a global variable from a Python expression, you can run import __main__ to get access to Houdini’s global Python namespace. For example, if foo is a function defined in your pythonrc.py file, you can access foo from a Python expression via __main__.foo.

Note that you can also access the Python expression namespace from the global namespace with hou.expressionGlobals. This function lets you add functions that are easily callable from Python expressions. For example:

# Put the following in your $HOME/houdiniX.Y/python2.5libs/pythonrc.py file:
def clamp(value, min, max):
    return (min if value < min else (max if value > max else value))
hou.expressionGlobals()["clamp"] = clamp

Also consider the following example. Normally, to access math.pi from a Python expression, you would either have to create a multi-line expression that imports math and then returns math.pi, or do it in one line with __import__("math").pi. By putting the following in pythonrc.py, you can simply write pi.

import math
hou.expressionGlobals()["pi"] = math.pi

String Parameter Expressions

Note that when Houdini evaluates string parameters without expressions, it will do string expansion on the result. So, if the unanimated string parameter contains image$F.pic, Houdini will expand $F, regardless of whether or not the node’s language is set to Hscript expressions. However, if you animate the string parameter, using the Hscript expression language, the expression needs to be "image$F.pic", because image$F.pic is not a valid Hscript expression evaluating to a string. (To convince yourself of this, run:

echo `image$F.pic`

and

echo `"image$F.pic"`

...in a textport.) Houdini’s UI goes through great pains to automatically convert between unexpanded strings and Hscript expressions for you, and the UI often tries to hide the actual expression. (To see the expression, you can inspect the hou.Keyframe with hou.Parm#keyframes.) For Python string expressions, you also need to write a valid Python expression, such as "image %d" % frame(). Thankfully, Houdini will let you see and edit those expressions, and it does not second-guess your intentions and automatically modify those expressions for you.

Local Variables

You can access Hscript expression local variables from Python with hou.lvar. For example, you can write the Hscript expression $TX in Python as lvar('TX'). Note that hou.lvar cannot access hscript global variables; for evaluate them, use hou.expandString.

Many local variables in Houdini correspond to a SOP or POP that iterates over a number of points or primitives, evaluating the nodes parameters for each iteration. Each time the parameters are evaluated, Houdini uses a different value for the local variable, corresponding to the current point or primitive. The hou module provides hou.SopNode.curPoint, hou.SopNode.curPrim, and hou.PopNode.curPoint, giving you access to a hou.Point or hou.Prim object. So, for example, lvar('Cr') in a Point SOP could also be written as curPoint().attribValue('C')[0]. While this approach is more verbose and has additional overhead, it is more generic, giving you access to information in points and primitives that may not be available through local variables.

Interrupting Expression Evaluation

If you call Python code that takes a long to evaluate, or it goes into an infinite loop, you can press Escape to interrupt expression evaluation.