def keys_shift(targets, incr=0.0, rand=0.0, rand_abs=False, round=False): """ This script will copy the keyframes from source to targets from selected channel box attributes Args: targets [pm.nt.Transform]: target transforms to sequentialize incr (float): Increment value through selection by x, 0 is no increment rand (float): Randomly shift by x, 0 is no shift rand_abs (bool): Random range will be absolute and not include negatives round (bool): whether or not to round the key shift value to an integer Returns (None) Example: keys_shift(pm.ls(sl=True), rand=5.0, round=True) """ #Determine Selected attributes from channelbox attrs = get_cb_sel_attrs() x_shift = 0 for target in targets: ast, aet = pm.playbackOptions(q=True, ast=True), pm.playbackOptions(q=True, aet=True) rand_val = 0 if rand: rand_val = random.randrange(-rand*(1-rand_abs), rand) x_shift += rand_val if round: x_shift=int(x_shift) pm.keyframe(target, edit=True, at=attrs, relative=True, timeChange=x_shift) x_shift += incr
def detectCurves(cls): curves = [] # Find selected keyframes if graph editor is open. graphEditor = selectedAttributes.GraphEditorInfo.detect( restrictToVisible=True) if graphEditor.isValid(): _log.debug("Searching for selected keys") # Find curves with selected keys for attr in pm.keyframe(query=1, name=1, selected=1) or []: curves.extend(cls.fromAttribute(attr)) if not curves and _settings.findCurrentKeys: # Nothing selected, set keys on current frame as selected _log.debug("No keys selected, grabbing from current frame") for attr in selectedAttributes.get(detectionType='panel'): curves.extend(cls.fromAttribute(attr)) time = pm.currentTime(query=1) for x in reversed(range(len(curves))): keyIndices = pm.keyframe(curves[x].name, query=1, indexValue=1, time=(time, time)) if keyIndices: curves[x].keys[keyIndices[0]].selected = True else: # Remove curves that have no keys on the current frame curves.pop(x).name return curves
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 setRotateKey(obj, count): obj_dict = {} frame_list = pm.keyframe(obj, q=True, timeChange=True, attribute='rotateZ', index=(0, count)) volue_list = pm.keyframe(obj, q=True, valueChange=True, attribute='rotateZ', index=(0, count)) for i in range(count): if i + 1 != count: volue_1 = volue_list[i] volue_2 = volue_list[i + 1] distance = volue_2 - volue_1 if abs(distance) > 179: if distance >= 0: start_volue = 0 while start_volue + 179 < distance: start_volue = start_volue + 179 volue_ratio = start_volue / distance set_volue = start_volue + volue_1 # print 'set_volue : %s' % (set_volue) frame_range = frame_list[i + 1] - frame_list[i] set_frame = frame_range * volue_ratio + frame_list[i] # print 'set_frame : %s' % (set_frame) obj_dict[str(set_frame)] = set_volue else: start_volue = 0 while start_volue - 179 > distance: start_volue = start_volue - 179 volue_ratio = start_volue / distance set_volue = start_volue - volue_1 # print 'set_volue : %s' % (set_volue) frame_range = frame_list[i + 1] - frame_list[i] set_frame = frame_range * volue_ratio + frame_list[i] # print 'set_frame : %s' % (set_frame) obj_dict[set_frame] = set_volue return obj_dict
def shift_curves(joints, START_FRAME=1, REMOVE_DOUBLES=True): connections = [] for j in joints: con = j.listConnections(type='animCurveTA', connections=1) connections.extend(con) for con in connections: crv = con[1] keys = pm.keyframe(crv, q=1, tc=1) time_change = START_FRAME - keys[0] pm.keyframe(crv, tc=time_change, r=1) keys = pm.keyframe(crv, q=1, tc=1) values = pm.keyframe(crv, q=1, vc=1) if REMOVE_DOUBLES: ranges = [] last = values[0] + 1 for i in range(len(keys)): if values[i] == last: ranges.append(keys[i]) last = values[i] for r in ranges: pm.cutKey(crv, time=(r, r))
def _bakeAnim(self, root): ''' Given root: - Bake the heirarchy animation data - Reset timeline to 1 if wasn't already set to 1 ''' print 'Starting: bakeAnim()...' # Getting time range from scene startFrame = int( pm.playbackOptions(q=1, min=1) ) endFrame = int( pm.playbackOptions(q=1, max=1) ) pm.select(root, hi=1, r=1) # Set timeline to start at frame 1 if startFrame != 1: if startFrame < 1: tChange = (-(startFrame))+1 elif startFrame > 1: tChange = (-(startFrame-1)) pm.keyframe(e=1, time=(startFrame, endFrame), relative=1, timeChange=tChange) pm.playbackOptions(e=1, min=1, max=endFrame+tChange ) pm.bakeResults(root, t=(startFrame, endFrame), simulation=True, hi='below' ) print 'bakeAnim(): Baked anim onto %s' % root print 'bakeAnim(): Range baked: %s - %s' % (startFrame, endFrame) print 'End: bakeAnim()'
def _get_frames_using_keyframes_only(robot, animation_settings): """ Get frames from animation using a robot's keyframes only. :param robot: :param animation_settings: :return: """ # Get relevant animation parameters. start_frame = animation_settings['Start Frame'] end_frame = animation_settings['End Frame'] # Get list of keyframes on robots IK attribute for the given range target_ctrl_path = get_target_ctrl_path(robot) ik_keyframes = pm.keyframe(target_ctrl_path, attribute='ik', query=True, time='{}:{}'.format(start_frame, end_frame)) # Verify that there is also a keyframe set on the FK controls' rotate # attributes. If there's not, we remove it from the list # Note: we only need to check on controller as they are all keyframed # together fk_test_handle_path = mimic_utils.format_path( '{0}|{1}robot_GRP|{1}FK_CTRLS|{}a1FK_CTRL.rotateY', robot) frames = [ frame for frame in ik_keyframes if pm.keyframe(fk_test_handle_path, query=True, time=frame) ] return frames
def writeRetimeFile(viz, pubShot): ''' Write the animated data on the currentTime attribute to a txt file. ''' tmpPath = None # Return None if the attribute is not keyed. if pm.keyframe('%s.currentTime'%viz, query=True, keyframeCount=True): # get framelist from pod podFile = str(pm.getAttr('%s.podFile'%viz)) ggcp = GtoGeometryCachePod.fromPodFile(podFile) ggcp.startFrame = pm.playbackOptions(q=True, animationStartTime=True) ggcp.endFrame = pm.playbackOptions(q=True, animationEndTime=True) frameList = ggcp.frameNumberList() # offset = float(pm.getAttr('%s.timeOffset'%viz)) # frameList = [frame + offset for frame in ggcp.frameNumberList()] # Get curve data animCurveData = list() for frame in frameList: value = pm.keyframe(viz, query=True, time=[frame], attribute='currentTime', eval=True) assert len(value) == 1, '%s keyframes found for time %s. One expected.' % (len(value), frame) animCurveData.append([frame, value[0]]) # Write it out to a temp file selCharName = str(pm.getAttr('%s.label'%viz)) if not tmpPath: name = '_'.join(['animLib', 'bd', pubShot, selCharName, 'retime.txt']) tmpPath = os.path.join(tempfile.gettempdir(), name) fh = open(tmpPath, 'w') for time, value in animCurveData: fh.write('%s %s\n' % (time, value)) fh.close() return tmpPath
def cleanTargetKeys(mainCtrl, switcher, times, switcherTarget): ''' Make sure the switcher is keyed at all the given times and the controls are unkeyed. *Technically* this should leave keys when it's keyed on, but this is already so complicated. ''' if times: # If we are range switching, we have to key everything. # Put keys at all frames that will be switched if not already there to anchor the values. # Only doing a single key because `insert=True` keying is done later if not keyframe(switcher, q=True): setKeyframe(switcher, t=times[0]) allControls = [ctrl for name, ctrl in mainCtrl.subControl.items() ] + [mainCtrl] # Remove all the old keys where the other side is active to some extent pairs = keyframe(switcher, q=1, tc=1, vc=1) start = times[0] end = times[-1] killTimes = [ t for t, v in pairs if not pdil.math.isCloseF(v, switcherTarget) and ( start <= t <= end) ] #cutKey( allControls, iub=True, t=(times[0], times[-1]), clear=True, shape=False ) cmds.cutKey(allControls, iub=True, clear=True, shape=False, t=[(t, t) for t in killTimes]) for t in times: setKeyframe(switcher, t=t, insert=True)
def inverseKeys(self, current, section, keyword): for arm in self.controls[section]: armParsed = current + ':' + arm if keyword != None: armParsed = current + ':' + arm.replace('IZQ', keyword) for attr in self.attributes: for i, axis in enumerate(self.axes): ii = i + self.attributes[attr] axisMult = self.controls[section][arm][ii] keyframes = pm.keyframe(armParsed, a=True, attribute=attr + axis, query=True, valueChange=True, timeChange=True) for key in keyframes: pm.keyframe(armParsed, a=True, attribute=attr + axis, time=key[0], edit=True, valueChange=(key[1] * axisMult))
def isValid(self): valid = True #gets nodes for pin layer self.layerNodes = self.affectingLayers[0].getAnimCurves() layerKeyTimesList = pm.keyframe(self.layerNodes[0], query = True, tc = True) #finds the first frame that the control is keyed on self.firstFrame = layerKeyTimesList[0] #finds the last frame the control is keyed on self.lastFrame = layerKeyTimesList[len(layerKeyTimesList)-1] #gets nodes for base layer self.baseAnimNode = self.affectingLayers[0].getBaseAnimCurves() baseKeyTimes = pm.keyframe(self.baseAnimNode[0], query = True, tc = True) #finds first frame self.baseFirstFrame = baseKeyTimes[0] #finds last frame self.baseLastFrame = baseKeyTimes[len(baseKeyTimes) -1] #checks that frames on pin layer are in range of the first and last frame on base layer if self.firstFrame < self.baseFirstFrame or self.lastFrame > self.baseLastFrame: timeInvalidWarning = QtWidgets.QMessageBox() timeInvalidWarning.setWindowTitle('Warning') timeInvalidWarning.setText('Frame range is not valid.') timeInvalidWarning.exec_() valid = False return valid
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 moveUnusedKeyframes(self, lastDictKey, lastKey, moveVal): for selObj in self._selectedObjects: pm.keyframe(selObj, e=1, relative=1, t=(lastDictKey, lastKey), tc=(moveVal))
def export(self, shot): """exports the given shot """ # collect some data which will be needed start_frame = shot.startFrame.get() end_frame = shot.endFrame.get() sequence_start = shot.sequenceStartFrame.get() offset_value = sequence_start - start_frame sequence_len = shot.endFrame.get() - shot.startFrame.get() shot.startFrame.set(sequence_start) shot.endFrame.set(shot.startFrame.get() + sequence_len) print("data is ready") #moves all animation keys to where should they to be anim_curves = pm.ls(type='animCurve') pm.keyframe(anim_curves, iub=False, animation='objects', relative=True, option='move', tc=offset_value) print("animation curves are ready") self.delete_all_others(shot) self.get_shot_frame_range(shot) self.save_as(shot) self.open_again(self.working_file_name)
def _bakeAnim(self, root): ''' Given root: - Bake the heirarchy animation data - Reset timeline to 1 if wasn't already set to 1 ''' print 'Starting: bakeAnim()...' # Getting time range from scene startFrame = int(pm.playbackOptions(q=1, min=1)) endFrame = int(pm.playbackOptions(q=1, max=1)) pm.select(root, hi=1, r=1) # Set timeline to start at frame 1 if startFrame != 1: if startFrame < 1: tChange = (-(startFrame)) + 1 elif startFrame > 1: tChange = (-(startFrame - 1)) pm.keyframe(e=1, time=(startFrame, endFrame), relative=1, timeChange=tChange) pm.playbackOptions(e=1, min=1, max=endFrame + tChange) pm.bakeResults(root, t=(startFrame, endFrame), simulation=True, hi='below') print 'bakeAnim(): Baked anim onto %s' % root print 'bakeAnim(): Range baked: %s - %s' % (startFrame, endFrame) print 'End: bakeAnim()'
def export(self, shot): """exports the given shot """ # collect some data which will be needed start_frame = shot.startFrame.get() end_frame = shot.endFrame.get() sequence_start = shot.sequenceStartFrame.get() offset_value = sequence_start - start_frame sequence_len = shot.endFrame.get() - shot.startFrame.get() shot.startFrame.set(sequence_start) shot.endFrame.set(shot.startFrame.get() + sequence_len) print("data is ready") #moves all animation keys to where should they to be anim_curves = pm.ls(type='animCurve') pm.keyframe( anim_curves, iub=False, animation='objects', relative=True, option='move', tc=offset_value ) print("animation curves are ready") self.delete_all_others(shot) self.get_shot_frame_range(shot) self.save_as(shot) self.open_again(self.working_file_name)
def change_time(self): ''' # this function will change the time for the key frame ''' pm.keyframe('%s' % (self.node), option='over', index=(int(self.index), int(self.index)), absolute= True, timeChange=int(self.int_field.getValue()))
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 detectCurves(cls): curves = [] # Find selected keyframes if graph editor is open. graphEditor = selectedAttributes.GraphEditorInfo.detect(restrictToVisible=True) if graphEditor.isValid(): _log.debug("Searching for selected keys") # Find curves with selected keys for attr in pm.keyframe(query=1, name=1, selected=1) or []: curves.extend(cls.fromAttribute(attr)) if not curves and _settings.findCurrentKeys: # Nothing selected, set keys on current frame as selected _log.debug("No keys selected, grabbing from current frame") for attr in selectedAttributes.get(detectionType='panel'): curves.extend(cls.fromAttribute(attr)) time = pm.currentTime(query=1) for x in reversed(range(len(curves))): keyIndices = pm.keyframe(curves[x].name, query=1, indexValue=1, time=(time, time)) if keyIndices: curves[x].keys[keyIndices[0]].selected = True else: # Remove curves that have no keys on the current frame curves.pop(x).name return curves
def move_all_keys(choice): offset_val = offset_intfield.getValue() if offset_val < 1: raise RuntimeError('Enter an Offset Value greater than 0.') if choice == 'back': offset_val = offset_intfield.getValue() * -1 unlock_val = unlock_state.getValue1() current_time = pm.currentTime() anim_curves = pm.ls(type='animCurve') non_moved_curves = [] if choice == 'back': check_overlapping(anim_curves, choice, current_time, offset_val) for anim_curve in anim_curves: try: if unlock_val is True and anim_curve.isLocked(): anim_curve.setLocked(0) key_cnt = anim_curve.numKeys() for i in range(1, key_cnt + 1): if choice == 'forward': ind = key_cnt - i if choice == 'back': ind = i - 1 if anim_curve.getTime(ind) >= current_time: pm.keyframe(anim_curve, index=ind, iub=False, animation='objects', relative=True, option='move', tc=offset_val) except: if anim_curve not in non_moved_curves: non_moved_curves.append(anim_curve) continue if not non_moved_curves: pm.confirmDialog(title='Info', message='Keys Moved Successfully.', button='OK') else: message = 'Anim Curves can NOT be moved:\r\n' message += '\r' for i in range(0, len(non_moved_curves)): message += '%s\n' % non_moved_curves[i] if i > 30: message += '+ More...\n' break print(non_moved_curves) pm.confirmDialog(title='Error', message=message, button='OK')
def select_in_tangents(): """select in tangents of current selected keys""" curvelist = pm.keyframe(q=True, sl=True, name=True) for curve in curvelist: sel_keys = pm.keyframe(curve, q=True, sl=True) # returns list of frames for i in range(len(sel_keys)): pm.selectKey(curve, time=(sel_keys[i],), inTangent=True, add=True)
def fromCurve(cls, curve): keys = [] selectedIndexes = set(pm.keyframe(curve.name, query=1, indexValue=1, selected=1) or []) for index in pm.keyframe(curve.name, query=1, indexValue=1): selected = index in selectedIndexes key = cls(curve, index, selected) keys.append(key) return keys
def value(self, value): # I'm still torn if this should be a property or an explicit # setter because we are setting state in Maya. self._cache['value'] = value pm.keyframe(self.curve.name, absolute=1, valueChange=value, index=(self.index, self.index))
def move_all_keys(choice): offset_val = offset_intfield.getValue() if offset_val < 1: raise RuntimeError('Enter an Offset Value greater than 0.') if choice == 'back': offset_val = offset_intfield.getValue() * -1 unlock_val = unlock_state.getValue1() current_time = pm.currentTime() anim_curves = pm.ls(type='animCurve') non_moved_curves = [] if choice == 'back': check_overlapping(anim_curves, choice, current_time, offset_val) for anim_curve in anim_curves: try: if unlock_val is True and anim_curve.isLocked(): anim_curve.setLocked(0) key_cnt = anim_curve.numKeys() for i in range(1, key_cnt + 1): if choice == 'forward': ind = key_cnt - i if choice == 'back': ind = i - 1 if anim_curve.getTime(ind) >= current_time: pm.keyframe(anim_curve, index=ind, iub=False, animation='objects', relative=True, option='move', tc=offset_val ) except: if anim_curve not in non_moved_curves: non_moved_curves.append(anim_curve) continue if not non_moved_curves: pm.confirmDialog(title='Info', message='Keys Moved Successfully.', button='OK') else: message = 'Anim Curves can NOT be moved:\r\n' message += '\r' for i in range(0, len(non_moved_curves)): message += '%s\n' % non_moved_curves[i] if i > 30: message += '+ More...\n' break print non_moved_curves pm.confirmDialog(title='Error', message=message, button='OK')
def fromCurve(cls, curve): keys = [] selectedIndexes = set( pm.keyframe(curve.name, query=1, indexValue=1, selected=1) or []) for index in pm.keyframe(curve.name, query=1, indexValue=1): selected = index in selectedIndexes key = cls(curve, index, selected) keys.append(key) return keys
def remove_non_transform_curves(self): objs = self.original_selection objs.extend(pm.listRelatives(pm.ls(sl=True), allDescendents=True, type='transform')) all_curves = set(pm.keyframe(objs, q=True, name=True)) transform_curves = set(pm.keyframe(objs, q=True, name=True, attribute=self.transform_attributes)) for curve in all_curves: if curve not in transform_curves: pm.delete(curve)
def change_value(self): ''' # this changes the value ''' pm.keyframe('%s' % (self.node), option='over', index=(int(self.index), int(self.index)), absolute=True, valueChange=float(self.int_field.getValue()))
def change_time(self): ''' # this function will change the time for the key frame ''' pm.keyframe('%s' % (self.node), option='over', index=(int(self.index), int(self.index)), absolute=True, timeChange=int(self.int_field.getValue()))
def getAnimDict(self, curve, multiply=None): '''Takes a animCurve and from the number of keys it returns a dictionary[time] = value''' animCurveDict = {} for i in range(curve.numKeys()): if multiply: animCurveDict[int(curve.getTime(i))] = '%04.2f' % (float(pm.keyframe(curve, index=i, query=True, eval=True)[0]) * float(multiply)) else: animCurveDict[int(curve.getTime(i))] = '%04.2f' % (pm.keyframe(curve, index=i, query=True, eval=True))[0] return self.animAttributeToNuke(animCurveDict)
def __get_key_values(anim_curve=None): # type: (pmc.nodetypes.AnimCurve) -> Dict[int, float] unordered = { k: anim_curve.getValue(k) for k in pmc.keyframe(anim_curve, q=True, sl=True, indexValue=True) } or { k: anim_curve.getValue(k) for k in pmc.keyframe(anim_curve, q=True, indexValue=True) } return OrderedDict(sorted(unordered.iteritems(), key=lambda x: x[0]))
def offsetCurve(self, animationCurve, offset): """ Move the animation curve relative in time to offset, """ pm.keyframe( animationCurve, edit=True, includeUpperBound=True, relative=True, option='over', timeChange=offset, )
def is_ani_obj(node): nodeTx = '%s.tx' % node nodeTy = '%s.ty' % node nodeTz = '%s.tz' % node nodeRx = '%s.rx' % node nodeRy = '%s.ry' % node nodeRz = '%s.rz' % node nodeSx = '%s.sx' % node nodeSy = '%s.sy' % node nodeSz = '%s.sz' % node keyframe_num = range(9) keyframe_num[0] = pm.keyframe(nodeTx, query=True, keyframeCount=True) keyframe_num[1] = pm.keyframe(nodeTy, query=True, keyframeCount=True) keyframe_num[2] = pm.keyframe(nodeTz, query=True, keyframeCount=True) keyframe_num[3] = pm.keyframe(nodeRx, query=True, keyframeCount=True) keyframe_num[4] = pm.keyframe(nodeRy, query=True, keyframeCount=True) keyframe_num[5] = pm.keyframe(nodeRz, query=True, keyframeCount=True) keyframe_num[6] = pm.keyframe(nodeSx, query=True, keyframeCount=True) keyframe_num[7] = pm.keyframe(nodeSy, query=True, keyframeCount=True) keyframe_num[8] = pm.keyframe(nodeSz, query=True, keyframeCount=True) i = 0 for item in keyframe_num: if item > 1: #print keyframe_num[i] return True i = i + 1 return False
def create(self): ''' this creates the gui components for the node ''' pm.setParent(self.layout) # layout for all other frame layouts self.temp_layout = pm.columnLayout(adjustableColumn= False, width= 340) # this will list all animCurve nodes associated with an object # because anim nodes are named object_attr # but if the object is renamed after it's been keyed the anim node # will still have it's old name # by listing the anim nodes of the object * naming wont be an issue anim_nodes = pm.keyframe( '%s' % (self.node), query=True, name=True ) for anim_node in anim_nodes: pm.setParent(self.temp_layout) # getting the amount of keyframes for the curve node count = pm.keyframe( '%s' % (anim_node) , query=True, keyframeCount=True ) # translate U my_ui = Anim_UI(node= '%s' % (anim_node), count = count) my_ui.create() # creating a new string node = '%s' % (anim_node) # getting the attr the curve node is for # the insert and delete key methods need an attr to act on # all anim nodes are named object_attr # so i'm splitting to get just hte attr part node_attr = node.split('_')[-1] # indsert key # this will build the section for key insertion pm.setParent('..') pm.text(label= 'Insert Key') pm.rowColumnLayout(numberOfColumns= 3, columnWidth= ([1,113], [2,113], [3,113])) pm.text(label= 'Key Position') insert_field = pm.intField() pm.button(label= 'Insert', command= pm.Callback(self.insert_key, attr= '%s.%s' % (self.node, node_attr), value= insert_field)) # delete key # this will build the section for key deletion pm.setParent('..') pm.text(label= 'Delete Key') pm.rowColumnLayout(numberOfColumns= 3, columnWidth= ([1,113], [2,113], [3,113])) pm.text(label= 'Key Index') delete_field = pm.intField() pm.button(label= 'Delete', command= pm.Callback(self.delete_key, attr= '%s.%s' % (self.node, node_attr), index= delete_field))
def remapKeys(self): kList, tList = self._createFilledTimeLists() if (round(tList[0]) - 1) < AnimationRemapper._startTime: print "Youre moving too fast!" return kList.reverse() # tList.reverse( ) # Reverse the lists so you cant accidentaly place keys on top of other keys lastSnappedKey = 0.0 for key, timeKey in zip(kList, tList): #print key, timeKey if self._snapKeys: timeKey = round(timeKey, 0) if timeKey == lastSnappedKey: timeKey = timeKey - 1 lastSnappedKey = timeKey for selectedObject in self._selectedObjects: r = pm.keyframe(selectedObject, e=1, t=(key, key + 1), tc=timeKey) if r == 10: print key, timeKey return for recordedFrame, recordTime in a: newFrame = round(recordTime * self.fps, 2) int_recordedFrame = int( float(recordedFrame)) #Converts from String to Int try: for selectedObject in self._selectedObjects: r = pm.keyframe(selectedObject, e=1, t=(int_recordedFrame, int_recordedFrame + 1), tc=newFrame) if r == 10.0: print "recordedFrame :", int_recordedFrame, "newFrame:", newFrame del AnimationRemapper._remapperDict[recordedFrame] except: print "Error at keyframing ", int_recordedFrame, newFrame pass #If the pm.keyframe command fails then we shouldnt empty the dict if AnimationRemapper._remapperDict: #Run the function recursively until the dictionary is empty return self._moveKeys else: return True
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 anisplits(arg): sel = pm.ls(sl=1) for i in range(len(sel)): selAC = pm.listConnections(sel[i],d=0,type="animCurve") if selAC!=[]: for a in range(len(selAC)): indexnum = pm.keyframe( selAC[a], query=True, keyframeCount=True ) for n in range(indexnum): frame = pm.keyframe( selAC[a], query=True,index=(n,n),timeChange=1)[0] if int(str(frame).split(".")[-1]) !=0: intframe = "%d" %frame pm.setKeyframe(selAC[a],t=intframe) pm.cutKey(selAC[a],t=frame)
def addKeysToAnimCurveNode( animCurveNode, frame=0, value=0, index=0, ): import pymel.core.animation as pymel pymel.setKeyframe(animCurveNode, insert=True, float=frame) pymel.keyframe(animCurveNode, index=(index, index), absolute=True, valueChange=value)
def select_curve_tangets(): animCurves = pm.keyframe(q=True, name=True) for c in animCurves: keys = pm.keyframe(c, q=True, tc=True, sl=True) if inTangent: for k in keys: pm.selectKey(c, add=True, inTangent=True, t=k) if outTangent: for k in keys: pm.selectKey(c, add=True, outTangent=True, t=k)
def __init__(self, pivot, user_scale, scale_type): self.pivot = pivot self.scale = user_scale.getValue() self.curves = pm.keyframe(query=True, selected=True, name=True) self.key_values = pm.keyframe(query=True, selected=True, valueChange=True, absolute=True) self.key_times = pm.keyframe(query=True, selected=True, timeChange=True, absolute=True) self.scale_type = scale_type
def mapAnimCurveToAttr(animCrv, attr, scale=1.0): ''' attr - time will be replaced by this attribute scale - time keys will be scaled by this value ''' attr >> animCrv.input # scale keys ktv_indices = animCrv.ktv.get(mi=True) keys = [animCrv.ktv[i].get()[0] for i in ktv_indices] for i, key in enumerate(keys): scaledKey = key * scale pm.keyframe(animCrv, index=(i), edit=True, tc=scaledKey)
def swap_space(self, index, previous_index = -1, frame = None, key_switch = True, end_cap = False): current_frame = frame if frame else pm.currentTime() control = self.network['controls'].get_first_connection() component_group = self.network['addon'].group component_constraint = self.get_space_constraint() ws_t = pm.xform(control, q=True, ws=True, t=True) ws_ro = pm.xform(control, q=True, ws=True, ro=True) if key_switch: attr_list = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] for x_attr in attr_list: attr = getattr(control, x_attr) pm.setKeyframe(attr, t = current_frame-1, v = attr.get(t=current_frame-1)) index_list = [index] if type(index) == int else index switch_attr_list = [] for index in index_list: switch_attr_list.append(component_constraint.listAttr(ud=True)[index]) # If a previous_index isn't passed key the previous frame with whatever values they are at that frame # Otherwise we'll key the previous_attr at 1 and all others to 0 previous_attr = component_constraint.listAttr(ud=True)[previous_index] if previous_index >= 0 else None for i, attr in enumerate(component_constraint.listAttr(ud=True)): # Set previous attr to 1 and all others to 0, and key it on the previous frame if previous_attr: set_value = 1 if attr == previous_attr else 0 attr.set(set_value) if key_switch: adjust_frame = -1 if not end_cap else 0 key_frames = pm.keyframe(attr, q = True, t = current_frame + adjust_frame) if not key_frames or end_cap: pm.setKeyframe(attr, t = current_frame + adjust_frame) # Set the attr we're switching to to 1 and all others to 0, and key it on the current frame set_value = 1 if attr in switch_attr_list else 0 attr.set(set_value) if key_switch: adjust_frame = 0 if not end_cap else 1 key_frames = pm.keyframe(attr, q = True, t = current_frame + adjust_frame) if not key_frames or not end_cap: pm.setKeyframe(attr, t = current_frame + adjust_frame) pm.xform(control, ws=True, t=ws_t) pm.xform(control, ws=True, ro=ws_ro) if key_switch: attr_list = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] for x_attr in attr_list: attr = getattr(control, x_attr) pm.setKeyframe(attr, t = current_frame, v = attr.get(t=current_frame))
def create(self): ''' # this creates the float field ''' current_time = pm.keyframe( '%s' % (self.node) , query=True, index= (self.index, self.index), valueChange= True )[0] self.int_field = pm.floatField(value= float(current_time), annotation= 'change the value for the keyframe', changeCommand= pm.Callback(self.change_value))
def getAnimDict(self, curve): '''Takes a animCurve and from the number of keys it returns a dictionary[time] = value''' animCurveDict = {} for i in range(curve.numKeys()): animCurveDict[int(curve.getTime(i))] = '%04.2f' % (pm.keyframe(curve, index=i, query=True, eval=True))[0] #animCurveDict[int(curve.getTime(index))] = '%04.2f' % (curve.getValue(index)) return self.animAttributeToNuke(animCurveDict)
def testLoadStoredKeys(self): name = self.storeAnimationAttrs() # clear keyframes on the cube pm.cutKey(self.cube,at="translateX", cl=1) self.store.loadStoredKeys(self.cube) keys = pm.keyframe(name + ".translateX", q=1, kc=1) eq_(keys,2)
def testAnimationAttrs(self): name = self.storeAnimationAttrs() keys = pm.keyframe( name + "." + name + "translateX" , q=1,kc=1 ) keys2 = pm.keyframe( name + ".translateX" , q=1,kc=1 ) eq_(keys,2) eq_(keys2,2) data = self.cube.getAttr('animationAttrs') eq_(data, '{"' + name + 'translateX": "' +name + '.translateX"}')
def value(self): try: self._cache['value'] except KeyError: self._cache['value'] = pm.keyframe( self.curve.name, query=True, absolute=True, valueChange=True, index=(self.index, self.index))[0] return self._cache['value']
def amcveProfile(cvSrc, trim): """ """ cvSrc = pm.ls(cvSrc)[0] tiLen = [] if trim: tiLen.append(pm.playbackOptions(q= 1, min= 1)) tiLen.append(pm.playbackOptions(q= 1, max= 1)) pm.undoInfo(ock= 1) pm.setKeyframe(cvSrc, insert= 1, t= tiLen, f= tiLen) pm.undoInfo(cck= 1) cvBaseMod = { 'cvTyp' : pm.objectType(cvSrc), 'prInf' : cvSrc.getPreInfinityType().key, 'poInf' : cvSrc.getPostInfinityType().key, 'weedT' : pm.keyTangent(cvSrc, q= 1, weightedTangents= 1), 'breaD' : pm.keyframe(cvSrc, q= 1, breakdown= 1) } cvPortray = { 'Frame' : pm.keyframe(cvSrc, q= 1, timeChange= 1), 'Float' : pm.keyframe(cvSrc, q= 1, floatChange= 1), 'Value' : pm.keyframe(cvSrc, q= 1, valueChange= 1) } cvFeature = { 'TLock' : pm.keyTangent(cvSrc, q= 1, lock= 1), 'WLock' : pm.keyTangent(cvSrc, q= 1, weightLock= 1), 'InTyp' : pm.keyTangent(cvSrc, q= 1, inTangentType= 1), 'OuTyp' : pm.keyTangent(cvSrc, q= 1, outTangentType= 1), 'InWet' : pm.keyTangent(cvSrc, q= 1, inWeight= 1), 'OuWet' : pm.keyTangent(cvSrc, q= 1, outWeight= 1), 'InAng' : pm.keyTangent(cvSrc, q= 1, inAngle= 1), 'OuAng' : pm.keyTangent(cvSrc, q= 1, outAngle= 1) } cvSrcProfile = { 'cvTrimmed' : tiLen, 'cvBaseMod' : cvBaseMod, 'cvPortray' : cvPortray, 'cvFeature' : cvFeature } if trim: pm.undo() return cvSrcProfile
def getSelectedCurvesKeys(): """ Get the currently selected animation curves and keys. @return: A dict containing animation curves and keys. @rtype: dict """ selList = {} for object in pm.ls( sl=True ): try: for curve in pm.keyframe( object, query=True, selected=True, name=True ): selList[curve] = tuple( pm.keyframe( curve, query=True, selected=True ) ) except: pass return selList
def test(self): kwargs = {'query':1, 'attribute':'tx', 'keyframeCount':1, flag:val} try: result = pm.keyframe(self.cube, **kwargs) except Exception: trace = traceback.format_exc() self.fail('Error executing keyframe for %s=%r:\n%s' % (flag, val, trace)) self.assertEqual(result, expected, "Wrong value for %s=%r - expected %r, got %r" % (flag, val, expected, result))
def _keyTickSpecial( enable=True ): keys_sl = True nodes = pm.ls( sl=1 ) # -- if no keys are selected, get keys at current time if not pm.keyframe( q=1, sl=1 ): keys_sl = False ct = pm.currentTime( q=1 ) pm.selectKey( nodes, k=1, t=( ct, ct ) ) # -- only update the ticks if we have selected keys if pm.keyframe( q=1, sl=1 ): pm.keyframe( e=1, tickDrawSpecial=enable ) # -- if we didn't start out with selected keys, clear the selection. if not keys_sl: pm.selectKey( cl=1 )
def time(self): try: self._cache['time'] except KeyError: self._cache['time'] = pm.keyframe( self.curve.name, query=True, index=(self.index, self.index), timeChange=True)[0] return self._cache['time']
def fromAttribute(cls, attribute): ''' Returns a list of curves associated with an attribute. ''' curveNames = pm.keyframe(attribute, query=1, name=1) or [] curves = [] for curveName in curveNames: curve = cls(curveName) curve.keys = Key.fromCurve(curve) curves.append(curve) return curves
def _bakeAnim(self, root): ''' Given root: - Bake the heirarchy animation data - Delete constraints - Reset timeline to 1 if wasn't already set to 1 - Remove root from heirarchy ''' pymelLogger.debug('Starting: bakeAnim()...') # Getting time range from scene startFrame = int( pm.playbackOptions(q=1, min=1) ) endFrame = int( pm.playbackOptions(q=1, max=1) ) # Bake the heirarchy #pm.select( root, hi=1 ) #pm.bakeResults(simulation=1, t=( startFrame, endFrame ) ) # Delete constraints #self._delConstraints(root) pm.select(root,hi=1, r=1) # Set timeline to start at frame 1 if startFrame != 1: if startFrame < 1: tChange = (-(startFrame))+1 elif startFrame > 1: tChange = (-(startFrame-1)) pm.keyframe(e=1, time=(startFrame,endFrame),relative=1, timeChange=tChange) pm.playbackOptions(e=1, min=1, max=endFrame+tChange ) # Remove root from it's heirarchy #pm.select(root, r=1) #try: # pm.parent(root, w=1) #except Exception,e: # pymelLogger.error('_bakeAnim(): %s'%e) pymelLogger.debug('bakeAnim(): Baked anim onto %s'%root) pymelLogger.debug('bakeAnim(): Range baked: %s - %s'%(startFrame,endFrame)) pymelLogger.debug('End: bakeAnim()')
def normalizeScale(target=None, iT=inTime(), oT=outTime()): x = 0 y = 0 z = 0 p = [] if not target: target = s() for i in range(0,len(target)): for j in range(iT,oT): t(j) pp = mc.py.xform(target[i], q=True, scale=True, ws=True) p.append(pp) pOrig = p[0] for m in range(iT,oT): try: x = p[m][0]/pOrig[0] y = p[m][1]/pOrig[1] z = p[m][2]/pOrig[2] py.keyframe(target[i]+'.scaleX',edit=True,time=[m],valueChange=x) py.keyframe(target[i]+'.scaleY',edit=True,time=[m],valueChange=y) py.keyframe(target[i]+'.scaleZ',edit=True,time=[m],valueChange=z) except: print "Couldn't set keyframe " + str(m) + "."
def keyController(ctrlList): """ 回傳有 keyframe 的 controller 字典 { ctrl : { ctrl.attr : animCurveNode } } """ ctrlKey = {} for ctrl in ctrlList: hasKey = False driven = pm.setDrivenKeyframe(ctrl, q= 1, dn= 1) keyNum = pm.keyframe(ctrl, q= 1, kc= 1) drnNum = 0 if keyNum: if driven[0] == 'No driven attributes found on the selected item.': # has key hasKey = True else: # has drivenKey for dn in driven: drnNum += pm.keyframe(dn, q= 1, kc= 1) if drnNum < keyNum: # has key hasKey = True if hasKey: atKey = {} ats = pm.listConnections(ctrl, d= 0, c= 1, scn= 1, t= 'animCurve') for at in ats: at = at[0] # skip driven if drnNum and at in driven: continue at = at.name() ac = pm.listConnections(at, d= 0, scn= 1, t= 'animCurve') atKey[str(at)] = str(ac[0].name()) ctrlKey[str(ctrl)] = atKey return ctrlKey
def flipCurve( curves=None, valuePiv=None ): """ Flip the selected curve(s). If valuePiv is C{'None'}, curve will be flipped over value at current time. @param valuePiv: default: C{None} If valuePiv is C{'None'}, curve will be flipped over value at current time. @type valuePiv: float """ if curves is None: curves = getSelectedCurvesKeys().iterkeys() for curve in curves: if valuePiv is None: valuePiv = pm.keyframe( curve, query=True, eval=True )[0] else: pass pm.scaleKey( curve, valueScale= -1.0, valuePivot=valuePiv )
def resetScale(target=None, iT=inTime(), oT=outTime()): if not target: target = s() for i in range(0,len(target)): for m in range(iT,oT): try: py.keyframe(target[i]+'.scaleX',edit=True,time=[m],valueChange=1) py.keyframe(target[i]+'.scaleY',edit=True,time=[m],valueChange=1) py.keyframe(target[i]+'.scaleZ',edit=True,time=[m],valueChange=1) except: print "Couldn't set keyframe " + str(m) + "."
def testDSaveState(self): self.standIn = pm.ls('testStandin_standInCtrl')[0] # add some keys to the controllers # and change some transforms contr1 = pm.ls('controllerA')[0] contr1.rotate.set((0,90,0)) contr1.translate.set((5,3,2)) pm.setKeyframe('controllerA.scaleX', t=1, v=1.3) pm.setKeyframe('controllerA.scaleX', t=5, v=1.9) # custom connected attribute # for testing dependency graph evaluations pm.setKeyframe('controllerB.testSrc', t=1, v=0.5) pm.select(self.standIn) self.cc.saveState() keys = pm.keyframe( 'testStandin_standInCtrl.controllerAscaleX', q=1, kc=1 ) eq_(keys, 2)