def _set_attribute_anim_data(mplug, data): mcurve = omanim.MFnAnimCurve(mplug) try: mcurve.name() #errors if does not exist except RuntimeError: mcurve.create(mplug) #create one if didn't exist set_anim_curve_data(mcurve, data)
def api(): """This function instead uses the OpenMaya api to query the keyframes""" # Get the start time start = time.time() # Get an iterator with all the anim curves in the scene # The argument provided is the type to search for it = om.MItDependencyNodes(om.MFn.kAnimCurveTimeToAngular) # This set will store all our keyframes keyframes = set() # We iterate through the iterator till it's done while not it.isDone(): # We get the Function sets for the anim curves so we can interact with the curve curveFn = oma.MFnAnimCurve(it.thisNode()) # We'll check how many keys it has for x in range(curveFn.numKeys): # Then query what time it happens on # The input method gives us back an MTime object # The value of the MTime is the frame number frame = curveFn.input(x).value # Then lets add it to the set keyframes.add(frame) # Finally go on to the next item in the iterator it.next() # Calculate how long this took and then return it delta = time.time() - start return delta
def add_keys(anim_curve, key_dict): # type: (unicode, dict) -> None """ Add keyframes to animation curve :param anim_curve: animation curve name :param key_dict: dictionary of keyframes in {frame_number (float): value (float)} format :return: None """ unit = om.MTime.uiUnit() nodeNattr = cmds.listConnections(anim_curve, d=True, s=False, p=True)[0] selList = om.MSelectionList() selList.add(nodeNattr) mplug = selList.getPlug(0) dArrTimes = om.MTimeArray() dArrVals = om.MDoubleArray() if 'rotate' in nodeNattr: for i in key_dict.keys(): dArrTimes.append(om.MTime(float(i), unit)) dArrVals.append(om.MAngle.uiToInternal(key_dict[i])) else: for i in key_dict.keys(): dArrTimes.append(om.MTime(float(i), unit)) dArrVals.append(key_dict[i]) crvFnc = oma.MFnAnimCurve(mplug) crvFnc.addKeys(dArrTimes, dArrVals, crvFnc.kTangentAuto, crvFnc.kTangentAuto)
def fill_keys(name, attrName, KEYS, frameValues): currentObject = name currentAttribute = attrName if not cmds.objExists('%s.%s' % (currentObject, currentAttribute)): return animCurveType = 1 # Anim Curve data timeList = KEYS #objectAttriData['timeList'] valueList = frameValues #objectAttriData['valueList'] # Convert current object and attribute to a new MPlug object mSelectionList = om.MSelectionList() mSelectionList.add('%s.%s' % (currentObject, currentAttribute)) currentMPlug = mSelectionList.getPlug(0) connectedList = currentMPlug.connectedTo(1, 0) newAnimCurve = 1 if connectedList: connectedNode = connectedList[0].node() if connectedNode.hasFn(om.MFn.kAnimCurve): mfnAnimCurve = oma.MFnAnimCurve(connectedNode) newAnimCurve = 0 if newAnimCurve == 1: mfnAnimCurve = oma.MFnAnimCurve() mfnAnimCurve.create(currentMPlug, animCurveType) #mfnAnimCurve.setPreInfinityType(preInfinity) #mfnAnimCurve.setPostInfinityType(postInfinity) #mfnAnimCurve.setIsWeighted(weightedTangents) mTimeList = om.MTimeArray() mDoubleValueList = om.MDoubleArray() for keyIndex in range(len(timeList)): mTimeList.append(om.MTime(timeList[keyIndex], om.MTime.uiUnit())) mDoubleValueList.append(valueList[keyIndex]) mfnAnimCurve.addKeys(mTimeList, mDoubleValueList, 0, 0, 1) #cmds.filterCurve( '%s_%s' % (currentObject, currentAttribute) ) for keyIndex in range(len(timeList)): pass
def it_node_anim_curves_data(dg_name, mitsel): while not mitsel.isDone(): mcurve = omanim.MFnAnimCurve(mitsel.getDependNode()) try: curve_data = get_anim_curve_data(mcurve, dg_name) except exceptions.OutputError: msg = '{} Skipping curve data.'.format(sys.exc_info()[1]) LOGGER.warning(msg) else: yield curve_data finally: mitsel.next()
def it_anim_curves_data(*dg_names): """ Gather data from the specified animation curve nodes. Args: *dg_names (str): Animation node dg names to process. Returns: dict: The collected data of each curve. """ omslist = om.MSelectionList() for i, c in enumerate(dg_names): omslist.add(c) mcurve = omanim.MFnAnimCurve(omslist.getDependNode(i)) yield get_anim_curve_data(mcurve)
def maya_api_addkeys(plugName, times, values): sel = OpenMaya.MSelectionList() sel.add(plugName) plug = sel.getPlug(0) animFn = OpenMayaAnim.MFnAnimCurve() animFn.create(plug, OpenMayaAnim.MFnAnimCurve.kAnimCurveTL) timeArray = OpenMaya.MTimeArray() valueArray = OpenMaya.MDoubleArray() for i in range(len(times)): timeArray.append(OpenMaya.MTime(times[i], OpenMaya.MTime.kSeconds)) valueArray.append(values[i]) animFn.addKeys(timeArray, valueArray)
def node_names_to_mfn_anim_curves(nodes): """ Convert an anim curve name to a maya.OpenMayaAnim.MFnAnimCurve object :param node: str or list() of string :param types: str or tuple() of str. Type of animation curves animCurveTU, TT, TA, TL :rtype: maya.OpenMayaAnim.MFnAnimCurve """ if isinstance(nodes, basestring): nodes = [nodes] sel = om2.MSelectionList() mfn_anim_curves = [] for i, node in enumerate(nodes): sel.add(node) mfn_anim_curves.append(oma2.MFnAnimCurve(sel.getDependNode(i))) return mfn_anim_curves
def setAnimCurves(self): """ :return: None Sets the animCurves for the selection """ self.curveList = [] animCurves = aou.extractAnimCurves(aou.getAllLinkedObjs()) cmds.select(animCurves) selectionList = om.MGlobal.getActiveSelectionList() if selectionList.length() > 0: kd = {} iterator = om.MItSelectionList(selectionList, om.MFn.kDagNode) while not iterator.isDone(): # iterator.getDependNode() returns mobj. we're forcing a AnimCurve Obj curve = oma.MFnAnimCurve(iterator.getDependNode()) kd[curve] = [] for k in range(curve.numKeys): kd[curve].append(KeyFrame(curve, k)) self.keydict.update(kd) self.curveList.append(curve) iterator.next()
def get_animcurve(m_dag_node, attribute): """Get MFnAnimCurve for given object and attribute. Args: m_dag_node (OpenMaya.MFnDagNode): maya object to get curve from. attribute (str): name of attribute to get curve from. Returns: OpenMayaAnim.MFnAnimCurve: the animation curve for given object, attribute. """ m_plug = m_dag_node.findPlug(attribute, False) m_source = m_plug.source() if m_source.isNull: return m_source_node = m_source.node() if not m_source_node.apiTypeStr.startswith('kAnimCurve'): return fn_curve = OpenMayaAnim.MFnAnimCurve(m_source_node) return fn_curve
dep_data = OpenMaya.MFnDependencyNode(node_obj) #listing the plug connection plug = dep_data.findPlug(attr,0) nodes = plug.connectedTo(True, False) if not nodes: return #if we have a connection we grab the first one and check if it is #and animation curve node = nodes[0].node() if (node.hasFn(OpenMaya.MFn.kAnimCurve)): return node node = __get_anim_crv(obj,attr) anim =OpenMayaAnim.MFnAnimCurve(node) x1 = 3.0 x2 = 3.002 t = OpenMaya.MTime(x1) t2 = OpenMaya.MTime(x2) y1 = anim.evaluate(t) y2 = anim.evaluate(t2) #so we have a vector, namely v1= (x,y) , v2 = (x2,y2) # we can extract the tangent vector by doing tanV = v2 -v1 print y2 time = OpenMaya.MTime(1.0,OpenMaya.MTime.kSeconds) conversionFactor= time.asUnits(OpenMaya.MTime.uiUnit()) tanV = [x2-x1, y2-y1] print tanV
def create_ac(self, dag_fn, dag, attribute, curve_type): attr = dag_fn.attribute(attribute) anim_curve = oma.MFnAnimCurve() anim_curve.create(dag.transform(), attr, curve_type) return anim_curve
mfnAttribute = om.MFnAttribute(attriMObject) attriName = mfnAttribute.name.encode() # 3. Find the Attribute - Animation curve is connected currentPlug = mfnDependencyNode.findPlug(attriName, 1) if currentPlug.connectedTo(1, 0): connectedList = currentPlug.connectedTo(1, 0) # Find the connected node type conNodeMObject = connectedList[0].node() # Check its is a Animation curve if conNodeMObject.hasFn(om.MFn.kAnimCurve): # Read Anim Curve Attribute valus mfnAnimCurve = oma.MFnAnimCurve(conNodeMObject) attributeDataList = { 'animCurveType': 0, 'preInfinity': 0, 'postInfinity': 0, 'weightedTangents': 0, 'time': [], 'value': [], 'inTangentType': [], 'inTangentAngle': [], 'inTangentWeight': [], 'outTangentType': [], 'outTangentAngle': [], 'outTangentWeight': [] }
def testComplexAdaptation(self): """Test that we can adapt a bullet simulation""" mayaUsdLib.SchemaApiAdaptor.Register(TestBulletMassShemaAdaptor, "shape", "PhysicsMassAPI") mayaUsdLib.SchemaApiAdaptor.Register(TestBulletRigidBodyShemaAdaptor, "shape", "PhysicsRigidBodyAPI") # Build a scene (and exercise the adaptor in a freeform context) cmds.file(f=True, new=True) s1T = cmds.polySphere()[0] cmds.loadPlugin("bullet") if not BulletUtils.checkPluginLoaded(): return rbT, rbShape = RigidBody.CreateRigidBody().command( autoFit=True, colliderShapeType=RigidBody.eShapeType.kColliderSphere, meshes=[s1T], radius=1.0, mass=5.0, centerOfMass=(0.9, 0.8, 0.7)) # See if the plugin adaptor can read the bullet shape under the mesh: sl = om.MSelectionList() sl.add(s1T) dagPath = sl.getDagPath(0) dagPath.extendToShape() adaptor = mayaUsdLib.Adaptor(dagPath.fullPathName()) self.assertEqual(adaptor.GetUsdType(), Tf.Type.FindByName('UsdGeomMesh')) # NOTICE: PhysicsRigidBodyAPI is not in the list because that API is # supported only on export!!! self.assertEqual(adaptor.GetAppliedSchemas(), ['PhysicsMassAPI']) physicsMass = adaptor.GetSchemaByName("PhysicsMassAPI") self.assertEqual(physicsMass.GetName(), "PhysicsMassAPI") massAttributes = set([ 'physics:centerOfMass', 'physics:density', 'physics:diagonalInertia', 'physics:mass', 'physics:principalAxes' ]) self.assertEqual(set(physicsMass.GetAttributeNames()), massAttributes) bulletAttributes = set(['physics:centerOfMass', 'physics:mass']) self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()), bulletAttributes) bulletMass = physicsMass.GetAttribute('physics:mass') self.assertAlmostEqual(bulletMass.Get(), 5.0) bulletMass.Set(12.0) bulletCenter = physicsMass.GetAttribute('physics:centerOfMass') bulletCenter.Set(Gf.Vec3f(3, 4, 5)) sl = om.MSelectionList() sl.add(s1T) bulletPath = sl.getDagPath(0) bulletPath.extendToShape(1) massDepFn = om.MFnDependencyNode(bulletPath.node()) plug = om.MPlug(bulletPath.node(), massDepFn.attribute("mass")) self.assertAlmostEqual(plug.asFloat(), 12.0) # Create an untranslated attribute: usdDensity = physicsMass.CreateAttribute('physics:density') usdDensity.Set(33.0) self.assertAlmostEqual(usdDensity.Get(), 33.0) # This will result in a dynamic attribute on the bulletShape: plug = massDepFn.findPlug("USD_ATTR_physics_density", True) self.assertAlmostEqual(plug.asFloat(), 33.0) bulletAttributes.add('physics:density') self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()), bulletAttributes) physicsMass.RemoveAttribute('physics:density') bulletAttributes.remove('physics:density') self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()), bulletAttributes) # Add some animation: cmds.setKeyframe(bulletPath, at="mass", t=0, v=3.0) cmds.setKeyframe(bulletPath, at="mass", t=10, v=30.0) # Modify the velocity so it can be exported to the RBD Physics schema. cmds.setKeyframe(bulletPath, at="initialVelocityX", t=0, v=5.0) cmds.setKeyframe(bulletPath, at="initialVelocityX", t=10, v=50.0) cmds.setKeyframe(bulletPath, at="initialVelocityY", t=0, v=6.0) cmds.setKeyframe(bulletPath, at="initialVelocityY", t=10, v=60.0) cmds.setKeyframe(bulletPath, at="initialVelocityZ", t=0, v=7.0) cmds.setKeyframe(bulletPath, at="initialVelocityZ", t=10, v=70.0) # Try applying the schema on a new sphere: s2T = cmds.polySphere()[0] sl.add(s2T) dagPath = sl.getDagPath(1) dagPath.extendToShape() adaptor = UsdMaya.Adaptor(dagPath.fullPathName()) physicsMass = adaptor.ApplySchemaByName("PhysicsMassAPI") self.assertEqual(physicsMass.GetName(), "PhysicsMassAPI") self.assertEqual(adaptor.GetUsdType(), Tf.Type.FindByName('UsdGeomMesh')) self.assertEqual(adaptor.GetAppliedSchemas(), ['PhysicsMassAPI']) usdDensity = physicsMass.CreateAttribute('physics:density') usdDensity.Set(33.0) # Export, but without enabling Bullet: usdFilePath = os.path.abspath('UsdExportSchemaApiTest_NoBullet.usda') cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath) # Check that there are no Physics API schemas exported: stage = Usd.Stage.Open(usdFilePath) for i in (1, 2): spherePrim = stage.GetPrimAtPath( '/pSphere{0}/pSphereShape{0}'.format(i)) self.assertFalse( "PhysicsMassAPI" in spherePrim.GetAppliedSchemas()) schemasToExport = ["PhysicsMassAPI", "PhysicsRigidBodyAPI"] # Export, with Bullet: usdFilePath = os.path.abspath('UsdExportSchemaApiTest_WithBullet.usda') cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath, apiSchema=schemasToExport, frameRange=(1, 10)) # Check that Physics API schemas did get exported: stage = Usd.Stage.Open(usdFilePath) values = [ ("physics:centerOfMass", (Gf.Vec3f(3, 4, 5), Gf.Vec3f(0, 0, 0))), ("physics:mass", (3.0, 1.0)), ("physics:density", (None, 33.0)), ] for i in (1, 2): spherePrim = stage.GetPrimAtPath( '/pSphere{0}/pSphereShape{0}'.format(i)) self.assertTrue("PhysicsMassAPI" in spherePrim.GetAppliedSchemas()) for n, v in values: if v[i - 1]: a = spherePrim.GetAttribute(n) self.assertEqual(a.Get(), v[i - 1]) if i == 1: # Is mass animated? a = spherePrim.GetAttribute("physics:mass") self.assertEqual(a.Get(10), 30) # This got exported even though invisible in interactive: self.assertTrue( "PhysicsRigidBodyAPI" in spherePrim.GetAppliedSchemas()) a = spherePrim.GetAttribute("physics:velocity") if i == 1: self.assertEqual(a.Get(0), (5, 6, 7)) self.assertEqual(a.Get(10), (50, 60, 70)) numberOfExportedKeys = len(a.GetTimeSamples()) # Try unapplying the schema: adaptor.UnapplySchemaByName("PhysicsMassAPI") self.assertEqual(adaptor.GetAppliedSchemas(), []) # Test import of USDPhysics without job context: cmds.file(new=True, force=True) cmds.mayaUSDImport(f=usdFilePath) sl = om.MSelectionList() # pSphereShape1 is a transform, since the bullet shape prevented merging the mesh and the # transform. The shape will be pSphereShape1Shape... sl.add("pSphereShape1") bulletPath = sl.getDagPath(0) # No bullet shape since we did not put Bullet as jobContext self.assertEqual(bulletPath.numberOfShapesDirectlyBelow(), 1) cmds.file(new=True, force=True) cmds.mayaUSDImport(f=usdFilePath, apiSchema=schemasToExport, readAnimData=True) sl = om.MSelectionList() sl.add("pSphereShape1") bulletPath = sl.getDagPath(0) # Finds bullet shape since we did put Bullet as jobContext self.assertEqual(bulletPath.numberOfShapesDirectlyBelow(), 2) # The bullet shape has animated mass and initial velocity since we read the animation. bulletPath.extendToShape(1) massDepFn = om.MFnDependencyNode(bulletPath.node()) for attrName in ("mass", "initialVelocityX", "initialVelocityY", "initialVelocityZ"): plug = om.MPlug(bulletPath.node(), massDepFn.attribute(attrName)) self.assertTrue(plug.isConnected) fcurve = oma.MFnAnimCurve(plug.source().node()) self.assertEqual(fcurve.numKeys, numberOfExportedKeys)
def exportAnimCurve(selectionList, animPath, animName, animGIFPath, iconPath): animDataDict = {} for currentObject in selectionList: objMSL = om.MSelectionList() objMSL.add(currentObject) objMObject = objMSL.getDependNode(0) # find the attribute of current object objMFnDPNode = om.MFnDependencyNode(objMObject) attributeCount = objMFnDPNode.attributeCount() nodeAnimInformationDict = {} for attributeIndex in range(attributeCount): attributeMObject = objMFnDPNode.attribute(attributeIndex) MFnAttribute = om.MFnAttribute(attributeMObject) attributeName = MFnAttribute.name # find the attribute that anim curve connected currentPlug = objMFnDPNode.findPlug(attributeName, 1) if currentPlug.connectedTo(1, 0): currentConnectedList = currentPlug.connectedTo(1, 0) # find the connected node type currentConnectNodeMObject = currentConnectedList[0].node() # check it is an anim curve if currentConnectNodeMObject.hasFn(om.MFn.kAnimCurve): # get anim curve MFnAnimCurve = oma.MFnAnimCurve(currentConnectNodeMObject) # get attribute animCurveType = MFnAnimCurve.animCurveType preInfinity = MFnAnimCurve.preInfinityType postInfinity = MFnAnimCurve.postInfinityType weightedTangents = int(MFnAnimCurve.isWeighted) # get value of each key numKeys = MFnAnimCurve.numKeys timeList = [] valueList = [] inTangentTypeList = [] inTangentAngleList = [] inTangentAngleWeightList = [] outTangentTypeList = [] outTangentAngleList = [] outTangentAngleWeightList = [] for index in range(numKeys): # time input = MFnAnimCurve.input(index) mTime = om.MTime(input) currentTime = mTime.value timeList.append(currentTime) # value value = MFnAnimCurve.value(index) valueList.append(value) # inTangent inTangentType = MFnAnimCurve.inTangentType(index) inTangentTypeList.append(inTangentType) inTangentAngleWeight = MFnAnimCurve.getTangentAngleWeight(index, 1) inTangentAngleMAngle = om.MAngle(inTangentAngleWeight[0]) inTangentValue = inTangentAngleMAngle.value inTangentAngleList.append(inTangentValue) inTangentAngleWeightList.append(inTangentAngleWeight[1]) # outTangent outTangentType = MFnAnimCurve.outTangentType(index) outTangentTypeList.append(outTangentType) outTangentAngleWeight = MFnAnimCurve.getTangentAngleWeight(index, 0) outTangentAngleMAngle = om.MAngle(outTangentAngleWeight[0]) outTangetValue = outTangentAngleMAngle.value outTangentAngleList.append(outTangetValue) outTangentAngleWeightList.append(outTangentAngleWeight[1]) attributeDataDict = {'animCurveType': animCurveType, 'preInfinity': preInfinity, 'postInfinity': postInfinity, 'weightedTangents': weightedTangents, 'numKeys': numKeys, 'timeList': timeList, 'valueList': valueList, 'inTangentTypeList': inTangentTypeList, 'inTangentAngleList': inTangentAngleList, 'inTangentAngleWeightList': inTangentAngleWeightList, 'outTangentAngleList': outTangentAngleList, 'outTangentTypeList': outTangentTypeList, 'outTangentAngleWeightList': outTangentAngleWeightList} nodeAnimInformationDict.setdefault(attributeName, attributeDataDict) animDataDict.setdefault(currentObject.encode(), nodeAnimInformationDict) # Data History owner = os.getenv('USERNAME') time = datetime.datetime.now().strftime("%A, %B, %d, %Y %H:%M %p") mayaVersion = cmds.about(q=1, v=1) version = '0.1' dataList = {'animCurve': animDataDict, 'history': [owner, time, mayaVersion, version]} dataPath = '%s/%s.anim' % (animPath, animName) if os.path.isfile(dataPath): try: os.chmod(dataPath, 0777) os.remove(dataPath) except Exception, result: print result
def pasteAnimation(): '''一時ファイルからアニメーションデータを読み込み、クリップボードに再登録 する。その後、選択されたオブジェクトにアニメーションのペーストを試みる。 ''' # jsonデータの読み込み jsonPath = 'C:/Users/0300091280/Desktop/hoge.json' with open(jsonPath, 'r') as jsonFile: animData = json.load(jsonFile) clipboard = oma.MAnimCurveClipboard.theAPIClipboard clipboard.clear() clipItems = list() # progress bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') mc.progressBar(gMainProgressBar, edit=True, beginProgress=True, isInterruptable=False, status='Import Animation Clipboard ...', maxValue=len(animData['animData'])) # アニメ情報を読み込んでMFnAnimCurveを作り、クリップボードに格納する。 for curveData in animData['animData']: # カーブタイプを取り出し、MFnAnimCurveを作る。 curveType = curveData['curveType'] animCurve = oma.MFnAnimCurve() animCurveObj = animCurve.create(curveType) # カーブ固有の情報をセット animCurve.setIsWeighted(curveData['isWeight']) animCurve.setPreInfinityType(curveData['preInf']) animCurve.setPostInfinityType(curveData['postInf']) # 先に時間情報を30FPS換算に変換しておく convTime = [ om.MTime(x, om.MTime.k30FPS) for x in curveData['keyData']['times'] ] '''上でやってるのはこの処理 convTime = list() for x in curveData['keyData']['times'] : mTime = om.MTime(x, om.MTime.k30FPS) convTime.append(mTime) 速くするなら配列を作るときに先にサイズを確定させる convTime = [ None ] * len(curveData['keyData']['times']) for i in range(len(curveData['keyData']['times'])) : mTime = om.MTime(x, om.MTime.k30FPS) convTime[i] = mTime ''' # キー情報を一気に流し込む animCurve.addKeysWithTangents( convTime, #curveData['keyData']['times'], curveData['keyData']['values'], oma.MFnAnimCurve.kTangentAuto, oma.MFnAnimCurve.kTangentAuto, curveData['keyData']['inTangentType'], curveData['keyData']['outTangentType'], curveData['keyData']['inTangentX'], curveData['keyData']['inTangentY'], curveData['keyData']['outTangentX'], curveData['keyData']['outTangentY'], curveData['keyData']['tangentLock'], curveData['keyData']['weightLock']) # addKeysWithTangents()では個別のタンジェントタイプが反映されないので、 # キー毎にタンジェントを設定。ついでにisBreakdownもセットする。 for i in range(len(curveData['keyData']['times'])): inT = curveData['keyData']['inTangentType'][i] outT = curveData['keyData']['outTangentType'][i] breakdown = curveData['keyData']['breakdown'][i] animCurve.setInTangentType(i, inT) animCurve.setOutTangentType(i, outT) animCurve.setIsBreakdown(i, breakdown) # クリップボードアイテムに登録する clipboardItem = oma.MAnimCurveClipboardItem() clipboardItem.setAddressingInfo(curveData['addrInfo'][0], curveData['addrInfo'][1], curveData['addrInfo'][2]) clipboardItem.setNameInfo(curveData['nodeName'], curveData['fullName'], curveData['leafName']) clipboardItem.setAnimCurve(animCurveObj) clipItems.append(clipboardItem) # update progress bar mc.progressBar(gMainProgressBar, edit=True, step=1) # クリップボードに登録 clipboard.set(clipItems) # ペースト時にクリップボードに格納されているノード名と選択されているノード名 # との文字列比較を行うので、まずクリップボードのノード名を取り出す。 clipboardArray = clipboard.clipboardItems() clipboardItemNames = [] for clipboardItem in clipboardArray: clipboardItemNames.append(clipboardItem.nodeName) # 順番はそのままで、重複したノード名を削除する clipboardItemNames = sorted(set(clipboardItemNames), key=clipboardItemNames.index) ''' print '---clipboard item list---' for i in clipboardItemNames: print i ''' # クリップボードに含まれたノード名と選択されたノード名で文字列比較を行い、 # 同じノード名があったら新しい選択リストに登録する。 # これでクリップボードと同じ順番で再選択できる。 selectedItems = mc.ls(selection=True) newSelectionList = [] isNameMatched = False for cItem in clipboardItemNames: cItemSplit = re.split('[:\|]', cItem) for sItem in selectedItems: sItemSplit = re.split('[:\|]', sItem) if cItemSplit[-1] == sItemSplit[-1]: newSelectionList.append(sItem) isNameMatched = True break ''' print '---newSelecton item list---' for i in newSelectionList: print i ''' # マッチしたノード名があった場合、クリップボード順になったリストで選択しなおす。 # その後、再選択したノード名とクリップボード内のノード名をもう一度比較し、 # クリップボードにだけ存在するノード名の要素を削除する。 # これをしないと順番が完全に合わない。めんどくさい。 if isNameMatched: mc.select(clear=True) mc.select(newSelectionList) # 再選択したノード名のリスト化 selectedItems = mc.ls(selection=True) sItemSplit = [] for selectedItem in selectedItems: sItemSplit.append(re.split('[:\|]', selectedItem)[-1]) # クリップボード内のノード名のリスト化 cItemSplit = [] for clipboardItem in clipboardArray: cNodeName = clipboardItem.nodeName cItemSplit.append(re.split('[:\|]', cNodeName)[-1]) # 再選択したノード名がクリップボード内に存在するか調べ、 # 存在している=消さないインデックスのリストを作る keepIndex = [] for s in sItemSplit: for i, c in enumerate(cItemSplit): if s == c: keepIndex.append(i) # print 'keepIndex', keepIndex # keepIndexの要素数とクリップボードの要素数を比較し、 # 異なった場合は消す対象が存在するということになる。 delIndex = list(range(len(cItemSplit))) if len(keepIndex) != len(delIndex): delIndex = list(set(delIndex) - set(keepIndex)) # print 'deleteIndex', delIndex for i in reversed(delIndex): clipboardArray.remove(i) # debug クリップボードの中を再確認 ''' for clipboardItem in clipboardArray: animCurveObj = clipboardItem.animCurve animCurve = oma.MFnAnimCurve(animCurveObj) print clipboardItem.nodeName, clipboardItem.leafAttributeName, animCurve.value(0) print mc.ls(selection=True) ''' # いじったclipboardArrayを再度クリップボードにセット clipboard.set(clipboardArray) # タイムスライダーで選択されている時間を取得 aPlayBackSliderPython = mm.eval('$tmpVar=$gPlayBackSlider') rangeArray = mc.timeControl(aPlayBackSliderPython, q=True, rangeArray=True) # 選択されたノードに対してペーストを実行 mc.pasteKey(clipboard='api', time=(rangeArray[0], rangeArray[0]), option='insert') # close progress bar mc.progressBar(gMainProgressBar, edit=True, endProgress=True)
def copyAnimation(): '''選択されたオブジェクトのアニメーションをクリップボードにコピーし、 一時ファイルに書き出す。 時間の選択はタイムスライダーで行う。 時間を選択していない場合はカレントフレームが対象。 ''' selectedItems = mc.ls(selection=True, long=True) # タイムスライダーで選択されている時間を取得 aPlayBackSliderPython = mm.eval('$tmpVar=$gPlayBackSlider') rangeArray = mc.timeControl(aPlayBackSliderPython, q=True, rangeArray=True) # 選択されているオブジェクトのアニメーションをクリップボードにコピー mc.copyKey(selectedItems, clipboard='api', animation='objects', includeUpperBound=True, forceIndependentEulerAngles=True, time=(int(rangeArray[0]), int(rangeArray[1])), option='keys', shape=False) # クリップボードからアニメーションを取り出す clipboard = oma.MAnimCurveClipboard.theAPIClipboard clipboardArray = clipboard.clipboardItems() animData = dict() animData['animData'] = [] # progress bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') mc.progressBar(gMainProgressBar, edit=True, beginProgress=True, isInterruptable=False, status='Export Animation Clipboard ...', maxValue=len(clipboardArray)) # アニメカーブに1つずつアクセス for clipboardItem in clipboardArray: animCurveObj = clipboardItem.animCurve animCurve = oma.MFnAnimCurve(animCurveObj) try: animCurve.animCurveType # アニメカーブがあるかチェック except: pass #print '{0} has no animation curve.'.format(clipboardItem.nodeName) else: # クリップボード再登録時に必要な情報と、アニメカーブ固有の情報を取得。 addr = clipboardItem.getAddressingInfo() animData['animData'].append({ 'addrInfo': [addr[0], addr[1], addr[2]], 'nodeName': clipboardItem.nodeName, 'fullName': clipboardItem.fullAttributeName, 'leafName': clipboardItem.leafAttributeName, 'curveType': animCurve.animCurveType, 'isWeight': animCurve.isWeighted, 'preInf': animCurve.preInfinityType, 'postInf': animCurve.postInfinityType, 'keyData': {} }) # キー情報の取り出し d = { 'times': [], 'values': [], 'inTangentType': [], 'outTangentType': [], 'inTangentX': [], 'inTangentY': [], 'outTangentX': [], 'outTangentY': [], 'tangentLock': [], 'weightLock': [], 'breakdown': [] } for j in range(animCurve.numKeys): d['times'].append(animCurve.input(j).asUnits(om.MTime.k30FPS)) d['values'].append(animCurve.value(j)) d['inTangentType'].append(animCurve.inTangentType(j)) d['outTangentType'].append(animCurve.outTangentType(j)) # animCurve.getTangentXY() is not working... ret = animCurve.getTangentAngleWeight(j, True) d['inTangentX'].append(3 * ret[1] * math.cos(ret[0].value)) d['inTangentY'].append(3 * ret[1] * math.sin(ret[0].value)) ret = animCurve.getTangentAngleWeight(j, False) d['outTangentX'].append(3 * ret[1] * math.cos(ret[0].value)) d['outTangentY'].append(3 * ret[1] * math.sin(ret[0].value)) d['tangentLock'].append(animCurve.tangentsLocked(j)) d['weightLock'].append(animCurve.weightsLocked(j)) d['breakdown'].append(animCurve.isBreakdown(j)) animData['animData'][-1]['keyData'] = d # update progress bar mc.progressBar(gMainProgressBar, edit=True, step=1) # jsonデータとして書き出し jsonPath = 'C:/Users/0300091280/Desktop/hoge.json' with open(jsonPath, 'w') as jsonFile: json.dump(animData, jsonFile) # close progress bar mc.progressBar(gMainProgressBar, edit=True, endProgress=True)
def importAnimCurve( selectionList, animPath, ): animData = open(animPath, 'r') data = json.load(animData) animData.close() if data and selectionList: for eachObject in selectionList: for eachAnimCurveAttribute in data['animCurve'][eachObject]: # get value animCurveType = data['animCurve'][eachObject][ eachAnimCurveAttribute]['animCurveType'] preInfinity = data['animCurve'][eachObject][ eachAnimCurveAttribute]['preInfinity'] postInfinity = data['animCurve'][eachObject][ eachAnimCurveAttribute]['postInfinity'] weightedTangents = data['animCurve'][eachObject][ eachAnimCurveAttribute]['weightedTangents'] numKeys = data['animCurve'][eachObject][ eachAnimCurveAttribute]['numKeys'] timeList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['timeList'] valueList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['valueList'] inTangentTypeList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['inTangentTypeList'] inTangentAngleList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['inTangentAngleList'] inTangentAngleWeightList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['inTangentAngleWeightList'] outTangentTypeList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['outTangentTypeList'] outTangentAngleList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['outTangentAngleList'] outTangentAngleWeightList = data['animCurve'][eachObject][ eachAnimCurveAttribute]['outTangentAngleWeightList'] # convert current object and attribute to a new MPlug object mSelectionList = om.MSelectionList() mSelectionList.add('%s.%s' % (eachObject, eachAnimCurveAttribute)) attributeMPlug = mSelectionList.getPlug(0) connectedList = attributeMPlug.connectedTo(1, 0) # whether to create a new curve or use the existed curve newAnimCurve = 1 if connectedList: connectedNode = connectedList[0].node() if connectedNode.hasFn(om.MFn.kAnimCurve): MFnAnimCurve = oma.MFnAnimCurve(connectedNode) newAnimCurve = 0 if newAnimCurve: MFnAnimCurve = oma.MFnAnimCurve() MFnAnimCurve.create(attributeMPlug, animCurveType) # set value MFnAnimCurve.setPreInfinityType(preInfinity) MFnAnimCurve.setPostInfinityType(postInfinity) MFnAnimCurve.setIsWeighted(weightedTangents) MTimeArray = om.MTimeArray() MDoubleValueList = om.MDoubleArray() for index in range(len(timeList)): MTimeArray.append( om.MTime(timeList[index], om.MTime.uiUnit())) MDoubleValueList.append(valueList[index]) MFnAnimCurve.addKeys(MTimeArray, MDoubleValueList, 0, 0, 1) for index in range(len(timeList)): MFnAnimCurve.setInTangentType(index, inTangentTypeList[index]) MFnAnimCurve.setOutTangentType(index, outTangentTypeList[index]) inTangentAngle = om.MAngle(inTangentAngleList[index]) outTangentAngle = om.MAngle(outTangentAngleList[index]) MFnAnimCurve.setAngle(index, inTangentAngle, 1) MFnAnimCurve.setAngle(index, outTangentAngle, 0) MFnAnimCurve.setWeight(index, inTangentAngleWeightList[index], 1) MFnAnimCurve.setWeight(index, outTangentAngleWeightList[index], 0) # read history historyData = data['history'] historyList = [ 'Owner: %s' % historyData[0], 'Created: %s' % historyData[1], 'Maya version: %s' % historyData[2], 'Module version: %s' % historyData[3] ] return historyList
# convert current object and attribute to a new MPlug object mSelectionList = om.MSelectionList() mSelectionList.add(eachAnimCurveAttribute) attributeMPlug = mSelectionList.getPlug(0) connectedList = attributeMPlug.connectedTo(1, 0) # whether to create a new curve or use the existed curve newAnimCurve = 1 if connectedList: connectedNode = connectedList[0].node() if connectedNode.hasFn(om.MFn.kAnimCurve): MFnAnimCurve = oma.MFnAnimCurve(connectedNode) newAnimCurve = 0 if newAnimCurve: MFnAnimCurve = oma.MFnAnimCurve() MFnAnimCurve.create(attributeMPlug, animCurveType) # set value MFnAnimCurve.setPreInfinityType(preInfinity) MFnAnimCurve.setPostInfinityType(postInfinity) MFnAnimCurve.setIsWeighted(weightedTangents) MTimeArray = om.MTimeArray() MDoubleValueList = om.MDoubleArray()
def createAnimCurve(self,dagNodeFn,dag,attribute): attr = dagNodeFn.attribute(attribute) attrCurve = oma.MFnAnimCurve() attrCurve.create(dag.transform(),attr, None ) return attrCurve
def prepare(mode): """ Prepares the dictionary of animation curves along with values before/after required to interpolate. """ global anim_cache global curve_key_values # get curves if utils.is_graph_editor(): curves = utils.get_selected_anim_curves() plugs = None else: nodes = utils.get_selected_objects() curves, plugs = utils.get_anim_curves_from_objects(nodes) # get prev and next values so we can use them to blend while dragging slider is_default = bool(mode == options.BlendingMode.default) is_curve_tangent = bool(mode == options.BlendingMode.curve) curve_key_values = {} time_range = utils.get_time_slider_range() unit = om.MTime.uiUnit() mtime_range = (om.MTime(time_range[0], unit), om.MTime(time_range[1], unit)) for plug_idx, curve_node in enumerate(curves): curve_fn = oma.MFnAnimCurve(curve_node.object()) default_val = None if is_default: if plugs: default_val = utils.get_attribute_default_value( plugs[plug_idx]) else: default_val = utils.get_anim_curve_default_value(curve_fn) key_group = KeyGroup(key_index=[], value=[], default_value=default_val, prev_value=[], next_value=[], tangent_points=[], has_two_segments=[]) selected_keys = cmds.keyframe(str(curve_fn.absoluteName()), q=True, selected=True, indexValue=True) if time_range[0] - time_range[1] != 0: # time range selected on time slider indices = cmds.keyframe(str(curve_fn.name()), q=True, time=time_range, iv=True) if indices is None: continue if indices[0] == 0: prev_index = 0 else: prev_index = indices[0] - 1 num_keys = curve_fn.numKeys next_index = indices[-1] + 1 if next_index >= num_keys: next_index = num_keys - 1 for idx in indices: add_to_key_group(curve_fn, idx, prev_index, next_index, key_group) if is_curve_tangent: for idx in indices: add_tangent_points_to_key_group(key_group, curve_fn, prev_index, next_index, idx) curve_key_values[curve_fn] = key_group elif selected_keys is not None: # keys selected in graph editor or dope sheet index_group = [] groups = [] # find groups of consecutive key indices index_group.append(selected_keys[0]) for i in range(1, len(selected_keys)): if selected_keys[i] - selected_keys[i - 1] < 2: index_group.append(selected_keys[i]) else: groups.append(index_group) index_group = [selected_keys[i]] # append last iteration groups.append(index_group) for grp in groups: prev_index = max(0, grp[0] - 1) next_index = min(grp[-1] + 1, curve_fn.numKeys - 1) for idx in grp: add_to_key_group(curve_fn, idx, prev_index, next_index, key_group) if is_curve_tangent: for idx in grp: add_tangent_points_to_key_group(key_group, curve_fn, prev_index, next_index, index=idx) curve_key_values[curve_fn] = key_group else: # no time range or keys selected current_index = curve_fn.find(mtime_range[0]) closest_index = curve_fn.findClosest(mtime_range[0]) closest_time = curve_fn.input(closest_index) if current_index is not None: prev_index = max(0, closest_index - 1) next_index = min(curve_fn.numKeys - 1, closest_index + 1) # key exists, so two curve tangent segments if is_curve_tangent: add_tangent_points_to_key_group(key_group, curve_fn, prev_index, next_index, current_index) else: if (closest_time.value - mtime_range[0].value) <= 0: prev_index = closest_index next_index = closest_index + 1 else: prev_index = closest_index - 1 next_index = closest_index if prev_index < 0: prev_index = 0 # add new key value = curve_fn.evaluate(mtime_range[0]) current_index = curve_fn.addKey(mtime_range[0], value, change=anim_cache) next_index = min(curve_fn.numKeys - 1, next_index + 1) # there isn't any key yet, so we only have one tangent segment and thus index=None if is_curve_tangent: add_tangent_points_to_key_group(key_group, curve_fn, prev_index, next_index, index=current_index) add_to_key_group(curve_fn, current_index, prev_index, next_index, key_group) curve_key_values[curve_fn] = key_group
attributeName = MFnAttribute.name # find the attribute that anim curve connected currentPlug = objMFnDPNode.findPlug(attributeName, 1) if currentPlug.connectedTo(1, 0): currentConnectedList = currentPlug.connectedTo(1, 0) # find the connected node type currentConnectNodeMObject = currentConnectedList[0].node() # check it is an anim curve if currentConnectNodeMObject.hasFn(om.MFn.kAnimCurve): # get anim curve MFnAnimCurve = oma.MFnAnimCurve(currentConnectNodeMObject) # get attribute animCurveType = MFnAnimCurve.animCurveType preInfinity = MFnAnimCurve.preInfinityType postInfinity = MFnAnimCurve.postInfinityType weightedTangents = int(MFnAnimCurve.isWeighted) # get value of each key numKeys = MFnAnimCurve.numKeys timeList = [] valueList = [] inTangentTypeList = [] inTangentAngleList = []
def do(): """ Creates a key on all attributes at any time-value, where a key exists in the curves list :return True on complete, False if cancelled :rtype bool """ # get selection if utils.is_graph_editor(): curves = utils.get_selected_anim_curves() else: nodes = utils.get_selected_objects() curves, plugs = utils.get_anim_curves_from_objects(nodes) # get curve functions curve_fns = [] for curve_node in curves: curve_fns.append(oma.MFnAnimCurve(curve_node.object())) if len(curve_fns) == 0: sys.stdout.write('# No anim curves to set keys on\n') return True # get time range time_range = utils.get_time_slider_range() is_range = time_range[0] - time_range[1] != 0 # get time for keyframes times = set() selected_keys = cmds.keyframe( q=True, selected=True, timeChange=True) if is_range is False else None if is_range: unit = om.MTime.uiUnit() min_time = om.MTime(time_range[0], unit) max_time = om.MTime(time_range[1], unit) for curve_fn in curve_fns: start_index = max(0, curve_fn.findClosest( min_time)) # -1 just to be safe, is checked later end_index = min( curve_fn.numKeys, curve_fn.findClosest(max_time)) # +1 just to be safe for i in range(start_index, end_index): times.add(curve_fn.input(i).value) elif selected_keys is not None: times = set(selected_keys) else: for curve_fn in curve_fns: for i in range(curve_fn.numKeys): times.add(curve_fn.input(i).value) # get main progress bar start progress gMainProgressBar = mel.eval('$tmp = $gMainProgressBar') cmds.progressBar(gMainProgressBar, e=True, beginProgress=True, isInterruptable=True, status='Adding keyframes...', maxValue=len(curve_fns)) # convert to MTime() m_times = [] unit = om.MTime.uiUnit() if is_range: for t in times: if time_range[0] <= t <= time_range[1]: m_times.append(om.MTime(t, unit)) else: for t in times: m_times.append(om.MTime(t, unit)) # add keys key_count = 0 cancelled = False for curve_fn in curve_fns: ts = [] vs = [] for mt in m_times: if curve_fn.find(mt) is None: ts.append(mt) vs.append(curve_fn.evaluate(mt)) for t, v in zip(ts, vs): curve_fn.addKey(t, v, change=animdata.anim_cache) key_count += 1 cmds.progressBar(gMainProgressBar, e=True, step=1) if cmds.progressBar(gMainProgressBar, q=True, isCancelled=True): cancelled = True break cmds.progressBar(gMainProgressBar, e=True, endProgress=True) if cancelled: sys.stdout.write('# Keyhammer cancelled...\n') return False else: sys.stdout.write('# Added %d key%s\n' % (key_count, '' if key_count == 1 else 's')) return True