def get_key_range(obj, start_frame=None, end_frame=None): ''' Find the first and last keyed frame from an object that lies outside of the given start and end frame range Args: obj (PyNode): The object to query start_frame (float): The current lowest frame to compare against end_frame (float): The current highest frame to compare against Returns: (float, float). The lowest and highest frame ''' first_key = start_frame last_key = end_frame historyNodes = pm.listHistory(obj, pruneDagObjects=True, leaf=False) animCurves = pm.ls(historyNodes, type='animCurve') if animCurves: # Warning - pm.findKeyframe will return currentTime if it's given no anim curves first_key = pm.findKeyframe(animCurves, which='first') last_key = pm.findKeyframe(animCurves, which='last') # We use frame -10000 and -10001 as a special holder frame for keys used by tools start_frame = first_key if first_key < start_frame or start_frame == None else start_frame start_frame = None if start_frame == -10000 or start_frame == -10001 else start_frame end_frame = last_key if last_key > end_frame or end_frame == None else end_frame end_frame = None if end_frame == -10000 or end_frame == -10001 else end_frame return (start_frame, end_frame)
def key_delete(all_keys=True, only_before=False): """Delete all keys before, after, or both, except the current one which has an insert key set""" current_frame = pm.getCurrentTime() curves = pm.findKeyframe(curve=True) first_key = 0.0 last_key = 0.0 for curve in curves: key = pm.findKeyframe(curve, which='first') if key < first_key: first_key = key key = pm.findKeyframe(curve, which='last') if key > last_key: last_key = key pm.setKeyframe(insert=True) if not all_keys: if only_before: pm.cutKey(clear=True, time=(first_key, current_frame - 1)) else: pm.cutKey(clear=True, time=(current_frame + 1, last_key)) else: pm.cutKey(clear=True, time=(first_key, current_frame - 1)) pm.cutKey(clear=True, time=(current_frame + 1, last_key))
def loopCurve( curveList=[], which='first' ): """ Adjust keyframes and tangents of selected curves to loop. @param curveList: a list of curves to affect. @type curveList: list @param which: default: Specify which keyframe will be adjusted. Options are C{'first'} (default) and {'last'} @type which: string """ if len( curveList ) is 0: curveList = getSelectedCurvesKeys().keys() for curve in curveList: endsKeys = [pm.findKeyframe( curve, which='first' ), pm.findKeyframe( curve, which='last' )] if which is 'last': endsKeys.reverse() lockState = pm.keyTangent( curve, time=( endsKeys[0], endsKeys[0] ), query=True, lock=True )[0] pm.keyframe( curve, time=( endsKeys[0], endsKeys[0] ), valueChange=pm.keyframe( curve, time=( endsKeys[1], endsKeys[1] ), query=True, valueChange=True )[0] ) if which is 'first': pm.keyTangent( curve, time=( endsKeys[0], endsKeys[0] ), edit=True, lock=False, outAngle=pm.keyTangent( curve, query=True, inAngle=True, time=( endsKeys[1], endsKeys[1] ) )[0] ) elif which is 'last': pm.keyTangent( curve, time=( endsKeys[0], endsKeys[0] ), edit=True, lock=False, inAngle=pm.keyTangent( curve, query=True, outAngle=True, time=( endsKeys[1], endsKeys[1] ) )[0] ) else: pass pm.keyTangent( curve, lock=lockState, time=( endsKeys[0], endsKeys[0] ) )
def transferRootJoint(src,dest): #This function is used to transfer the root joint #We don't have to convert this into another space. #we just copy the rotation and translation over firstFrame = pm.findKeyframe(src, which ='first') lastFrame = pm.findKeyframe(src, which = 'last') current = firstFrame pm.setCurrentTime(current) while current <= lastFrame: pm.setCurrentTime(current) dest.setTranslation(src.getTranslation()) dest.setRotation(src.getRotation()) dest.rotate.setKey() dest.translate.setKey() if current == lastFrame: break current = pm.findKeyframe(src , time = current, which='next')
def toggleRelativeKeyframeDisplay(self): sender = self.sender() onionCore.viewRenderOverrideInstance.setRelativeKeyDisplay(self.sender().isChecked()) futureKeys = [] pastKeys = [] nextKey = pm.findKeyframe(ts=True, w="next") pastKey = pm.findKeyframe(ts=True, w="previous") # add next keys to list bufferKey = pm.getCurrentTime() for i in range(self.mRelativeFrameAmount/2): if nextKey <= bufferKey: break futureKeys.append(nextKey) bufferKey = nextKey nextKey = pm.findKeyframe(t=bufferKey, ts=True, w="next") # add prev keys to list bufferKey = pm.getCurrentTime() for i in range(self.mRelativeFrameAmount/2): if pastKey >= bufferKey: break pastKeys.append(pastKey) bufferKey = pastKey pastKey = pm.findKeyframe(t=bufferKey, ts=True, w="previous")
def toggleRelativeKeyframeDisplay(self): sender = self.sender() onionCore.viewRenderOverrideInstance.setRelativeKeyDisplay( self.sender().isChecked()) futureKeys = [] pastKeys = [] nextKey = pm.findKeyframe(ts=True, w="next") pastKey = pm.findKeyframe(ts=True, w="previous") # add next keys to list bufferKey = pm.getCurrentTime() for i in range(self.mRelativeFrameAmount / 2): if nextKey <= bufferKey: break futureKeys.append(nextKey) bufferKey = nextKey nextKey = pm.findKeyframe(t=bufferKey, ts=True, w="next") # add prev keys to list bufferKey = pm.getCurrentTime() for i in range(self.mRelativeFrameAmount / 2): if pastKey >= bufferKey: break pastKeys.append(pastKey) bufferKey = pastKey pastKey = pm.findKeyframe(t=bufferKey, ts=True, w="previous")
def smart_loop(): with pm.UndoChunk(): for obj in pm.ls(sl=True): for curve in pm.keyframe(obj, q=True, name=True): first = pm.findKeyframe(curve, which='first') last = pm.findKeyframe(curve, which='last') t = (first, last) pm.copyKey(curve) pm.pasteKey(curve, time=last, option='insert', connect=True)
def cut_key(self): """ Delete animations that exceed the range of frames. :return: """ max_time = pm.playbackOptions(query=1, maxTime=1) for curve in self.animation_data.keys(): last_frame = pm.findKeyframe(curve, which='last') while last_frame > max_time: pm.cutKey(curve, time=last_frame) last_frame = pm.findKeyframe(curve, which='last')
def tweenPose(self, biasValue): self.selectedObjects = pm.ls(sl=True) currentFrame = pm.currentTime(query=True) for item in self.selectedObjects: curves = pm.keyframe(item, query=True, name=True) for curve in curves: # Find where the prev and next keyframes were set framePrev = pm.findKeyframe(timeSlider=True, which="previous") frameNext = pm.findKeyframe(timeSlider=True, which="next") # Find which tangent type was used by the prev and next keyframes tanOutPrevKey = mel.eval('keyTangent -time ' + str(framePrev) + ' -q -ott ' + curve)[0] tanInNextKey = mel.eval('keyTangent -time ' + str(frameNext) + ' -q -itt ' + curve)[0] tanInNewKey = tanOutPrevKey tanOutNewKey = tanInNextKey # Set the new keyframe's tangent to 'auto' if the next or prev keyframes uses 'fixed' if tanOutPrevKey == 'fixed' or tanInNextKey == 'fixed': tanInNewKey = 'auto' tanOutNewKey = 'auto' elif tanOutPrevKey == 'step': tanInNewKey = 'linear' tanOutNewKey = 'step' # Retrieve the values of the next and previous keyframes prevCurveVal = pm.keyframe(curve, time=framePrev, query=True, valueChange=True)[0] nextCurveVal = pm.keyframe(curve, time=frameNext, query=True, valueChange=True)[0] # Compute the value of the new keyframe based on the bias value percentBias = (biasValue + 100) / float(200) newCurveVal = ( (nextCurveVal - prevCurveVal) * percentBias) + prevCurveVal # Set a new keyframe using the new value pm.setKeyframe(curve, time=currentFrame, value=newCurveVal, itt=tanInNewKey, ott=tanOutNewKey) # Reset the current time to refresh the values shown in the channel box pm.currentTime(currentFrame, edit=True)
def fetchShotFrameRange_Fn(self, shotName): self.shotName = shotName if pm.objExists(self.shotName + '_shotCam'): self.camName = pm.PyNode(self.shotName + '_shotCam') pm.select(self.camName, r=1) if pm.objectType(self.camName.getShape()) == 'camera': startFrame = pm.findKeyframe(timeSlider=False, which='first') endFrame = pm.findKeyframe(timeSlider=False, which='last') pm.select(cl=1) if startFrame == endFrame: return sys.stderr.write('Please check the keyframes on %s_shotCam\n' % self.shotName) else: return {'shotName':self.shotName, 'cameraName':str(self.camName.name()), 'mpStartFrame':startFrame, 'mpEndFrame':endFrame}
def reverseCurve( timePiv=None ): """ Reverse the selected curve(s). If timePiv is C{'None'}, curve will be reversed at current time. @param timePiv: timePiv: C{None} If timePiv is C{'None'}, curve will be reversed at current time. @type timePiv: float """ for curve in getSelectedCurvesKeys().iterkeys(): if timePiv is None: timePiv = ( pm.findKeyframe( curve, which='first' ) + pm.findKeyframe( curve, which='last' ) ) / 2 else: pass pm.scaleKey( curve, timeScale= -1.0, timePivot=timePiv )
def alMoveACsegment(startFrame, endFrame): lastFrame = 0.0 preRange = "0:" + str((startFrame - 1)) allaCurves = pm.ls(type="animCurve") refCurves = pm.ls(type="animCurve", referencedNodes=1) animCurves = [x for x in allaCurves if x not in refCurves] for aCurve in animCurves: if (pm.objectType(aCurve) == "animCurveTU") or ( pm.objectType(aCurve) == "animCurveTA") or (pm.objectType(aCurve) == "animCurveTL"): pm.setAttr((str(aCurve) + ".ktv"), l=1) pm.setAttr((str(aCurve) + ".ktv"), l=0) lastFrame = float(pm.findKeyframe(aCurve, which="last")) if lastFrame <= endFrame: lastFrame = float(endFrame + 2) postRange = str((endFrame + 1)) + ":" + str(lastFrame) if (pm.getAttr(str(aCurve) + ".pre") == 0) and (pm.getAttr(str(aCurve) + ".pst") == 0): pm.setKeyframe(aCurve, insert=1, time=startFrame) pm.setKeyframe(aCurve, insert=1, time=endFrame) pm.cutKey(aCurve, time=preRange) pm.cutKey(aCurve, time=postRange) #print "\nanimCurve: " + str(aCurve) pm.keyframe(aCurve, e=1, iub=True, o='over', r=1, time=(str(startFrame) + ":" + str(endFrame)), tc=(-(startFrame - 1)))
def shift_curves(amount=1): """Shift curves forwards or backwards by defined frame (amount)""" curves = pm.findKeyframe(curve=True) if len(curves) > 0: for curve in curves: pm.keyframe(curve, edit=True, relative=True, timeChange=amount)
def exportAnim(self, *args): objs = pm.ls( sl=True ) successState = True filePath = pm.fileDialog2( caption='Save Animation', startingDirectory=uad , fileFilter="Anim Files (*.anim)" ) if not filePath: sys.stdout.write('Save animation cancelled.') return None animInfos = {} # dictionary containing dictionaries of every object's animations for obj in objs: if not ( self.hasUniqueName( obj ) ): # if object'n name is not unique, doesn't save animation for it successState = False pm.warning( "Object %s's name is not unique. skipped"%obj.name() ) continue nameSpace = self.getNameSpace( obj ) if nameSpace: objName = obj.name().split(':')[1] else: objName = obj.name() # find all anim curves on the object curves = pm.findKeyframe( obj , curve=True ) if not curves: # jump to next object if no anim curve found continue animInfo = {} # dictionary containing one object's animations for curve in curves: # for each curve, find where it's connected to, keys' times, values and tangents attr = pm.listConnections( '%s.output'%curve, plugs=True )[0] if nameSpace: attrName = attr.name().split(':')[1] else: attrName = attr.name() times = pm.keyframe( attr, q=True, timeChange=True ) values = pm.keyframe( attr, q=True, valueChange=True ) outWeights = pm.keyTangent( attr, q=True, outWeight=True ) outAngles = pm.keyTangent( attr, q=True, outAngle=True ) inWeights = pm.keyTangent( attr, q=True, inWeight=True ) inAngles = pm.keyTangent( attr, q=True, inAngle=True ) animInfo[ attrName ] = { 'times':times, 'values':values, 'outWeights':outWeights, 'outAngles':outAngles, 'inWeights':inWeights, 'inAngles':inAngles } animInfos[ objName ] = animInfo # write anim info to file filePath = filePath[0] logfile = open( filePath , 'w') logfile.write( str(animInfos) ) logfile.close() if successState: sys.stdout.write( 'Animation was successfully exported.' ) else: pm.warning( 'Some objects animtions were not saved due to multiple object with the same name, check script editor for more info.' )
def setRelativeFrames(self, value): if not self.mRelativeKeyDisplay: return nextKeys = [] pastKeys = [] nextKey = pm.findKeyframe(ts=True, w="next") pastKey = pm.findKeyframe(ts=True, w="previous") # add next keys to list bufferKey = pm.getCurrentTime() for i in range(4): if nextKey <= bufferKey: break nextKeys.append(nextKey) bufferKey = nextKey nextKey = pm.findKeyframe(t=bufferKey, ts=True, w="next") # add prev keys to list bufferKey = pm.getCurrentTime() for i in range(4): if pastKey >= bufferKey: break pastKeys.append(pastKey) bufferKey = pastKey pastKey = pm.findKeyframe(t=bufferKey, ts=True, w="previous") pastKeys = list(reversed(pastKeys)) for frameIndex in self.mRelativeOnions: blendPass = self.mRelativeOnions[frameIndex] if frameIndex < 0: # past if pastKeys and len(pastKeys) >= frameIndex*-1: blendPass.setActive(True) blendPass.setFrame(pastKeys[frameIndex]) else: blendPass.setActive(False) else: # future if nextKeys and len(nextKeys) >= frameIndex: blendPass.setActive(True) blendPass.setFrame(nextKeys[frameIndex-1]) else: blendPass.setActive(False)
def connectAttribute(): grp = pm.ls(sl=True) pm.delete(grp,sc=True) CtrlName = "Fingers_R.Fist" animCurve = pm.findKeyframe(grp,c=True) for i in range(len(animCurve)): connect = pm.connectAttr(CtrlName,animCurve[i]+".input") print "animCurve Connected...",
def SourceAnimation(keygiver): ##Gets the first and last keyFrames first = pm.findKeyframe(keygiver, which='first') last = pm.findKeyframe(keygiver, which='last') for i in range(int(last + 1)): pm.setCurrentTime(i) keygiver.translate.setKey() keygiver.rotate.setKey() keygiver.scale.setKey() for child in keygiver.getChildren(): print child animation(child) ##Finds the next keyframe once the first keyframe has been set! i = pm.findKeyframe(keygiver, time=i, which='next')
def SourceAnimation(keygiver): ##Gets the first and last keyFrames first = pm.findKeyframe(keygiver, which='first') last = pm.findKeyframe(keygiver, which='last') for i in range(int(last+1)): pm.setCurrentTime(i) keygiver.translate.setKey() keygiver.rotate.setKey() keygiver.scale.setKey() for child in keygiver.getChildren(): print child animation(child) ##Finds the next keyframe once the first keyframe has been set! i = pm.findKeyframe(keygiver, time=i, which='next')
def fetchShotFrameRange_Fn(self, shotName): self.shotName = shotName if pm.objExists(self.shotName + '_shotCam'): self.camName = pm.PyNode(self.shotName + '_shotCam') pm.select(self.camName, r=1) if pm.objectType(self.camName.getShape()) == 'camera': startFrame = pm.findKeyframe(timeSlider=False, which='first') endFrame = pm.findKeyframe(timeSlider=False, which='last') pm.select(cl=1) if startFrame == endFrame: return sys.stderr.write( 'Please check the keyframes on %s_shotCam\n' % self.shotName) else: return { 'shotName': self.shotName, 'cameraName': str(self.camName.name()), 'mpStartFrame': startFrame, 'mpEndFrame': endFrame }
def GetJointKeyframes(jointName): pm.select(jointName) curr = first = pm.findKeyframe(jointName, which='first') pm.setCurrentTime(first) last = pm.findKeyframe(jointName, which='last') kc = pm.keyframe( jointName, sl=False, q=True, keyframeCount=True) / 10 #THIS IS LOGICAL AND MAKES SENSE! #node.setKeyframe(); print("\n") if (kc > 0): keyframeList = [] while curr <= last: node = pm.PyNode(jointName) kf = Keyframe() kf.time = curr / 24 kf.Scale = node.getScale() kf.rotation = node.getRotation() kf.translation = node.getTranslation() print kf.Scale[0] print("SCALE: " + str(kf.Scale)) keyframeList.append(kf) if curr == last: return keyframeList curr = pm.findKeyframe(jointName, time=curr, which='next') pm.setCurrentTime(curr) else: print("No Keyframes in this animation layer")
def getFloatingValue(cam, attr_name, cut_in, cut_out): result = {} curve_list = pm.findKeyframe(cam, curve=True, at=attr_name) attr = cam.attr(attr_name) if curve_list: c = pm.PyNode(curve_list[0]) if not c.isStatic(): for i in range(0, c.numKeys()): result.update({int(c.getTime(i)):c.getValue(i)}) if not result: result = {cut_in:attr.get()} if len(result.values())==1 and result.values()==[0]: result = {} return result
def get_curves(direction=None): curves = pmc.animCurveEditor("graphEditor1GraphEd", q=True, curvesShown=True) log.debug(curves) if not curves: return [] displayed_curves = [ ("_".join(x.split("_")[:-1]), x.split("_")[-1]) for x in curves ] log.debug(displayed_curves) keys = list(set(pmc.findKeyframe(x[0], attribute=x[1], which=direction) for x in displayed_curves)) keys.sort() log.debug(keys) return keys
def transferRootJoint(src, dest): #This function is used to transfer the root joint #We don't have to convert this into another space. #we just copy the rotation and translation over firstFrame = pm.findKeyframe(src, which='first') lastFrame = pm.findKeyframe(src, which='last') current = firstFrame pm.setCurrentTime(current) while current <= lastFrame: pm.setCurrentTime(current) dest.setTranslation(src.getTranslation()) dest.setRotation(src.getRotation()) dest.rotate.setKey() dest.translate.setKey() if current == lastFrame: break current = pm.findKeyframe(src, time=current, which='next')
def find_frame_of_key(frame): """ Return the nearest key on or before frame, or None if there aren't any. """ keys = get_singleton(create=False) if keys is None: return None # Why is there no <= search? frames = pm.findKeyframe(keys.attr('keyframes'), t=frame + 0.000001, which='previous') if frames is None: return None if frames > frame: return None return frames
def get_selection_frame_value_length(): """Print the frame and value length of selected keys on a single curve""" import pymel.core as pm curve = pm.findKeyframe(c=True) if len(curve) == 1: # only 1 curve selected l_keys = pm.keyframe(q=True, selected=True, tc=True) v_keys = pm.keyframe(q=True, selected=True, vc=True) if len(l_keys) > 1: # at least 2 keys selected key_length = abs(l_keys[-1] - l_keys[0]) # frame length key_value = abs(max(v_keys) - min(v_keys)) # value range print ("frame length: {}, value range: {:.3f}".format(key_length, key_value)), else: pm.warning('Need to select at least 2 keys'), else: pm.warning('Select only 1 curve'),
def key_attr(attr, new_value=None, copy_previous=None): """ Key given attr on previous and current frame. :param attr: Attribute to be keyed of type Attribute(). :param new_value: Explicitly set key value on current frame. :param copy_previous: Explicitly copy previous key or value onto previous frame for a single-frame switch. """ log.debug("Keying attr...") cur_time = pmc.currentTime(q=True) log.debug("Attr: {}".format(attr)) log.debug("New value: {}".format(new_value)) log.debug("Copy previous: {}".format(copy_previous)) log.debug("Current time: {}".format(cur_time)) if copy_previous: prev_key_time = pmc.findKeyframe(attr, which="previous") prev_key_value = attr.get(t=prev_key_time) prev_key = pmc.copyKey(attr, t=prev_key_time) log.debug("Previous key time: {}".format(prev_key_time)) log.debug("Previous key value: {}".format(prev_key_value)) # If a key did not exist if prev_key == 0: pmc.setKeyframe(attr, t=(cur_time - 1)) # If a key exists elif prev_key == 1: pmc.pasteKey(attr, t=(cur_time - 1)) else: pmc.setKeyframe(attr, t=(cur_time - 1)) if new_value: pmc.setKeyframe(attr, t=cur_time, v=new_value) attr.set(new_value) else: pmc.setKeyframe(attr, t=cur_time)
def stopRecording(self): self.scriptNode.before.set("pass") #Inactivates the scriptNode if len(AnimationRemapper._mapKeyFrameList) < 2: print "Stopped script. No recorded keys" return #Converts the time list to delta time in keyframes self._convertTimeList() #Print for debugging lastKeyFrame = AnimationRemapper._mapKeyFrameList[-1] # lastTime = AnimationRemapper._mapTimeList[ -1] #convert time to keyframe lastKey = max([ pm.findKeyframe(selObj, w="last") for selObj in self._selectedObjects ]) moveVal = lastTime - lastKeyFrame #Set timerange options if lastTime > pm.playbackOptions(q=1, max=True): pm.playbackOptions(e=1, max=lastTime) #If moveVal is greater than zero move the untouched keyframes further away before we remap if moveVal > 0: self.moveUnusedKeyframes(lastKeyFrame, lastKey, moveVal) #Do the magic self.remapKeys() #If moveVal is less than zero move the untouched keyframes closer to the remapped animation #(if you only remapped parts of the animation) if moveVal < 0: self.moveUnusedKeyframes(lastKeyFrame, lastKey, moveVal)
def main(jointList, newJointList, hip, newHip): first = pm.findKeyframe(hip, which='first') last = pm.findKeyframe(hip, which='last') pm.setCurrentTime(0) parentList = [] targetParentList = [] parents(hip, dt.Matrix(), parentList, jointList) parents(newHip, dt.Matrix(), targetParentList, newJointList) i = 0 a = 0 identityMatrix = dt.Matrix() identityMatrix2 = dt.Matrix() while i < len(jointList): curr = first pm.setCurrentTime(0) pyJoint = pm.PyNode(jointList[i]) targetJoint = pm.PyNode(newJointList[i]) parentJoint = parentList[i] targetParentJoint = targetParentList[i] bindPoseInverse = pyJoint.getRotation().asMatrix().inverse() bindPose = pyJoint.getRotation().asMatrix() bindPoseTarget = targetJoint.getRotation().asMatrix() while curr <= last: curr = pm.findKeyframe(hip, time=curr, which='next') pm.setCurrentTime(curr) if i == 0: k = pyJoint.getRotation().asMatrix() * bindPoseInverse kPrim = identityMatrix.setToIdentity().inverse() * k * identityMatrix2.setToIdentity() kPrim2 = parentList[i] * kPrim * parentList[i].inverse() final = bindPoseTarget * kPrim2 targetJoint.setRotation(dt.degrees(dt.EulerRotation(final))) targetJoint.setTranslation(pyJoint.getTranslation()) pm.setKeyframe(targetJoint) else: ####################################HIP DONE########################################### bodyK = bindPoseInverse * pyJoint.getRotation().asMatrix() bodykPrim = parentList[i].inverse() * bodyK * parentList[i] bodykPrim2 = targetParentList[i] * bodykPrim * targetParentList[i].inverse() bodyFinal = bindPoseTarget * bodykPrim2 targetJoint.setRotation(dt.degrees(dt.EulerRotation(bodyFinal))) pm.setKeyframe(targetJoint) # apply key values if curr==last: i = i + 1 break
def transferOneJoint(src, dest): #get the upper most parent node of the source, If there is none it will return itself #This is done because we need the root node to to the change of basis srcRootNode = getRootNode(src) destRootNode = getRootNode(dest) if srcRootNode == src: #this checks if the root node is being processed #then we need to include the translation #we have another function only for the root node transformation transferRootJoint(src, dest) print "THIS IS THE ROOTNODE" else: #do the normal transfer firstFrame = pm.findKeyframe(src, which='first') #Find first key frame lastFrame = pm.findKeyframe(src, which='last') #Find the lat key frame current = firstFrame pm.setCurrentTime(current) #Set current key frame to the first one #get the rotation of the source root in the first frame (IT's the bind pose) Needed when changing basis srcRootRotation = srcRootNode.getRotation().asMatrix() #get the rotation of the destination root joint in the first frame. (Needed when changing basis to destination node) #destRootRotation = destRootNode.getRotation().asMatrix() #Get the bind pose of the destination joint. Needed when applying rotation to destination destRotation = dest.getRotation().asMatrix() srcHierarcyMatrix = src.getRotation().asMatrix() #This will be done on the first frame. #A matrix of the hierarcys TPose will be returned #srcHierarchyMatrix is used to isolate the rotation from the source joint srcChangeofBasisMatrix = getChangeOfBasisMatrix(src) #This creates the matrix that is needed when we change the basis of the orientation #it is similar to the hierarchyMatrix, However, it is multiplicated in the reverse order, and it does not include the source joint orientation destChangeofBasisMatrix = getChangeOfBasisMatrix(dest) # Loop through the frames while current <= lastFrame: pm.setCurrentTime(current) srcRotation = getRotationFromJoint( src, srcHierarcyMatrix ) #Extract the Rotation from the source, using the hierarchy matrix # Rotation is extracted from the joint, #Now it needs to be transformed into standard coordinate space. #this is achieved by doing a change of basis. # inv(srcChangeofBasisMatrix) * srcRotation * srcChangeofBasisMatrix srcRotation = srcChangeofBasisMatrix.inverse( ) * srcRotation * srcChangeofBasisMatrix #Now we need to transform it from the standard coordinate space to the space of the destination joint # (h * k * h-1 = k2) srcRotation = destChangeofBasisMatrix * srcRotation * destChangeofBasisMatrix.inverse( ) setRotationToJoint(srcRotation, dest, destRotation) dest.rotate.setKey() #Set the keyframe! if current == lastFrame: break current = pm.findKeyframe(src, time=current, which='next') #Jump to next frame
def findKeyframe(cls, which, time=None): kwargs = {"which": which} if which in ["next", "previous"]: kwargs["time"] = (time, time) return mc.findKeyframe(**kwargs)
for fbx_jnt in pm.ls(src_namespace + "root", dag=1, ni=1): fbx_base = fbx_jnt.split(':')[1] skin_jnt = dst_namespace + ':' + fbx_base if pm.objExists(skin_jnt): # change jointOrientX and key it for tmp in 'XYZ': pm.setKeyframe('%s.jointOrient%s' % (fbx_jnt, tmp)) or_value = pm.getAttr('%s.jointOrient%s' % (skin_jnt, tmp)) pm.setAttr('%s.jointOrient%s' % (fbx_jnt, tmp), or_value) for trs in 'trs': for xyz in 'xyz': attr = trs + xyz try: v = pm.getAttr(skin_jnt + '.' + attr) fbx_anim_node = pm.findKeyframe(fbx_jnt, curve=True, at=attr) if not fbx_anim_node: #key pm.setKeyframe('%s.%s' % (fbx_jnt, attr)) # key it first #pm.setKeyframe('pCube1.scaleX') pm.setAttr(fbx_jnt + '.' + attr, v) except BaseException: print("error", skin_jnt) pass # keyframe_match = { # "LfArm_Switch" : "LfArm_Switch", # "RtArm_Switch" : "RtArm_Switch",
def clean_raw_data(self): # Create and check self.create_directory() # Get all files path file_path, maya_file_path = self.get_path_file_mixamo() # Loop through all path for path in file_path: # Create new scene cm.file(force=True, newFile=True) # Rename path for maya can read new_path = path.replace("\\", "/") # Import fbx file into scene with out namespace cm.file(new_path, i=True, mergeNamespacesOnClash=True, namespace=':') cm.currentUnit(time='ntsc') self.clean_namespace() # Get list joint under world list_joints = self.check_parent() skipped_file = [] if pm.objExists("World"): world_joint = pm.PyNode("World") else: # Create a world joint world_joint = pm.joint(n="World", r=True) # Loop through joint and parent it under world joint for joint in list_joints: first_key = int(pm.findKeyframe(joint, which='first')) last_key = int(pm.findKeyframe(joint, which='last')) + 1 cm.playbackOptions(animationStartTime=first_key, animationEndTime=last_key, minTime=first_key, maxTime=last_key) pm.parent(joint, world_joint, relative=False) # Get fbx file name without the path fbx_name = path.split("/")[-1] # Set path to new folder export we create path_fbx = (os.path.join(self.directory, fbx_name)).replace(os.sep, '/') # Export fbx file pm.select(world_joint) self.export_option(path_fbx) # Create new scene again for clean maya cm.file(force=True, newFile=True)
def exportAnim(self, *args): objs = pm.ls(sl=True) successState = True filePath = pm.fileDialog2(caption='Save Animation', startingDirectory=uad, fileFilter="Anim Files (*.anim)") if not filePath: sys.stdout.write('Save animation cancelled.') return None animInfos = { } # dictionary containing dictionaries of every object's animations for obj in objs: if not ( self.hasUniqueName(obj) ): # if object'n name is not unique, doesn't save animation for it successState = False pm.warning("Object %s's name is not unique. skipped" % obj.name()) continue nameSpace = self.getNameSpace(obj) if nameSpace: objName = obj.name().split(':')[1] else: objName = obj.name() # find all anim curves on the object curves = pm.findKeyframe(obj, curve=True) if not curves: # jump to next object if no anim curve found continue animInfo = {} # dictionary containing one object's animations for curve in curves: # for each curve, find where it's connected to, keys' times, values and tangents attr = pm.listConnections('%s.output' % curve, plugs=True)[0] if nameSpace: attrName = attr.name().split(':')[1] else: attrName = attr.name() times = pm.keyframe(attr, q=True, timeChange=True) values = pm.keyframe(attr, q=True, valueChange=True) outWeights = pm.keyTangent(attr, q=True, outWeight=True) outAngles = pm.keyTangent(attr, q=True, outAngle=True) inWeights = pm.keyTangent(attr, q=True, inWeight=True) inAngles = pm.keyTangent(attr, q=True, inAngle=True) animInfo[attrName] = { 'times': times, 'values': values, 'outWeights': outWeights, 'outAngles': outAngles, 'inWeights': inWeights, 'inAngles': inAngles } animInfos[objName] = animInfo # write anim info to file filePath = filePath[0] logfile = open(filePath, 'w') logfile.write(str(animInfos)) logfile.close() if successState: sys.stdout.write('Animation was successfully exported.') else: pm.warning( 'Some objects animtions were not saved due to multiple object with the same name, check script editor for more info.' )
# Animation code import pymel.core as pm import time root = pm.PyNode('iPi:Hip') first = pm.findKeyframe(root, which='first') last = pm.findKeyframe(root, which='last') print first, last curr = first while curr <= last: curr = pm.findKeyframe(root, time=curr, which='next') pm.setCurrentTime(curr) # apply key values if curr==last: break
def setTimesliderToKeyrange(): keyedObj = pm.ls(sl=1) firstKf = pm.findKeyframe(which='first') lastKf = pm.findKeyframe(which='last') pm.playbackOptions(min=firstKf, max=lastKf) return [firstKf, lastKf]
# Animation code import pymel.core as pm import time root = pm.PyNode('iPi:Hip') first = pm.findKeyframe(root, which='first') last = pm.findKeyframe(root, which='last') print first, last curr = first while curr <= last: curr = pm.findKeyframe(root, time=curr, which='next') pm.setCurrentTime(curr) # apply key values if curr == last: break
def setKeyframesNow(): if self.slider.value() == 0: if self._buttonCounter == 0 and self.keyCounter <= 1: calculo = start_end_compare(newData, True) for key, val in calculo.items(): for clave, valor in val.items(): #formated = "{}.{} at {}".format(key,clave,valor) pm.setKeyframe(key, v=valor, at=clave) self.createTemps(self.Name, newData, self.randomNum) self.keyCounter += 1 else: compareAttr = getAttributeChange(START, oldData, newData) for key, val in compareAttr.items(): for clave, valor in val.items(): pm.setKeyframe(key, v=valor, at=clave) calculo = start_end_compare(newData) for key, val in calculo.items(): time = pm.findKeyframe(key, timeSlider=True, which="last") for clave, valor in val.items(): pm.setKeyframe(key, v=valor, at=clave, t=time) self.createTemps(self.Name, newData, self.randomNum) self.keyCounter += 1 om.MGlobal.displayInfo("# Start Keyframe Values Set - - ") self.keyButton.setEnabled(False) elif self.slider.value() == 49: if self._buttonCounter == 0 and self.keyCounter <= 1: calculo = start_end_compare(newData) for key, val in calculo.items(): for clave, valor in val.items(): #formated = "{}.{} at {}".format(key,clave,valor) pm.setKeyframe(key, v=valor, at=clave) self.createTemps(self.Name, newData, self.randomNum) self.keyCounter += 1 else: compareAttr = getAttributeChange(END, oldData, newData) self.keyCounter += 1 for key, val in compareAttr.items(): for clave, valor in val.items(): pm.setKeyframe(key, v=valor, at=clave) calculo = start_end_compare(newData, True) for key, val in calculo.items(): time = pm.findKeyframe(key, timeSlider=True, which="first") for clave, valor in val.items(): pm.setKeyframe(key, v=valor, at=clave, t=time) self.createTemps(self.Name, newData, self.randomNum) om.MGlobal.displayInfo(" # End Keyframe Values Set - - ") self.keyButton.setEnabled(False) else: om.MGlobal.displayWarning( "You must set the slider at start or end position in order to keyframe values" )
def transferOneJoint(src,dest): #get the upper most parent node of the source, If there is none it will return itself #This is done because we need the root node to to the change of basis srcRootNode = getRootNode(src) destRootNode = getRootNode(dest) if srcRootNode == src: #this checks if the root node is being processed #then we need to include the translation #we have another function only for the root node transformation transferRootJoint(src,dest) print "THIS IS THE ROOTNODE" else: #do the normal transfer firstFrame = pm.findKeyframe(src, which ='first') #Find first key frame lastFrame = pm.findKeyframe(src, which = 'last') #Find the lat key frame current = firstFrame pm.setCurrentTime(current) #Set current key frame to the first one #get the rotation of the source root in the first frame (IT's the bind pose) Needed when changing basis srcRootRotation = srcRootNode.getRotation().asMatrix() #get the rotation of the destination root joint in the first frame. (Needed when changing basis to destination node) #destRootRotation = destRootNode.getRotation().asMatrix() #Get the bind pose of the destination joint. Needed when applying rotation to destination destRotation = dest.getRotation().asMatrix() srcHierarcyMatrix = src.getRotation().asMatrix() #This will be done on the first frame. #A matrix of the hierarcys TPose will be returned #srcHierarchyMatrix is used to isolate the rotation from the source joint srcChangeofBasisMatrix = getChangeOfBasisMatrix(src) #This creates the matrix that is needed when we change the basis of the orientation #it is similar to the hierarchyMatrix, However, it is multiplicated in the reverse order, and it does not include the source joint orientation destChangeofBasisMatrix = getChangeOfBasisMatrix(dest) # Loop through the frames while current <= lastFrame: pm.setCurrentTime(current) srcRotation = getRotationFromJoint(src,srcHierarcyMatrix) #Extract the Rotation from the source, using the hierarchy matrix # Rotation is extracted from the joint, #Now it needs to be transformed into standard coordinate space. #this is achieved by doing a change of basis. # inv(srcChangeofBasisMatrix) * srcRotation * srcChangeofBasisMatrix srcRotation = srcChangeofBasisMatrix.inverse() * srcRotation * srcChangeofBasisMatrix #Now we need to transform it from the standard coordinate space to the space of the destination joint # (h * k * h-1 = k2) srcRotation = destChangeofBasisMatrix * srcRotation * destChangeofBasisMatrix.inverse() setRotationToJoint(srcRotation,dest,destRotation) dest.rotate.setKey() #Set the keyframe! if current == lastFrame: break current = pm.findKeyframe(src , time = current, which='next') #Jump to next frame