Houdini for TD - Events

Note

This article is part of the serie Houdini for TD

Houdini Event System

Most events triggered by Houdini call script stored in "named" files stored in `$HOUDINI_PATH/scripts` locations. However, some additional events can be defined by code, but we gonna see all of that threw this page.

You can find some additional details on the various things we are going to see here in the official Python script location documentation.

Startup Scripts

pythonrc.py

`pythonX.Xlibs/pythonrc.py`

This is the first script executed by Houdini and is usually a place where you might run code to initialize functionality that will be executed later on in the startup process.

123.py

`scripts/123.py`

This script is executed second when Houdini is started without a scene file. Only the first `scripts/123.py` file found in `$HOUDINI_PATH` will be executed.

This script is useful for customizing an empty scene, but only at houdini startup! If you are then later on creating a "New scene", this script won't be called.

Note

Only HoudiniFX starts `123.py`, HoudiniCore starts a file that could share the same content named: `houdinicore.py`

456.py

`scripts/456.py`

This scripts is executed anytime a scene file is loaded, even at startup and when houdini starts without any scene.

IMO, this script though is actually the best place to customize anytime an empty scene is created. You can do so by using this sort script:

import hou

if hou.hipFile.name() == "untitled.hip":
    # This is a new scene
    # hou.hipFile.name() will always return the fullpath to the scene
    # so if the scene is named untitled.hip, it would return /path/untitled.hip
else:
    # A scene has been loaded

Scene Events

beforescenesave.py / afterscenesave.py

`scripts/beforescenesave.py` and `scripts/afterscenesave.py`

Those two scripts are respectively called before and after a scene is saved.

I am recommending to use Hip file Events instead as they can handle more situation.

Hip file Events

Hip File Events are callback function that are being triggered whenever a scene file changes. Each file operation has a corresponding "before" and "after" event types.

As this type of events are callback, they need to be registered, and I usually recommend to do so in the file pythonrc.py.

# python3.7libs/pythonrc.py

import hou

def scene_event_callback(event_type):
    if event_type == hou.hipFileEventType.BeforeClear:
        # Called before the current hipfile is cleared
    elif event_type == hou.hipFileEventType.AfterClear:
        # Called after the current hipfile is cleared
    elif event_type == hou.hipFileEventType.BeforeLoad:
        # Called immediatly before a hipfile is loaded
    elif event_type == hou.hipFileEventType.AfterLoad:
        # Called immediatly after a hipfile is loaded
    elif event_type == hou.hipFileEventType.BeforeMerge:
        # Called immediatly before a hipfile is merged
    elif event_type == hou.hipFileEventType.AfterMerge:
        # Called immediatly after a hipfile is merged
    elif event_type == hou.hipFileEventType.BeforeSave:
        # Called immediatly before a hipfile is saved
    elif event_type == hou.hipFileEventType.AfterSave:
        # Called immediatly after a hipfile is saved

hou.hipFile.addEventCallback(scene_event_callback)

Node Events

Houdini offer a multitude of events when interacting with nodes. The list bellow list interaction with the instances of specific node types.

Those node events can be either embedded into HDA definition by adding as an additional section. Or they can be used for any node types by placing them in a specific location in your packages.

# To apply to a specific node type
<package_root>/scripts/<category>/<nodename>_<event>.py

# Or to apply to every matching node types
<package_root>/scripts/<event>.py
Event Triggered Usage
PreFirstCreate Runs when the first instance of the node type is created in the scene. This include when the node is loaded for the first time in the scene. This can be used to check the usage of a node type, or assign a user preffered color to the node type.
OnCreated Runs after the user creates a new instance of the node type. This could be used to customize the node at its creation or attach node events.
OnLoaded Run after an instance of the node type is created as part of of Houdini hipfile loading sequence. This also run when the user paste node from the clipboard. This can be used to attach node events to each instances.
OnUpdated Run for each instance of the node type when the definition is updated.
OnDeleted Run before an instance of the node type is deleted. This also run when user is creating a new scene or quitting.
PostLastDelete Runs after the last instance of a node type has been deleted in the scene. This could be use to uninstall an deprecaded definition of an HDA, or release a software license.
OnInputChanged Runs when an input on a node of this type is connected, disconnected or switched.
OnNameChanged Runs after the user changes the name of the node of this type. This can be used to enforce naming on a node.
OnInstall Runs when this node type is installed in the session. Updating the definition also trigger this event.
OnUninstall Runs when this node type is uninstalled in the session. Updating th edefinition also trigger this event.
SyncNodeVersion Runs when Houdini notice the instance of the node type version differ from the previously saved version. This script can be used to update a node when its version change.

Additional details can be found in the Node events types official documentation.

Node Event Handlers

Similarly to Hipfile Event Handlers, each node can have its own events defined. Those could be setup by some of the events described above.

You can find the full list of hou.nodeEventType in the documentation.

# OnCreated.py and OnLoaded.py

def rename_node(event_type, **kwargs):
    """Function to rename node when display flag is changed."""
    node = kwargs["node"]
    visible = node.isGenericFlagSet(hou.nodeFlag.Display)
    if visible:
        node.setName(node.name().replace("off", "on"))
    else:
        node.setName(node.name().replace("on", "off"))

kwargs["node"].addEventCallback(
    event_types=[hou.nodeEventType.FlagChanged],
    rename_node
)

Parameter Callback

When editing the Parameter interface on a node (or it's ParmTemplates), you have the ability to set a "callback script". This is hscript or python script that will be trigger anytime the you change the parameter value from the UI or call the method `hou.Parm.pressButton()` from code. This functionality is really useful to trigger updates on parameter change.

Python States

https://www.sidefx.com/docs/houdini/hom/python_states.html

Warning

This section is not yet written. Please come back to it later.

Other Events

hdefereval

Note

This module require Houdini to be in interactive mode which can be checked by running `hou.isUIAvailable()`.

The module `hdefereval` provide function to perform deferred evaluation of python code. You can call those functions from any thread and they are executed in the main thread when Houdini's event loop is idle.

# pythonrc.py
import hdefereval

def hello_world():
    """This function will be called as soon as the UI is available and idle.""
    print("Hello World")

hdefereval,executeDeferred(hello_world)

atexit

This is actually a python builtin module which can be use to invoke code right right before the python thread closes.

# pythonrc.py
import atexit

def hello_world():
    print("Hello World")

atexit.register(hello_world)