Example #1
0
def switchToFk( control, handle=None, attrName='ikBlend', onValue=1, offValue=0, key=False, joints=None ):
	if handle is None:
		handle = control

	if handle is None or not objExists( handle ):
		printWarningStr( "no ikHandle specified" )
		return

	#if we weren't passed in joints - discover them now
	if joints is None:
		joints = getJointsFromIkHandle( handle )

	#make sure ik is on before querying rotations
	setAttr( '%s.%s' % (control, attrName), onValue )
	rots = []
	for j in joints:
		rot = getAttr( "%s.r" % j )[0]
		rots.append( rot )

	#now turn ik off and set rotations for the joints
	setAttr( '%s.%s' % (control, attrName), offValue )
	for j, rot in zip( joints, rots ):
		for ax, r in zip( ('x', 'y', 'z'), rot ):
			if getAttr( '%s.r%s' % (j, ax), se=True ):
				setAttr( '%s.r%s' % (j, ax), r )

	alignFast( joints[2], handle )
	if key:
		setKeyframe( joints )
		setKeyframe( '%s.%s' % (control, attrName) )
Example #2
0
def switchAnimationToFk(control,
                        handle=None,
                        attrName='ikBlend',
                        onValue=1,
                        offValue=0,
                        key=True,
                        startFrame=None,
                        endFrame=None):

    #grab the key times for keys set on the t or r channels on the ik control - these are the frames we want to switch to fk on
    keyTimes = keyframe(control, q=True, at=('t', 'r'), tc=True)
    if not keyTimes:
        switchToFk(control, handle, attrName, offValue, key)
        printWarningStr("No keys found on the ik control - nothing to do!")
        return

    #remove duplicate key times and sort them
    keyTimes = removeDupes(keyTimes)
    keyTimes.sort()
    cropValues(keyTimes, startFrame, endFrame)

    joints = getJointsFromIkHandle(handle)
    for time in keyTimes:
        currentTime(time, e=True)
        switchToFk(control, handle, attrName, onValue, offValue, key, joints)

    select(joints[-1])
Example #3
0
def switchAnimationToIk( control, poleControl=None, handle=None, attrName='ikBlend', onValue=1, key=True, startFrame=None, endFrame=None ):

	#get the joints the ik control drives - we need these to get keyframes from so we know which frames to trace the ik control on
	joints = getJointsFromIkHandle( handle )
	if not joints:
		printWarningStr( "Cannot find the fk controls for the given ik control" )
		return

	#grab the key times for keys set on the t or r channels on the ik control - these are the frames we want to switch to fk on
	keyTimes = keyframe( joints, q=True, at=('t', 'r'), tc=True )
	if not keyTimes:
		switchToIk( ikControl, poleControl, handle, attrName, onValue, key )
		printWarningStr( "No keys found on the fk controls - nothing to do!" )
		return

	#remove duplicate key times and sort them
	keyTimes = removeDupes( keyTimes )
	keyTimes.sort()
	cropValues( keyTimes, startFrame, endFrame )

	#clear out the keys for the ik control
	cutKey( control, poleControl, t=(keyTimes[0], keyTimes[-1]), cl=True )

	startFrame = keyTimes[0]
	currentTime( startFrame, e=True )
	setKeyframe( control, poleControl, t=(startFrame,) )

	for time in keyTimes:
		currentTime( time, e=True )
		switchToIk( control, poleControl, handle, attrName, onValue, key, joints, _isBatchMode=True )

	setKeyframe( control, t=keyTimes, at=attrName, v=onValue )

	select( control )
Example #4
0
	def on_filterChanged( self, *args ):
		self.UI_files.setFilter( self.UI_filter.getValue() )
		if self._filterChangeCB:
			try:
				self._filterChangeCB()
			except:
				printWarningStr( "The filter change callback %s failed!" % self._filterChangeCB )
def changeParent( parent=0, objs=None ):
	if objs is None:
		objs = ls( sl=True, type='transform' ) or []

	#only bother with objects that have a "parent" attribute and whose parent attribute value is not the same as the one we've been passed
	objsToActOn = []
	for obj in objs:
		if objExists( '%s.parent' % obj ):
			objsToActOn.append( obj )

	objs = objsToActOn

	#if there are no objects, bail
	if not objs:
		printWarningStr( "There are no objects to work on - aborting!" )
		return

	#store the initial time so we can restore it at the end
	initialTime = currentTime( q=True )

	#first we need to make sure that any frame with a rotation key needs to have a key on ALL rotation axes - so make this happen
	keyTimes = keyframe( objs, q=True, at=('t', 'r'), tc=True )
	if not keyTimes:
		printWarningStr( "No keys found on the objects - nothing to do!" )
		return

	#remove duplicate key times and sort them
	keyTimes = removeDupes( keyTimes )
	keyTimes.sort()

	#store the objects that each have keys at each key time in a dict so we don't have to query maya again. maya queries are slower than accessing python data structures
	timeObjs = {}
	for time in keyTimes:
		currentTime( time, e=True )
		timeObjs[ time ] = objsWithKeysAtThisTime = []
		for obj in objs:
			keyOnCurrentTime = keyframe( obj, q=True, t=(time,), at=('parent', 't', 'r'), kc=True )
			if keyOnCurrentTime:
				setKeyframe( obj, at=('parent', 't', 'r') )
				objsWithKeysAtThisTime.append( obj )

	#now that we've secured the translation/rotation poses with keys on all axes, change the parent on each keyframe
	for time, objsWithKeysAtThisTime in timeObjs.iteritems():
		currentTime( time, e=True )
		for obj in objsWithKeysAtThisTime:
			pos = xform( obj, q=True, rp=True, ws=True )
			rot = xform( obj, q=True, ro=True, ws=True )

			#change the parent and move/rotate back to the original world space pose
			setAttr( '%s.parent' % obj, parent )

			move( pos[0], pos[1], pos[2], obj, ws=True, rpr=True )
			rotate( rot[0], rot[1], rot[2], obj, ws=True )

			#lock in the pose
			setKeyframe( obj, at=('parent', 't', 'r') )

	#finally restore the initial time
	currentTime( initialTime, e=True )
Example #6
0
def getControlsFromObjs( control ):
	'''
	attempts to retrieve the pole vector control, the ik handle and all fk controls given an ik rig control.  The
	information is returned in a 3 tuple containing:

	ikHandle, poleControl, fkControls
	'''
	errorValue = None, None, None, None

	try:
		part = rigPrimitives.RigPart.InitFromItem( control )

		return part.getControl( 'control' ), part.getIkHandle(), part.getControl( 'poleControl' ), part.getFkControls()
	except rigPrimitives.RigPartError: pass

	#so if the control we've been given isn't a rig primitive, lets try to extract whatever information we can from right click commands - if any exist
	trigger = Trigger( ikControl )
	switchCmdStr = None
	for n, cmdName, cmdStr in trigger.iterMenus():
		if cmdName.lower() == _IK_CMD_NAME:
			switchCmdStr = trigger.resolve( cmdStr )
			break

	if switchCmdStr is None:
		printWarningStr( "Cannot find the %s command - aborting!" % _IK_CMD_NAME )
		return errorValue

	#extract the control handle from the switch command - it may or may not exist, depending on which
	rexStr = re.compile( '-ikHandle \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE )
	match = rexStr.search( switchCmdStr )
	if not match:
		if match.groups()[0]:
			control = match.groups()[0]

	#extract the ik handle from the switch command
	rexStr = re.compile( '-ikHandle \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE )
	match = rexStr.search( switchCmdStr )
	if not match:
		printWarningStr( "Could not determine the ik handle from the given control" )
		return errorValue

	handle = match.groups()[0]
	if handle is None:
		printWarningStr( "Could not find the ik handle at the given connect index!" )
		return errorValue

	#now extract the pole control from the switch command
	rexStr = re.compile( '-pole \%([a-ZA-Z0-9_:|]+)', re.IGNORECASE | re.MULTILINE )
	match = rexStr.search( switchCmdStr )
	if not match:
		printWarningStr( "Could not determine the pole vector control from the given control" )
		return errorValue

	poleControl = match.groups()[0]
	if poleControl is None:
		printWarningStr( "Could not find the ik handle at the given connect index!" )
		return errorValue

	return control, poleControl, handle, getJointsFromIkHandle( handle )
Example #7
0
def getJointsFromIkHandle( handle ):

	#get the joints the ik control drives - we need these to get keyframes from so we know which frames to trace the ik control on
	joints = ikHandle( handle, q=True, jl=True )
	effector = ikHandle( handle, q=True, ee=True )
	cons = listConnections( '%s.tx' % effector, d=False )
	if not cons:
		printWarningStr( "Could not find the end effector control!" )
		return

	joints.append( cons[0] )

	return joints
Example #8
0
def getJointsFromIkHandle(handle):

    #get the joints the ik control drives - we need these to get keyframes from so we know which frames to trace the ik control on
    joints = ikHandle(handle, q=True, jl=True)
    effector = ikHandle(handle, q=True, ee=True)
    cons = listConnections('%s.tx' % effector, d=False)
    if not cons:
        printWarningStr("Could not find the end effector control!")
        return

    joints.append(cons[0])

    return joints
Example #9
0
def propagateWeightChangesToModel_confirm():
	'''
	simply wraps the propagateWeightChangesToModel function with a confirmation dialog
	'''
	allMeshNodes = ls( type='mesh' )
	allSkinnedMeshes = [ mesh for mesh in allMeshNodes if mel.findRelatedSkinCluster( mesh ) ]
	if not allSkinnedMeshes:
		printWarningStr( "No skinned meshes can be found in the scene!  Aborting!" )
		return

	BUTTONS = OK, CANCEL = 'Ok', 'Cancel'
	ret = confirmDialog( m='Are you sure you want to push skinning changes to the model?', t='Are you sure?', b=BUTTONS, db=CANCEL )
	if ret == OK:
		propagateWeightChangesToModel( allSkinnedMeshes )
Example #10
0
def switchAnimationToIk(control,
                        poleControl=None,
                        handle=None,
                        attrName='ikBlend',
                        onValue=1,
                        key=True,
                        startFrame=None,
                        endFrame=None):

    #get the joints the ik control drives - we need these to get keyframes from so we know which frames to trace the ik control on
    joints = getJointsFromIkHandle(handle)
    if not joints:
        printWarningStr("Cannot find the fk controls for the given ik control")
        return

    #grab the key times for keys set on the t or r channels on the ik control - these are the frames we want to switch to fk on
    keyTimes = keyframe(joints, q=True, at=('t', 'r'), tc=True)
    if not keyTimes:
        switchToIk(ikControl, poleControl, handle, attrName, onValue, key)
        printWarningStr("No keys found on the fk controls - nothing to do!")
        return

    #remove duplicate key times and sort them
    keyTimes = removeDupes(keyTimes)
    keyTimes.sort()
    cropValues(keyTimes, startFrame, endFrame)

    #clear out the keys for the ik control
    cutKey(control, poleControl, t=(keyTimes[0], keyTimes[-1]), cl=True)

    startFrame = keyTimes[0]
    currentTime(startFrame, e=True)
    setKeyframe(control, poleControl, t=(startFrame, ))

    for time in keyTimes:
        currentTime(time, e=True)
        switchToIk(control,
                   poleControl,
                   handle,
                   attrName,
                   onValue,
                   key,
                   joints,
                   _isBatchMode=True)

    setKeyframe(control, t=keyTimes, at=attrName, v=onValue)

    select(control)
Example #11
0
	def trace( self ):
		if not self._tracePairs:
			printWarningStr( "No objects to trace!" )
			return

		#wrap the following in a try so we can ensure cleanup gets called always
		try:

			#make sure the objects in the transform list are sorted properly
			self._sortTransformNodes()

			#run the pre-trace method on all tracePair instances
			for tracePair in self._tracePairs:
				tracePair.preTrace()

			#early out if there are no keyframes
			keyTimes = self.getKeyTimes()
			if not keyTimes:
				printWarningStr( "No keys to trace!" )
				return

			#match rotation orders if required
			transformTracePairs = list( self.getTransformNodePairs() )
			if self._matchRotationOrder:
				for tracePair in transformTracePairs:
					src, tgt = tracePair.getSrcTgt()
					if getAttr( '%s.ro' % tgt, se=True ):
						setAttr( '%s.ro' % tgt, getAttr( '%s.ro' % src ) )

			#clear out existing animation for the duration of the trace on target nodes
			for tracePair in self._tracePairs:
				src, tgt = tracePair.getSrcTgt()
				cutKey( tgt, t=(keyTimes[0], keyTimes[-1]), clear=True )

			#execute the traceFrame method for each tracePair instance
			for keyTime in keyTimes:
				currentTime( keyTime )
				for tracePair in self._tracePairs:
					tracePair.traceFrame( keyTime )

		#make sure the postTrace method gets executed once the trace finishes
		finally:
			for tracePair in self._tracePairs:
				tracePair.postTrace()
	def __init__( self, partContainer, skeletonPart=None ):
		if partContainer is not None:
			assert isRigPartContainer( partContainer ), "Must pass a valid rig part container! (received %s - a %s)" % (partContainer, nodeType( partContainer ))

		self._container = partContainer
		self._skeletonPart = skeletonPart
		self._worldPart = None
		self._worldControl = None
		self._partsNode = None
		self._qss = None
		self._idx = None

		if partContainer:
			if skeletonPart is None:
				try:
					self.getSkeletonPart()

				#this isn't fatal, although its not good
				except RigPartError, x:
					printWarningStr( str( x ) )
	def __init__( self, partContainer, skeletonPart=None ):
		if partContainer is not None:
			assert isRigPartContainer( partContainer ), "Must pass a valid rig part container! (received %s - a %s)" % (partContainer, nodeType( partContainer ))

		self._container = partContainer
		self._skeletonPart = skeletonPart
		self._worldPart = None
		self._worldControl = None
		self._partsNode = None
		self._qss = None
		self._idx = None

		if partContainer:
			if skeletonPart is None:
				try:
					self.getSkeletonPart()

				#this isn't fatal, although its not good
				except RigPartError, x:
					printWarningStr( str( x ) )
Example #14
0
def switchAnimationToFk( control, handle=None, attrName='ikBlend', onValue=1, offValue=0, key=True, startFrame=None, endFrame=None ):

	#grab the key times for keys set on the t or r channels on the ik control - these are the frames we want to switch to fk on
	keyTimes = keyframe( control, q=True, at=('t', 'r'), tc=True )
	if not keyTimes:
		switchToFk( control, handle, attrName, offValue, key )
		printWarningStr( "No keys found on the ik control - nothing to do!" )
		return

	#remove duplicate key times and sort them
	keyTimes = removeDupes( keyTimes )
	keyTimes.sort()
	cropValues( keyTimes, startFrame, endFrame )

	joints = getJointsFromIkHandle( handle )
	for time in keyTimes:
		currentTime( time, e=True )
		switchToFk( control, handle, attrName, onValue, offValue, key, joints )

	select( joints[-1] )
def propagateWeightChangesToModel_confirm():
    '''
	simply wraps the propagateWeightChangesToModel function with a confirmation dialog
	'''
    allMeshNodes = ls(type='mesh')
    allSkinnedMeshes = [
        mesh for mesh in allMeshNodes if mel.findRelatedSkinCluster(mesh)
    ]
    if not allSkinnedMeshes:
        printWarningStr(
            "No skinned meshes can be found in the scene!  Aborting!")
        return

    BUTTONS = OK, CANCEL = 'Ok', 'Cancel'
    ret = confirmDialog(
        m='Are you sure you want to push skinning changes to the model?',
        t='Are you sure?',
        b=BUTTONS,
        db=CANCEL)
    if ret == OK:
        propagateWeightChangesToModel(allSkinnedMeshes)
Example #16
0
    def __call__(self):
        if not self.ENABLED:
            return

        #if autokey is turned on, bail - this + autokey = potentially weird behaviour
        #NOTE: the tool will turn autokey off automatically when loaded - so if its on, its because the user has turned it back on.  Also
        #worth noting - this tool will restore the initial autokey state when closed/turned off...
        if autoKeyframe(q=True):
            printWarningStr(
                "Autokey is enabled - This tool doesn't play nice with autokey!  Please turn it off!"
            )
            return

        #if there are no entries in here - bail, they've already been handled
        if not PRE_ATTR_VALUES:
            return

        #put the following into a single undo chunk
        try:
            undoInfo(openChunk=True)
            for attrpath, preValue in PRE_ATTR_VALUES.iteritems():
                curValue = getAttr(attrpath)
                valueDelta = curValue - preValue

                #if there was no delta, keep loopin
                if not valueDelta:
                    continue

                #if there are no keyframes on this attribute - keep loopin
                if not keyframe(attrpath, q=True, kc=True):
                    continue

                keyframe(attrpath, e=True, t=(), vc=valueDelta, relative=True)

            PRE_ATTR_VALUES.clear()
        finally:
            undoInfo(closeChunk=True)

        #setup an idle event to re-populate the PRE_ATTR_VALUES dict when everything has finished processing
        scriptJob(runOnce=True, idleEvent=self.ui.on_selectionChange)
Example #17
0
def changeRo( objs=None, ro=XYZ ):
	if ro not in ROT_ORDER_STRS:
		raise TypeError( "need to specify a valid rotation order - one of: %s" % ' '.join( ROT_ORDER_STRS ) )

	if objs is None:
		objs = ls( sl=True, type='transform' )

	roIdx = list( ROT_ORDER_STRS ).index( ro )

	#filter out objects that don't have all 3 rotation axes settable and while we're at it store the rotation orders for each object
	#in a dict - since accessing a python dict is WAY faster than doing a getAttr for each frame in the loop below
	RO_DICT = {}
	objsWithAllChannelsSettable = []

	for obj in objs:
		if not getAttr( '%s.r' % obj, se=True ):
			printWarningStr( "Not all rotation axes on the object %s are settable - skipping!" % obj )
			continue

		objRo = getAttr( '%s.ro' % obj )

		#if the rotation order of this object is the same as what we're changing it to - skip the object entirely
		if objRo == roIdx:
			printWarningStr( "The object %s already has the rotation order %s - skipping!" % (obj, ro) )
			continue

		RO_DICT[ obj ] = objRo
		objsWithAllChannelsSettable.append( obj )

	#early out if we have no objects to work on
	objs = objsWithAllChannelsSettable
	if not objs:
		printWarningStr( "No objects to act on - exiting" )
		return

	#cache the conversion method
	convertToMethod = MATRIX_ROTATION_ORDER_CONVERSIONS_TO[ roIdx ]

	#construct a key server object to march over keys and objects
	keyServer = KeyServer( objs, True )
	for time in keyServer:
		for obj in keyServer.getNodesAtTime():
			setKeyframe( obj, at='r' )

	#now that we're secured the rotation poses with keys on all axes, fix up each rotation value to use the desired rotation order
	for time in keyServer:
		for obj in keyServer.getNodesAtTime():
			currentRoIdx = RO_DICT[ obj ]

			rot = getAttr( '%s.r' % obj )[0]
			rotMatrix = MATRIX_ROTATION_ORDER_CONVERSIONS_FROM[ currentRoIdx ]( degrees=True, *rot )

			newRot = convertToMethod( rotMatrix, True )
			setAttr( '%s.r' % obj, *newRot )
			setKeyframe( obj, at='r' )

	#now change the rotation order to what it should be
	for obj in objs:
		setAttr( '%s.ro' % obj, roIdx )
Example #18
0
	def __call__( self ):
		if not self.ENABLED:
			return

		#if autokey is turned on, bail - this + autokey = potentially weird behaviour
		#NOTE: the tool will turn autokey off automatically when loaded - so if its on, its because the user has turned it back on.  Also
		#worth noting - this tool will restore the initial autokey state when closed/turned off...
		if autoKeyframe( q=True ):
			printWarningStr( "Autokey is enabled - This tool doesn't play nice with autokey!  Please turn it off!" )
			return

		#if there are no entries in here - bail, they've already been handled
		if not PRE_ATTR_VALUES:
			return

		#put the following into a single undo chunk
		try:
			undoInfo( openChunk=True )
			for attrpath, preValue in PRE_ATTR_VALUES.iteritems():
				curValue = getAttr( attrpath )
				valueDelta = curValue - preValue

				#if there was no delta, keep loopin
				if not valueDelta:
					continue

				#if there are no keyframes on this attribute - keep loopin
				if not keyframe( attrpath, q=True, kc=True ):
					continue

				keyframe( attrpath, e=True, t=(), vc=valueDelta, relative=True )

			PRE_ATTR_VALUES.clear()
		finally:
			undoInfo( closeChunk=True )

		#setup an idle event to re-populate the PRE_ATTR_VALUES dict when everything has finished processing
		scriptJob( runOnce=True, idleEvent=self.ui.on_selectionChange )
Example #19
0
def switchToIk(control,
               poleControl=None,
               handle=None,
               attrName='ikBlend',
               onValue=1,
               key=False,
               joints=None,
               _isBatchMode=False):
    if handle is None:
        handle = control

    if handle is None or not objExists(handle):
        printWarningStr("no ikHandle specified")
        return

    #if we weren't passed in joints - discover them now
    if joints is None:
        joints = getJointsFromIkHandle(handle)

    alignFast(control, joints[2])
    if poleControl:
        if objExists(poleControl):
            pos = findPolePosition(joints[2], joints[1], joints[0])
            move(pos[0],
                 pos[1],
                 pos[2],
                 poleControl,
                 a=True,
                 ws=True,
                 rpr=True)
            setKeyframe(poleControl)

    setAttr('%s.%s' % (control, attrName), onValue)
    if key:
        setKeyframe(control, at=('t', 'r'))
        if not _isBatchMode:
            setKeyframe(control, at=attrName)
Example #20
0
def switchToFk(control,
               handle=None,
               attrName='ikBlend',
               onValue=1,
               offValue=0,
               key=False,
               joints=None):
    if handle is None:
        handle = control

    if handle is None or not objExists(handle):
        printWarningStr("no ikHandle specified")
        return

    #if we weren't passed in joints - discover them now
    if joints is None:
        joints = getJointsFromIkHandle(handle)

    #make sure ik is on before querying rotations
    setAttr('%s.%s' % (control, attrName), onValue)
    rots = []
    for j in joints:
        rot = getAttr("%s.r" % j)[0]
        rots.append(rot)

    #now turn ik off and set rotations for the joints
    setAttr('%s.%s' % (control, attrName), offValue)
    for j, rot in zip(joints, rots):
        for ax, r in zip(('x', 'y', 'z'), rot):
            if getAttr('%s.r%s' % (j, ax), se=True):
                setAttr('%s.r%s' % (j, ax), r)

    alignFast(joints[2], handle)
    if key:
        setKeyframe(joints)
        setKeyframe('%s.%s' % (control, attrName))
Example #21
0
def switchToIk( control, poleControl=None, handle=None, attrName='ikBlend', onValue=1, key=False, joints=None, _isBatchMode=False ):
	if handle is None:
		handle = control

	if handle is None or not objExists( handle ):
		printWarningStr( "no ikHandle specified" )
		return

	#if we weren't passed in joints - discover them now
	if joints is None:
		joints = getJointsFromIkHandle( handle )

	alignFast( control, joints[2] )
	if poleControl:
		if objExists( poleControl ):
			pos = findPolePosition( joints[2], joints[1], joints[0] )
			move( pos[0], pos[1], pos[2], poleControl, a=True, ws=True, rpr=True )
			setKeyframe( poleControl )

	setAttr( '%s.%s' % (control, attrName), onValue )
	if key:
		setKeyframe( control, at=('t', 'r') )
		if not _isBatchMode:
			setKeyframe( control, at=attrName )
Example #22
0
def changeRo( objs=None, ro=XYZ ):
	if ro not in ROTATION_ORDER_STRS:
		raise TypeError( "need to specify a valid rotation order - one of: %s" % ' '.join( ROTATION_ORDER_STRS ) )

	if objs is None:
		objs = ls( sl=True, type='transform' )

	roIdx = list( ROTATION_ORDER_STRS ).index( ro )

	#filter out objects that don't have all 3 rotation axes settable and while we're at it store the rotation orders for each object
	#in a dict - since accessing a python dict is WAY faster than doing a getAttr for each frame in the loop below
	RO_DICT = {}
	objsWithAllChannelsSettable = []

	for obj in objs:
		if not getAttr( '%s.r' % obj, se=True ):
			printWarningStr( "Not all rotation axes on the object %s are settable - skipping!" % obj )
			continue

		objRo = getAttr( '%s.ro' % obj )

		#if the rotation order of this object is the same as what we're changing it to - skip the object entirely
		if objRo == roIdx:
			printWarningStr( "The object %s already has the rotation order %s - skipping!" % (obj, ro) )
			continue

		RO_DICT[ obj ] = objRo
		objsWithAllChannelsSettable.append( obj )

	#early out if we have no objects to work on
	objs = objsWithAllChannelsSettable
	if not objs:
		printWarningStr( "No objects to act on - exiting" )
		return

	#first we need to make sure that any frame with a rotation key needs to have a key on ALL rotation axes - so make this happen
	keyTimes = keyframe( objs, q=True, at='r', tc=True )
	if not keyTimes:
		printWarningStr( "No keys found on the objects - nothing to do!" )
		return

	#remove duplicate key times and sort them
	keyTimes = removeDupes( keyTimes )
	keyTimes.sort()

	#cache out the conversion method
	convertToMethod = MATRIX_ROTATION_ORDER_CONVERSIONS_TO[ roIdx ]

	#store the objects that each have keys at each key time in a dict so we don't have to query maya again. maya queries are slower than accessing python data structures
	timeObjs = {}
	for time in keyTimes:
		currentTime( time, e=True )
		timeObjs[ time ] = objsWithKeysAtThisTime = []
		for obj in objs:
			keyOnCurrentTime = keyframe( obj, q=True, t=(time,), kc=True )
			if keyOnCurrentTime:
				setKeyframe( obj, at='r' )
				objsWithKeysAtThisTime.append( obj )

	#now that we're secured the rotation poses with keys on all axes, fix up each rotation value to use the desired rotation order
	for time, objsWithKeysAtThisTime in timeObjs.iteritems():
		currentTime( time, e=True )
		for obj in objsWithKeysAtThisTime:
			currentRoIdx = RO_DICT[ obj ]

			rot = getAttr( '%s.r' % obj )[0]
			rotMatrix = MATRIX_ROTATION_ORDER_CONVERSIONS_FROM[ currentRoIdx ]( degrees=True, *rot )

			newRot = convertToMethod( rotMatrix, True )
			setAttr( '%s.r' % obj, *newRot )
			setKeyframe( obj, at='r' )

	#now change the rotation order to what it should be
	for obj in objs:
		setAttr( '%s.ro' % obj, roIdx )
Example #23
0
def getControlsFromObjs(control):
    '''
	attempts to retrieve the pole vector control, the ik handle and all fk controls given an ik rig control.  The
	information is returned in a 3 tuple containing:

	ikHandle, poleControl, fkControls
	'''
    errorValue = None, None, None, None

    try:
        part = rigPrimitives.RigPart.InitFromItem(control)

        return part.getControl('control'), part.getIkHandle(), part.getControl(
            'poleControl'), part.getFkControls()
    except rigPrimitives.RigPartError:
        pass

    #so if the control we've been given isn't a rig primitive, lets try to extract whatever information we can from right click commands - if any exist
    trigger = Trigger(ikControl)
    switchCmdStr = None
    for n, cmdName, cmdStr in trigger.iterMenus():
        if cmdName.lower() == _IK_CMD_NAME:
            switchCmdStr = trigger.resolve(cmdStr)
            break

    if switchCmdStr is None:
        printWarningStr("Cannot find the %s command - aborting!" %
                        _IK_CMD_NAME)
        return errorValue

    #extract the control handle from the switch command - it may or may not exist, depending on which
    rexStr = re.compile('-ikHandle \%([a-ZA-Z0-9_:|]+)',
                        re.IGNORECASE | re.MULTILINE)
    match = rexStr.search(switchCmdStr)
    if not match:
        if match.groups()[0]:
            control = match.groups()[0]

    #extract the ik handle from the switch command
    rexStr = re.compile('-ikHandle \%([a-ZA-Z0-9_:|]+)',
                        re.IGNORECASE | re.MULTILINE)
    match = rexStr.search(switchCmdStr)
    if not match:
        printWarningStr(
            "Could not determine the ik handle from the given control")
        return errorValue

    handle = match.groups()[0]
    if handle is None:
        printWarningStr(
            "Could not find the ik handle at the given connect index!")
        return errorValue

    #now extract the pole control from the switch command
    rexStr = re.compile('-pole \%([a-ZA-Z0-9_:|]+)',
                        re.IGNORECASE | re.MULTILINE)
    match = rexStr.search(switchCmdStr)
    if not match:
        printWarningStr(
            "Could not determine the pole vector control from the given control"
        )
        return errorValue

    poleControl = match.groups()[0]
    if poleControl is None:
        printWarningStr(
            "Could not find the ik handle at the given connect index!")
        return errorValue

    return control, poleControl, handle, getJointsFromIkHandle(handle)
Example #24
0
def changeRo(objs=None, ro=XYZ):
    if ro not in ROTATION_ORDER_STRS:
        raise TypeError("need to specify a valid rotation order - one of: %s" %
                        ' '.join(ROTATION_ORDER_STRS))

    if objs is None:
        objs = ls(sl=True, type='transform')

    roIdx = list(ROTATION_ORDER_STRS).index(ro)

    #filter out objects that don't have all 3 rotation axes settable and while we're at it store the rotation orders for each object
    #in a dict - since accessing a python dict is WAY faster than doing a getAttr for each frame in the loop below
    RO_DICT = {}
    objsWithAllChannelsSettable = []

    for obj in objs:
        if not getAttr('%s.r' % obj, se=True):
            printWarningStr(
                "Not all rotation axes on the object %s are settable - skipping!"
                % obj)
            continue

        objRo = getAttr('%s.ro' % obj)

        #if the rotation order of this object is the same as what we're changing it to - skip the object entirely
        if objRo == roIdx:
            printWarningStr(
                "The object %s already has the rotation order %s - skipping!" %
                (obj, ro))
            continue

        RO_DICT[obj] = objRo
        objsWithAllChannelsSettable.append(obj)

    #early out if we have no objects to work on
    objs = objsWithAllChannelsSettable
    if not objs:
        printWarningStr("No objects to act on - exiting")
        return

    #first we need to make sure that any frame with a rotation key needs to have a key on ALL rotation axes - so make this happen
    keyTimes = keyframe(objs, q=True, at='r', tc=True)
    if not keyTimes:
        printWarningStr("No keys found on the objects - nothing to do!")
        return

    #remove duplicate key times and sort them
    keyTimes = removeDupes(keyTimes)
    keyTimes.sort()

    #cache out the conversion method
    convertToMethod = MATRIX_ROTATION_ORDER_CONVERSIONS_TO[roIdx]

    #store the objects that each have keys at each key time in a dict so we don't have to query maya again. maya queries are slower than accessing python data structures
    timeObjs = {}
    for time in keyTimes:
        currentTime(time, e=True)
        timeObjs[time] = objsWithKeysAtThisTime = []
        for obj in objs:
            keyOnCurrentTime = keyframe(obj, q=True, t=(time, ), kc=True)
            if keyOnCurrentTime:
                setKeyframe(obj, at='r')
                objsWithKeysAtThisTime.append(obj)

    #now that we're secured the rotation poses with keys on all axes, fix up each rotation value to use the desired rotation order
    for time, objsWithKeysAtThisTime in timeObjs.iteritems():
        currentTime(time, e=True)
        for obj in objsWithKeysAtThisTime:
            currentRoIdx = RO_DICT[obj]

            rot = getAttr('%s.r' % obj)[0]
            rotMatrix = MATRIX_ROTATION_ORDER_CONVERSIONS_FROM[currentRoIdx](
                degrees=True, *rot)

            newRot = convertToMethod(rotMatrix, True)
            setAttr('%s.r' % obj, *newRot)
            setKeyframe(obj, at='r')

    #now change the rotation order to what it should be
    for obj in objs:
        setAttr('%s.ro' % obj, roIdx)
Example #25
0
		def doCreate():
			positions = []
			for obj in objs:
				positions.append( xform( obj, q=True, ws=True, rp=True ) )

			#the objs may not be in the same hierarchy, so create a proxy chain that IS in a heirarchy
			proxyJoints = []
			for obj in objs:
				select( cl=True )
				j = createNode( 'joint' )
				j = rename( j, '%s_dynChainProxy#' % obj.split( ':' )[-1].split( '|' )[-1] )
				if proxyJoints:
					parent( j, proxyJoints[-1] )

				delete( parentConstraint( obj, j ) )
				proxyJoints.append( j )

				#constrain the original to the proxy
				parentConstraint( j, obj )

			#hook up the proxy root to a special message attribute so we can easily find the proxy chain again for things like baking etc...
			connectAttr( '%s.message' % proxyJoints[0], '%s.proxyRoot' % setNode )

			#build a linear curve
			linearCurve = curve( d=1, p=positions )
			linearCurveShape = listRelatives( linearCurve, s=True, pa=True )[0]
			select( linearCurve )
			maya.mel.eval( 'makeCurvesDynamicHairs 1 0 1;' )

			#find the dynamic curve shape
			cons = listConnections( '%s.worldSpace' % linearCurveShape, s=False )
			if not cons:
				printWarningStr( "Cannot find follicle" )
				return

			follicleShape = cons[0]
			cons = listConnections( '%s.outHair' % follicleShape, s=False )
			if not cons:
				printWarningStr( "Cannot find hair system!" )
				return

			hairSystemNode = cons[0]
			setAttr( '%s.startFrame' % hairSystemNode, playbackOptions( q=True, min=True ) )
			cons = listConnections( '%s.outCurve' % follicleShape, s=False )
			if not cons:
				printWarningStr( "Cannot find out curve!" )
				return

			dynamicCurve = cons[0]
			dynamicCurveParent = listRelatives( dynamicCurve, p=True, pa=True )  #grab the dynamic curve's shape

			select( dynamicCurve )
			maya.mel.eval( 'displayHairCurves "current" 1;' )

			follicle = listRelatives( linearCurve, p=True, pa=True )[0]
			objParent = listRelatives( objs[0], p=True, pa=True )
			if objParent:
				objParent = objParent[0]
				parent( follicle, objParent )
				parent( proxyJoints[0], objParent )

			setAttr( '%s.overrideDynamics' % follicle, 1 )
			setAttr( '%s.pointLock' % follicle, 1 )

			#hook up all the attributes
			connectAttr( '%s.stiffness' % setNode, '%s.stiffness' % follicle )
			connectAttr( '%s.lengthFlex' % setNode, '%s.lengthFlex' % follicle )
			connectAttr( '%s.damping' % setNode, '%s.damp' % follicle )
			connectAttr( '%s.drag' % setNode, '%s.drag' % hairSystemNode )
			connectAttr( '%s.friction' % setNode, '%s.friction' % hairSystemNode )
			connectAttr( '%s.gravity' % setNode, '%s.gravity' % hairSystemNode )
			connectAttr( '%s.turbStrength' % setNode, '%s.turbulenceStrength' % hairSystemNode )
			connectAttr( '%s.turbFreq' % setNode, '%s.turbulenceFrequency' % hairSystemNode )
			connectAttr( '%s.turbSpeed' % setNode, '%s.turbulenceSpeed' % hairSystemNode )

			splineIkHandle = ikHandle( sj=proxyJoints[0], ee=proxyJoints[-1], curve=dynamicCurve, sol='ikSplineSolver', ccv=False )[0]

			#for some reason the dynamic curve gets re-parented by the ikHandle command (weird) so set the parent back to what it was originally
			parent( dynamicCurve, dynamicCurveParent )
Example #26
0
	def construct( self ):
		'''
		builds the actual dynamic hair network
		'''
		setNode = self._node
		objs = self.getObjs()

		#before we do anything, check to see whether the selected objects have any incoming connections
		warnAboutDisconnections = False
		for obj in objs:

			#check the object for incoming connections - if it has any, remove them
			for chan in ('t', 'r'):
				for ax in Axis.BASE_AXES:
					cons = listConnections( '%s.%s%s' % (obj, chan, ax), d=False )
					if cons:
						warnAboutDisconnections = True
						if objectType( cons[0], isAType='animCurve' ):
							delete( cons[0] )
						else:
							raise TypeError( "The object %s has non anim curve incoming connections - aborting!  Please remove connections manually before proceeding" % obj )

		if warnAboutDisconnections:
			printWarningStr( "Some of the objects had incoming connections (probably from animation).  These connections have been broken!  undo if you want them back" )

		#wrap the creation of the nodes in a function - below this we execute this function via a wrapper which returns a list of new nodes created
		#this is done so we can easily capture the nodes created and store them in the set that describes this dynamic chain
		def doCreate():
			positions = []
			for obj in objs:
				positions.append( xform( obj, q=True, ws=True, rp=True ) )

			#the objs may not be in the same hierarchy, so create a proxy chain that IS in a heirarchy
			proxyJoints = []
			for obj in objs:
				select( cl=True )
				j = createNode( 'joint' )
				j = rename( j, '%s_dynChainProxy#' % obj.split( ':' )[-1].split( '|' )[-1] )
				if proxyJoints:
					parent( j, proxyJoints[-1] )

				delete( parentConstraint( obj, j ) )
				proxyJoints.append( j )

				#constrain the original to the proxy
				parentConstraint( j, obj )

			#hook up the proxy root to a special message attribute so we can easily find the proxy chain again for things like baking etc...
			connectAttr( '%s.message' % proxyJoints[0], '%s.proxyRoot' % setNode )

			#build a linear curve
			linearCurve = curve( d=1, p=positions )
			linearCurveShape = listRelatives( linearCurve, s=True, pa=True )[0]
			select( linearCurve )
			maya.mel.eval( 'makeCurvesDynamicHairs 1 0 1;' )

			#find the dynamic curve shape
			cons = listConnections( '%s.worldSpace' % linearCurveShape, s=False )
			if not cons:
				printWarningStr( "Cannot find follicle" )
				return

			follicleShape = cons[0]
			cons = listConnections( '%s.outHair' % follicleShape, s=False )
			if not cons:
				printWarningStr( "Cannot find hair system!" )
				return

			hairSystemNode = cons[0]
			setAttr( '%s.startFrame' % hairSystemNode, playbackOptions( q=True, min=True ) )
			cons = listConnections( '%s.outCurve' % follicleShape, s=False )
			if not cons:
				printWarningStr( "Cannot find out curve!" )
				return

			dynamicCurve = cons[0]
			dynamicCurveParent = listRelatives( dynamicCurve, p=True, pa=True )  #grab the dynamic curve's shape

			select( dynamicCurve )
			maya.mel.eval( 'displayHairCurves "current" 1;' )

			follicle = listRelatives( linearCurve, p=True, pa=True )[0]
			objParent = listRelatives( objs[0], p=True, pa=True )
			if objParent:
				objParent = objParent[0]
				parent( follicle, objParent )
				parent( proxyJoints[0], objParent )

			setAttr( '%s.overrideDynamics' % follicle, 1 )
			setAttr( '%s.pointLock' % follicle, 1 )

			#hook up all the attributes
			connectAttr( '%s.stiffness' % setNode, '%s.stiffness' % follicle )
			connectAttr( '%s.lengthFlex' % setNode, '%s.lengthFlex' % follicle )
			connectAttr( '%s.damping' % setNode, '%s.damp' % follicle )
			connectAttr( '%s.drag' % setNode, '%s.drag' % hairSystemNode )
			connectAttr( '%s.friction' % setNode, '%s.friction' % hairSystemNode )
			connectAttr( '%s.gravity' % setNode, '%s.gravity' % hairSystemNode )
			connectAttr( '%s.turbStrength' % setNode, '%s.turbulenceStrength' % hairSystemNode )
			connectAttr( '%s.turbFreq' % setNode, '%s.turbulenceFrequency' % hairSystemNode )
			connectAttr( '%s.turbSpeed' % setNode, '%s.turbulenceSpeed' % hairSystemNode )

			splineIkHandle = ikHandle( sj=proxyJoints[0], ee=proxyJoints[-1], curve=dynamicCurve, sol='ikSplineSolver', ccv=False )[0]

			#for some reason the dynamic curve gets re-parented by the ikHandle command (weird) so set the parent back to what it was originally
			parent( dynamicCurve, dynamicCurveParent )

		newNodes, returnValue = getNodesCreatedBy( doCreate )

		#stuff the nodes created into the set that describes this dynamic chain - just add transform nodes...
		for aNode in newNodes:
			if objectType( aNode, isAType='transform' ):
				sets( aNode, e=True, add=setNode )
def propagateWeightChangesToModel(meshes):
    '''
	Given a list of meshes to act on, this function will store the skin weights, remove any
	edits from the skin clusters that affect them, open the scene file the meshes come from
	and apply the weights to the geometry in that scene.

	This makes it possible to fix skinning problems while animating with minimal workflow
	changes
	'''
    curFile = Path(file(q=True, sn=True))
    referencedMeshes = getRefFilepathDictForNodes(meshes)

    if not curFile.name():
        printWarningStr(
            "The current scene isn't saved - please save the current scene first before proceeding!"
        )
        return

    for refFilepath, refNodeMeshDict in referencedMeshes.iteritems():
        referencesToUnload = []

        #make sure we don't visit any of the meshes more than once
        meshesToUpdateWeightsOn = []
        meshesToUpdateWeightsOn_withNS = []
        for refNode, refMeshes in refNodeMeshDict.iteritems():

            #get the maya filepath for the reference (with the "copy number")
            mayaFilepathForRef = referenceQuery(refNode, f=True)

            #get the namespace for this reference
            refNodeNamespace = file(mayaFilepathForRef, q=True, namespace=True)

            #check to see if there are any meshes in this reference that we need to store weights for
            for mesh_withNS in refMeshes:
                mesh = stripNamespaceFromNamePath(mesh_withNS,
                                                  refNodeNamespace)
                if mesh in meshesToUpdateWeightsOn:
                    continue

                meshesToUpdateWeightsOn.append(mesh)
                meshesToUpdateWeightsOn_withNS.append(
                    (mesh_withNS, refNodeNamespace))

            #append the file to the list of reference files that we need to unload
            referencesToUnload.append(mayaFilepathForRef)

        #get a list of skin cluster nodes - its actually the skin cluster nodes we want to remove edits from...
        nodesToCleanRefEditsFrom = []
        for m, ns in meshesToUpdateWeightsOn_withNS:
            nodesToCleanRefEditsFrom.append(mel.findRelatedSkinCluster(m))

        #now we want to store out the weighting from the referenced meshes
        weights = []
        for mesh, meshNamespace in meshesToUpdateWeightsOn_withNS:
            weights.append(storeWeightsById(mesh, meshNamespace))

            #also lets remove any ref edits from the mesh and all of its shape nodes - this isn't strictly nessecary, but I can't think of a reason to make edits to these nodes outside of their native file
            nodesToCleanRefEditsFrom.append(mesh)
            nodesToCleanRefEditsFrom += listRelatives(mesh, s=True,
                                                      pa=True) or []

        #remove the skinweights reference edits from the meshes in the current scene
        for f in referencesToUnload:
            file(f, unloadReference=True)

        #remove ref edits from the shape node as well - this isn't strictly nessecary but there probably shouldn't be changes to the shape node anyway
        for node in nodesToCleanRefEditsFrom:
            referenceEdit(node,
                          removeEdits=True,
                          successfulEdits=True,
                          failedEdits=True)

        #re-load references
        for f in referencesToUnload:
            file(f, loadReference=True)

        #save this scene now that we've removed ref edits
        ensureCurrentFileIsCheckedOut()
        file(save=True, f=True)

        #load up the referenced file and apply the weighting to the meshes in that scene
        file(refFilepath, open=True, f=True)

        for mesh, weightData in zip(meshesToUpdateWeightsOn, weights):

            #if there is no weight data to store - keep loopin...
            if not weightData:
                continue

            skinCluster = mel.findRelatedSkinCluster(mesh)
            if not skinCluster:
                printWarningStr(
                    "Couldn't find a skin cluster driving %s - skipping this mesh"
                    % mesh)
                continue

            skinWeights.setSkinWeights(skinCluster, weightData)

        #save the referenced scene now that we've applied the weights to it
        ensureCurrentFileIsCheckedOut()
        file(save=True, f=True)

    #reload the original file
    file(curFile, o=True, f=True)
Example #28
0
def propagateWeightChangesToModel( meshes ):
	'''
	Given a list of meshes to act on, this function will store the skin weights, remove any
	edits from the skin clusters that affect them, open the scene file the meshes come from
	and apply the weights to the geometry in that scene.

	This makes it possible to fix skinning problems while animating with minimal workflow
	changes
	'''
	curFile = Path( file( q=True, sn=True ) )
	referencedMeshes = getRefFilepathDictForNodes( meshes )

	if not curFile.name():
		printWarningStr( "The current scene isn't saved - please save the current scene first before proceeding!" )
		return

	for refFilepath, refNodeMeshDict in referencedMeshes.iteritems():
		referencesToUnload = []

		#make sure we don't visit any of the meshes more than once
		meshesToUpdateWeightsOn = []
		meshesToUpdateWeightsOn_withNS = []
		for refNode, refMeshes in refNodeMeshDict.iteritems():

			#get the maya filepath for the reference (with the "copy number")
			mayaFilepathForRef = referenceQuery( refNode, f=True )

			#get the namespace for this reference
			refNodeNamespace = file( mayaFilepathForRef, q=True, namespace=True )

			#check to see if there are any meshes in this reference that we need to store weights for
			for mesh_withNS in refMeshes:
				mesh = stripNamespaceFromNamePath( mesh_withNS, refNodeNamespace )
				if mesh in meshesToUpdateWeightsOn:
					continue

				meshesToUpdateWeightsOn.append( mesh )
				meshesToUpdateWeightsOn_withNS.append( (mesh_withNS, refNodeNamespace) )

			#append the file to the list of reference files that we need to unload
			referencesToUnload.append( mayaFilepathForRef )

		#get a list of skin cluster nodes - its actually the skin cluster nodes we want to remove edits from...
		nodesToCleanRefEditsFrom = []
		for m, ns in meshesToUpdateWeightsOn_withNS:
			nodesToCleanRefEditsFrom.append( mel.findRelatedSkinCluster( m ) )

		#now we want to store out the weighting from the referenced meshes
		weights = []
		for mesh, meshNamespace in meshesToUpdateWeightsOn_withNS:
			weights.append( storeWeightsById( mesh, meshNamespace ) )

			#also lets remove any ref edits from the mesh and all of its shape nodes - this isn't strictly nessecary, but I can't think of a reason to make edits to these nodes outside of their native file
			nodesToCleanRefEditsFrom.append( mesh )
			nodesToCleanRefEditsFrom += listRelatives( mesh, s=True, pa=True ) or []

		#remove the skinweights reference edits from the meshes in the current scene
		for f in referencesToUnload:
			file( f, unloadReference=True )

		#remove ref edits from the shape node as well - this isn't strictly nessecary but there probably shouldn't be changes to the shape node anyway
		for node in nodesToCleanRefEditsFrom:
			referenceEdit( node, removeEdits=True, successfulEdits=True, failedEdits=True )

		#re-load references
		for f in referencesToUnload:
			file( f, loadReference=True )

		#save this scene now that we've removed ref edits
		ensureCurrentFileIsCheckedOut()
		file( save=True, f=True )

		#load up the referenced file and apply the weighting to the meshes in that scene
		file( refFilepath, open=True, f=True )

		for mesh, weightData in zip( meshesToUpdateWeightsOn, weights ):

			#if there is no weight data to store - keep loopin...
			if not weightData:
				continue

			skinCluster = mel.findRelatedSkinCluster( mesh )
			if not skinCluster:
				printWarningStr( "Couldn't find a skin cluster driving %s - skipping this mesh" % mesh )
				continue

			skinWeights.setSkinWeights( skinCluster, weightData )

		#save the referenced scene now that we've applied the weights to it
		ensureCurrentFileIsCheckedOut()
		file( save=True, f=True )

	#reload the original file
	file( curFile, o=True, f=True )
Example #29
0
def changeRo(objs=None, ro=XYZ):
    if ro not in ROT_ORDER_STRS:
        raise TypeError("need to specify a valid rotation order - one of: %s" %
                        ' '.join(ROT_ORDER_STRS))

    if objs is None:
        objs = ls(sl=True, type='transform')

    roIdx = list(ROT_ORDER_STRS).index(ro)

    #filter out objects that don't have all 3 rotation axes settable and while we're at it store the rotation orders for each object
    #in a dict - since accessing a python dict is WAY faster than doing a getAttr for each frame in the loop below
    RO_DICT = {}
    objsWithAllChannelsSettable = []

    for obj in objs:
        if not getAttr('%s.r' % obj, se=True):
            printWarningStr(
                "Not all rotation axes on the object %s are settable - skipping!"
                % obj)
            continue

        objRo = getAttr('%s.ro' % obj)

        #if the rotation order of this object is the same as what we're changing it to - skip the object entirely
        if objRo == roIdx:
            printWarningStr(
                "The object %s already has the rotation order %s - skipping!" %
                (obj, ro))
            continue

        RO_DICT[obj] = objRo
        objsWithAllChannelsSettable.append(obj)

    #early out if we have no objects to work on
    objs = objsWithAllChannelsSettable
    if not objs:
        printWarningStr("No objects to act on - exiting")
        return

    #cache the conversion method
    convertToMethod = MATRIX_ROTATION_ORDER_CONVERSIONS_TO[roIdx]

    #construct a key server object to march over keys and objects
    keyServer = KeyServer(objs, True)
    for time in keyServer:
        for obj in keyServer.getNodesAtTime():
            setKeyframe(obj, at='r')

    #now that we're secured the rotation poses with keys on all axes, fix up each rotation value to use the desired rotation order
    for time in keyServer:
        for obj in keyServer.getNodesAtTime():
            currentRoIdx = RO_DICT[obj]

            rot = getAttr('%s.r' % obj)[0]
            rotMatrix = MATRIX_ROTATION_ORDER_CONVERSIONS_FROM[currentRoIdx](
                degrees=True, *rot)

            newRot = convertToMethod(rotMatrix, True)
            setAttr('%s.r' % obj, *newRot)
            setKeyframe(obj, at='r')

    #now change the rotation order to what it should be
    for obj in objs:
        setAttr('%s.ro' % obj, roIdx)
Example #30
0
	def appendPair( self, src, tgt ):
		if not objExists( src ) or not objExists( tgt ):
			printWarningStr( "Either the src or tgt nodes don't exist!" )
			return

		self._tracePairs.append( TracePair( src, tgt ) )