def bakeRotateDelta( src, ctrl, presetStr ): ''' Bakes a post trace command into the ctrl object such that when ctrl is aligned to src (with post trace cmds enabled) src and tgt are perfectly aligned. This is useful because rig controls are rarely aligned to the actual joints they drive, but it can be useful when you have motion from a tool such as SFM, or generated from motion capture that needs to be applied back to a rig. ''' mat_j = Matrix( getAttr( '%s.worldInverseMatrix' % srcJoint ) ) mat_c = Matrix( getAttr( '%s.worldMatrix' % jointControl ) ) #generate the matrix describing offset between joint and the rig control mat_o = mat_j * mat_c #put into space of the control rel_mat = mat_o * Matrix( getAttr( '%s.parentInverseMatrix' % jointControl ) ) #now figure out the euler rotations for the offset ro = getAttr( '%s.ro' % jointControl ) offset = MATRIX_ROTATION_ORDER_CONVERSIONS_TO[ ro ]( rel_mat, True ) cmd.rotate( asEuler[ 0 ], asEuler[ 1 ], asEuler[ 2 ], jointControl, relative=True, os=True ) mel.zooSetPostTraceCmd( ctrl, presetStr % offset ) mel.zooAlign( "-src %s -tgt %s -postCmds 1" % (src, ctrl) ) return offset
def bakeManualRotateDelta( src, ctrl, presetStr ): ''' When you need to apply motion from a skeleton that is completely different from a skeleton driven by the rig you're working with (transferring motion from old assets to newer assets for example) you can manually align the control to the joint and then use this function to generate offset rotations and bake a post trace cmd. ''' srcInvMat = Matrix( getAttr( '%s.worldInverseMatrix' % src ) ) ctrlMat = Matrix( getAttr( '%s.worldMatrix' % ctrl ) ) #generate the offset matrix as mat_o = ctrlMat * srcInvMat #now figure out the euler rotations for the offset ro = getAttr( '%s.ro' % ctrl ) rotDelta = MATRIX_ROTATION_ORDER_CONVERSIONS_TO[ ro ]( mat_o, True ) #now get the positional delta posDelta = Vector( xform( src, q=True, ws=True, rp=True ) ) - Vector( xform( ctrl, q=True, ws=True, rp=True ) ) posDelta *= -1 ctrlParentInvMat = Matrix( getAttr( '%s.parentInverseMatrix' % ctrl ) ) posDelta = posDelta * ctrlParentInvMat #construct a list to use for the format str formatArgs = tuple( rotDelta ) + tuple( posDelta ) #build the post trace cmd str mel.zooSetPostTraceCmd( ctrl, presetStr % formatArgs ) return rotDelta
def loadPostTraceSchemeFilepath( presetFile ): ''' re-applies a stored post trace command scheme back to the controls found in the current scene ''' #first we need to purge all existing post trace commands clearPostTraceScheme() if not isinstance( presetFile, Path ): presetFile = Path( presetFile ) if not presetFile.isfile(): raise IOError, "no such preset" xportDict, postTraceDict = presetFile.unpickle() for n, postTraceCmd in postTraceDict.iteritems(): n = n.split( '.' )[ 0 ] #strip off the attribute possibles = ls( '*%s' % n, r=True ) if possibles: nInScene = possibles[0] mel.zooSetPostTraceCmd( nInScene, postTraceCmd )