I’m an animator with some basic rigging skills but nearly no scripting knowledge at all and I’m wondering if someone could help me out with a repetative task I find myself doing when I’m setting up characters for games.
I would be superduper grateful if someone would help me out with a basic script that duplicates a selected joint chain then add a point and a orient constraint between them so that the new joint chain drives the old one.
import pymel.core as pm
def createControllingChain( startJnt=None, ignoreEnds=True ):
if startJnt is None:
jnt = pm.selected( type='joint' )
if not jnt:
raise TypeError( 'A joint must either be specified, or selected.' )
jnt = jnt[0]
else:
jnt = pm.PyNode( startJnt )
chain = jnt.listRelatives( ad=True )
chain.reverse()
chain.insert( 0, jnt )
# Removes any joints without children from the list
if ignoreEnds:
for jnt in chain[:]:
if not jnt.getChildren():
chain.remove( jnt )
ctrls = []
for i, jnt in enumerate( chain ):
# Duplicate one joint at a time
dup = jnt.duplicate( parentOnly=True )[0]
dup.rename( jnt.name()+'CTRL' )
ctrls.append( dup )
# Constrain the original to the new duplicate
pm.pointConstraint( dup, jnt )
pm.orientConstraint( dup, jnt )
# If the parent is in the chain, it has already been duplicated
if jnt.getParent() in chain:
# We find the joint's parent's index in the chain
jntIndex = chain.index( jnt.getParent() )
# And set the parent of the duplicate joint to the corresponding duplicate
dup.setParent( ctrls[jntIndex] )
else:
# Otherwise, it is the start of the joint chain,
# so we parent the first control to the world
dup.setParent( world=True )
return ctrls[0]
I’m assuming this is for Maya – In which case that should do it. If no joint is specified, the first joint in the selection will be used. If the ‘ignoreEnds’ argument is True, the script will not create controller joints for any end joint with no children. Hopefully that helps! :):
What I wrote is just a python function - you have to call the function in order to execute it.
If you then write:
createControllingChain()
and execute that with a joint selected, it should do the magic.
If you want to make controls for the end joints, you should add ‘ignoreEnds=False’ inside those parentheses.
If you want to make a shelf button for the whole thing, just paste that line at the bottom of the function I wrote, and middle mouse drag the whole business onto the shelf.
You can also call the function specifying a joint name - but it sounds to me like you’re just looking for a button to click.
Great! i tried it and it works.
But I wonder if there is any way to make the joint copy without weight? When I used it on my old rig, the original joint and the copied joint both had weight, causing the weight rig to error