calin_casian Posted April 13, 2008 Share Posted April 13, 2008 (edited) Hi, I'm trying to port some maya python rigging scripts to houdini python scripts to post it on my rigging blog as examples, shameless plug follows: Please visit my blog at http://vanillarigging.blogspot.com If all goes well maybe start some sort of transition guide or repository about python in maya and houdini. I know that sort of thing will help the houdini community. Anyway I'm kind of lost at the first attempt to get a selection out of houdini. Here is maya code "maya.cmds.ls(selection=True)" which will return a list of all the objects selected, transforms, shaders, custom nodes you name it. I was advised that I could do something like this in houdini loop trough all children of /obj and test for selection with hou.Node.isSelected(). This works but I think this method has some big issues. First is the loop, if I have thousands of objects it might take a while . The bigger issue to me id the fact that this seems to go backwards, instead of saying give me the selection it says give me all the objects then take the selected out. Could someone (Luke, maybe) please point me to a better, simpler way of getting my selection from houdini, wink wink, see the simplicity of mayas cheers calin ps. I'm sure tons of question will follow because here is the script I'm trying to port: import maya.cmds as mc # Build the UI def startUI(): print 'starting the UI' # end of UI def createJoints(nrJoints, boneLength): # create a number of joints, 'nrJoints' along the Y axis # the joints will be spread apart by the 'boneLength' value print 'Create Joints' jointsList = [] # create the root joint then orient it to point in +Y jointName = mc.joint(position=(0,0,0), name='spineJoint1', orientation=(-90,0,90)) jointsList.append(jointName) for i in range(2, nrJoints): jointName = mc.joint(position=(boneLength,0,0), relative=True, name='spineJoint' + str(i)) jointsList.append(jointName) return jointsList def addBoneLengthToJoints(jointsList): # add an 'originalLength' attribute to every joint that follows after root # that stores the original length. Since the translate X is taken as original # length the joints must be oriented along X for custon skeletons print 'Add original bone length attribute to joints' selection = mc.ls(selection=True) # take the root joint out of the joint list because there is no bone length # on the root joint stretchJointsList = jointsList[1:] for i in stretchJointsList: mc.select(i, replace=True) tempXvalue = mc.getAttr(i + '.translateX') mc.addAttr(longName='originalLength', attributeType='double', defaultValue=tempXvalue) mc.setAttr(i + '.originalLength', lock=True) return stretchJointsList def createSpineHierarchy(): # create a spine hierarchy where the joints are unde the skeleton group, # the controls under controls group and everything else is under the helpers group print 'Create spine hierarchy' spineRig = mc.createNode('transform', name='spineRig') spineSkeleton = mc.createNode('transform', name='spineSkeleton', parent=spineRig) spineControls = mc.createNode('transform', name='spineControls', parent=spineRig) spineHelpers = mc.createNode('transform', name='spineHelpers', parent=spineRig) mc.setAttr('spineSkeleton.template', 1) spineHierarchyList = [spineRig, spineSkeleton, spineControls, spineHelpers] return spineHierarchyList def buildStretchySpine(spineJointsList, stretchJointsList): # create the stretchy spine setup based on the provided diagram print 'Build stretchy spine' # adding spline IK solver to the bones print 'Add IK solver' mc.ikHandle(name='spineIkHandle', startJoint=spineJointsList[0], endEffector=spineJointsList[-1], solver='ikSplineSolver', numSpans=2) spineSolverCurveShape = mc.ikHandle('spineIkHandle', query=True, curve=True) spineSolverCurve = mc.listRelatives(spineSolverCurveShape, parent=True) mc.setAttr(spineSolverCurve[0] + '.template', 1) spineCurve = 'spineCurve' mc.rename(spineSolverCurve[0], spineCurve) mc.parent(spineCurve, 'spineHelpers') # create the curveInfo node that will compute the arclen of the spine print "Add cruveInfo node that computes the spine's length" spineCurveInfoNode = mc.arclen(spineCurve, constructionHistory=True) spineLengthNode = 'spineComputeCurveLength' mc.rename(spineCurveInfoNode, spineLengthNode) # store the original curve length in the 'originalLength' attribute print "Add spine curve original length attribute" spineCurveOrigLength = mc.getAttr(spineLengthNode + '.arcLength') mc.select(spineCurve, replace=True) mc.addAttr(longName='originalLength', attributeType='double', defaultValue=spineCurveOrigLength) mc.setAttr(spineCurve + '.originalLength', lock=True) mc.parent('spineIkHandle', 'spineHelpers') mc.setAttr('spineIkHandle.visibility', 0) # create a locator which will be a control for spine options, stretchiness # we default this value to .2 which means that the spine will stretch and # compress with .2 of the difference between the original length and the # current length print 'Create a control for the spine options' spineOptions = mc.createNode('transform', name='spineOptionsCtrl', parent='spineControls') mc.createNode('locator', name='spineOptionsCtrlShape', parent=spineOptions) mc.setAttr(spineOptions + '.translateX', 4) mc.parentConstraint('spineJoint1', spineOptions, maintainOffset=True) print 'Add spine options attributes' mc.select(spineOptions, replace=True) mc.addAttr(longName='spineStretchiness', attributeType='double', minValue=0, maxValue=1, defaultValue=0.2, keyable=True) # create the stretchiness network which mainly consists of adding shading nodes # and connect attributes print 'Add stretchiness network' # create a plusMinusAverage node. this node will take the current length # and subtract the original length to find out with how much the curve changed spineSubtractOriginalCurveLengthNode = mc.shadingNode('plusMinusAverage', asUtility=True, name='spineSubtractOriginalCurveLength') mc.connectAttr(spineLengthNode + '.arcLength', spineSubtractOriginalCurveLengthNode + '.input1D[0]', force=True) mc.connectAttr(spineCurve + '.originalLength', spineSubtractOriginalCurveLengthNode + '.input1D[1]', force=True) mc.setAttr(spineSubtractOriginalCurveLengthNode + '.operation', 2) # create a multiplyDivide node that multiplies the result from the subtract node with # the spine stretchiness to find out what's the length we care about spineMultiplyStretchinessNode = mc.shadingNode('multiplyDivide', asUtility=True, name='spineMultiplyStretchiness') mc.connectAttr(spineSubtractOriginalCurveLengthNode + '.output1D', spineMultiplyStretchinessNode + '.input1X', force=True) mc.connectAttr(spineOptions + '.spineStretchiness', spineMultiplyStretchinessNode + '.input2X', force=True) # create a plusMinusAverage node and we add back the original curve to find out the # total length of the curve we have to stretch the bones spineAddOriginalCurveLengthNode = mc.shadingNode('plusMinusAverage', asUtility=True, name='spineAddOriginalCurveLength') mc.connectAttr(spineMultiplyStretchinessNode + '.outputX', spineAddOriginalCurveLengthNode + '.input1D[0]', force=True) mc.connectAttr(spineCurve + '.originalLength', spineAddOriginalCurveLengthNode + '.input1D[1]', force=True) # create a multiplyDivide node and divide the total length we care about with the original # length to find out the ratio. spineDivideByOriginalCurveLengthNode = mc.shadingNode('multiplyDivide', asUtility=True, name='spineDivideByOriginalCurveLength') mc.connectAttr(spineAddOriginalCurveLengthNode + '.output1D', spineDivideByOriginalCurveLengthNode + '.input1X', force=True) mc.connectAttr(spineCurve + '.originalLength', spineDivideByOriginalCurveLengthNode + '.input2X', force=True) mc.setAttr(spineDivideByOriginalCurveLengthNode + '.operation', 2) # once we know the ration we have to create a multiplyDivide node for each joint # and multyply the original bone length with the computed ratio print "Change the bone Tx value to accomodate stretchiness" for i in stretchJointsList: spineMultiplyByOriginalBoneLengthNode = mc.shadingNode('multiplyDivide', asUtility=True, name='spine' + i + 'MultiplyOriginalLength') mc.connectAttr(spineDivideByOriginalCurveLengthNode + '.outputX', spineMultiplyByOriginalBoneLengthNode + '.input1X', force=True) mc.connectAttr(i + '.originalLength', spineMultiplyByOriginalBoneLengthNode + '.input2X', force=True) mc.connectAttr(spineMultiplyByOriginalBoneLengthNode + '.outputX', i + '.translateX', force=True) def createClusters(): print 'Create clusters' for i in range(0,5): cv = 'spineCurve.cv[%d]' %i cluster = mc.cluster(cv, name='spineCurveCluster' + str(i)) mc.parent(cluster, 'spineHelpers') def main(createJointsOption, nrJoints, boneLength): if createJointsOption==1: spineJointsList = createJoints(nrJoints, 2) spineHierarchyList = createSpineHierarchy() mc.parent(spineJointsList[0], spineHierarchyList[1]) stretchJointsList = addBoneLengthToJoints(spineJointsList) buildStretchySpine(spineJointsList, stretchJointsList) createClusters() main(1, 20, 2) Edited April 13, 2008 by calin_casian Quote Link to comment Share on other sites More sharing options...
symek Posted April 13, 2008 Share Posted April 13, 2008 (edited) Thank you Calin, porting Maya rigs can be extremely helpful for us and for a number of reasons actually (not only its usage). As to getting selection, surly someone from SESI can give better advice, but maybe you can use Shelf Tools. In its modules there are many useful stuff (not sure if all can be used in custom scripts outside shelf context). Here for example (from Combine tool): # Ask for the objects to combine selected_objects = list(scene_viewer.selectObjects( prompt = toolutils.selectionPrompt(hou.objNodeTypeCategory()), allow_multisel = True, allowed_types = ("geo",))) Your work is really helpful here, thanks again! Cheers, Simon. PS Could you (or admins) add code tags to first post? thanks. Edited April 13, 2008 by SYmek Quote Link to comment Share on other sites More sharing options...
calin_casian Posted April 13, 2008 Author Share Posted April 13, 2008 Thanks Simon, I'll look into the list() thing, seems the right way to do it although shading nodes don't have representation in the viewer but maybe there's something else. If you're interested to see some rig bits in both packages please check my blog regularly or subscribe to the RSS. I'll try and post here a link every time I'll post some scenes and scripts. cheers calin Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.