Object Transform Example: A Simple Example
Overview
This example illustrates how to retrieve and set transformations on object nodes.
Location
Supporting files for this example are in $HFS/mozilla/documents/hom/cookbook/object_xform, also found in the cookbook/object_xform directory of cookbook_files.tar.gz.
Getting Started
Load obj_xform.hip and you’ll see a series of boxes chained together in a transformation hierarchy. Translate and rotate a box object in the middle of the chain to see that the outputs of that box inherit the transformations.
Open up a Python shell window in Houdini and observe the effects on box_object4 in both the viewport and network editor as you enter the following:
# Store the hou.ObjNode for /obj/box_object4 into a Python variable.>>> box_object4 = hou.node("/obj/box_object4")>>> box_object4<hou.ObjNode of type geo at /obj/box_object4># Ask for box_object4's world transformation. This transformation matrix# includes the parm transformation (determined from the translate, rotate,# scale, etc. parameters on the object), pretransformations, parent# transformations, transformations on the containing object, etc.>>> xform = box_object4.worldTransform()>>> xform<hou.Matrix4 [[0.942106, -0.147233, -0.301261, 0],[0.134676, 0.988938, -0.062158, 0],[0.3070 8, 0.017987, 0.951514, 0],[-5.04816, -0.769449, -9.42593, 1]]># Disconnect box_object4's input. box_object4 will move, since it no longer# inherits its input's transformations. If we print out its new transformation# matrix, we see that it's different.>>> box_object4.inputs()(<hou.ObjNode of type geo at /obj/box_object3>,)>>> box_object4.setFirstInput(None)>>> box_object4.inputs()()>>> box_object4.worldTranform()<hou.Matrix4 [[0.966956, 0, 0.254942, 0],[0, 1, 0, 0],[-0.254942, 0, 0.966956, 0],[0.885497 , 0, -3.01977, 1]]># Restore box_object4's transformation to its previous value. We'll leave# its input disconnected, so we'll have unparented it but kept its position.# setWorldTransform will adjust the objects parameters to achieve the# desired end result, accounting for inputs, pretransforms, etc.>>> box_object4.setWorldTransform(xform)
Writing a Function to Unparent
Next, let’s package up the logic to unparent a node and keep its position into a function, and we’ll call that function on box_object4 from a shelf tool.
Reload obj_xform.hip so that box_object4 is parented again, and add the following code to a new shelf tool. Right-click on an empty area of the shelf, select New Tool, create a tool named “Unparent”, and add the following in the Script tab:
def unparentAndKeepPos(obj_node):"""Unparent an object node, but keep it in the same position as it waswhen it was parented."""xform = obj_node.worldTransform()obj_node.setFirstInput(None)obj_node.setWorldTransform(xform)unparentAndKeepPos(hou.node("/obj/box_object4"))
Unparenting the Selected Node
Let’s generalize the shelf tool to work with the viewport’s selected node instead of box_object4. To do that, we can use hou.SceneViewer.selectObjects to return the currently selected object. Here is the new shelf tool:
# The toolutils module ships with Houdini and is used to perform common# shelf tool operations. It can be found in $HFS/houdini/scripts/python.import toolutilsdef unparentAndKeepPos(obj_node):"""Unparent an object node, but keep it in the same position as it waswhen it was parented."""xform = obj_node.worldTransform()obj_node.setFirstInput(None)obj_node.setWorldTransform(xform)# If an object is already selected, we'll use it. If nothing is selected,# we'll prompt the user to select something. If multiple objects are selected,# we'll use the last one, since that should correspond to the parameter pane# contents.viewer = toolutils.sceneViewer()obj_node = viewer.selectObjects(quick_select=True)[-1]unparentAndKeepPos(obj_node)
Reparenting the Selected Node
Next, let’s write another shelf tool that will reparent the selected node. It will prompt the user for the new parent node.
# The toolutils module ships with Houdini and is used to perform common# shelf tool operations. It can be found in $HFS/houdini/scripts/python.import toolutilsdef parentAndKeepPos(obj_node, new_parent):"""Parent an object node, but keep it in the same position as it waswhen it was unparented."""xform = obj_node.worldTransform()obj_node.setFirstInput(new_parent)obj_node.setWorldTransform(xform)# We'll select the object to reparent in the same way the unparent tool works.# We'll prompt the user to select the new parent in the viewer.viewer = toolutils.sceneViewer()node_to_reparent = viewer.selectObjects(quick_select=True)[-1]new_parent = viewer.selectObjects(use_existing_selection=False,quick_select=True,prompt="Select new parent node")[-1]parentAndKeepPos(node_to_reparent, new_parent)
See also: hou.ObjNode.worldTransform, hou.ObjNode.setWorldTransform, hou.Node.setFirstInput, hou.SceneViewer.selectObjects
