Expressions, expression, expressions. They are everywhere in Houdini. It’s one of the many things that makes the software so powerful and sooner or later you’re going to have to face the music and get your hands dirty with them. More specifically, I’m talking about
Python parameter expressions.
If you’re just starting out, most likely you will encounter
HScript expressions but let’s say you have some Python knowledge and you would like to leverage that. Well, you are in luck! Houdini allows you to use Python expressions in its parameter fields just like you would HScript. Of course, it’s not a direct translation. There are some caveats due to syntax and API differences. I will also say that at first, it may seem verbose compared to HScript. However, it does have its advantages. The biggest advantage is you have access to Python’s Standard Library. That in itself is big! You also have the option to mix and match the languages.
I will break this topic into several posts. This post is just a quick overview of using expression parameters. This is aimed at beginners but I do assume you have some passing knowledge of scripting in general. If you invented the Google search algorithms, written several thousand apps that have sold in the millions of dollars or at the very least invented the Internet, you should be in good shape! Let’s get started!
You can find the other parts here:
- Part I – Python Parameter Expressions I: Basics
- Part II – Python Parameter Expressions II: Custom Functions
- Part III –Python Parameter Expressions III: Auto Import
In the Beginning
The first thing you will need to know is that you just can’t use the typical global or local variables in parameter fields if you intend to use Python. There are several ways to start using strictly Python but let us assume you want to use HScript and drizzle a pinch of Python here and there like you would pepper on a hotdog.
In the parameters dialog for a node you will see on the top, right hand side a graphic of an
H. This is indicating Houdini is using HScript as its primary scripting language. This is the default. If you click on it you will see that you have the option to change it to Python.
Changing from one to the other does not affect the current expressions you already have evaluating. It just sets it up for new expressions. You can change back and forth at any time. The colors of the fields will change to indicate the difference. The fields will be green if you are using expressions native to the expression language chosen, otherwise they will be a red-like color.
If you want to use a different expression language in a specific field, you first need to convert that parameter to the language you intend to use. You do this by right clicking on the parameter and selecting the Expressions item. There you will see the options to change to Python or HScript.
If you decide to only use Python as your main expression language for new nodes created, you can set this up as a default option through the preferences under the Scripting section.
One thing you need to be aware of is that Python uses different syntax for accessing familiar local or global variables. Go ahead and try the following:
- Create a Geometry node, dive in and delete the file node.
- Add a Box node.
- Add a transform node to the box.
- Change the scripting language for the Transform node from HScript to Python by using the expression language button.
- Rotate the box in the y-axis by typing the handy global variable
$FFin the Transform node’s
yparameter. I’ll wait.
BAM! Error Alert! Call the fire department! The familiar global variable
$F is not recognized by Python. In order to accomplish this, you need to use the function
frame() function returns the playbar’s current frame and is equivalent to HScript’s
$FF variable. If you want to use HScript’s
$F variable, you would use
intFrame(), which rounds the frame to the nearest integer. If you wanted to use the Python equivalent of HScript’s global variable
$T, you would use the function
Now let’s say you want to place the cube right on top of the grid using the local variable
$YMAX. As you might have guessed, it will not work. So what is the equivalent function to these local variables? In order to access local variables, you need to use the
lvar() function and pass in the local variable as its argument. This function will then return the value of the node’s local variable. So instead of just writing
$YMAX, you would write
Notice two things. First, the
lvar() parameter is of type
string, so you need to enclose the local variable within single or double quotes. Second, you omit the dollar sign character
lvar($YMAX) will cause Houdini to yell at you and the cat will be pee on your couch.
So wait! Local variables are accessed through
lvar() and every global variable has a corresponding Python function right? I’m not exactly sure but I believe most global variables have a function in their place. You also have the option of using the function
HScriptExpression() and passing it your HScript expression like so
HScriptExpression("$F"). Notice this function does take the dollar sign character. I’m still rummaging through the docs so I will get back to you.
Ok, so how do you access the parameter values themselves in Python? Here is one area where you can use the familiar
ch() function. I’m not sure if it will be deprecated but the preferred method is by using the
evalParm() function. The
ch() is provided for backwards compatibility. The python expression
evalParm("./sizex") is equivalent to
I know what you are thinking, this is more trouble than it’s worth. While it does take a bit more typing, after a while it becomes second nature. One more thing I want to point out is that Python parameter expressions are evaluated differently depending on whether they are single line or multi line expressions.
Single lines are evaluated like regular old expressions. However, multiple lines are evaluated as function bodies. That is, if you press
cmd + e to bring up the
Multi Line Editor, you can write something like this:
Yes, you are seeing that correctly. I’m importing a Python Standard Library module. Obviously, this is a convoluted example and you need to be careful because you may run into trouble with recursion issues and performance.
I’m still experimenting so only time will tell if I revert back to HScript. However, there is nothing wrong with knowing both ways. Also, remember we only touched on parameter expressions. I haven’t even mentioned the scripting abilities.
Next time I’ll touch on creating your own custom Python functions that you can call directly from within parameter fields! This is some cool stuff. I will also go over some small technical details I left out so stay tuned.
If you want to learn the in and outs make sure you visit the Houdini Documentation on the Houdini Object Model. You will find some excellent information with examples on how to use Python in Houdini.