// Description: // Given a clipboard and an ifstream, read the ifstream and add // all of the anim curves described in ther stream into the // API clipboard. // public void readClipboard(ref StreamReaderExt readAnim, MAnimCurveClipboard cb) { // Set the default values for the start and end of the clipboard. // The MAnimCurveClipboard::set() method will examine all of the // anim curves are determine the proper start and end values, if the // start time is greater than the end value. // // By default, the start values are greater than the end values to // ensure correct behavior if the file does not specify the start and // end values. // double startTime = 1.0; double endTime = 0.0; double startUnitless = 1.0; double endUnitless = 0.0; resetUnits(); convertAnglesFromV2To3 = false; convertAnglesFromV3To2 = false; // Read the header. The header officially ends when the first non-header // keyword is found. The header contains clipboard specific information // where the body is anim curve specific. // string dataType = ""; bool hasVersionString = false; while (!readAnim.EndOfStream) { advance(ref readAnim); dataType = asWord(ref readAnim); if (string.Compare(dataType, kAnimVersion) == 0) { string version = asWord(ref readAnim); animVersion = Convert.ToDouble(version); string thisVersion = kAnimVersionString; hasVersionString = true; // Add versioning control here. // if (version != thisVersion) { // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kInvalidVersion); string msg = string.Format(msgFmt, thisVersion, version); MGlobal.displayWarning(msg); } } else if (string.Compare(dataType, kMayaVersion) == 0) { string version = asWord(ref readAnim, true); string currentVersion = MGlobal.mayaVersion; if (currentVersion.Substring(0, 2) == "2.") { string vCheck = version.Substring(0, 2); if (vCheck != "2.") convertAnglesFromV3To2 = true; } else { // If this is a pre-Maya 3.0 file, then the tangent angles // will need to be converted to work in Maya 3.0+ // string vCheck = version.Substring(0, 2); if (vCheck == "2.") { convertAnglesFromV2To3 = true; } } } else if (string.Compare(dataType, kTimeUnit) == 0) { string timeUnitString = asWord(ref readAnim); if (!animUnitNames.setFromName(timeUnitString, ref timeUnit)) { string unitName = ""; timeUnit = MTime.uiUnit; animUnitNames.setToShortName(timeUnit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kTimeUnit, unitName); MGlobal.displayWarning(msg); } } else if (string.Compare(dataType, kLinearUnit) == 0) { string linearUnitString = asWord(ref readAnim); if (!animUnitNames.setFromName(linearUnitString, ref linearUnit)) { string unitName = ""; linearUnit = MDistance.uiUnit; animUnitNames.setToShortName(linearUnit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kLinearUnit, unitName); MGlobal.displayWarning(msg); } } else if (string.Compare(dataType, kAngularUnit) == 0) { string angularUnitString = asWord( ref readAnim); if (!animUnitNames.setFromName(angularUnitString, ref angularUnit)) { string unitName = ""; angularUnit = MAngle.uiUnit; animUnitNames.setToShortName(angularUnit, ref unitName); // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kSettingToUnit); string msg = string.Format(msgFmt, kAngularUnit, unitName); MGlobal.displayWarning(msg); } } else if (string.Compare(dataType, kStartTime) == 0) startTime = asDouble(ref readAnim); else if (string.Compare(dataType, kEndTime) == 0) endTime = asDouble(ref readAnim); else if (string.Compare(dataType, kStartUnitless) == 0) startUnitless = asDouble(ref readAnim); else if (string.Compare(dataType, kEndUnitless) == 0) endUnitless = asDouble(ref readAnim); else { // The header should be finished. Begin to parse the body. // break; } } // The animVersion string is required. // if (!hasVersionString) { // Use format to place variable string into message string msgFmt = MStringResource.getString(RegisterMStringResources.kMissingKeyword); string msg = string.Format(msgFmt, kAnimVersion); throw new ArgumentException(msg, "cb"); } // Set the linear and angular units to be the same as the file // being read. This will allow fixed tangent data to be read // in properly if the scene has different units than the .anim file. // MDistance.Unit oldDistanceUnit = MDistance.uiUnit; MTime.Unit oldTimeUnit = MTime.uiUnit; MDistance.uiUnit = linearUnit; MTime.uiUnit = timeUnit; MAnimCurveClipboardItemArray clipboardArray = new MAnimCurveClipboardItemArray(); while (!readAnim.EndOfStream) { if ("" == dataType) { dataType = asWord(ref readAnim); } if (string.Compare(dataType, kAnim) == 0) { string fullAttributeName = "", leafAttributeName="", nodeName = ""; // If this is from an unconnected anim curve, then there // will not be an attribute name. // if (!isNextNumeric(ref readAnim)) { fullAttributeName = asWord(ref readAnim); // If the node names were specified, then the next two // words should be the leaf attribute and the node name. // if (!isNextNumeric(ref readAnim)) { leafAttributeName = asWord(ref readAnim); nodeName = asWord(ref readAnim); } } uint rowCount, childCount, attrCount; rowCount = (uint)asDouble(ref readAnim); childCount = (uint)asDouble(ref readAnim); attrCount = (uint)asDouble(ref readAnim); // If the next keyword is not an animData, then this is // a place holder for the API clipboard. // dataType = asWord(ref readAnim); if (string.Compare(dataType, kAnimData) == 0) { MAnimCurveClipboardItem clipboardItem = new MAnimCurveClipboardItem(); if (readAnimCurve(ref readAnim, ref clipboardItem)) { clipboardItem.setAddressingInfo(rowCount, childCount, attrCount); clipboardItem.setNameInfo( nodeName, fullAttributeName, leafAttributeName); clipboardArray.append(clipboardItem); } else { // Could not read the anim curve. // string msg = MStringResource.getString(RegisterMStringResources.kCouldNotReadAnim); MGlobal.displayError(msg); } } else { // This must be a place holder object for the clipboard. // MAnimCurveClipboardItem clipboardItem = new MAnimCurveClipboardItem(); clipboardItem.setAddressingInfo(rowCount, childCount, attrCount); // Since there is no anim curve specified, what is // in the fullAttributeName string is really the node // name. // clipboardItem.setNameInfo( fullAttributeName, nodeName, leafAttributeName); clipboardArray.append(clipboardItem); // dataType already contains the next keyword. // continue; } } else { if (!readAnim.EndOfStream) { 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); // Skip to the next line, this one is invalid. // readAnim.ReadLine(); } else { // The end of the file was reached. // break; } } // Skip any whitespace. // dataType = ""; } try { cb.set( clipboardArray, new MTime(startTime, timeUnit), new MTime(endTime, timeUnit), (float) startUnitless, (float) endUnitless) ; } catch (System.Exception) { string msg = MStringResource.getString(RegisterMStringResources.kClipboardFailure); MGlobal.displayError(msg); } // Restore the old units. // MDistance.uiUnit = oldDistanceUnit; MTime.uiUnit = oldTimeUnit; }
// 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; }
// Description: // Write out the anim curve from the clipboard item into the // stream. The position of the anim curve in the clipboard // and the attribute to which it is attached is written out in this // method. // // This method returns true if the write was successful. // protected void writeAnim( ref StreamWriter clip, MAnimCurveClipboardItem clipboardItem, bool placeHolder = false, bool nodeNames = false) { if (clip == null) { throw new ArgumentNullException( "clip" ); } clip.Write(kAnim); // If this is a clipboard place holder then there will be no full // or leaf attribute names. // if (placeHolder) { clip.Write(kSpaceChar + clipboardItem.nodeName ); } else { clip.Write(kSpaceChar + clipboardItem.fullAttributeName); if (nodeNames) { clip.Write( kSpaceChar + clipboardItem.leafAttributeName); clip.Write( kSpaceChar + clipboardItem.nodeName ); } } uint rowCount = 0, childCount = 0, attrCount = 0; clipboardItem.getAddressingInfo(ref rowCount, ref childCount, ref attrCount); clip.Write( kSpaceChar); clip.Write(rowCount); clip.Write(kSpaceChar); clip.Write(childCount); clip.Write(kSpaceChar); clip.Write(attrCount); clip.Write(kSemiColonChar); clip.Write(Environment.NewLine); }
protected void writeAnim( ref StreamWriter clip, MAnimCurveClipboardItem clipboardItem, bool placeHolder = false, bool nodeNames = false) // Description: // Write out the anim curve from the clipboard item into the // stream. The position of the anim curve in the clipboard // and the attribute to which it is attached is written out in this // method. // // This method returns true if the write was successful. // { if (clip == null) { throw new ArgumentNullException( "clip" ); } clip.Write(kAnim); // If this is a clipboard place holder then there will be no full // or leaf attribute names. // if (placeHolder) { clip.Write(kSpaceChar + clipboardItem.nodeName ); } else { clip.Write(kSpaceChar + clipboardItem.fullAttributeName); if (nodeNames) { clip.Write( kSpaceChar + clipboardItem.leafAttributeName); clip.Write( kSpaceChar + clipboardItem.nodeName ); } } uint rowCount = 0, childCount = 0, attrCount = 0; clipboardItem.getAddressingInfo(ref rowCount, ref childCount, ref attrCount); clip.Write( kSpaceChar); clip.Write(rowCount); clip.Write(kSpaceChar); clip.Write(childCount); clip.Write(kSpaceChar); clip.Write(attrCount); clip.Write(kSemiColonChar); clip.Write(Environment.NewLine); }