Script for duplicating a joint hierarchy and then add constraints

Hello!

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.

Cheers!

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

1 Like

I’ve done similar with max script. let me know if you’re using max and i’ll post…

It’s for Maya but thanks anyway Mambo4!

Cheers Kyle! I just pasted it in my script editor (in the python tab) and executed it but nothing happens. Any ideas what I’m doing wrong?

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.

1 Like

That did the trick. Thanks!

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