def retime(animation_curves, start_frame, end_frame, new_start_frame, new_end_frame, offset_contiguous_animation=True, snap_keys=True): """Scale time range but also offset what's contiguous to keep continuity""" # Define offsets happening before and after: end_offset = new_end_frame - end_frame start_offset = new_start_frame - start_frame # Define offset functions: keys = mc.keyframe(animation_curves, query=True) max_keyframe = max(keys) + start_offset + end_offset offset_after_function = partial(mc.keyframe, animation_curves, edit=True, t=(end_frame + 1, max_keyframe), relative=True, timeChange=end_offset, option='over') min_keyframe = min(keys) - end_offset - start_offset offset_before_function = partial(mc.keyframe, animation_curves, edit=True, t=(min_keyframe, start_frame - 1), relative=True, timeChange=start_offset, option='over') # Offsets in case of expansion: if offset_contiguous_animation and end_offset > 0: offset_after_function() if offset_contiguous_animation and start_offset < 0: offset_before_function() # Retime/scale animation: mc.scaleKey(animation_curves, time=(start_frame, end_frame), newStartTime=new_start_frame, newEndTime=new_end_frame) if snap_keys: mc.snapKey(animation_curves, t=(new_start_frame, new_end_frame)) # Offsets in case of shrinking: if offset_contiguous_animation and end_offset < 0: offset_after_function() if offset_contiguous_animation and start_offset > 0: offset_before_function()
def era_UnIntKeys(integer = 0): import re retTx = '' re_objs = [] objs = mc.ls(tr = True,v = True,ut = True) for obj in objs: i = 0 keys = mc.keyframe(obj,q = True,timeChange = True) if keys: for key in keys: if not re.match('^[-0-9]+.[0]*$','%s'%key): retTx += obj + era_SplitFlag() re_objs.append(obj) break if re_objs and integer: mc.snapKey(re_objs) else: return retTx
def snapKey(*args, **kwargs): for flag in ['t', 'time']: try: rawVal = kwargs[flag] except KeyError: continue else: kwargs[flag] = _factories.convertTimeValues(rawVal) res = cmds.snapKey(*args, **kwargs) return res
def smartSnapKeys(): getCurves = animMod.getAnimCurves() animCurves = getCurves[0] if not animCurves or len(animCurves) == 0: return getFrom = getCurves[1] keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom) keysSel = animMod.getTarget("keysSel", animCurves, getFrom) hasDecimalKeys = False for loopKey in utilMod.mergeLists(keysSel): if loopKey != round(loopKey) > 0: hasDecimalKeys = True break if not hasDecimalKeys: return keyTangentsType = animMod.getTarget("keyTangentsType", animCurves, getFrom) firstStep = 0 totalSteps = len(animCurves) estimatedTime = None status = "aTools - Smart Snap Curves..." startChrono = None utilMod.startProgressBar(status) for thisStep, loopCurve in enumerate(animCurves): startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status) if None in [keyTimes[thisStep], keysSel[thisStep]]: continue stepKeys = [ loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and keyTangentsType[thisStep][nn][1] == "step" ] linearKeys = [ loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and keyTangentsType[thisStep][nn][1] == "linear" ] decimalKeys = [ loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and loopKey not in stepKeys + linearKeys ] for loopKey in stepKeys: cmds.snapKey(loopCurve, time=(loopKey, loopKey)) for loopKey in linearKeys: cmds.snapKey(loopCurve, time=(loopKey, loopKey)) if len(decimalKeys) == 0: continue if not getFrom: if cmds.keyframe(query=True, selected=True) != None: getFrom = "graphEditor" #inLinearKeys = [round(loopKey) for nn, loopKey in enumerate(keyTimes[thisStep]) if keyTangentsType[thisStep][nn][0] == "linear"] #outLinearKeys = [round(loopKey) for nn, loopKey in enumerate(keyTimes[thisStep]) if keyTangentsType[thisStep][nn][1] == "linear"] createKeys = list(set([round(loopKey) for loopKey in decimalKeys])) selectKeys = [] #print "inlinearKeys", inLinearKeys, outLinearKeys if getFrom == "graphEditor": selectKeys = list( set([ round(loopKey) for loopKey in keysSel[thisStep] if round(loopKey) in createKeys ])) for loopKey in createKeys: cmds.setKeyframe(loopCurve, time=(loopKey, loopKey), insert=True) for loopKey in selectKeys: cmds.selectKey(loopCurve, addTo=True, time=(loopKey, loopKey)) for loopKey in decimalKeys: cmds.cutKey(loopCurve, time=(loopKey, loopKey)) #for loopKey in outLinearKeys: cmds.keyTangent(loopCurve, edit=True, time=(loopKey, loopKey), outTangentType="linear") #for loopKey in inLinearKeys: cmds.keyTangent(loopCurve, edit=True, time=(loopKey, loopKey), inTangentType="linear") estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps) utilMod.setProgressBar(endProgress=True)
def smartSnapKeys(): getCurves = animMod.getAnimCurves() animCurves = getCurves[0] if not animCurves or len(animCurves) == 0: return getFrom = getCurves[1] keyTimes = animMod.getTarget("keyTimes", animCurves, getFrom) keysSel = animMod.getTarget("keysSel", animCurves, getFrom) hasDecimalKeys = False for loopKey in utilMod.mergeLists(keysSel): if loopKey != round(loopKey) > 0: hasDecimalKeys = True break if not hasDecimalKeys: return keyTangentsType = animMod.getTarget("keyTangentsType", animCurves, getFrom) firstStep = 0 totalSteps = len(animCurves) estimatedTime = None status = "aTools - Smart Snap Curves..." startChrono = None utilMod.startProgressBar(status) for thisStep, loopCurve in enumerate(animCurves): startChrono = utilMod.chronoStart(startChrono, firstStep, thisStep, totalSteps, estimatedTime, status) if None in [keyTimes[thisStep], keysSel[thisStep]]: continue stepKeys = [loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and keyTangentsType[thisStep][nn][1] == "step"] linearKeys = [loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and keyTangentsType[thisStep][nn][1] == "linear"] decimalKeys = [loopKey for nn, loopKey in enumerate(keyTimes[thisStep]) if loopKey != round(loopKey) and loopKey in keysSel[thisStep] and loopKey not in stepKeys + linearKeys] for loopKey in stepKeys: cmds.snapKey(loopCurve, time=(loopKey, loopKey)) for loopKey in linearKeys: cmds.snapKey(loopCurve, time=(loopKey, loopKey)) if len(decimalKeys) == 0: continue if not getFrom: if cmds.keyframe(query=True, selected=True) != None: getFrom = "graphEditor" #inLinearKeys = [round(loopKey) for nn, loopKey in enumerate(keyTimes[thisStep]) if keyTangentsType[thisStep][nn][0] == "linear"] #outLinearKeys = [round(loopKey) for nn, loopKey in enumerate(keyTimes[thisStep]) if keyTangentsType[thisStep][nn][1] == "linear"] createKeys = list(set([round(loopKey) for loopKey in decimalKeys])) selectKeys = [] #print "inlinearKeys", inLinearKeys, outLinearKeys if getFrom == "graphEditor": selectKeys = list(set([round(loopKey) for loopKey in keysSel[thisStep] if round(loopKey) in createKeys])) for loopKey in createKeys: cmds.setKeyframe(loopCurve, time=(loopKey, loopKey), insert=True) for loopKey in selectKeys: cmds.selectKey(loopCurve, addTo=True, time=(loopKey, loopKey)) for loopKey in decimalKeys: cmds.cutKey(loopCurve, time=(loopKey, loopKey)) #for loopKey in outLinearKeys: cmds.keyTangent(loopCurve, edit=True, time=(loopKey, loopKey), outTangentType="linear") #for loopKey in inLinearKeys: cmds.keyTangent(loopCurve, edit=True, time=(loopKey, loopKey), inTangentType="linear") estimatedTime = utilMod.chronoEnd(startChrono, firstStep, thisStep, totalSteps) utilMod.setProgressBar(endProgress=True)
def do_snap_keys(first_key, last_key): cmds.selectKey(clear=True) # Must clear the selection to use the -time flag cmds.snapKey(time=(first_key, last_key), timeMultiple=1)
def retime_animation_curves(animation_curves, start_frame, end_frame, new_start_frame, new_end_frame, add_boundary_keyframes=False, offset_contiguous_animation=True, snap_keys=True): """ Scale time range but also offset what's contiguous to keep continuity. :param list[str] animation_curves: animation curves names :param float start_frame: :param float end_frame: :param float new_start_frame: :param float new_end_frame: :param bool add_boundary_keyframes: add keyframes before and after retime to ensure de animation will not change out of the scaled range. :param bool offset_contiguous_animation: shift the animation before and after the scale to match the new timing. :param bool snap_key: round the new key frame time to the closest int. """ # Define offsets happening before and after: end_offset = new_end_frame - end_frame start_offset = new_start_frame - start_frame # Define offset functions: keys = cmds.keyframe(animation_curves, query=True) max_keyframe = max(keys) + start_offset + end_offset offset_after_function = partial(cmds.keyframe, animation_curves, edit=True, t=(end_frame + 1, max_keyframe), relative=True, timeChange=end_offset, option='over') min_keyframe = min(keys) - end_offset - start_offset offset_before_function = partial(cmds.keyframe, animation_curves, edit=True, t=(min_keyframe, start_frame - 1), relative=True, timeChange=start_offset, option='over') if add_boundary_keyframes: cmds.setKeyframe(animation_curves, time=start_frame, inTangentType="linear", outTangentType="linear") cmds.setKeyframe(animation_curves, time=end_frame, inTangentType="linear", outTangentType="linear") # Offsets in case of expansion: if offset_contiguous_animation and end_offset > 0: offset_after_function() if offset_contiguous_animation and start_offset < 0: offset_before_function() # Retime/scale animation: cmds.scaleKey(animation_curves, time=(start_frame, end_frame), newStartTime=new_start_frame, newEndTime=new_end_frame) if snap_keys: cmds.snapKey(animation_curves, t=(new_start_frame, new_end_frame)) # Offsets in case of shrinking: if offset_contiguous_animation and end_offset < 0: offset_after_function() if offset_contiguous_animation and start_offset > 0: offset_before_function()