Python in Houdini

Python Parameter Expressions III: Auto Import

So we covered basic Python expressions and how to work with custom functions. Alright, that’s nice and dandy but how do we get Houdini to load our custom functions so they are always available? Custom functions can auto load in a couple of ways. You need to setup a few of things but it’s quite straightforward. Today, we will look at how to auto import our functions so they are always available.

If you need to catch up, here are the previous posts:

Setup Python Files

First, navigate to your Houdini preferences folder. Create a folder called python2.7libs and dive inside. Create a file called pythonrc.py. This file will contain your code. The file name is important. Don’t name the file waffle.py or scrambles.py.

pythonrc.py file
pythonrc.py file

Houdini runs the code in the file when it starts up. This will give us the ability to just type in our function name in any parameter field. Open the file with your text editor. We are ready to drop in some code.

Globals Dictionary

What we need to do now is wrap our code inside function syntax. Recall single lines of Python code run as standard expressions, but many lines of code run as part of a function body. Transfer the jitter code over to your pythonrc.py file.

import random

def lineJitter(alpha, beta):
  return(random.gammavariate(alpha, beta) / hou.lvar("NPT"))

First, this is a start but Houdini still won’t know what to do with the code. We need to tell Houdini, “Here, take my code and place it alongside your other expression code”. For this, we will make use of the hou.expressionGlobals() function. This function returns the globals dictionary used by the parameter expression evaluation namespace. Python expressions run in a different namespace than the global namespace. This helps avoid polluting the global namespace and getting in all sorts of trouble. We are adding our custom function to the expressionGlobals() dictionary so it’s available when we invoke it in a parameter field.

Have a look at the output of the hou.expressionGlobals() function in a Houdini Python shell. You will see a bunch of key/value pairs scroll by. We want to inject our code into that sea of madness.

hou.expressionGlobals()
hou.expressionGlobals() method
hou.expressionGlobals() method

Second, notice I’m appending hou to the lvar() function. The reason is because of namespaces as well. When you are running Houdini, it automatically does from hou import * which brings in the Python expression namespace and allows us to drop the hou in the parameter fields. The pythonrc.py file is not running in the Python expression namespace.

Third, I’ve refactored the function to accept arguments. You can hard code the numbers but this gives you the ability to experiment without having to restart Houdini every time you want to change the numbers.

import random

def lineJitter(alpha, beta):
  return(random.gammavariate(alpha, beta) / hou.lvar("NPT"))


hou.expressionGlobals()["lineJitter"] = lineJitter

The last line of code is just saying create a key called “lineJitter” and assign it the value lineJitter. In this case, we are assigning the function we just defined. The key portion of this can be called anything you want. This name is what we type in our parameter fields when we write our expression. The value is the code we want to run.

Let’s Jitter

At this point you want to start a new Houdini session if it was running. Once Houdini is back up, you can type your function name in the appropriate parameter field, passing any arguments and do a happy dance. You should see that Houdini pops up our function signature. You can even create custom parameters to interactively change the arguments in your function.

Custom python functions
Custom python functions

 

Well, that does it for now. Next time, we will improve upon this idea by placing our functions in a separate module to keep pythonrc.py nice and light.

Share:
990adjustments

990adjustments

I am a motion designer & developer based out of South Florida. When not designing or animating pixels, I wrangle some code. If all else fails, I watch Twilight Zone, I Love Lucy, or Three's Company reruns.