'why is duplicating joints by code not working?

I'm creating multiple joints by code in maya, this is what I want to do. Create, and parent them like this...

L_Arm_00IK parent of L_Arm01IK parent of L_Arm02IK

L_Arm_00FK parent of L_Arm01FK parent of L_Arm02FK

L_Arm_00IKDriver parent of L_Arm01IKDriver parent of L_Arm02IKDriver

L_Arm_00Blend parent of L_Arm01Blend parent of L_Arm02Blend

but when I run my code, the First joints are created L_Arm_00IK, L_Arm_00FK, L_Arm_00IKDriver, L_Arm_00Blend

but their children aren't created. What am I doing wrong? It looks like def duplicate_chain isn't going through.

def ikfkchain(name, side, parent, joints, fktemplate, iktemplate, pvtemplate, fkcolor, ikcolor):



fk_joints = duplicate_chain(joints, None, "_JNT", "Fk_JNT")
ik_joints = duplicate_chain(joints, None, "_JNT", "Ik_JNT")
ik_driver_joints = duplicate_chain(joints, None, "_JNT", "IkDriver_JNT")
blend_joints = duplicate_chain(joints, None, "_JNT", "Blend_JNT")





def duplicate_chain(joints, parent, replace_what, replace_with):
new_joints = []
new_joints_parent = parent

for jnt in joints:
    new_jnt = cmds.duplicate(jnt, n=jnt.replace(replace_what, replace_with), po=True)[0]
    if new_joints_parent:
        cmds.parent(new_jnt, new_joints_parent)


    new_joints_parent = new_jnt 
    new_joints.append(new_jnt)

    return new_joints


Solution 1:[1]

It looks like you are just returning in your loop, which means that your function goes through the loop once, and returns without looping further.

You can fix it by simply changing your code like this :

def duplicate_chain(joints, parent, replace_what, replace_with):
    new_joints = []
    new_joints_parent = parent
    
    for jnt in joints:
        print(jnt)
        new_jnt = cmds.duplicate(jnt, n=jnt.replace(replace_what, replace_with), po=True)[0]
        print(new_jnt)
        if new_joints_parent:
            cmds.parent(new_jnt, new_joints_parent)
    
    
        new_joints_parent = new_jnt 
        new_joints.append(new_jnt)
    
    return new_joints

That said, when duplicating objects in Maya, by default Maya duplicates the whole hierarchy of descendants of that object as well.

You can just do something as simple as this :

from maya import cmds

top_joint = cmds.ls(selection=True)

duplicated_top_joint = cmds.duplicate(top_joint)

This will duplicate your entire hierarchy. This is often enough when duplicating joint chains as we usually want the whole chain anyway.

Then you can just rename them by starting from the bottom of the hierarchy :

def rename_jnts(top_jnt, replace_what, replace_with):
    new_joints = cmds.listRelatives(top_jnt, allDescendents=True, fullPath=True) # we use fullPath so that each of the names contain the full hierarchy, in order to rename properly
    new_joints.append(top_jnt)
    new_joints.sort(key=len) # we sort by length to get the joints in hierarchical order
    new_joints.reverse() # we reverse the list to get the longer names first, since these are long names that means that the joints at the bottom of the hierarchy will be first in that list, and the first ones in the hierarchy will be last, this avoids renaming the top joints first and having Maya not find the other ones because their long names will have changed.
    for jnt in new_joints:
        short_name = jnt.split("|")[-1] # first we split the long name by the pipe (|) character and keep the last token to get only the short name 
        new_name = short_name.replace(replace_what, replace_with) # We build the new name by replacing the proper token
        cmds.rename(jnt, new_name) # rename

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Martin