Thursday, May 8, 2014

Python tool switch keys between two animator controls


I was animating a dog walk cycle in Maya and i wanted a way to reuse a pose from an earlier frame.  But after i copied the pose to the new frame i actually wanted the hands to be opposite to where they were.  So i wrote this script that given two selected animator controls it puts all the translates, rotates user values of one onto the other.  the result is a quick way to help start blocking a mirrored pose.  It does require to set a keyframe after running this tool.  It also needs both animator controls to have a mirrored type of behavior (if they don't i assume can go in and put a minus sign in translates that need it).

Hope its helpful.
#@author Nathaniel Anozie

#modify at own risk

#last updated: 05/08/2014-05/08/2014 -- initial release

#how to use
#select two objects want to switch keys between example left and right hand control.

import maya.cmds as cmds
import sys

def na_switchKey():
    """switch keys between first selected and second selected (keys not set automatically so need to key them)"""
    #assumption names of attributes are identical for both
    firstObj = ''
    secondObj = ''
    firstAttr = []
    firstVal = []
    secondAttr = []
    secondVal = []
    sel = = True)
    if len(sel) != 2:
        sys.exit("Requires two objects selected!!")
    firstObj = sel[0]
    secondObj = sel[1]
    #get current keyframe info for both selected before we do the switch
    #ex: {u'translateX': 2.7141762512786562, u'translateY': 0.0, u'translateZ': 0.0}
    firstAttr = cmds.listAttr(firstObj, keyable = True) 
    firstLockedAttr = cmds.listAttr(firstObj, locked = True)
    if firstLockedAttr is not None:
        for locked in firstLockedAttr:
                firstAttr.remove(locked) #remove locked attributes
            except ValueError:
    firstVal = [ cmds.getAttr( firstObj + "." + at ) for at in firstAttr  ]
    firstData = {}
    attr = ''
    val = 0.0
    for i in xrange( len(firstAttr) ):
        attr = firstAttr[i]
        val = firstVal[i]
        firstData[attr] = val
    secondAttr = cmds.listAttr(secondObj, keyable = True) 
    secondLockedAttr = cmds.listAttr(secondObj, locked = True)
    if secondLockedAttr is not None:
        for locked in secondLockedAttr:
                secondAttr.remove(locked) #remove locked attributes
            except ValueError:
    secondVal = [ cmds.getAttr( secondObj + "." + at ) for at in secondAttr  ]
    secondData = {}
    attr = ''
    val = 0.0
    for i in xrange( len(secondAttr) ):
        attr = secondAttr[i]
        val = secondVal[i]
        secondData[attr] = val
    #switch keyframe info
    #print firstData
    #{u'translateX': 2.7141762512786562, u'translateY': 0.0, u'translateZ': 0.0, u'scaleX': 1.0, u'scaleY': 1.0, u'visibility': 1, u'rotateX': 0.0, u'rotateY': 0.0, u'scaleZ': 1.0, u'toe': 0.0}
    for a, v in firstData.items():
        cmds.setAttr( (secondObj+"."+a),v )
    for a, v in secondData.items():
        cmds.setAttr( (firstObj+"."+a),v )
    #now pose is set but if you move in timeline we will lose info so set a key to save it