Houdini Python
· Houdini MOC · Python ·
TOC
- Links
- Tips
- Snippets
- Simple UI
- Buttons
- Installing python packages using pip
- Using an IDE to write into python nodes
- Solaris inspector custom data
Links
- Houdini Python Wiki
- Python snippets
- vfxbrain Python posts
- Petfactory LOPs tips with scene examples
- Omniverse Developer Guide
- Intro to Houdini Python video course
- Houdini & Python includes RS material creation
- Coding an asset browser video course
Tips
To get available packages dir()
Hscript $F becomes in Python hou.frame(), $T becomes hou.time()
Local parameters: Hscript $CY becomes in Python lvar("CY")
To store some form of variable in a way that it persists over multiple scripts or executes of a script, you can use hou.session. Open the python shell and write hou.session.foo = "Hello!" Now you can call hou.session.foo anywhere and your variable will persist!
Snippets
Basic node operations
SOPs
import hou
# Define geometry node name
geometryName = 'MY_GEO'
# Get selected node
node = hou.selectedNodes()[0] # can also drag and drop into shell
# Get node upstream connections
listParents = node.inputAncestors()
# To get the parent node n:
n.node("..")
# Get scene root node
sceneRoot = hou.node('/obj/')
# Check if "MY_GEO" exists
if hou.node('/obj/{}'.format(geometryName)) == None:
# Create empty geometry node in scene root
geometry = sceneRoot.createNode('geo', run_init_scripts=False)
# Set geometry node name
geometry.setName(geometryName)
# Display creation message
hou.ui.displayMessage('{} node created!'.format(geometryName))
else:
# Display fail message
hou.ui.displayMessage('{} already exists in the scene'.format(geometryName))
LOPs
# get the selection of a lopnetwork inside a geo sop network
hou.node('/obj/geo1/lopnet1').selection()
# get the selection of the "root" stage context
hou.node('/stage').selection()
# set selection
paths = ['/scene/geo/sub/sphere', '/scene/geo/sub/box']
hou.node('/stage').setSelection(paths)
lop_node = hou.node('/stage').node('null_1')
# <hou.LopNode of type null at /stage/null_1>
stage = lop_node.stage()
# Usd.Stage.Open(rootLayer=... ...LOP:rootlayer-session.usda'))
stage.GetPrimAtPath('/materials/green')
# Usd.Prim(</materials/green>)
A python expression can use hou.lvar('primpath') to get the path and from there get the USD prim from which further information can be retrieved, for instance pwd().input(0).stage().GetPrimAtPath(hou.lvar('primpath')).GetPrimStack()[-1].layer.identifier
Toggle update mode hotkey bind
# David Torno "Toggle Update mode Auto/Manual"
# Make a Shelf Tool and assign it a Hotkey, and place this code in the "Script" Tab...
import hou
mode = hou.updateModeSetting().name()
if(mode == "AutoUpdate"):
hou.setUpdateMode(hou.updateMode.Manual)
if(mode == "Manual"):
hou.setUpdateMode(hou.updateMode.AutoUpdate)
Camera lock hotkey bind
# David Torno "Toggle camera lock/unlock"
# Make a Shelf Tool and assign it a Hotkey, and place this code in the "Script" Tab...
pane = hou.ui.paneTabOfType(hou.paneTabType.SceneViewer)
view = pane.curViewport()
view.lockCameraToView(not view.isCameraLockedToView())
Get current camera
Python expression to get the path to the current viewport's camera
cd = hou.ui.curDesktop()
tab = cd.paneTabOfType(hou.paneTabType.SceneViewer)
vc = tab.curViewport()
return vc.cameraPath()
External Commands
Using subprocess
import subprocess
subprocess.call(["cmd"])
import os.path as op
test = op.join(hou.expandString("$HFS"),"bin","hcmd")
subprocess. call([test])
Create Karma Material subnet and USD Preview Material subnet with Python
import hou
import voptoolutils
materialLibrary = hou.node('/obj/lopnet1/materiallibrary1')
#create Karma MtlX builder inside specified LOP materiallibrary
mask = voptoolutils.KARMAMTLX_TAB_MASK
mtlxbuilder = materiallibrary.createNode("subnet", "karmamaterial")
voptoolutils._setupMtlXBuilderSubnet(mtlxbuilder, "karmamaterial", "karmamaterial", mask, "Karma Material Builder", "kma")
#create UsdPreviewMaterialBuilder inside specified LOP materiallibrary
mask = voptoolutils.USDPREVIEW_TAB_MASK
usdpreviewbuilder = materiallibrary.createNode("subnet", "usdpreviewmaterial")
voptoolutils._setupUsdPreviewBuilderSubnet(usdpreviewbuilder, "usdpreviewsubnet", mask, "USD Preview Material",)
Simple UI
hou.ui.displayMessage('Hello')
hou.ui.displayMessage('hello', ['ok','cancel'])
hou.ui.readInput('Type your input')
Buttons
Button callback python expression
Wired to a button, that rewrites values of the dictionary interface named groups
hou.pwd().parm('groups').setFromData({'dictionary': {'Eyebrows':'brows|eyebrow','Eyelashes':'eyelashes'}})
Button python code
Create a multistring field
Set language to Python
Use python callback:
exec(kwargs['node'].parm('pythoncode').eval()) # where python code is the name of the filed
Installing python packages using pip
Houdini comes with its own python environment that is independent of the system python. Out of the box it will at times lack some packages.
To install a new python package using pip inside of houdini's python environment, in the python shell use:
import pip
pip.main(['install', 'package_name'])
Using an IDE to write into python nodes
Create a folder in your $HIP directory where you will place your .py files. For example, you can create a file working directory"/python/example_file.py
Create a Python node and insert the following code:
file = "example_file"
folder = "python"
exec(open(hou.getenv('HIP') + '/' + folder + '/' + file + '.py', 'r').read())
Enjoy all the benefits of your favorit IDE!
Solaris inspector custom data
This can run a custom python code to evaluate something useful.
The code is located in Program Files/SideFx.../Houdini v.v.v/houdini/scene/inspect_usd_prim.py
Wrote this little function to fetch the first Mesh subprim and a specific attribute from it. It detects if the attribute is a list/array and then it outputs min:max values, otherwise it outputs the actual value or indicates if the attribute is not present.
Not sure how Python can handle all the diversity of the USD datatypes yet, so you'll have to take care of it from here for vectors/matrices/etc. Code updates require a Viewport reset (at least I haven't found another way yet).
import hou
from pxr import Sdf, Usd, UsdGeom # can be useful but not here
def inspect(viewer, viewport, stage, primpath):
attr_name = "primvars:hl" # set the attribute name
try:
parent_prim = stage.GetPrimAtPath(primpath)
child_prim = parent_prim.GetChildren()[0]
attr = child_prim.GetAttribute(attr_name)
if attr.IsValid():
attr_val = attr.Get(hou.time())
if hasattr(type(attr_val), '__len__'):
res = f'{child_prim.GetName()}\n {attr_name}({len(attr_val)}) = {min(attr_val)}:{max(attr_val)}' # min:max values for data that has length
else:
res = f'{child_prim.GetName()}\n {attr_name} = {attr_val}'
else:
res = f'{child_prim.GetName()}\n {attr_name} not found'
return res
except:
import traceback
return traceback.format_exc()