Houdini - HDA

The notes below are based on info found in the Houdini docs as well as other sources.

Asset name

The general form of an asset’s internal name is

[namespace::]node_name[::version]

The namespace and version are both optional. You can have a name with both a namespace and a version, or just a namespace, or just a version, or neither.

Namespaces

The namespace identifier lets you name your assets without worrying about using the same name as a built-in Houdini node or as a third-party asset you might use someday. (Note that this only applies to the internal name of the node… you can always use any string you want for the human readable label that appears in the user interface.) A useful convention to ensure you use a unique namespace name is to reverse the DNS address of your website. For example, if the creator´s website is at houdini.bacon.org, they would use org.bacon.houdini as the namespace for their assets.

Versions

The version string allows you to create multiple independent versions of an asset without having to change the “main name”. Instances of the old version will still work and use the old implementation, while users placing a new node will get the latest version. The version can only contain numbers and periods (.). For example, myasset::2, myasset::2.1, myasset::19.1.3, but not myasset::2a or myasset::alpha.

Asset name & scripting

Some scripting commands require the node category and node name together (for example Object/geo, Sop/copy, Dop/popsolver). To use namespaced names with these commands, use the form [namespace::]node_category/node_name[::version] For example, com.sundae::Sop/copy::2.0

Custom HDA Path

Set custom path to HDA

Parameters

  • Add Parms to HDA
    • Alt MMB click the parm of a node (in the HDA subnet) with the Operator Type Properties window open
  • Conditional display (docs)
    • { parm_name [operator] value …} …
    • Available operators: ==, !=, <, >, >=, <=, =~ (matches pattern), !~ (doesn’t match pattern).
    • { enablefeature == 1 count > 10 }

HDA Python Scripts

PythonModule

HDAModule User-defined Python module containing functions, classes, and constants that are stored with and accessed from a digital asset.

  • RMB click the HDA Allow Editing of Contents
  • RMB click the HDA Type Properites
  • On the scripts tab select Python Module from the Event Handler combobox. We now get a python module “automatically” added to our HDA.

Lets write som test code and execute it from a button on the HDA.

  • On the scripts tab, with the PythonModule selected enter the some code to be called
def speak():
    print('speak was called from PythonModule')
  • Add a button to the HDA and as a python callback script we add the following snippet:
hou.phm().speak()
  • Note
    • phm() → hou.HDAModule
      • This shortcut lets you write hou.phm() instead of hou.pwd().hdaModule(). You are most likely to use this shortcut from event handlers, button callbacks, and menu generation scripts in digital assets.
    • To make this work the python module must be named PythonModule (which it is if we add it this way)

Additional Modules

If you find that a digital asset has too much Python code to store in one module, it’s possible to create submodules. Lets create a separate python module and call it from our “main” python module.

  • RMB click the HDA > Type Properties and select the Scripts tab
  • In the Event Handler combobox select Custom Script
  • Select the python script to include (with the filebrowser labeled “filename”)
  • This will autopopulate the section name with the file name (which is fine i guess, you can remove the .py extension if you want)
  • Click Add File to add the custom script to the HDA.
  • Now we need to import the custom module in our main python module (we also have a speak method in out custom module, which we also call)
  • NOTE
    • New to Houdini 18.0, the createModuleFromSection function expects the code in the HDA section to have Python 3 style print statements.
# toolutils.createModuleFromSection(module_name, node_type, section_name)

import toolutils
custom_module = toolutils.createModuleFromSection("custom_module", kwargs["type"], "custom_module.py")

def speak():
    print('called "speak" from PythonModule')
    custom_module.speak()

Extra Files

Lets add an extra file to an HDA.

  • RMB click the HDA > Type Properties and select the Extra Files tab.
  • Click the Filename file chooser amnd navigate to the file.
  • Click Add File and press Accept to close the type properties widget.

Now the file has been saved inside the HDA on disc. So lets load the file within the HDA.

  • On the file node (inside the HDA) click the geometry file chooser.
  • On the left hand side, in the Locations section of the file chooser widget select opdef:/
  • Navigate to the HDA that we just saved our file to.
    • Note we will find the file in a directory of the HDA type. If we created a sop HDA it will be inside the sop dir. If we created the HDA with a namespace the directory of the HDA will be prefixed with this namespace as well. If we have different versions, the versions will be stored in different dirs.