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! :):