def dataToCurve(allData, plug): if isinstance(allData, dict): data = allData['keys'] else: data = allData allData = None cutKey(plug, t=(data[0]['time'], data[-1]['time']), cl=True, iub=True) for key in data: setKeyframe(plug, f=key['time'], t=key['time'], v=key['val']) for key in data: keyTangent(plug, f=(key['time'], ), t=key['time'], ia=key['inAngle'], oa=key['outAngle'], iw=key['inWeight'], ow=key['outWeight'], itt=key['inType'], ott=key['outType']) if allData: node = plug.listConnections(s=True)[0] node.preInfinity.set(allData['preInfinity']) node.postInfinity.set(allData['postInfinity'])
def create_key_at_time(frame): """ Create a key at the given time. If a key already exists, return its index. """ keys = get_singleton() # Find the name index for frame, if it already exists. idx = _get_key_index_at_frame(frame) if idx is not None: return idx # There's no key at the current frame. Find an unused name index and create it. # We have to set the value, then set the keyframe. If we just call setKeyframe, # the value won't be set correctly if it's in a character set. # # Disable auto-keyframe while we do this. Otherwise, a keyframe will also # be added at the current frame (which seems like a bug). with maya_helpers.disable_auto_keyframe(): idx = _get_unused_name_index() keys.attr('keyframes').set(idx) pm.setKeyframe(keys, at='keyframes', time=frame, value=idx) # setKeyframe can do this, but it's buggy: outTangentType='step' isn't applied if # we add a key before any other existing keys. pm.keyTangent(keys, time=frame, inTangentType='stepnext', outTangentType='step') # Keyframes can be deleted by the user, which leaves behind stale entries. Remove # any leftover data in the slot we're using. pm.removeMultiInstance(keys.attr('entries').elementByLogicalIndex(idx)) return idx
def keyFlash(obj=None, channel=None, fade=18): if obj == None: obj = pm.ls(sl=1)[0] if channel == None: channel = 'translateX' current = pm.currentTime(q=1) kf = [current - 1, current, current + 1, current + fade] value = pm.getAttr('%s.%s' % (obj, channel)) #see if already keys if pm.listConnections('%s.%s' % (obj, channel)) is not []: pm.cutKey(obj, at=channel, time=(kf[0], kf[-1])) pm.setKeyframe(obj, at=channel, v=0, t=[kf[0]], ott='stepnext') pm.setKeyframe(obj, at=channel, v=value, t=[kf[1]], ott='stepnext') pm.setKeyframe(obj, at=channel, v=value * 0.75, t=[kf[2]], ott='auto') pm.setKeyframe(obj, at=channel, v=0, t=[kf[3]], ott='auto') pm.keyTangent(obj, at=channel, a=1, outWeight=1, e=1, t=[kf[2]], outAngle=-10.253096)
def gather_tangent_informations(self, nodes, channels, startFrame, endFrame): # type: (List[pm.nodetypes.Transform], List[str], int, int) -> List[Dict[str, List[str]]] """Returns tangent informations, containing ' '.""" res = [] for node in nodes: tangents = {} for attr in channels: opts = { "query": True, "attribute": attr } in_tangents = [] out_tangents = [] for i in range(startFrame, endFrame): opts.update({"time": (i, )}) in_tangents.append(pm.keyTangent(node, inTangentType=True, **opts)) out_tangents.append(pm.keyTangent(node, outTangentType=True, **opts)) tangents[attr] = [in_tangents, out_tangents] res.append(tangents) return res
def bounceOnce(ball, firstFrame, height, squash, decay): # this function defines the keys for a 24 frame bouncing ball of any size # top of bounce: pm.currentTime(firstFrame) ball.scaleX.set(1) ball.scaleY.set(1) ball.scaleZ.set(1) ball.translateY.set(height) pm.setKeyframe(ball) pm.keyTangent(ball.translateY, time=firstFrame, itt='auto', ott='auto', lock=False) # bottom of bounce # contact key pm.currentTime(firstFrame + 11) ball.scaleX.set(1) ball.scaleY.set(1 + (1 - squash)) ball.scaleZ.set(1) ball.translateY.set(0) pm.setKeyframe(ball) pm.keyTangent(ball.translateY, time=firstFrame + 11, itt='linear', ott='linear', lock=False) pm.keyTangent(ball.scaleY, time=firstFrame + 11, itt='linear', ott='step', lock=False) # create a squash key pm.currentTime(firstFrame + 12) ball.scaleX.set(1) ball.scaleY.set(squash) ball.scaleZ.set(1) ball.translateY.set(0) pm.setKeyframe(ball) pm.keyTangent(ball.translateY, time=firstFrame + 12, itt='linear', ott='linear', lock=False) pm.currentTime(firstFrame + 24) ball.scaleX.set(1) ball.scaleY.set(1) ball.scaleZ.set(1) ball.translateY.set(height) pm.setKeyframe(ball) pm.keyTangent(ball.translateY, time=firstFrame + 24, itt='auto', ott='auto', lock=False) return
def restore_tangent_information(self, nodes, infos, startFrame, endFrame): # type: (List[pm.nodetypes.Transform], List[Dict[str, List[str]]], int, int) -> None for node, info in zip(nodes, infos): for attr, tangents in info.iteritems(): in_val = tangents[0] out_val = tangents[1] for i in range(len(in_val)): opts = { "edit": True, "attribute": attr, # "index": (i, ) } for i in range(startFrame, endFrame): try: if not in_val[i]: continue except: continue opts.update({"time": (i, )}) pm.keyTangent(node, inTangentType=in_val[i][0], **opts) pm.keyTangent(node, outTangentType=out_val[i][0], **opts)
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 deserialise(self, data): # -- Start by creating the node node = pm.createNode(data['node_type']) pm.PyNode(data['driver']).connect(node.attr('input'), force=True) node.attr('output').connect(data['driven'], force=True) # -- Set the curve data node.preInfinity.set(data['pre_infinity_type']) node.postInfinity.set(data['post_infinity_type']) # -- Now build the curve for key_data in data['key_data']: pm.setDrivenKeyframe( data['driven'], currentDriver=data['driver'], driverValue=key_data['time'], value=key_data['value'], ) # -- Get the key index key_idx = node.numKeys() - 1 # -- Set the key properties node.setInTangentType(key_idx, key_data['in_tangent_type']) node.setOutTangentType(key_idx, key_data['out_tangent_type']) pm.keyTangent( index=[key_idx, key_idx], ix=key_data['in_tangent'][0], iy=key_data['in_tangent'][1], ox=key_data['out_tangent'][0], oy=key_data['out_tangent'][1], )
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 serialise(self, node=None): # -- If we're not given a specific node, then look at the selection try: node = node or pm.selected()[0] except: print('No set driven key provided.') return False # -- Check our node is valid if 'animCurveU' not in node.nodeType(): print('%s is not of type AnimCurveU*' % node) return False driver = self.resolve_input(node.attr('input')).name() driven = self.resolve_output(node.attr('output')).name() curve_data = dict( driver=driver, driven=driven, node_type=node.nodeType(), post_infinity_type=node.getPostInfinityType().index, pre_infinity_type=node.getPreInfinityType().index, key_data=list(), ) in_tangents_x = pm.keyTangent(node, q=True, ix=True) in_tangents_y = pm.keyTangent(node, q=True, iy=True) out_tangents_x = pm.keyTangent(node, q=True, ox=True) out_tangents_y = pm.keyTangent(node, q=True, oy=True) for key_idx in range(node.numKeys()): time = node.getUnitlessInput(key_idx) key_data = dict( time=time, value=node.getValue(key_idx), in_tangent_type=node.getInTangentType(key_idx).index, out_tangent_type=node.getOutTangentType(key_idx).index, locked_tangent=node.getTangentsLocked(key_idx), locked_weights=node.getWeightsLocked(key_idx), is_breakdown=node.isBreakdown(key_idx), in_tangent=[in_tangents_x[key_idx], in_tangents_y[key_idx]], out_tangent=[out_tangents_x[key_idx], out_tangents_y[key_idx]], ) curve_data['key_data'].append(key_data) self.options.curve_data = str(curve_data) self.save() return curve_data
def set_to_time_editor(): keying_target = pm.timeEditorPanel('timeEditorPanel1TimeEd', q=True, keyingTarget=True) if not keying_target: return False # The time editor has weird native hooks for applying keyframes, which calls # teSetKeyFrameOnActiveLayerOrClip in teKeyingFunctions.mel. It's very broken: # it looks at the channel box to see what to key, which causes it to key the wrong # attributes. We can't just set what's shown in the channel box: that requires # changing the selection (which will screw with the graph editor), and we can't change # the selection and the channel box at the same time since the CB update is async. # # Instead, bypass all of that and set the key on the time editor layer directly. # # This means we can't control tangents on time editor clips, which sucks. keying_target = pm.ls(keying_target)[0] clip_id = keying_target.node().attr('clip[0].clipid').get() layer_id = keying_target.attr('layerId').get() is_layer = isinstance(keying_target.node(), pm.nodetypes.TimeEditorClip ) and keying_target.attr('layerName').get() != '' if not is_layer: return False # timeEditorClipLayer doesn't take tangentType arguments like pm.setKeyframe, so we have # to work around this the long way by temporarily changing the default. old_in_tangent_type = pm.keyTangent(q=True, g=True, inTangentType=True)[0] old_out_tangent_type = pm.keyTangent(q=True, g=True, outTangentType=True)[0] if inTangentType is not None: pm.keyTangent(g=True, inTangentType=inTangentType) if outTangentType is not None: pm.keyTangent(g=True, outTangentType=outTangentType) try: # Set the key. pm.timeEditorClipLayer(e=True, clipId=clip_id, layerId=layer_id, setKeyframe=True, attribute=attr) finally: # Restore the tangent type. pm.keyTangent(g=True, inTangentType=old_in_tangent_type) pm.keyTangent(g=True, outTangentType=old_out_tangent_type) return True
def getSDKInfo(animNode): """get all the information from an sdk/animCurve in a dictioanry for exporting. Args: animNode (pynode): name of node, pynode Returns: dict: dictionary of all the attrs to be exported """ sdkInfo_dict = {} sdkKey_Info = [] numberOfKeys = len(pm.listAttr("{0}.ktv".format(animNode), multi=True)) / 3 itt_list = pm.keyTangent(animNode, itt=True, q=True) ott_list = pm.keyTangent(animNode, ott=True, q=True) # maya doesnt return value if there is only one key frame set. if itt_list == None: itt_list = ["linear"] if ott_list == None: ott_list = ["linear"] for index in range(0, numberOfKeys): value = pm.getAttr("{0}.keyTimeValue[{1}]".format(animNode, index)) absoluteValue = pm.keyframe(animNode, q=True, valueChange=True, index=index)[0] keyData = [value[0], absoluteValue, itt_list[index], ott_list[index]] sdkKey_Info.append(keyData) sdkInfo_dict["keys"] = sdkKey_Info sdkInfo_dict["type"] = animNode.type() sdkInfo_dict["preInfinity"] = animNode.getAttr("preInfinity") sdkInfo_dict["postInfinity"] = animNode.getAttr("postInfinity") sdkInfo_dict["weightedTangents"] = animNode.getAttr("weightedTangents") animNodeInputPlug = "{0}.input".format(animNode.nodeName()) sourceDriverAttr = pm.listConnections(animNodeInputPlug, source=True, plugs=True, scn=True)[0] driverNode, driverAttr = sourceDriverAttr.split(".") sdkInfo_dict["driverNode"] = driverNode sdkInfo_dict["driverAttr"] = driverAttr animNodeOutputPlug = "{0}.output".format(animNode.nodeName()) drivenNode, drivenAttr = getSDKDestination(animNodeOutputPlug) sdkInfo_dict["drivenNode"] = drivenNode sdkInfo_dict["drivenAttr"] = drivenAttr return sdkInfo_dict
def createCurveControl(controlObj, controlAttribute, destinationAttribute): ''' Script: js_createCurveControl.mel Author: Jason Schleifer Descr: This script will create a single curve which can be used to control the given attribute on the selected objects. For example, if you want to drive the ty attribute on 10 objects with a "height" curve on another object, you would select the 10 objects, and then enter: js_createControlCurve controlObj height ty Note: make sure the given object and attribute exists ''' if not pm.objExists(controlObj): pm.pm.mel.error(controlObj + " does not exist. Exiting..\n") if not pm.attributeQuery(controlAttribute, node=controlObj, exists=1): pm.addAttr(controlObj, ln=controlAttribute, at='double') pm.setAttr((controlObj + "." + controlAttribute), k=1) # find the selected objects objs = pm.ls(sl=1) if len(objs) == 0: pm.pm.mel.error("Nothing Selected.\n") numControls = len(objs) # now that we have the objects, we can create the animation curve which will control the attribute objAttr = (controlObj + "." + controlAttribute) pm.setKeyframe(controlObj, v=0, at=controlAttribute, t=1) pm.setKeyframe(controlObj, v=0, at=controlAttribute, t=numControls) pm.keyTangent(controlObj, wt=1, at=controlAttribute) pm.keyTangent(controlObj, at=controlAttribute, weightLock=False) pm.keyTangent(objAttr, a=1, e=1, t=1, outAngle=50) pm.keyTangent(objAttr, a=1, e=1, t=numControls, inAngle=-50) # next, we'll create frameCache nodes for each object, and attach them to the object's attribute for x in range(0, numControls): fc = pm.createNode('frameCache') # create the frameCache node fc = pm.rename(fc, (str(objs[x]) + "_frameCache")) # connect the attribute pm.connectAttr(objAttr, (str(fc) + ".stream")) # set the frame pm.setAttr((str(fc) + ".vt"), (x + 1)) # connect the output # check and see if the destination attribute exists. if not, create it if not pm.attributeQuery(destinationAttribute, node=objs[x], exists=1): pm.addAttr(objs[x], ln=destinationAttribute, at='double') pm.setAttr((str(objs[x]) + "." + destinationAttribute), k=1) pm.connectAttr((str(fc) + ".v"), (str(objs[x]) + "." + destinationAttribute), f=1) pm.select(objAttr)
def curveToData(animCurve): keys = keyframe(animCurve, q=True, tc=True, fc=True, vc=True) # fc and tc are mutually ex tangents = keyTangent(animCurve, q=True, ia=True, oa=True, iw=True, ow=True, itt=True, ott=True) chunk = 6 # keyTanget returns a giant flat list keyData = [] for i, key in enumerate(keys): keyData.append( KeyData(key[0], key[1], *tangents[i * chunk:(i + 1) * chunk]).toDict()) return { 'keys': keyData, 'preInfinity': animCurve.preInfinity.get(), 'postInfinity': animCurve.postInfinity.get() }
def snapRoot(): # let's make a loop that goes through the key times and fixes the root! for t in animRange: pm.select(clear=True) pm.currentTime( t ) # set current time to the value of the current index in the list pm.select(root) pm.select(locator, add=True) pm.align(atl=True, x='Mid', y='Mid') # align root to locator on the ground plane pm.select(clear=True) pm.select(root) pm.setKeyframe(root) pm.keyTangent(root, time=t, itt='linear', ott='linear', lock=False) return
def createSDKFromDict(sdkInfo_dict): """Create a sdk node from the provided info dict Args: sdkInfo_dict (dict): dict of node information to create Returns: PyNode: created sdk node """ sdkName = "{0}_{1}".format(sdkInfo_dict["drivenNode"], sdkInfo_dict["drivenAttr"]) sdkNode = pm.createNode(sdkInfo_dict["type"], name=sdkName, ss=True) pm.connectAttr("{0}.{1}".format(sdkInfo_dict["driverNode"], sdkInfo_dict["driverAttr"]), "{0}.input".format(sdkNode), f=True) drivenAttrPlug = "{0}.{1}".format(sdkInfo_dict["drivenNode"], sdkInfo_dict["drivenAttr"]) if pm.listConnections(drivenAttrPlug): targetAttrPlug = getBlendNodes(drivenAttrPlug) else: targetAttrPlug = drivenAttrPlug pm.connectAttr(sdkNode.output, targetAttrPlug, f=True) animKeys = sdkInfo_dict["keys"] for index in range(0, len(animKeys)): frameValue = animKeys[index] pm.setKeyframe(sdkNode, float=frameValue[0], value=frameValue[1], itt=frameValue[2], ott=frameValue[3]) sdkNode.setAttr("preInfinity", sdkInfo_dict["preInfinity"]) sdkNode.setAttr("postInfinity", sdkInfo_dict["postInfinity"]) pm.keyTangent(sdkNode) sdkNode.setWeighted(sdkInfo_dict["weightedTangents"]) return sdkNode
def create(self): current_type = pm.keyTangent('%s' % (self.node), query=True, index=(self.index, self.index), outTangentType=True)[0] self.text_field = pm.textField( text='%s' % (current_type), changeCommand=pm.Callback(self.change_type), editable=True, annotation="Use spline, clamped, linear, flat, step, stepnext,\ plateau, fixed or auto.")
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 set_position(self,key_frame, location, rotation, scale, visibility): if location is not None: pm.setKeyframe(self.object_name, attribute='tx', value=location[0], time=key_frame) pm.setKeyframe(self.object_name, attribute='ty', value=location[1], time=key_frame) pm.setKeyframe(self.object_name, attribute='tz', value=location[2], time=key_frame) if rotation is not None: pm.setKeyframe(self.object_name, attribute='rx', value=rotation[0], time=key_frame) pm.setKeyframe(self.object_name, attribute='ry', value=rotation[1], time=key_frame) pm.setKeyframe(self.object_name, attribute='rz', value=rotation[2], time=key_frame) if scale is not None: pm.setKeyframe(self.object_name, attribute='sx', value=scale[0], time=key_frame) pm.setKeyframe(self.object_name, attribute='sy', value=scale[1], time=key_frame) pm.setKeyframe(self.object_name, attribute='sz', value=scale[2], time=key_frame) if visibility is not None: ''' keyTangent -itt auto -ott auto; ''' pm.setKeyframe(self.object_name, attribute='v', value=visibility, time=key_frame) pm.keyTangent('{}.v'.format(self.object_name), edit=True, itt='auto', ott='auto') pm.cutKey(self.object_name.getShape(), attribute='v', clear=True) pm.setAttr('{}.v'.format(self.object_name.getShape()), True) objectShape = None
def keyFastinSlowout(obj=None, channel=None, span=18): if obj == None: obj = pm.ls(sl=1)[0] if channel == None: channel = 'translateX' current = pm.currentTime(q=1) kf = [current, current + span] value = pm.getAttr('%s.%s' % (obj, channel)) #see if already keys if pm.listConnections('%s.%s' % (obj, channel)) is not []: pm.cutKey(obj, at=channel, time=(kf[0], kf[-1])) pm.setKeyframe(obj, at=channel, v=value, t=[kf[0]], ott='linear') pm.setKeyframe(obj, at=channel, v=value + 12, t=[kf[1]], ott='auto') pm.keyTangent(obj, at=channel, a=1, outWeight=1, e=1, t=[kf[0]], outAngle=57.815214)
def change_tangents(tangent): """Function to change the default tangent based @param tangent (string) the type of default in and out tangent """ pm.keyTangent(g=True, ott=tangent) if tangent == "step": pm.keyTangent(itt="clamped", g=True) else: pm.keyTangent(g=True, itt=tangent) logger.info("Current Tangents: %s" % tangent.capitalize())
def get_useless_anim_crvs(anim_curves=None): if not anim_curves: anim_curves = pm.ls(type="animCurve") useless_anim_crvs = list() for anim_curve in anim_curves: anim_curve = pm.PyNode(anim_curve) # 删除只有一个关键点的动画曲线 if anim_curve.numKeys() <= 1: useless_anim_crvs.append(anim_curve) continue # 删除完全水平的动画曲线 # -判断值是否有变化 value_set = set([anim_curve.getValue(i) for i in xrange(anim_curve.numKeys())]) is_same_value = len(value_set) == 1 # -判断手柄是否水平 is_horizontal = sum(pm.keyTangent(anim_curve, q=True, ia=True, oa=True)) == 0 if is_same_value and is_horizontal: useless_anim_crvs.append(anim_curve) return useless_anim_crvs
def copyTangents(): """nevermind, this is useless. just copy and paste the key in the graph editor and paste while at desired frame""" attrs = pmc.animCurveEditor("graphEditor1GraphEd", q=True, curvesShown=True) for attr in attrs: frames = pmc.keyframe(attrs, q=True, sl=True) if len(frames) != 2: pmc.error("Select a source key and a destination key") # must do angles BEFORE weights or there's weird behavior ia, oa = pmc.keyTangent(attr, q=True, t=frames[0], ia=True, oa=True) pmc.keyTangent(attr, e=True, t=frames[1], ia=ia, oa=oa) iw, ow = pmc.keyTangent(attr, q=True, t=frames[0], iw=True, ow=True) pmc.keyTangent(attr, e=True, t=frames[1], iw=iw, ow=ow)
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 amcveRebuild(cvNew, cvSrcProfile): """ """ cvTrimmed = cvSrcProfile['cvTrimmed'] cvBaseMod = cvSrcProfile['cvBaseMod'] cvPortray = cvSrcProfile['cvPortray'] cvFeature = cvSrcProfile['cvFeature'] ''' A. create animCurve ''' # create same type of animation curve cvNew = pm.createNode(cvBaseMod['cvTyp'], n= cvNew) ''' B. build curve base ''' # whatever this animationCurve is time-base or float-base, # one of lists will be empty, just add them up. cvInp = cvPortray['Frame'] + cvPortray['Float'] # set value to each keyframe for i, x in enumerate(cvInp): if cvTrimmed and (x < cvTrimmed[0] or x > cvTrimmed[1]): continue # whatever this animationCurve is time-base or float-base, # just set both, the one incorrect will take no effect. y = cvPortray['Value'][i] isBD = True if x in cvBaseMod['breaD'] else False pm.setKeyframe(cvNew, t= x, f= x, v= y, bd= isBD) ''' C. inject curve feature ''' cvNew.setPreInfinityType(cvBaseMod['prInf']) cvNew.setPostInfinityType(cvBaseMod['poInf']) weedT = cvBaseMod['weedT'][0] pm.keyTangent(cvNew, wt= weedT) if weedT: for i, x in enumerate(cvInp): if cvTrimmed and (x < cvTrimmed[0] or x > cvTrimmed[1]): continue WLock = cvFeature['WLock'][i] pm.keyTangent(cvNew, index= [i], wl= WLock) for i, x in enumerate(cvInp): if cvTrimmed and (x < cvTrimmed[0] or x > cvTrimmed[1]): continue pm.keyTangent(cvNew, index= [i], l= cvFeature['TLock'][i]) pm.keyTangent(cvNew, index= [i], iw= cvFeature['InWet'][i]) pm.keyTangent(cvNew, index= [i], ow= cvFeature['OuWet'][i]) pm.keyTangent(cvNew, index= [i], ia= cvFeature['InAng'][i]) pm.keyTangent(cvNew, index= [i], oa= cvFeature['OuAng'][i]) pm.keyTangent(cvNew, index= [i], itt= cvFeature['InTyp'][i]) pm.keyTangent(cvNew, index= [i], ott= cvFeature['OuTyp'][i]) return cvNew
def importAnim( self, nameSpace=None, replaceString=None, *args ): successState = True # *.anim file filePath = pm.fileDialog2( caption='Read Animation', fileMode=1, startingDirectory=uad , fileFilter="Anim Files (*.anim)" ) if not filePath: pm.warning( 'Read animation cancelled.' ) return None # read anim info from file filePath = filePath[0] logfile = open( filePath , 'r' ) fileContent = logfile.read() # dictionary containing dictionaries of every object's animations logfile.close() # we can replace some parts of file to use animations on other objects. # for example, replace 'L' with 'R' copy animation from left side to right side. #replaceString = ('L','R') if replaceString: fileContent = fileContent.replace( replaceString[0], replaceString[1] ) # convert file content to a animInfos dictionary animInfos = eval( fileContent ) objs = animInfos.keys() try: nameSpaceRaw = pm.ls( sl=True )[0].name().split(':') if len(nameSpaceRaw) > 1: nameSpace = nameSpaceRaw[0] except: nameSpace = None for obj in objs: if nameSpace: try: objNode = pm.PyNode( nameSpace + ':' + obj ) except: successState = False pm.warning( 'Could not find object to import anim to, skipped.') continue else: try: objNode = pm.PyNode( obj ) except: successState = False pm.warning( 'Could not find object to import anim to, skipped.' ) continue # print objNode # print '__________________________________________________________' attrs = animInfos[ obj ].keys() # print attrs for attr in attrs: #print attr #print '=============================' animCurveInfos = animInfos[ obj ][ attr ] #print animCurveInfos for animCurveAttribute in animCurveInfos: animCurveValues = animInfos[ obj ][ attr ][ animCurveAttribute ] #print animCurveAttribute # anim curve attrs such as times, values, outWeights, inWeights, inAngles, outAngles #print animCurveValues # anim curve values for times, values, outWeights, inWeights, inAngles, outAngles #print '--------------' times = animCurveInfos[ 'times' ] values = animCurveInfos[ 'values' ] outWeights = animCurveInfos[ 'outWeights' ] outAngles = animCurveInfos[ 'outAngles' ] inWeights = animCurveInfos[ 'inWeights' ] inAngles = animCurveInfos[ 'inAngles' ] for i in range( len( animCurveInfos[ 'times' ] ) ): if nameSpace: if pm.objExists( nameSpace + ':' + attr ): attrNode = pm.PyNode( nameSpace + ':' + attr ) elif pm.objExists( attr ): attrNode = pm.PyNode( attr ) else: successState = False pm.warning( 'attrtibute was not found on target to apply animation, skipped.' ) continue else: if pm.objExists( attr ): attrNode = pm.PyNode( attr ) else: successState = False pm.warning( 'attrtibute was not found on target to apply animation, skipped.' ) continue pm.setKeyframe( attrNode, time= times[i] , value= values[i] ) pm.keyTangent( attrNode, e=True, index=(i,i), outWeight=outWeights[i], outAngle=outAngles[i], inWeight=inWeights[i], inAngle=inAngles[i] ) if successState: sys.stdout.write( 'Animation was successfully imported.' ) else: pm.warning( 'Animation was imported. Not all objects or their attributes were the same. So, animation was not applied to them.' )
def create(self): # this creates the field current_type = pm.keyTangent( '%s' % (self.node) , query=True, index= (self.index, self.index), outTangentType= True )[0] self.text_field = pm.textField(text= '%s' % (current_type), changeCommand= pm.Callback(self.change_type), editable= True, annotation= "Use spline, clamped, linear, flat, step, step, next, plateau, fixed or auto.")
def sharpen_out_tangent(): """sharpen in tangent (set tangent weight to .01)""" pm.keyTangent(edit=True, weightLock=False, lock=False, outWeight=.01)
def make_flat_tangents(): """sets selected keys tangents to flat""" pm.keyTangent(edit=True, itt='flat', ott='flat')
def change_type(self): pm.keyTangent('%s' % (self.node), index= (self.index, self.index), inTangentType= '%s' % (self.text_field.getText())) print 'in_tangent', self.node, self.text_field.getText()
import pymel.core as pm baseShape = pm.PyNode('bs_baseShape') blend50 = pm.PyNode('bs_baseShape_a_50') blend100 = pm.PyNode('bs_baseShape_a') #create 50offset shape dup = pm.duplicate(baseShape, name='temp_50offset')[0] pm.delete([x for x in dup.listRelatives() if x.name() != dup.getShape()]) bs = pm.blendShape(blend50, blend100, dup) pm.blendShape( bs, edit=True, w=[(0, 1), (1, -0.5)] ) blend50offset = pm.duplicate(dup, name = 'bs_baseShape_a_50offset')[0] pm.delete(dup) bs = pm.blendShape(blend100, blend50offset, baseShape)[0] dvr_attr = "%s.%s" %(bs.name(), blend100.name()) dvn_attr = "%s.%s" %(bs.name(), blend50offset.name()) pm.setDrivenKeyframe(dvn_attr, v=0.0, cd=dvr_attr, dv=0.0, itt='spline', ott='spline') pm.setDrivenKeyframe(dvn_attr, v=1.0, cd=dvr_attr, dv=0.5, itt='flat', ott='flat') pm.setDrivenKeyframe(dvn_attr, v=0.0, cd=dvr_attr, dv=1.0, itt='spline', ott='spline') pm.keyTangent('%s_%s'%(bs.name(), blend50offset), e=True, ow=1, index=[2], inAngle=-10) pm.keyTangent('%s_%s'%(bs.name(), blend50offset), e=True, ow=1, index=[0], outAngle=10)
def BOUNCE(RevealClass, start_frame, end_frame, start_location, start_rotation, start_scale, absolute_location=True, absolute_rotation=True, absolute_scale=True, distance_bounce=0, extra_keyframes=None, start_visibility=None): object_name = RevealClass.object_name if start_location is None: start_location = object_name.getTranslation() elif not absolute_location: start_location = tuple(i - j for i, j in zip(RevealClass.end_location, start_location)) if start_rotation is None: start_rotation = object_name.getRotation() elif not absolute_rotation: start_rotation = tuple(i - j for i, j in zip(RevealClass.end_rotation, start_rotation)) rotation_total = tuple(i - j for i, j in zip(RevealClass.end_rotation, start_rotation)) if start_scale is None: start_scale = object_name.getScale() elif not absolute_scale: start_scale = tuple(i * j for i, j in zip(start_scale, RevealClass.end_scale)) if start_visibility is None: start_visibility = pm.getAttr('{}.v'.format(object_name)) distance_total = find_distance(*(i - j for i, j in zip(RevealClass.end_location, start_location))) if distance_bounce: distance_ratio = distance_total / (distance_total + distance_bounce) frame_total = end_frame - start_frame #Calculate the bounce ratio with a weighting of 2:1 (distance of 1 and bounce of 1 will result in 0.666:0.333) bounce_ratio = distance_ratio / (distance_ratio + 1) * 2 frame_bounce = start_frame + frame_total * bounce_ratio #Calculate the bounce location bounce_ratio = (distance_bounce / distance_total) end_bounce = tuple(i + (i - j) * bounce_ratio for i, j in zip(RevealClass.end_location, start_location)) RevealClass.set_position(frame_bounce, end_bounce, None, RevealClass.end_scale, None) #Set the keyframes RevealClass.set_position(start_frame, start_location, start_rotation, start_scale, start_visibility) RevealClass.set_position(end_frame, RevealClass.end_location, RevealClass.end_rotation, RevealClass.end_scale, RevealClass.end_visibility) #Set extra keyframes relative to the current position if extra_keyframes: for frame, new_position in extra_keyframes.iteritems(): current_frame = start_frame + frame location, rotation, scale, absolute_location, absolute_rotation, absolute_scale = new_position new_location = None new_rotation = None new_scale = None if location is not None: if not absolute_location: new_location = location elif absolute_location == 1: location_at_frame = list(pm.getAttr(object_name + '.translate', time=current_frame)) new_location = tuple(i + j for i, j in zip(location_at_frame, location)) elif absolute_location == 2: new_location = tuple(i + j for i, j in zip(start_location, location)) elif absolute_location == 3: new_location = tuple(i + j for i, j in zip(RevealClass.end_location, location)) else: raise ValueError("incorrect location type") if rotation is not None: if not absolute_rotation: new_rotation = rotation elif absolute_rotation == 1: rotation_at_frame = list(pm.getAttr(object_name + '.rotate', time=current_frame)) new_rotation = tuple(i + j for i, j in zip(rotation_at_frame, rotation)) elif absolute_rotation == 2: new_rotation = tuple(i + j for i, j in zip(start_rotation, rotation)) elif absolute_rotation == 3: new_rotation = tuple(i + j for i, j in zip(RevealClass.end_rotation, rotation)) else: raise ValueError("incorrect rotation type") if scale is not None: if not absolute_scale: new_scale = scale elif absolute_scale == 1: scale_at_frame = list(pm.getAttr(object_name + '.scale', time=current_frame)) new_scale = tuple(i + j for i, j in zip(scale_at_frame, scale)) elif absolute_scale == 2: new_scale = tuple(i + j for i, j in zip(start_scale, scale)) elif absolute_scale == 3: new_scale = tuple(i + j for i, j in zip(RevealClass.end_scale, scale)) else: raise ValueError("incorrect scale type") RevealClass.set_position(current_frame, new_location, new_rotation, new_scale, None) #Adjust tangents at end of animation #DISABLED FOR NOW if distance_bounce and False: key_values = list(start_location) + list(rotation_total) key_names = ['translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ'] for i, value in enumerate(key_values): if value: attribute = '{}.{}'.format(object_name, key_names[i]) if value > 0: angle_amount = 90 else: angle_amount = -90 pm.keyTangent(attribute, weightedTangents=True, edit=True) in_weight = pm.keyTangent(attribute, time=end_frame, inWeight=True, query=True)[0] out_weight = pm.keyTangent(attribute, time=end_frame, outWeight=True, query=True)[0] pm.keyTangent(attribute, edit=True, time=end_frame, inAngle=angle_amount, inWeight=in_weight, outAngle=angle_amount, outWeight=out_weight)
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 importAnim(self, nameSpace=None, replaceString=None, *args): successState = True # *.anim file filePath = pm.fileDialog2(caption='Read Animation', fileMode=1, startingDirectory=uad, fileFilter="Anim Files (*.anim)") if not filePath: pm.warning('Read animation cancelled.') return None # read anim info from file filePath = filePath[0] logfile = open(filePath, 'r') fileContent = logfile.read( ) # dictionary containing dictionaries of every object's animations logfile.close() # we can replace some parts of file to use animations on other objects. # for example, replace 'L' with 'R' copy animation from left side to right side. #replaceString = ('L','R') if replaceString: fileContent = fileContent.replace(replaceString[0], replaceString[1]) # convert file content to a animInfos dictionary animInfos = eval(fileContent) objs = animInfos.keys() try: nameSpaceRaw = pm.ls(sl=True)[0].name().split(':') if len(nameSpaceRaw) > 1: nameSpace = nameSpaceRaw[0] except: nameSpace = None for obj in objs: if nameSpace: try: objNode = pm.PyNode(nameSpace + ':' + obj) except: successState = False pm.warning( 'Could not find object to import anim to, skipped.') continue else: try: objNode = pm.PyNode(obj) except: successState = False pm.warning( 'Could not find object to import anim to, skipped.') continue # print objNode # print '__________________________________________________________' attrs = animInfos[obj].keys() # print attrs for attr in attrs: #print attr #print '=============================' animCurveInfos = animInfos[obj][attr] #print animCurveInfos for animCurveAttribute in animCurveInfos: animCurveValues = animInfos[obj][attr][animCurveAttribute] #print animCurveAttribute # anim curve attrs such as times, values, outWeights, inWeights, inAngles, outAngles #print animCurveValues # anim curve values for times, values, outWeights, inWeights, inAngles, outAngles #print '--------------' times = animCurveInfos['times'] values = animCurveInfos['values'] outWeights = animCurveInfos['outWeights'] outAngles = animCurveInfos['outAngles'] inWeights = animCurveInfos['inWeights'] inAngles = animCurveInfos['inAngles'] for i in range(len(animCurveInfos['times'])): if nameSpace: if pm.objExists(nameSpace + ':' + attr): attrNode = pm.PyNode(nameSpace + ':' + attr) elif pm.objExists(attr): attrNode = pm.PyNode(attr) else: successState = False pm.warning( 'attrtibute was not found on target to apply animation, skipped.' ) continue else: if pm.objExists(attr): attrNode = pm.PyNode(attr) else: successState = False pm.warning( 'attrtibute was not found on target to apply animation, skipped.' ) continue pm.setKeyframe(attrNode, time=times[i], value=values[i]) pm.keyTangent(attrNode, e=True, index=(i, i), outWeight=outWeights[i], outAngle=outAngles[i], inWeight=inWeights[i], inAngle=inAngles[i]) if successState: sys.stdout.write('Animation was successfully imported.') else: pm.warning( 'Animation was imported. Not all objects or their attributes were the same. So, animation was not applied to them.' )
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 squishySplineIk(startLoc, endLoc): ikJoints = list() startJoint = pmc.createNode('joint') adv.alignObjects(startJoint, startLoc) endJoint = pmc.createNode('joint') adv.alignObjects(endJoint, endLoc) pmc.parent(endJoint, startJoint) startJoint.orientJoint('xzy', secondaryAxisOrient='zup') pmc.makeIdentity(endJoint, apply=True, jointOrient=True) Splitter.doSplit(startJoint, 10) ikJoints.append(startJoint) ikJoints.extend(reversed(startJoint.getChildren(ad=True, type='joint'))) for i, ikj in enumerate(ikJoints): ikj.radius.set(2) ikj.rename('ikj_spine{0:02d}'.format(i)) # Create second set of joints rigJoints = adv.makeDuplicateJoints(joints=ikJoints, search='ikj_', replace='local_rig_', connectBone=False) # HACK I haven't figured out how to create SDK nodes procedurally, # so making some dummy locs to make the curve I need a = pmc.createNode('transform') b = pmc.createNode('transform') pmc.setKeyframe(a.ty, t=0, value=2.5, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(a.ty, t=10, value=0, inTangentType='flat', outTangentType='flat') pmc.keyTangent(a.ty, index=[0], inAngle=0) pmc.keyTangent(a.ty, index=[1], inAngle=-30) pmc.keyTangent(a.ty, index=[0], outAngle=0) pmc.keyTangent(a.ty, index=[1], outAngle=-30) animSquashCurve = a.ty.listConnections()[0] animSquashCurve.output.disconnect(a.ty) animSquashCurve.rename('squash_ramp') pmc.setKeyframe(a.tx, t=0, value=0, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(a.tx, t=5, value=1, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(a.tx, t=10, value=0, inTangentType='flat', outTangentType='flat') animTwistCurve = a.tx.listConnections()[0] animTwistCurve.output.disconnect(a.tx) animTwistCurve.rename('twist_ramp') pmc.delete(a, b) animControls = dict() animControls['lower_spine'] = adv.makeControlNode('ctl_lower_spine', targetObject=rigJoints[2], alignRotation=False) animControls['middle_spine'] = adv.makeControlNode('ctl_middle_spine') animControls['upper_spine'] = adv.makeControlNode('ctl_upper_spine', targetObject=rigJoints[-2], alignRotation=False) animControls['lower_spine'][0].rotateOrder.set(adv.ROO_YXZ) animControls['middle_spine'][0].rotateOrder.set(adv.ROO_YXZ) animControls['upper_spine'][0].rotateOrder.set(adv.ROO_YXZ) pmc.pointConstraint(animControls['lower_spine'][0], animControls['upper_spine'][0], animControls['middle_spine'][1], mo=False) pmc.orientConstraint(animControls['lower_spine'][0], animControls['upper_spine'][0], animControls['middle_spine'][1], mo=False) splineIk = pmc.ikHandle(sj=ikJoints[0], ee=ikJoints[-1], sol='ikSplineSolver', parentCurve=False, createCurve=True, simplifyCurve=True, numSpans=2, rootOnCurve=False, n='sik_spine') splineIkHandle = splineIk[0] spline = splineIk[2] spline.rename('crv_spine') clusterJoints = list() clusterJoints.append(pmc.createNode('joint', n='clj_spine0')) pmc.parentConstraint(animControls['lower_spine'][0], clusterJoints[-1]) clusterJoints.append(pmc.createNode('joint', n='clj_spine1')) pmc.parentConstraint(animControls['middle_spine'][0], clusterJoints[-1]) clusterJoints.append(pmc.createNode('joint', n='clj_spine2')) pmc.parentConstraint(animControls['upper_spine'][0], clusterJoints[-1]) pmc.skinCluster(clusterJoints, spline, maximumInfluences=3) pmc.parentConstraint(animControls['lower_spine'][0], ikJoints[0], maintainOffset=True) for clj in clusterJoints: clj.radius.set(3) splineIkHandle.dTwistControlEnable.set(1) splineIkHandle.dWorldUpType.set(4) splineIkHandle.dWorldUpAxis.set(0) splineIkHandle.dWorldUpVector.set([0.0, 0.0, 1.0]) splineIkHandle.dWorldUpVectorEnd.set([0.0, 0.0, 1.0]) animControls['lower_spine'][0].worldMatrix[0].connect(splineIkHandle.dWorldUpMatrix) animControls['upper_spine'][0].worldMatrix[0].connect(splineIkHandle.dWorldUpMatrixEnd) normalizeNode = stretchySplineIk(splineIkHandle, useScale=True, globalScaleAttr='ctl_main.size') sqrtScale = pmc.createNode('multiplyDivide', n='sqrt_spine_scale') sqrtScale.operation.set(3) sqrtScale.input2X.set(0.5) normalizeNode.outputX.connect(sqrtScale.input1X) invScale = pmc.createNode('multiplyDivide', n='div_spine_inverse_scale') invScale.operation.set(2) invScale.input1X.set(1.0) sqrtScale.outputX.connect(invScale.input2X) jointGroups = list() for i, jnt in enumerate(rigJoints): preTransform = adv.zeroOut(jnt, 'pre') jointGroups.append(preTransform) ikNode = adv.zeroOut(jnt, 'hlp_ik') pmc.pointConstraint(ikJoints[i], ikNode) pmc.orientConstraint(ikJoints[i], ikNode) twistNode = adv.zeroOut(jnt, 'hlp_twist') twistCache = pmc.createNode('frameCache', n='frm_{0}_twist'.format(jnt)) animTwistCurve.output.connect(twistCache.stream) twistCache.varyTime.set(i) rotateMultiplier = pmc.createNode('multiplyDivide', n='mul_{0}_twist'.format(jnt.shortName())) twistCache.varying.connect(rotateMultiplier.input2X) animControls['middle_spine'][0].rotateY.connect(rotateMultiplier.input1X) rotateMultiplier.outputX.connect(twistNode.rotateX) volumeCache = pmc.createNode('frameCache', n='frm_{0}_volume'.format(jnt.shortName())) animSquashCurve.output.connect(volumeCache.stream) volumeCache.varyTime.set(i) pow_ = pmc.createNode('multiplyDivide', n='pow_{0}'.format(jnt.shortName())) pow_.operation.set(3) invScale.outputX.connect(pow_.input1X) volumeCache.varying.connect(pow_.input2X) pow_.outputX.connect(jnt.scaleY) pow_.outputX.connect(jnt.scaleZ) pmc.group(animControls['lower_spine'][1], animControls['upper_spine'][1], animControls['middle_spine'][1], n='grp_spine_anim') pmc.group(splineIkHandle, spline, n='grp_spine_rig_systems') pmc.group(clusterJoints, startJoint, n='grp_spine_system_joints') pmc.group(jointGroups, n='grp_spine_bind_joints') return rigJoints
def smoothTangent( side='in' ): """ Adjusts selected key tangents to have a smooth linear in or out. @param side: default: C{'in'} Which tangent side to set linear angle. Valid options are 'in' and 'out'. @type side: string """ for ( curve, keys ) in getSelectedCurvesKeys().iteritems(): for key in keys: lockState = pm.keyTangent( curve, time=( key, key ), query=True, lock=True )[0] if side == 'in': pm.keyTangent( curve, time=( key, key ), outTangentType='linear', lock=False ) pm.keyTangent( curve, time=( key, key ), inAngle=pm.keyTangent( curve, query=True, outAngle=True, time=( key, key ) )[0] ) elif side == 'out': pm.keyTangent( curve, time=( key, key ), inTangentType='linear', lock=False ) pm.keyTangent( curve, time=( key, key ), outAngle=pm.keyTangent( curve, query=True, inAngle=True, time=( key, key ) )[0] ) else: pm.mel.error( 'Invalid argument: "%s"' % side ) pm.keyTangent( curve, lock=lockState, time=( key, key ) )
def paste(self, dataContent): ''' Description Function for set(paste) the animation curve value of maya objects. :Type - class function :param dataContent <dict> example {'mObect': {'attributes': {animation information}, 'namespace': 'Clifan:'}} :return None :example to execute from smartCopy import mayaAnim reload(mayaAnim) data = {} ma= mayaAnim.MayaAnim(objects=objects) ma.paste(dataContent=data) ''' pymel.undoInfo(openChunk=True) objects = {} for eachObject in self._mObjects: if pymel.referenceQuery(eachObject, inr=True): currentNamespace = eachObject.namespace().encode() currentObject = eachObject.name().replace( currentNamespace, '').encode() if currentObject not in dataContent: continue objects.setdefault(currentObject, currentNamespace) else: if eachObject.name() not in dataContent: continue objects.setdefault(eachObject.name().encode(), None) if not objects: warnings.warn( 'sorry, your selected object can not find in the copy data.') return None startFrame = int(pymel.currentTime(q=1)) for eachNode, eachNamespace in objects.iteritems(): currentNode = '{}{}'.format(eachNamespace, eachNode) if not eachNamespace: currentNode = eachNode print '\n' for eachAttri, eachValue in dataContent[eachNode][ 'attributes'].iteritems(): if not pymel.objExists('{}.{}'.format(currentNode, eachAttri)): continue pyNode = pymel.PyNode(currentNode) pyAttributes = pymel.PyNode('{}.{}'.format( currentNode, eachAttri)) animCurve = eachValue['animCurve'] animCurveType = eachValue['animCurveType'] weightTangent = eachValue['weightTangent'] preInfinity = eachValue['preInfinity'] postInfinity = eachValue['postInfinity'] inTangentType = eachValue['inTangentType'] outTangentType = eachValue['outTangentType'] inAngle = eachValue['inAngle'] outAngle = eachValue['outAngle'] timeChange = eachValue['timeChange'] valueChange = eachValue['valueChange'] animCurves = pyAttributes.listConnections(d=False, s=True) if animCurves: if animCurves[0].type() == 'animCurveTL' or animCurves[ 0].type() == 'animCurveTA' or animCurves[0].type( ) == 'animCurveTU': currentAnimCurve = animCurves[0] else: currentAnimCurve = pymel.createNode( animCurveType, n=pyAttributes.name().replace('.', '_')) currentAnimCurve.connectAttr('output', pyAttributes) pymel.keyTangent(currentAnimCurve, e=True, wt=weightTangent) # Set weightTangent currentAnimCurve.setAttr('preInfinity', preInfinity) # Set preInfinity currentAnimCurve.setAttr('postInfinity', postInfinity) # Set postInfinity # Set frames and key for index in range(len(timeChange)): precentage = float(valueChange[index]) * 100 / 100.00 currentFrame = (startFrame + timeChange[index]) - 1 pymel.setKeyframe(currentAnimCurve, time=float(currentFrame), value=precentage) pymel.keyTangent(currentAnimCurve, e=1, t=(currentFrame, currentFrame), itt=inTangentType[index], ott=outTangentType[index]) pymel.keyTangent(currentAnimCurve, e=1, t=(currentFrame, currentFrame), ia=inAngle[index], oa=float(outAngle[index])) print eachNode, eachAttri, eachValue pymel.undoInfo(closeChunk=True)
def make_spline_tangents(): """sets selected keys tangents to spline""" pm.keyTangent(edit=True, itt='spline', ott='spline')
def copy(self): ''' Description Function for store(copy) the animation curve value of maya objects. :Type - class function :param None :return dataList <dict> example {'mObect': {'attributes': {animation information}, 'namespace': 'Clifan:'}} :example to execute from smartCopy import mayaPose reload(mayaPose) objects = pymel.ls(sl=1) ma = mayaAnim.MayaAnim(objects=objects) animData = ma.copy() ''' if not self._mObjects: warnings.warn( 'function set \"copy\" _mObjects attribute value is none, update the _mObjects attribute value' ) return None startFrame = int(pymel.playbackOptions(q=True, min=True)) endFrame = int(pymel.playbackOptions(q=True, max=True)) dataList = {} boolInt = {True: 1, False: 0} for eachObject in self._mObjects: currentNamespace = 'None' currentObject = eachObject.name() if pymel.referenceQuery(eachObject, inr=True): currentNamespace = eachObject.namespace() currentObject = eachObject.name().replace(currentNamespace, '') attriList = eachObject.listAttr(r=True, w=True, k=True, u=True, v=True, m=True, s=True) if not attriList: print 'attributes are does not exists', eachObject.name() continue attributesAnimation = {} for eachAttri in attriList: sourceKey = pymel.keyframe(eachAttri, q=True) if not sourceKey: continue animCurves = eachAttri.listConnections(d=False, s=True) if not animCurves: continue if 'animCurve' not in animCurves[0].type(): continue weightTangent = int( pymel.keyTangent(animCurves[0], q=True, wt=True)[0]) preInfinity = animCurves[0].getAttr('preInfinity') postInfinity = animCurves[0].getAttr('postInfinity') inTangentType = pymel.keyTangent(animCurves[0], q=True, t=(startFrame, endFrame), itt=True) if inTangentType: inTangentType = [ eachInTangent.encode() for eachInTangent in inTangentType ] outTangentType = pymel.keyTangent(animCurves[0], q=True, t=(startFrame, endFrame), ott=True) if outTangentType: outTangentType = [ eachOutTangent.encode() for eachOutTangent in outTangentType ] inAngle = pymel.keyTangent(animCurves[0], q=1, t=(startFrame, endFrame), ia=1) outAngle = pymel.keyTangent(animCurves[0], q=1, t=(startFrame, endFrame), oa=1) timeChange = pymel.keyframe(eachAttri.nodeName(), at=eachAttri.attrName(), query=True, t=(startFrame, endFrame), tc=True) valueChange = pymel.keyframe(eachAttri.nodeName(), at=eachAttri.attrName(), query=True, t=(startFrame, endFrame), vc=True) currentAnimation = {} currentAnimation['animCurve'] = animCurves[0].name().encode() currentAnimation['animCurveType'] = animCurves[0].type( ).encode() currentAnimation['weightTangent'] = weightTangent currentAnimation['preInfinity'] = preInfinity currentAnimation['postInfinity'] = postInfinity currentAnimation['inTangentType'] = inTangentType currentAnimation['outTangentType'] = outTangentType currentAnimation['inAngle'] = inAngle currentAnimation['outAngle'] = outAngle currentAnimation['timeChange'] = timeChange currentAnimation['valueChange'] = valueChange attributesAnimation.setdefault(eachAttri.attrName().encode(), currentAnimation) controlDatas = { 'namespace': currentNamespace.encode(), 'attributes': attributesAnimation } dataList.setdefault(currentObject, controlDatas) pprint.pprint(dataList) return dataList
def volumeConservation( ikHandleTorso, curveInfoNodeBack, jntList, opt = 1 ): pymelLogger.debug('Starting: volumeConservation()...') # for now volumeConservation inclues yes and no # List with all joints endJnt = len(jntList)-1 jntToScale = jntList[:-1] if opt == 0: # Connect output x of the multiplydivide node to the x scale of the joint # (or the axis that goes down the joint) # Do not connect the end joint for jnt in jntToScale: pm.connectAttr( curveInfoNodeBack + '.normalizedScale', jnt + '.scaleX') else: # if volume # following jasons techniques # we will create a anim curve that will be used to determine # the scaling power of the joints # Add Attr to curve (scalePower) this will let us control the curve pm.addAttr(ikHandleTorso[2], longName='scalePower', attributeType='double') # Make it keyable pm.setAttr(ikHandleTorso[2] + '.scalePower', keyable = True) # Get total number of joints to scale # this will be the range we will have to keyframe # we will put keyframe on 1 and another at X (depending on how many joints are created) numOfJnts = len(jntToScale) # Set the two keyframes pm.setKeyframe(ikHandleTorso[2], attribute = 'scalePower', time = 1, value = 0) pm.setKeyframe(ikHandleTorso[2], attribute = 'scalePower', time = numOfJnts, value = 0) # We configure the shape of the animation curve # weightingtangents and setting an out and in angle pm.keyTangent(ikHandleTorso[2], weightedTangents=True, weightLock = False, attribute = 'scalePower') pm.keyTangent(ikHandleTorso[2], edit=True, absolute = True, time=(1,numOfJnts), outAngle=50, attribute = 'scalePower') pm.keyTangent(ikHandleTorso[2], edit=True, absolute = True, time=(numOfJnts,numOfJnts), inAngle=-50, attribute = 'scalePower') # Creating a frameCache for each joint to be scaled # Connecting scalePower to each frameCache Stream fCount = 1 for jnt in jntToScale: frameC = pm.createNode('frameCache', name = jnt + '_'+Names.suffixes['frameCache']) pm.connectAttr(ikHandleTorso[2] + '.scalePower', frameC + '.stream') # set frame number pm.setAttr(frameC+'.vt', fCount) fCount += 1 # Create Attr Pow for each joint powJnt = pm.addAttr(jnt, longName='pow', attributeType='double') pm.setAttr(jnt + '.pow', keyable = True) # Connect Attr varying to jnt.pow pm.connectAttr(frameC + '.v', jnt + '.pow', force=True) # Writing the expression to apply the scale expr = '$scale = ' + curveInfoNodeBack + '.normalizedScale;\n' # inv scale expr += '$sqrt = 1/sqrt($scale);\n' for jnt in jntToScale: # x joint scale expr += jnt+'.scaleX = $scale;\n' expr += jnt+'.scaleY = pow($sqrt,'+jnt+'.pow);\n' expr += jnt+'.scaleZ = pow($sqrt,'+jnt+'.pow);\n' # Create expression expressionNode = pm.expression(string=expr, name=ikHandleTorso[2]+'_'+Names.suffixes['expression']) rList = [expr, expressionNode] return rList pymelLogger.debug('End: volumeConservation()...')
def change_type(self): # this changes the out tangent type pm.keyTangent('%s' % (self.node), index= (self.index, self.index), outTangentType= '%s' % (self.text_field.getText())) print 'out_tangent', self.node, self.text_field.getText()
def volumeConservation(ikHandleTorso, curveInfoNodeBack, jntList, opt=1): pymelLogger.debug('Starting: volumeConservation()...') # for now volumeConservation inclues yes and no # List with all joints endJnt = len(jntList) - 1 jntToScale = jntList[:-1] if opt == 0: # Connect output x of the multiplydivide node to the x scale of the joint # (or the axis that goes down the joint) # Do not connect the end joint for jnt in jntToScale: pm.connectAttr(curveInfoNodeBack + '.normalizedScale', jnt + '.scaleX') else: # if volume # following jasons techniques # we will create a anim curve that will be used to determine # the scaling power of the joints # Add Attr to curve (scalePower) this will let us control the curve pm.addAttr(ikHandleTorso[2], longName='scalePower', attributeType='double') # Make it keyable pm.setAttr(ikHandleTorso[2] + '.scalePower', keyable=True) # Get total number of joints to scale # this will be the range we will have to keyframe # we will put keyframe on 1 and another at X (depending on how many joints are created) numOfJnts = len(jntToScale) # Set the two keyframes pm.setKeyframe(ikHandleTorso[2], attribute='scalePower', time=1, value=0) pm.setKeyframe(ikHandleTorso[2], attribute='scalePower', time=numOfJnts, value=0) # We configure the shape of the animation curve # weightingtangents and setting an out and in angle pm.keyTangent(ikHandleTorso[2], weightedTangents=True, weightLock=False, attribute='scalePower') pm.keyTangent(ikHandleTorso[2], edit=True, absolute=True, time=(1, numOfJnts), outAngle=50, attribute='scalePower') pm.keyTangent(ikHandleTorso[2], edit=True, absolute=True, time=(numOfJnts, numOfJnts), inAngle=-50, attribute='scalePower') # Creating a frameCache for each joint to be scaled # Connecting scalePower to each frameCache Stream fCount = 1 for jnt in jntToScale: frameC = pm.createNode('frameCache', name=jnt + '_' + Names.suffixes['frameCache']) pm.connectAttr(ikHandleTorso[2] + '.scalePower', frameC + '.stream') # set frame number pm.setAttr(frameC + '.vt', fCount) fCount += 1 # Create Attr Pow for each joint powJnt = pm.addAttr(jnt, longName='pow', attributeType='double') pm.setAttr(jnt + '.pow', keyable=True) # Connect Attr varying to jnt.pow pm.connectAttr(frameC + '.v', jnt + '.pow', force=True) # Writing the expression to apply the scale expr = '$scale = ' + curveInfoNodeBack + '.normalizedScale;\n' # inv scale expr += '$sqrt = 1/sqrt($scale);\n' for jnt in jntToScale: # x joint scale expr += jnt + '.scaleX = $scale;\n' expr += jnt + '.scaleY = pow($sqrt,' + jnt + '.pow);\n' expr += jnt + '.scaleZ = pow($sqrt,' + jnt + '.pow);\n' # Create expression expressionNode = pm.expression(string=expr, name=ikHandleTorso[2] + '_' + Names.suffixes['expression']) rList = [expr, expressionNode] return rList pymelLogger.debug('End: volumeConservation()...')
import pymel.core as pm cvSrc = pm.ls('pCube1_translateX')[0] cvNew = 'hahaha' 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) } ''' A. create animCurve ''' # create same type of animation curve