HDK
|
Every node in Houdini has a unique path. To obtain the full path of a node, use the OP_Node::getFullPath() function. To obtain the relative path a node to some ancestor node, use OP_Node::getRelativePathTo().
Given a node path, we can find the corresponding OP_Node via the OP_Node::findNode() function.
Often times, you will want obtain a specific type of the OP_Node instead. This is defined by the OP_Node::findFOONode() functions where FOO is the desired node type. If the path doesn't reference a node of the desired type, then these functions return NULL
.
To create a node, you create it as a child of some parent node. Thereafter, you should call its creation script. Upon success, you can now manipulate the node such as connecting its inputs and outputs, setting parameters (Working with Parameters), and/or positioning the node.
There are several ways to traverse the node hierarchy explicitly as well. One way is to iteratively walk along a node's inputs using OP_Node::getInput() or OP_Node::getInputReference(), or to walk its outputs using OP_Node::getOutputNodes(), OP_Node::getOutputItem(), or using and OP_OutputIterator object. To iterate over the child nodes, one can use OP_Node::getChild(). For an example of how to do this, see the traverse.C example. A higher-level method to do this is to use supply a callback to the OP_Node::traverseInputs() and OP_Node::traverseChildren() methods.
Users can set various flags on nodes from the network view pane. Although these are defined at the OP_Node level, which ones get used depend on the network type. For example, although the render flag exists at the OP_Node level, OBJ_Node's ignore them. Here are the main ones:
For certain network types (eg. OBJ_Node), it can only have one child node (eg. SOP_Node) that has its display or render flag set. To obtain the child display or render nodes use OP_Network::getDisplayNodePtr() or OP_Network::getRenderNodePtr() respectively.
Node selections in Houdini are implemented via the "picked" flag on OP_Node. To add a node to the selection, call OP_Node::pickRequest(false). To replace the global node selection with just a single node, call OP_Node::pickRequest(true). To manipulate the entire node selection, OP_Director provides higher level functions.
As mentioned in the Node Organization, an OP_Bundle abstracts a set of nodes contained inside that bundle. To add, modify, or delete an OP_Bundle, you will need to work with the OP_BundleList class, which owns all the bundles in Houdini. There is only one global list of bundles in Houdini and it can be obtained by:
Once you obtain an OP_BundleList pointer, you can then add and remove bundles in this list, and the list will take care of sending notification and other necessary processing. For example:
Once you obtain an OP_Bundle pointer you can modify the contents of the bundle. However, it is best to use the OP_BundleList methods for modifying a bundle because the list creates undo blocks and also sends notifications to interested parties that the bundle contents has changed. For example:
Finally, you can obtain the member nodes using OP_Bundle::getMembers().
OP_Bundle class can search for any node in Houdini scene based on the node path or a name using globbing. You can use this ability any time you want to get a complete set of nodes based on some name pattern. Then you can obtain the list of nodes from the bundle for processing. For example, the viewport may want to display only the object nodes that match a visible mask pattern. The user may specify "mynode*" as such a pattern, which would match any node that starts with "mynode" prefix. In such case, the OP_BundleList::getPattern() may be utilized for that purpose:
Very often an operator has a parameter that specifies a node path or node names. It is very useful to allow the node names to contain globbing characters, so that many nodes can be matched with a simple pattern. When the operator node cooks, it needs to obtain the nodes that match the pattern specified in a parameter. There is a utility method OP_Node::getParmBundle() which returns a bundle containing the nodes matching a given pattern. In addition, this method registers an interest in the bundle, so that the operator is dirtied when the bundle contents changes, for example, when a new node is added and it matches the pattern, or when a member node is renamed and it no longer matches the pattern. Also, when the operator gets deleted, the bundle is properly dereferenced.
The following code demonstrates how to use OP_Node::getParmBundle() method.
To convert an OP_Node pointer to a specific type, there are CAST_FOONODE() defines where FOO is the desired type. They are a wrapper around the OP_Node::castToFOONode() methods that take into account the possibility of the node being NULL
.
Although a node's purpose in life varies depending on the network type, once a node has been defined and instantiated in a network, the OP_Node::cook() method becomes the focal point for cooking the network and generating data. This method performs preliminary testing and preparation of inputs before actually calling the pure virtual OP_Node::cookMe() method which must be defined in the network type subclass to actually perform the cook. It is also worth noting that not all calls to the cook() method will result in calls to the subclass cookMe() method. The cook() method will avoid doing an actual "cook" if it deems it to be unnecessary. A cook might be unnecessary if the data is already cached and nothing critical (eg. parameters) has changed since the previous cook. If you want to force cook() to always perform a full cook, first call OP_Node::forceRecook().