// Description: // Read a block of the stream that should contain anim curve // data in the format determined by the animData keyword. // protected bool readAnimCurve(ref StreamReaderExt clipFile, ref MAnimCurveClipboardItem item) { MFnAnimCurve animCurve = new MFnAnimCurve(); MObject animCurveObj = new MObject(); // Anim curve defaults. // animBase.AnimBaseType input = wordAsInputType(kWordTypeTime); animBase.AnimBaseType output = wordAsOutputType(kWordTypeLinear); MFnAnimCurve.InfinityType preInf = wordAsInfinityType(kWordConstant); MFnAnimCurve.InfinityType postInf = wordAsInfinityType(kWordConstant); string inputUnitName = ""; animUnitNames.setToShortName(timeUnit, ref inputUnitName); string outputUnitName = ""; MAngle.Unit tanAngleUnit = angularUnit; bool isWeighted = false; string dataType = ""; while (!clipFile.EndOfStream) { advance(ref clipFile); dataType = asWord(ref clipFile); if (string.Compare(dataType, kInputString) == 0) { input = wordAsInputType(asWord(ref clipFile)); } else if (string.Compare(dataType, kOutputString) == 0) { output = wordAsOutputType(asWord(ref clipFile)); } else if (string.Compare(dataType, kWeightedString) == 0) { isWeighted = (asDouble(ref clipFile) == 1.0); } else if (string.Compare(dataType, kPreInfinityString) == 0) { preInf = wordAsInfinityType(asWord(ref clipFile)); } else if (string.Compare(dataType, kPostInfinityString) == 0) { postInf = wordAsInfinityType(asWord(ref clipFile)); } else if (string.Compare(dataType, kInputUnitString) == 0) { inputUnitName = asWord(ref clipFile); } else if (string.Compare(dataType, kOutputUnitString) == 0) { outputUnitName = asWord(ref clipFile); } else if (string.Compare(dataType, kTanAngleUnitString) == 0) { string tUnit = asWord(ref clipFile); if (!animUnitNames.setFromName(tUnit, ref tanAngleUnit)) { string unitName=""; tanAngleUnit = angularUnit; animUnitNames.setToShortName(tanAngleUnit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingTanAngleUnit); string msg = string.Format(msgFmt, unitName); MGlobal.displayError(msg); } } else if (string.Compare(dataType, kKeysString) == 0) { // Ignore the rest of this line. // clipFile.ReadLine(); break; } else if (string.Compare(dataType, "{") == 0) { // Skippping the '{' character. Just ignore it. // continue; } else { // An unrecogized keyword was found. // string warnStr = (dataType); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kUnknownKeyword); string msg = string.Format(msgFmt, warnStr); MGlobal.displayError(msg); continue; } } // Read the animCurve // MFnAnimCurve.AnimCurveType type = typeAsAnimCurveType(input, output); try { animCurveObj = animCurve.create(type,null); } catch (System.Exception ) { string msg = MStringResource.getString(RegisterMStringResources.kCouldNotCreateAnim); MGlobal.displayError(msg); return false; } animCurve.setIsWeighted(isWeighted); animCurve.setPreInfinityType(preInf); animCurve.setPostInfinityType(postInf); // Set the appropriate units. // MTime.Unit inputTimeUnit = MTime.Unit.kInvalid; if (input == AnimBaseType.kAnimBaseTime) { if (!animUnitNames.setFromName(inputUnitName, ref inputTimeUnit)) { string unitName = ""; inputTimeUnit = timeUnit; animUnitNames.setToShortName(inputTimeUnit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kInputUnitString, unitName); MGlobal.displayWarning(msg); } } MTime.Unit outputTimeUnit= MTime.Unit.kInvalid; if (output == AnimBaseType.kAnimBaseTime) { if (!animUnitNames.setFromName(outputUnitName, ref outputTimeUnit)) { string unitName = ""; outputTimeUnit = timeUnit; animUnitNames.setToShortName(outputTimeUnit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kOutputUnitString, unitName); MGlobal.displayWarning(msg); } } uint index = 0; double conversion = 1.0; if (output == AnimBaseType.kAnimBaseLinear) { MDistance.Unit unit = MDistance.Unit.kInvalid; if (outputUnitName.Length != 0) { if (!animUnitNames.setFromName(outputUnitName, ref unit)) { string unitName = ""; unit = linearUnit; animUnitNames.setToShortName(unit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kOutputUnitString, unitName); MGlobal.displayWarning(msg); } } else unit = linearUnit; if (unit != MDistance.Unit.kCentimeters) { MDistance one = new MDistance(1.0, unit); conversion = one.asCentimeters; } } else if (output == AnimBaseType.kAnimBaseAngular) { MAngle.Unit unit = MAngle.Unit.kInvalid; if (outputUnitName.Length != 0) { if (!animUnitNames.setFromName(outputUnitName, ref unit)) { string unitName = ""; unit = angularUnit; animUnitNames.setToShortName(unit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kOutputUnitString, unitName); MGlobal.displayWarning(msg); } } else unit = angularUnit; if (unit != MAngle.Unit.kRadians) { MAngle one = new MAngle(1.0, unit); conversion = one.asRadians; } } // Now read each keyframe // advance(ref clipFile); char c = (char)clipFile.Peek(); while (!clipFile.EndOfStream && c != kBraceRightChar) { double t = asDouble(ref clipFile); double val = asDouble(ref clipFile); MFnAnimCurve.TangentType tanIn = wordAsTangentType(asWord(ref clipFile)); MFnAnimCurve.TangentType tanOut = wordAsTangentType(asWord(ref clipFile)); switch (type) { case MFnAnimCurve.AnimCurveType.kAnimCurveTT: index = animCurve.addKey( new MTime(val, inputTimeUnit), new MTime(val, outputTimeUnit), tanIn, tanOut, null); break; case MFnAnimCurve.AnimCurveType.kAnimCurveTL: case MFnAnimCurve.AnimCurveType.kAnimCurveTA: case MFnAnimCurve.AnimCurveType.kAnimCurveTU: index = animCurve.addKey( new MTime(t, inputTimeUnit), val*conversion, tanIn, tanOut, null); break; case MFnAnimCurve.AnimCurveType.kAnimCurveUL: case MFnAnimCurve.AnimCurveType.kAnimCurveUA: case MFnAnimCurve.AnimCurveType.kAnimCurveUU: index = animCurve.addKey( t, val*conversion, tanIn, tanOut, null); break; case MFnAnimCurve.AnimCurveType.kAnimCurveUT: index = animCurve.addKey( t, new MTime(val, outputTimeUnit), tanIn, tanOut, null); break; default: string msg = MStringResource.getString(RegisterMStringResources.kUnknownNode); MGlobal.displayError(msg); return false; } // Tangent locking needs to be called after the weights and // angles are set for the fixed tangents. // bool tLocked = asDouble(ref clipFile) == 1.0; bool swLocked = asDouble(ref clipFile) == 1.0; bool isBreakdown = false; if (animVersion >= kVersionNonWeightedAndBreakdowns) { isBreakdown = (asDouble(ref clipFile) == 1.0); } // Only fixed tangents need additional information. // if (tanIn == MFnAnimCurve.TangentType.kTangentFixed) { MAngle inAngle = new MAngle(asDouble(ref clipFile), tanAngleUnit); double inWeight = asDouble(ref clipFile); // If this is from a pre-Maya3.0 file, the tangent angles will // need to be converted. // if (convertAnglesFromV2To3) { convertAnglesAndWeights2To3(type,isWeighted,ref inAngle,ref inWeight); } else if (convertAnglesFromV3To2) { convertAnglesAndWeights3To2(type,isWeighted,ref inAngle,ref inWeight); } // By default, the tangents are locked. When the tangents // are locked, setting the angle and weight of a fixed in // tangent may change the tangent type of the out tangent. // animCurve.setTangentsLocked(index, false); animCurve.setTangent(index, inAngle, inWeight, true); } // Only fixed tangents need additional information. // if (tanOut == MFnAnimCurve.TangentType.kTangentFixed) { MAngle outAngle = new MAngle(asDouble(ref clipFile), tanAngleUnit); double outWeight = asDouble(ref clipFile); // If this is from a pre-Maya3.0 file, the tangent angles will // need to be converted. // if (convertAnglesFromV2To3) { convertAnglesAndWeights2To3(type,isWeighted,ref outAngle,ref outWeight); } else if (convertAnglesFromV3To2) { convertAnglesAndWeights3To2(type,isWeighted,ref outAngle,ref outWeight); } // By default, the tangents are locked. When the tangents // are locked, setting the angle and weight of a fixed out // tangent may change the tangent type of the in tangent. // animCurve.setTangentsLocked(index, false); animCurve.setTangent(index, outAngle, outWeight, false); } // To prevent tangent types from unexpectedly changing, tangent // locking should be the last operation. See the above comments // about fixed tangent types for more information. // animCurve.setWeightsLocked(index, swLocked); animCurve.setTangentsLocked(index, tLocked); animCurve.setIsBreakdown (index, isBreakdown); // There should be no additional data on this line. Go to the // next line of data. // clipFile.ReadLine(); // Skip any comments. // advance(ref clipFile); c = (char)clipFile.Peek(); } // Ignore the brace that marks the end of the keys block. // if (c == kBraceRightChar) { clipFile.ReadLine(); } // Ignore the brace that marks the end of the animData block. // advance(ref clipFile); if ( (char)clipFile.Peek() == kBraceRightChar) { clipFile.ReadLine(); } else { // Something is wrong. // string msg = MStringResource.getString(RegisterMStringResources.kMissingBrace); MGlobal.displayError(msg); } // Do not set the clipboard with an empty clipboard item. // if (!animCurveObj.isNull) { item.animCurve = animCurveObj; } // Delete the copy of the anim curve. // MGlobal.deleteNode(animCurveObj); return true; }