def test_selection_change_deselect(): cube = setupCube() collection = sak.SegmentCollection.detect(forceSelectedKeys=True) pm.selectKey(cube.tx.connections()[0], rm=1, k=1, t="3") assert collection.hasSelectionChanged( sak.SegmentCollection.detect(forceSelectedKeys=True))
def snapKey(): # NOTE 通过命令将 关键帧 吸附 start = pm.playbackOptions(q=1, min=1) end = pm.playbackOptions(q=1, max=1) # NOTE 清空关键帧选择避免 snapKey 报错 pm.selectKey(cl=1) pm.snapKey(t=(start, end), tm=1.0) # NOTE 获取关键帧曲线 | 区分出驱动关键帧 anim_list = [] for sel in pm.ls(sl=1): anim_list.extend(sel.listConnections(type="animCurveTA")) anim_list.extend(sel.listConnections(type="animCurveTU")) anim_list.extend(sel.listConnections(type="animCurveTL")) # NOTE 找出前后有关键帧 但是关键帧为小数中间的值进行删除 remove_dict = {} for anim in anim_list: for keyframe in range(anim.numKeys()): time = anim.getTime(keyframe) if not time.is_integer(): if not remove_dict.has_key(anim): remove_dict[anim] = [] remove_dict[anim].append(time) for anim, times in remove_dict.items(): for time in times: pm.cutKey(anim, clear=1, time=time)
def test_selection_change_clear(): setupCube() collection = sak.SegmentCollection.detect(forceSelectedKeys=True) pm.selectKey(clear=True) assert collection.hasSelectionChanged( sak.SegmentCollection.detect(forceSelectedKeys=True))
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 select_object_from_curve(): curves = pm.keyframe(q=True, name=True) objs = [] for c in curves: c = pm.PyNode(c) objs = objs + c.attr('output').outputs() pm.select(objs, r=True) pm.selectKey(curves, add=True, k=True)
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 test_selection_change_more(): cube = setupCube() # Force graph will force sgment collection to consider selected keys # instead of keys on the current frame. collection = sak.SegmentCollection.detect(forceSelectedKeys=True) # Selected keys for x in xrange(1, 4): # deselect pm.selectKey(cube.tx.connections()[0], rm=1, k=1, t=x) assert collection.hasSelectionChanged( sak.SegmentCollection.detect(forceSelectedKeys=True)) # reset pm.selectKey(cube.tx.connections()[0], add=1, k=1, t=x) assert not collection.hasSelectionChanged( sak.SegmentCollection.detect(forceSelectedKeys=True)) for x in [0, 4]: # select pm.selectKey(cube.tx.connections()[0], add=1, k=1, t=x) assert collection.hasSelectionChanged( sak.SegmentCollection.detect(forceSelectedKeys=True)) # reset pm.selectKey(cube.tx.connections()[0], rm=1, k=1, t=x) assert not collection.hasSelectionChanged( sak.SegmentCollection.detect(forceSelectedKeys=True))
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 setupCube(): cube = pm.polyCube()[0] pm.setKeyframe() for x in xrange(5): pm.currentTime(x) cube.tx.set(x) cube.ty.set(x) pm.setKeyframe() pm.selectKey(clear=True) pm.selectKey(cube.tx.connections()[0], add=1, k=1, t="1:3") pm.selectKey(cube.ty.connections()[0], add=1, k=1, t="1:3") return cube
def custom_bake(self, time_range): stepped_limit = 0.0001 # get objects to bake # baked_objects = list(self.original_selection) # copy the list # joints = pm.listRelatives(self.original_selection, allDescendents=True, type='joint') # baked_objects.extend(pm.listRelatives(self.original_selection, allDescendents=True, type='transform')) # pm.select(baked_objects, r=True) # obj_list = om.MGlobal.getActiveSelectionList() # iterator = om.MItSelectionList(obj_list, om.MFn.kDagNode) try: to_bake = pm.ls(self.original_selection, type='transform') to_bake += pm.listRelatives(self.original_selection, allDescendents=True, type='transform') # create a set, and add all joints to the set filtered = set(pm.ls(self.original_selection, type='joint')) filtered |= set( pm.listRelatives(self.original_selection, allDescendents=True, type='joint')) # union op. except: print "error 1" # add blendshapes and animated transforms to the set for node in to_bake: # blendshape? try: in_mesh = node.getShape() if in_mesh is not None: blendshape = in_mesh.attr('inMesh').inputs() if pm.nodeType(blendshape) == 'blendShape': filtered.add(in_mesh[0]) except Exception as e: pm.warning("Could not determine blendshape: %s" % e) # any inputs to transform attributes? i.e. any animation? for at in self.transform_attributes: if pm.hasAttr(node, at) and len(node.attr(at).inputs()) > 0: filtered.add(node) break to_bake = list(filtered) samples = 1 has_stepped = self.has_stepped_checkbox.isChecked() if has_stepped: samples = 0.5 # merge animation layers if necessary if len(pm.ls(type='animLayer')) > 1: pm.mel.eval('animLayerMerge( `ls -type animLayer` )') if len(to_bake) == 0: pm.select(self.original_selection, r=True) return # bake selected transforms and children with half step pm.bakeResults(to_bake, time=time_range, sampleBy=samples, hierarchy='none', disableImplicitControl=True, preserveOutsideKeys=False, sparseAnimCurveBake=False, simulation=True, minimizeRotation=False) # remove static channels to speed up analysis # to_bake.extend(joints) pm.select(to_bake, r=True) pm.delete(staticChannels=True) muted_curves = [] for obj in to_bake: for curve in pm.keyframe(obj, q=True, name=True): # find muted curves connection = pm.listConnections(curve, d=True, s=False)[0] if pm.nodeType(connection) == 'mute': if pm.getAttr('%s.mute' % connection): muted_curves.append(curve) continue # analyse half frames to determine which are stepped if has_stepped: for key in range(int(time_range[0]), int(time_range[1])): try: epsilon_half = abs( pm.keyframe(curve, q=True, valueChange=True, time=(key, ))[0] - pm.keyframe(curve, q=True, valueChange=True, time=(key + 0.5, ))[0]) epsilon_full = abs( pm.keyframe(curve, q=True, valueChange=True, time=(key, ))[0] - pm.keyframe(curve, q=True, valueChange=True, time=(key + 1))[0]) if epsilon_half < stepped_limit < epsilon_full: pm.keyTangent(curve, time=(key, ), ott='step') except IndexError: continue pm.delete(muted_curves) # remove unsnapped keys if has_stepped: pm.selectKey(to_bake, unsnappedKeys=True) pm.cutKey(animation='keys', clear=True) # apply euler filter if self.euler_filter_checkbox.isChecked(): self.apply_euler_filter(to_bake) pm.currentTime(time_range[0]) pm.setKeyframe(to_bake, attribute=self.transform_attributes, t=time_range[0], insertBlend=False) # re-select original selection, so that we export the right thing pm.select(self.original_selection, r=True)
def custom_bake(self, time_range): stepped_limit = 0.0001 # get objects to bake # baked_objects = list(self.original_selection) # copy the list # joints = pm.listRelatives(self.original_selection, allDescendents=True, type='joint') # baked_objects.extend(pm.listRelatives(self.original_selection, allDescendents=True, type='transform')) # pm.select(baked_objects, r=True) # obj_list = om.MGlobal.getActiveSelectionList() # iterator = om.MItSelectionList(obj_list, om.MFn.kDagNode) try: to_bake = pm.ls(self.original_selection, type='transform') to_bake += pm.listRelatives(self.original_selection, allDescendents=True, type='transform') # create a set, and add all joints to the set filtered = set(pm.ls(self.original_selection, type='joint')) filtered |= set( pm.listRelatives(self.original_selection, allDescendents=True, type='joint')) # union op. except Exception as e: sys.stdout.write("error 1: %s\n" % e) # add blendshapes and animated transforms to the set blendshapes = set() for node in to_bake: # blendshape? try: for shape in node.getShapes(): shape_inputs = shape.inputs() # shape_inputs.extend(shape.attr('inMesh').inputs()) # maybe not needed # this should perhaps be rewritten as a recursive function, # that keeps traversing down the hierarchy for shape_input in shape_inputs: if pm.nodeType(shape_input) == 'blendShape': blendshapes.add(shape_input) elif pm.nodeType(shape_input) in ('skinCluster', 'objectSet'): for inp in shape_input.inputs(): if pm.nodeType(inp) == 'blendShape': blendshapes.add(inp) except Exception as e: pm.warning("Could not determine blendshape: %s" % e) # any inputs to transform attributes? i.e. any animation? for at in self.transform_attributes: if pm.hasAttr(node, at) and len(node.attr(at).inputs()) > 0: filtered.add(node) break to_bake = list(filtered.union(blendshapes)) samples = 1 has_stepped = self.has_stepped_checkbox.isChecked() if has_stepped: samples = 0.5 maya.utils.processIdleEvents() qApp.processEvents() if len(to_bake) == 0: pm.select(self.original_selection, r=True) return # set key tangent to auto when baking itt = pm.keyTangent(q=True, g=True, itt=True) ott = pm.keyTangent(q=True, g=True, ott=True) pm.keyTangent(g=True, itt='auto', ott='auto') # bake selected transforms and children with half step pm.bakeResults(to_bake, time=time_range, sampleBy=samples, hierarchy='none', disableImplicitControl=True, preserveOutsideKeys=False, sparseAnimCurveBake=False, simulation=True, minimizeRotation=False, removeBakedAnimFromLayer=True) # set key tangent back to default pm.keyTangent(g=True, itt=itt, ott=ott) pm.flushUndo() # maya.utils.processIdleEvents() # qApp.processEvents() # remove static channels to speed up analysis # to_bake.extend(joints) try: pm.select(to_bake, r=True) pm.delete(staticChannels=True) except Exception as e: sys.stdout.write(str(e) + '\n') muted_curves = [] # progress bar try: gMainProgressBar = maya.mel.eval('$tmp = $gMainProgressBar') pm.progressBar(gMainProgressBar, e=True, beginProgress=True, isInterruptable=True, status='Working...', maxValue=len(to_bake)) except Exception as e: sys.stdout.write(str(e) + '\n') for obj in to_bake: for curve in pm.keyframe(obj, q=True, name=True): # find muted curves connection = pm.listConnections(curve, d=True, s=False)[0] if pm.nodeType(connection) == 'mute': if pm.getAttr('%s.mute' % connection): muted_curves.append(curve) continue # analyse half frames to determine which are stepped if has_stepped: for key in range(int(time_range[0]), int(time_range[1])): try: epsilon_half = abs( pm.keyframe(curve, q=True, valueChange=True, time=(key, ))[0] - pm.keyframe(curve, q=True, valueChange=True, time=(key + 0.5, ))[0]) epsilon_full = abs( pm.keyframe(curve, q=True, valueChange=True, time=(key, ))[0] - pm.keyframe(curve, q=True, valueChange=True, time=(key + 1))[0]) if epsilon_half < stepped_limit < epsilon_full: pm.keyTangent(curve, time=(key, ), ott='step') except IndexError: continue # update progress pm.progressBar(gMainProgressBar, e=True, step=1) if pm.progressBar(gMainProgressBar, q=True, isCancelled=True): break # end progressbar pm.progressBar(gMainProgressBar, e=True, endProgress=True) qApp.processEvents() pm.delete(muted_curves) # remove unsnapped keys if has_stepped: pm.selectKey(to_bake, unsnappedKeys=True) pm.cutKey(animation='keys', clear=True) # apply euler filter if self.euler_filter_checkbox.isChecked(): self.apply_euler_filter(to_bake) pm.currentTime(time_range[0]) # set a key on the first frame # todo: when doing stepped animation, all rotations needs to be either stepped or not, because of the way unity interpolates try: if has_stepped: tangent_type = 'step' else: tangent_type = 'auto' if to_bake: pm.setKeyframe(to_bake, attribute=self.transform_attributes, t=time_range[0], insertBlend=False, ott=tangent_type) if blendshapes: pm.setKeyframe(blendshapes, t=time_range[0], insertBlend=False, ott=tangent_type) except Exception as e: sys.stdout.write(str(e) + '\n') # re-select original selection, so that we export the right thing pm.select(self.original_selection, r=True) # select all child constraints if enabled if self.constraints_checkbox.isChecked(): constraints = pm.listRelatives(pm.ls(sl=True), allDescendents=True, type='constraint') pm.select(constraints, add=True)
def one_cam_to_shots(self): # make sure selected object is a camera sel = pm.selected() if len(sel) != 1: raise RuntimeError('Select just 1 camera.') the_cam = sel[0] if the_cam.getShape().type() != 'camera': message = 'Select just 1 Camera.\r\n' pm.confirmDialog(title='Error', message=message, button='OK') raise RuntimeError('Select just 1 camera.') # unlock locked attrs attributes_locked = [] for attr in pm.listAttr(the_cam, locked=1): attributes_locked.append(attr) for attr in pm.listAttr(the_cam.getShape(), locked=1): attributes_locked.append(attr) for attr in attributes_locked: the_cam.attr(attr).unlock() id = 0 for shot in self.shots_descending: s_frame = shot.getStartTime() e_frame = shot.getEndTime() # duplicate, clear parents and unparent shot cam from original pm.currentTime(s_frame) id += 1 shot_camera = pm.duplicate(the_cam, rr=1, name='camera__shotExp_%s' % str(id)) tr_parents = shot_camera[0].listRelatives(type='transform') for tr in tr_parents: pm.delete(tr) pm.parent(shot_camera, w=1) # connect animation curves from original to duplicated shot cam anim_curves = [] connections = the_cam.getShape().listConnections() for connection in connections: if 'animCurve' in str(connection.type()): attribute_name = str( connection.listConnections(p=1)[0].split('.')[-1:][0]) new_key = pm.duplicate(connection, rr=1) anim_curves.append(new_key[0]) pm.connectAttr( '%s.output' % new_key[0], '%s.%s' % (shot_camera[0].getShape(), attribute_name)) # parent constraint shot cam to original constraint = pm.parentConstraint(the_cam, shot_camera[0], mo=0, weight=1) # isolate none to speed things up panel_list = pm.getPanel(type='modelPanel') pm.select(None) for panel in panel_list: pm.isolateSelect(panel, state=1) # bake all keyable attrs between shot frame range pm.mel.eval( 'bakeResults -simulation true -t "%s:%s" -sampleBy 1 -disableImplicitControl true ' '-preserveOutsideKeys true -sparseAnimCurveBake false -removeBakedAttributeFromLayer false ' '-bakeOnOverrideLayer false -minimizeRotation true -controlPoints false -shape true %s;' % (int(s_frame), int(e_frame), shot_camera[0])) # restore isolation for panel in panel_list: pm.isolateSelect(panel, state=0) # set some forced attrs shot_camera[0].disconnectAttr('scaleX') shot_camera[0].setAttr('scaleX', 1) shot_camera[0].disconnectAttr('scaleY') shot_camera[0].setAttr('scaleY', 1) shot_camera[0].disconnectAttr('scaleZ') shot_camera[0].setAttr('scaleZ', 1) shot_camera[0].disconnectAttr('visibility') shot_camera[0].setAttr('visibility', 1) shot_camera[0].getShape().disconnectAttr('farClipPlane') shot_camera[0].getShape().setAttr('farClipPlane', 10000000) # make all camera anim curves linear for curve in shot_camera[0].listAttr(k=1): pm.selectKey(curve, add=1, k=1) pm.keyTangent(itt='linear', ott='linear') for curve in shot_camera[0].getShape().listAttr(k=1): pm.selectKey(curve, add=1, k=1) pm.keyTangent(itt='linear', ott='linear') # no need for constraint node pm.delete(constraint) # lock previously unlocked attrs again for attr in attributes_locked: the_cam.attr(attr).lock() # set shot camera pm.select(cl=1) shot.set_camera(shot_camera[0])
def makeTreads(*args): try: if ('world_object_up' ): # if locator exists from a previous attempt, delete it pm.delete('world_object_up') pm.spaceLocator(name='world_object_up') pm.addAttr(ln="Tread_Cycle", at='double', dv=0, hidden=False, k=True) pm.select(clear=True) pm.parentConstraint('treadCurve', 'world_object_up') except: pm.spaceLocator(name='world_object_up') # or else just create it pm.addAttr(ln="Tread_Cycle", at='double', dv=0, hidden=False, k=True) pm.select(clear=True) pm.parentConstraint('treadCurve', 'world_object_up') try: for j in treadJnts: # if motionPaths exist from a previous attempt, delete them if ('motionPath' + str(treadJnts.index(j) + 1)): pm.delete('motionPath' + str(treadJnts.index(j) + 1)) except: pass # get the Max Value of the curve, so the treads loop properly curveMaxValue = pm.getAttr('treadCurve.maxValue') print curveMaxValue # this loop will go through each joint in the treadJnts list for i in treadJnts: # for the first joint, which has index '0' if treadJnts.index(str(i)) == 0: # select the first joint and then the curve pm.select(clear=True) pm.select(i) pm.select('treadCurve', add=True) # constrain the first joint to the curve using motion path animation pm.pathAnimation(fractionMode=False, follow=True, followAxis='y', upAxis='z', worldUpType='object', worldUpObject='world_object_up', inverseUp=True, inverseFront=False, bank=False) # delete useless nodes we're not gonna need pm.delete('addDoubleLinear1', 'addDoubleLinear2', 'addDoubleLinear3', 'motionPath1_uValue') # connect motionPath allCoordinates node into the joint's translates pm.connectAttr('motionPath1.allCoordinates', str(i) + '.translate', force=True) # set driven keys for the anim curve driving the joints around the curve pm.setAttr('world_object_up.Tread_Cycle', 0) pm.setAttr('motionPath1.uValue', 0) pm.setDrivenKeyframe('motionPath1.uValue', currentDriver='world_object_up.Tread_Cycle') pm.setAttr('world_object_up.Tread_Cycle', curveMaxValue) pm.setAttr('motionPath1.uValue', curveMaxValue) pm.setDrivenKeyframe('motionPath1.uValue', currentDriver='world_object_up.Tread_Cycle') pm.selectKey('motionPath1.uValue') pm.keyTangent(itt='linear', ott='linear') # make them linear and cycle pm.setInfinity(pri='cycle', poi='cycle') pm.select(clear=True) pm.rename( 'motionPath1_uValue', 'setDrivenKeys_anim_1' ) # rename it to something with number at the end, easier to work with if it's duplicated # for the rest of the joints: else: # constrain the joint to the curve using motion path animation pm.select(clear=True) pm.select(i) pm.select('treadCurve', add=True) pm.pathAnimation(fractionMode=False, follow=True, followAxis='y', upAxis='z', worldUpType='object', worldUpObject='world_object_up', inverseUp=True, inverseFront=False, bank=False) pm.select(clear=True) # delete useless nodes we're not gonna need pm.delete('addDoubleLinear1', 'addDoubleLinear2', 'addDoubleLinear3', 'motionPath' + str(treadJnts.index(i) + 1) + '_uValue') # connect motionPath allCoordinates node into joint's translates pm.connectAttr('motionPath' + str(treadJnts.index(i) + 1) + '.allCoordinates', str(i) + '.translate', force=True) pm.select(clear=True) # duplicate the previous set driven keys anim curve pm.select('setDrivenKeys_anim_' + str(treadJnts.index(i))) pm.duplicate() pm.select(clear=True) # connect the new duplicated setDrivenKeys anim's output into the joint's motionPath's uValue pm.connectAttr('setDrivenKeys_anim_' + str(treadJnts.index(i) + 1) + '.output', 'motionPath' + str(treadJnts.index(i) + 1) + '.uValue', force=True) # connect the animation curve to the Tread Cycle attribute pm.connectAttr('world_object_up.Tread_Cycle', 'setDrivenKeys_anim_' + str(treadJnts.index(i) + 1) + '.input', force=True) # shift the animation curve to the side so the treads won't be on top of each other and move accordingly pm.select('setDrivenKeys_anim_' + str(treadJnts.index(i) + 1)) pm.selectKey() num = spaceInput.getValue1() # get the spacing the user wants pm.keyframe(option='over', relative=True, floatChange=(num)) pm.select(clear=True)
animCurveTL = pm.listConnections(t="animCurveTL") animCurveTA = pm.listConnections(t="animCurveTA") animCurveTU = pm.listConnections(t="animCurveTU") for crv in animCurveTL: allAnimCurves.append(crv) for crv in animCurveTA: allAnimCurves.append(crv) for crv in animCurveTU: allAnimCurves.append(crv) for crv in allAnimCurves: print crv pm.selectKey(crv) pm.keyframe(animation="keys", option="over", relative=1, timeChange=(0 + 288)) ############# # reset speakers timing ############# import pymel.core as pm ctrl = pm.ls("SPEAKERANIMATION") pm.select(ctrl[0], r=1) allAnimCurves = []
def one_cam_to_shots(self): # make sure selected object is a camera sel = pm.selected() if len(sel) != 1: raise RuntimeError('Select just 1 camera.') the_cam = sel[0] if the_cam.getShape().type() != 'camera': message = 'Select just 1 Camera.\r\n' pm.confirmDialog(title='Error', message=message, button='OK') raise RuntimeError('Select just 1 camera.') # unlock locked attrs attributes_locked = [] for attr in pm.listAttr(the_cam, locked=1): attributes_locked.append(attr) for attr in pm.listAttr(the_cam.getShape(), locked=1): attributes_locked.append(attr) for attr in attributes_locked: the_cam.attr(attr).unlock() id = 0 for shot in self.shots_descending: s_frame = shot.getStartTime() e_frame = shot.getEndTime() # duplicate, clear parents and unparent shot cam from original pm.currentTime(s_frame) id += 1 shot_camera = pm.duplicate(the_cam, rr=1, name='camera__shotExp_%s' % str(id)) tr_parents = shot_camera[0].listRelatives(type='transform') for tr in tr_parents: pm.delete(tr) pm.parent(shot_camera, w=1) # connect animation curves from original to duplicated shot cam anim_curves = [] connections = the_cam.getShape().listConnections() for connection in connections: if 'animCurve' in str(connection.type()): attribute_name = str(connection.listConnections(p=1)[0].split('.')[-1:][0]) new_key = pm.duplicate(connection, rr=1) anim_curves.append(new_key[0]) pm.connectAttr('%s.output' % new_key[0], '%s.%s' % (shot_camera[0].getShape(), attribute_name)) # parent constraint shot cam to original constraint = pm.parentConstraint(the_cam, shot_camera[0], mo=0, weight=1) # isolate none to speed things up panel_list = pm.getPanel(type='modelPanel') pm.select(None) for panel in panel_list: pm.isolateSelect(panel, state=1) # bake all keyable attrs between shot frame range pm.mel.eval('bakeResults -simulation true -t "%s:%s" -sampleBy 1 -disableImplicitControl true ' '-preserveOutsideKeys true -sparseAnimCurveBake false -removeBakedAttributeFromLayer false ' '-bakeOnOverrideLayer false -minimizeRotation true -controlPoints false -shape true %s;' % (int(s_frame), int(e_frame), shot_camera[0])) # restore isolation for panel in panel_list: pm.isolateSelect(panel, state=0) # set some forced attrs shot_camera[0].disconnectAttr('scaleX') shot_camera[0].setAttr('scaleX', 1) shot_camera[0].disconnectAttr('scaleY') shot_camera[0].setAttr('scaleY', 1) shot_camera[0].disconnectAttr('scaleZ') shot_camera[0].setAttr('scaleZ', 1) shot_camera[0].disconnectAttr('visibility') shot_camera[0].setAttr('visibility', 1) shot_camera[0].getShape().disconnectAttr('farClipPlane') shot_camera[0].getShape().setAttr('farClipPlane', 10000000) # make all camera anim curves linear for curve in shot_camera[0].listAttr(k=1): pm.selectKey(curve, add=1, k=1) pm.keyTangent(itt='linear', ott='linear') for curve in shot_camera[0].getShape().listAttr(k=1): pm.selectKey(curve, add=1, k=1) pm.keyTangent(itt='linear', ott='linear') # no need for constraint node pm.delete(constraint) # lock previously unlocked attrs again for attr in attributes_locked: the_cam.attr(attr).lock() # set shot camera pm.select(cl=1) shot.set_camera(shot_camera[0])