Tips and Tricks
Introduction
I find myself re-using a few techniques and methods frequently in my Houdini digital asset creation techniques. These are my top tips & tricks.
On Creation - Namespaces
I always put my operator name into a namespace I come up with, as well as a version number. The syntax for namespacing your digital assets is: nameSpace::nodeName::versionNumber
Example can be seen below. Note: I will be using the Normal Map From Heightfield HDA as an example, that will fill in any gaps from the post detailing the functionality of this node.
I add all my digital assets into a namespace so that I can easily get to them through Python, which can come in handy. Below is a Python function that will get all nodes from a scene with my namespace.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Usage: myNodes = getNodesByNamespace('lcg', hou.pwd().getParent()) def getNodesByNamespace(namespace, parentNode): if namespace.endswith('::'): namespace = namespace[:-2] all_instances = [] filteredInstances = [] for node_type in hou.sopNodeTypeCategory().nodeTypes().values(): if node_type.name().startswith('%s::' % namespace): all_instances.extend(node_type.instances()) for instance in all_instances: if instance.parent().path() == parentNode.path(): filteredInstances.append(instance) return filteredInstances |
Basic - Icon
Use one of the hundreds of icons that ship with Houdini (if you don't have time to make your own).
Scripts - Callbacks
Hook up the On Create Python callback immediately to set the color and shape of tools.
The Python snippets below has the code for the OnCreated, PythonModule as well as a function that prints out the string representation of all the node shapes that are available by default in Houdini.
1 |
kwargs["node"].hdaModule().onCreated(kwargs["node"]) |
1 2 3 4 |
def onCreated(node): # To play with the color values, create a color node and find the values you want quickly. node.setColor(hou.Color((1.0, 0.678, 0.0))) node.setUserData("nodeshape", "gurgle") |
1 2 3 |
def printNodeShapes(): editor = hou.ui.paneTabOfType(hou.paneTabType.NetworkEditor) print(editor.nodeShapes()) |
Parameters
Disable & Hide Rules
Prevent the execution of a button click unless you have all the inputs you need - use the HDA disable and hide rules. Simple example below - disable the export button unless the export path has been filled in.
You can get pretty complex with these rule operators. Here is a cheat sheet when comparing different parameter values against each other.
For AND operation: { option1 != 1 option2 != 1 }
For OR operation: { option1 != 1 } { option2 != 1 }
Combination: { option1 != 1 option2 != 1 } { optionX > 0 }
Tricky - ALWAYS use "" and not '' (example { option1 == "" } NOT { option1 == '' } - gets me all the time (thanks Python)
Parameter callbacks
While you can drag and drop parameters from nodes inside your HDA into the parameter interface to connect them, do not forget about the power of callbacks.
One use case is a callback on the output path in the above example. When that changes, we can check if the file exists, is read only and we may want to implement a source control check out before attempting to write the file. We could also set the enable/disable state of the export button in this Python callback.
Example implemented below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import os import lcg.system.file import lcg.perforce def onCreated(node): node.setColor(hou.Color((1.0, 0.678, 0.0))) node.setUserData("nodeshape", "gurgle") def evaluatePath(kwargs): path = kwargs['script_value'] if not path: return if not os.path.exists(path): return if lcg.system.file.is_read_only(path): lcg.perforce.checkout(path) |
Get as complex as you need with callbacks and do pretty much anything - power!!
Help!
You gotta love a tool framework where they have already thought of providing a hook to the help documentation. If you select any Houdini factory node and RMB -> Help... you will land on the documentation page for that node.
TIP: In your Houdini Environment, set the flag HOUDINI_EXTERNAL_HELP_BROWSER = 1 to get the documentation showing in your default browser instead of Houdini's internal browser.
Side Fx made it very easy for you to hook into this system through the help section of the Houdini Digital Asset. The template code below can be found in this SideFx documentation. I also provide the code snippet below. The code adds everything you need for a documentation page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
= My Asset = #icon: path/to/icon """A quick summary of what the node does.""" == Overview == Explanation of the node's purpose and operation. @inputs Label: What the input is for. @parameters Label: #id: internalname Explanation of what the parameter does. Label: #id: internalname Explanation of what the parameter does. @related * [Node:sop/copy] |
The code modified to work with this Houdini digital asset creation.
Tip: For internal images, you map the image by providing the path: CATEGORYNAME/svgName
From the example above, the icon name is "BUTTONS_add_image.svg" - becomes BUTTONS/add_image.
You can find all the icons in "C:\Program Files\Side Effects Software\Houdini HoudiniVersion\houdini\help\icons.zip".
Browse that file to see how things are organized.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
= Normal Map From Heightfield = #icon: BUTTONS/add_image """Generate a normal map from heightfield.""" == Overview == Computes a normal map from a height field input. It can either downsample and create a differential normal map between the low and high voxel count or create a full normal map computed from 0 (a flat heightfield). You can preview the result of the normal map in close to realtime. To get the map to draw in the composite view, just double click the HDA, there is a dive target that will select the correct node for display in the Composite view. @inputs Heightfield: Plug in a height field to generate a normal map. @parameters Normal From Flat Heightfield: #id: fromPlane Check to calculate a normal map from a flat heightfield and not a downsampled "low res" one. Resolution Scale: #id: resscale Resolution scale of the downsampled heightfield. As the scale increases, it gets closer to the full voxel resolution of the input heighfield and the normal map thus becomes weaker. Flip R: #id: flipR Check to flip the red channel. Flip G: #id: flipG Check to flip the green channel. Output Path: #id: copoutput Select a path to write the file to. Export: #id: execute Click to write the file. == Normal Smoothing == Radius: #id: radius Radius of the smoothing effect. Number of Passets: #id: passes The more passes, the stronger the smoothing effect. |
This is the web page result from the above help section.
Conclusion
Hopefully, some of these tips & tricks can help you in your Houdini digital asset creation process. Keep an eye out for updates. I will add more tips and tricks when I learn new things I deem worthy. Drop a message below, if you know of something I should add or if you just want to say hello.