Node Event Callbacks

You may want to add more callbacks to trigger in your handler/hook subclasses.

These are the currently exposed hook methods you should extend from:

Houdini Events 1

NodeHandlerBase methods

AfterLastDelete

after_last_delete()

BeforeFirstCreate

before_first_create()

OnCreated

on_created()

OnDeleted

on_deleted()

OnInputChanged

on_input_changed()

OnLoaded

on_loaded()

OnNameChanged

on_name_changed()

OnUpdated

on_updated()

Just to keep things short, all following method code will assume you are defining the it under a child hook class setup like this unless explicitly mentioned in the code block’s caption

child_handler.py
 import sgtk

 HookBaseClass = sgtk.get_hook_baseclass()

 class ChildHandler(HookBaseClass):

Existing methods

So for example, if you want Shotgun to log a warning when a node name has changed, you would want to write something like this:

def on_name_changed(self, node):
    self.logger.warn("Node renamed: %s", node.path())
    super(ChildHandler, self).on_name_changed(node)  # Python 2

The super statement to call the parent class’s on_name_changed implementation is important to make sure any original functionality isn’t lost.

This is especially true when it comes to these methods which the NodeHandlerBase has implemented and needs to be called for everything to work correctly:

For example:

def on_created(self, node):
    super(ChildHandler, self).on_name_changed(node)  # Call as first thing to setup Shotgun
    self.logger.info(
        "Node created and %s using Shotgun: %s",
        "is" if self.using_sgtk(node) else "isn't",
        node.path(),
    )

The on_loaded() should also be decorated by a gracefully_error() decorator to log errors encountered during a delicate state of Houdini 2 i.e. when it’s loading nodes for a scene file:

@HookBaseClass.gracefully_error
def on_loaded(self, node):
    super(ChildHandler, self).on_loaded(node)
    raise RuntimeError("This should not crash Houdini")

gracefully_error() decorator can also be used for other event callback methods if you discover that Houdini seg-faults when any Python errors are raised from them.

New methods

If there are other Houdini Events you wish to hook into.

  1. Create a Python script file in <repo>/houdini/scripts sub-folder

  2. Name it as per Houdini Events, e.g. PreFirstCreate.py

  3. Populate it in a similar way to the other <repo>/houdini/scripts Python scripts

    Basically only call the handler’s pre_first_create method if this tk-houdini Shotgun engine is loaded and there are node handlers assigned to this node

    PreFirstCreate.py
    def run_pre_first_create(node):
        try:
            import sgtk
        except ImportError:
            return
        engine = sgtk.platform.current_engine()
        if engine:
            handler = engine.node_handler(node)
            if handler:
                handler.pre_first_create(node)
    
    
    run_pre_first_create(kwargs["node"])
    
  4. Add a new method to NodeHandlerBase. Doesn’t require any implementations

    NodeHandlerBase
    def pre_first_create(self, node):
        pass
    
  5. Implement the callback in your own child hook class:

    def pre_first_create(self, node):
         super(ChildHandler, self).pre_first_create(node)
         self.logger.info("First encounter of %s", node.type().nameWithCategory())
    

What about addEventCallback?

on_node_event() is your answer! Like on_loaded(), you will need to extend it in order to keep everything running smoothly:

def on_node_event(self, event_type, **kwargs):
    # MUST handle parent's routine first
    super(ChildHandler, self).on_node_event(event_type, **kwargs)

    if event_type == hou.nodeEventType.PositionChanged:
        self.logger.debug("wwwwwwweeeeeeeeeeeeeeeee")

Note

1

Even though these events comes under the “Digital asset” heading, they are still triggered by most nodes since they are technically also digital assets.

2

Discovered while testing Houdini 18.5: any Python errors raised during scene load will cause Houdini to crash by “Segmentation Fault”