def switchFrame(control, targetSpace): ''' Space switch a single frame. ''' switchToSpace(control, targetSpace) if globalSettings.singleSwitchEuler: filterCurve(control)
def keys_to_motion_path(objs=None, axis="x", up_axis="y", wuv=(0, 1, 0)): if not objs: objs = pmc.selected(transforms=True) with msu.MayaUndoChunkManager(): for obj in objs: # curve from keys keys = sorted(set(pmc.keyframe(obj, q=True))) r = int(keys[0]), int(keys[-1]) + 1 pts = (obj.t.get(t=f) for f in xrange(*r)) c = pmc.curve(d=3, ep=pts) # to set motion path keys, need to link current keys to u param curve_keys = dict( (k, c.getParamAtPoint(obj.t.get(t=k))) for k in xrange(*r)) pmc.cutKey(obj, t=r, cl=True) mp = pmc.nt.MotionPath() c.ws >> mp.geometryPath mp.follow.set(True) mp.fa.set(axis.upper()) mp.ua.set(up_axis.upper()) mp.wu.set(wuv) mp.ac >> obj.t mp.r >> obj.r for t, v in curve_keys.items(): pmc.setKeyframe(mp.u, t=t, v=v) pmc.filterCurve(mp.u, f="simplify", tto=.05) # markers clutter and slow pmc.delete(mp.pmt.inputs())
def switchRange(control, targetSpace, range=(None, None)): ''' Switch the `control` into the targetSpace across the given range (includes) endpoints. This alters the keyframes ''' attrs = [ENUM_ATTR] + [t + a for t in 'tr' for a in 'xyz'] curTime = currentTime(q=True) times = keyframe(control, at=attrs, q=True, tc=True) times = sorted(set(times)) if range[0] is not None and range[1] is not None: times = [t for t in times if range[0] <= t <= range[1]] elif range[0]: times = [t for t in times if range[0] <= t] elif range[1]: times = [t for t in times if t <= range[1]] if not times: switchToSpace(control, targetSpace) return # Set initial keys if needed so insert=True works later for attr in attrs: if not keyframe(control.attr(attr), q=True, tc=True): control.attr(attr).setKey(t=times[0]) control.attr(attr).setKey(t=times[-1]) for t in times: control.t.setKey(insert=True, t=t) control.r.setKey(insert=True, t=t) control.attr(ENUM_ATTR).setKey(insert=True, t=t) for t in times: currentTime(t) switchToSpace(control, targetSpace) control.attr(ENUM_ATTR).setKey() control.t.setKey() control.r.setKey() currentTime(curTime) if globalSettings.autoEuler: filterCurve(control)
def eulerFilterEnhance(): # NOTE 获取关键帧曲线 | 区分出驱动关键帧 anim_dict = {} filter_flag = False anim_list = pm.keyframe(q=1, sl=1, n=1) if anim_list: for anim in anim_list: anim = pm.PyNode(anim) anim_dict[anim] = {} selected = pm.keyframe(anim, q=1, sl=1, iv=1) for idx in pm.keyframe(anim, q=1, iv=1): if idx not in selected: anim_dict[anim][idx] = anim.getValue(idx) else: filter_flag = True else: # NOTE 单帧曲线过滤 # # NOTE 获取当前时间帧 # cur = pm.currentTime(q=1) # for sel in pm.ls(sl=1): # anim_list.extend(sel.listConnections(type="animCurveTA")) # # NOTE 找出前后有关键帧 但是关键帧为小数中间的值进行删除 # for anim in anim_list: # anim_dict[anim] = {} # for idx in pm.keyframe(anim,q=1,iv=1): # time = anim.getTime(idx) # if time != cur: # anim_dict[anim][idx] = anim.getValue(idx) # else: # filter_flag = True mel.eval("performEulerFilter graphEditor1FromOutliner") if filter_flag: # NOTE 过滤曲线 pm.filterCurve(anim_list) # NOTE 复原其他关键帧 for anim, data in anim_dict.items(): for idx, val in data.items(): anim.setValue(idx, val)
def _onRelease(self): ''' This is called when the tool is released. Here we'll remove our callback and cleanup everything. ''' # Remove the callback om.MMessage.removeCallback(self.callbackID) # Set the current tool to the move tool pmc.setToolTo('moveSuperContext') # Simplify the animation curves if self.simplify: for target in self.targets: pmc.filterCurve(target, f='simplify', startTime=self.startFrame, endTime=pmc.currentTime(q=True), timeTolerance=self.tolerance) # End the scrub pmc.timeControl(self.playbackSlider, edit=True, endScrub=True)
def apply_euler_filter(self, objs): curves = pm.keyframe(objs, q=True, name=True, attribute=['rx', 'ry', 'rz']) pm.filterCurve(curves, filter='euler')
def bake_objects(obj_list, translate, rotate, scale, use_settings=True, custom_attrs=None, bake_range=None, **kwargs): ''' Wrapper around pm.bakeResults and sets up the scene to ensure the objects are bake-able and using the user's custom bake settings. Note: At the end we set a key at -10000 and value 0 for rotation as a reference point for a eurler filter operation. Args: obj_list (list<PyNode>): List of objects to perform the bake operation on translate (boolean): Whether or not to bake translate channels rotate (boolean): Whether or not to bake rotate channels scale (boolean): Whether or not to bake scale channels use_settings (boolean): Whether or not to use user defined settings for bake settings custom_attrs (list<str>): A list of strings defining all custom attributes that should also be baked kwargs (kwargs): keyword arguments for pm.bakeResults ''' # Temporary disable cycle checks during baking cycle_check = pm.cycleCheck(q=True, e=True) pm.cycleCheck(e=False) try: # Disable viewport refresh to speed up execution pm.refresh(su=True) # Anim Layers with a single keyframe don't bake reliably, add a second key 1 frame after the first on any single keyframe layers fix_solo_keyframe_layers() # Objects on hidden layers don't reliably bake correctly, toggle them all true, then reset values after baking. layer_dict = {} default_display_layer = pm.PyNode('defaultLayer') if pm.objExists( 'defaultLayer') else None for layer in pm.ls(type='displayLayer'): if layer != default_display_layer: layer_dict[layer] = layer.visibility.get() layer.visibility.set(True) attr_list = [] if translate: attr_list += ['.tx', '.ty', '.tz'] if rotate: attr_list += ['.rx', '.ry', '.rz'] if scale: attr_list += ['.sx', '.sy', '.sz'] if custom_attrs: attr_list += custom_attrs process = System.Diagnostics.Process.GetCurrentProcess() # In maya standalone don't use user settings file if "mayapy" in process.ToString(): use_settings = False bake_settings = v1_core.global_settings.GlobalSettings().get_category( v1_core.global_settings.BakeSettings, default=not use_settings) sample = bake_settings.sample_by # Set/get time range time_range = (pm.playbackOptions(q=True, ast=True), pm.playbackOptions(q=True, aet=True)) if use_settings: time_range = get_bake_time_range(obj_list, bake_settings) elif bake_range: time_range = bake_range time_range = [int(time_range[0]), int(time_range[1])] if type(time_range[0]) != int or type(time_range[1]) != int: raise BakeRangeError v1_core.v1_logging.get_logger().info( "Baking {0} \n Use Settings: {1}, over range {2}\nBake Attrs: {3}\nBakeSettings: {4}" .format(obj_list, use_settings, time_range, attr_list, kwargs)) bake_start = time.clock() # Baking is stupidly slower if you pass in a value to smart bake(sr), even if it's False, so we split out the command if bake_settings.smart_bake: pm.bakeResults(obj_list, at=attr_list, t=time_range, sb=sample, sr=True, preserveOutsideKeys=True, **kwargs) else: pm.bakeResults(obj_list, at=attr_list, t=time_range, sb=sample, preserveOutsideKeys=True, **kwargs) v1_core.v1_logging.get_logger().info( "Bake Command Completed in {0} Seconds".format(time.clock() - bake_start)) pm.setKeyframe(obj_list, t=-1010, at='rotate', v=0) pm.filterCurve(obj_list) pm.cutKey(obj_list, t=-1010) for layer, value in layer_dict.iteritems(): layer.visibility.set(value) except Exception, e: exception_info = sys.exc_info() v1_core.exceptions.except_hook(exception_info[0], exception_info[1], exception_info[2])