void connectMStringArray(MString& des, const MStringArray& src) { des.clear(); for(std::size_t i=0; i<src.length(); ++i){ des += src[ i ] + ","; } }
//----------------------------------------------------------------------------- // Adds a color set to the input history of the passed mesh //----------------------------------------------------------------------------- MObject ValveMaya::AddColorSetToMesh( const MString &colorSetName, const MDagPath &mDagPath, MDagModifier &mDagModifier ) { if ( !mDagPath.hasFn( MFn::kMesh ) ) return MObject::kNullObj; MFnMesh meshFn( mDagPath ); MString uniqueColorSetName; { MStringArray colorSetNames; meshFn.getColorSetNames( colorSetNames ); const uint nColorSets( colorSetNames.length() ); for ( int i( 0 ); uniqueColorSetName.length() == 0; ++i ) { uniqueColorSetName = colorSetName; if ( i > 0 ) { uniqueColorSetName += i; } for ( uint j( 0U ); j != nColorSets; ++j ) { if ( uniqueColorSetName == colorSetNames[ j ] ) { uniqueColorSetName.clear(); break; } } } } // Create a 'createColorSet' node MObject ccsObj( mDagModifier.MDGModifier::createNode( "createColorSet" ) ); mDagModifier.doIt(); const MFnDependencyNode ccsFn( ccsObj ); MPlug csnP( ccsFn.findPlug( "colorSetName" ) ); csnP.setValue( uniqueColorSetName ); // Insert it in the history of the mesh MPlug inMeshP( meshFn.findPlug( "inMesh" ) ); MPlugArray mPlugArray; if ( inMeshP.connectedTo( mPlugArray, true, false ) && mPlugArray.length() ) { mDagModifier.disconnect( mPlugArray[ 0 ], inMeshP ); mDagModifier.connect( mPlugArray[ 0 ], ccsFn.findPlug( "inputGeometry" ) ); } mDagModifier.connect( ccsFn.findPlug( "outputGeometry" ), inMeshP ); mDagModifier.doIt(); return ccsObj; }
MStringArray boingRbCmd::parseArguments(MString arg, MString token) { MStringArray jobArgsArray; MString stringBuffer; for (unsigned int charIdx = 0; charIdx < arg.numChars(); charIdx++) { MString ch = arg.substringW(charIdx, charIdx); //cout<<"ch = "<<ch<<endl; if (ch == token ) { if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); //cout<<"jobArgsArray = "<<jobArgsArray<<endl; stringBuffer.clear(); } } else { stringBuffer += ch; //cout<<"stringBuffer = "<<stringBuffer<<endl; } } jobArgsArray.append(stringBuffer); return jobArgsArray; }
// Write method of the GE2.0 translator / file exporter MStatus ge2Translator::writer ( const MFileObject & fileObject, const MString & options, MPxFileTranslator::FileAccessMode mode) { char LTmpStr[MAXPATHLEN]; unsigned int i, LN; // const MString fname = fileObject.fullName (); MString extension; MString baseFileName; // Lets strip off the known extension of .grp if it is there. extension.set (".grp"); int extLocation = fileObject.name ().rindex ('.'); if ( (extLocation != -1) && // no '.' in name (extLocation != 0) && // name was ".grp" -- that's ok?? (fileObject.name ().substring (extLocation, fileObject.name ().length () - 1) == extension) ) { baseFileName = fileObject.name ().substring (0, extLocation - 1); } else { baseFileName = fileObject.name (); extension.clear (); } geWrapper.setBaseFileName( baseFileName ); geWrapper.setPathName( fileObject.fullName() ); geWrapper.pluginVersion = version; // Set the directory at the Dt level strncpy( LTmpStr, geWrapper.getPathName().asChar(), MAXPATHLEN ); LN = (int)strlen( LTmpStr ); if ( LTmpStr[LN - 1] == '/' ) LTmpStr[LN - 1] = '\0'; DtSetDirectory( LTmpStr ); // in an ideal world, everything in setDefaults() should be overridden // with the option parsing. If the mel script doesn't get run for whatever // reason, or neglects to return some values, hopefully setDefaults will // enable the export to go through anyway geWrapper.setDefaults(); // Turn off this pesky warning on NT - performance warning // for int -> bool conversion. #ifdef WIN32 #pragma warning ( disable : 4800 ) #endif // Lets now do all of the option processing if ( options.length () > 0 ) { //Start parsing. MStringArray optionList; MStringArray theOption; options.split(';', optionList); //break out all the options. for ( i = 0; i < optionList.length (); ++i ) { theOption.clear (); optionList[i].split( '=', theOption ); if ( theOption.length () > 1 ) { if ( theOption[0] == MString( "enableAnim" ) ) { geWrapper.enableAnim = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animStart" ) ) { geWrapper.frameStart = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animEnd" ) ) { geWrapper.frameEnd = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animStep" ) ) { geWrapper.frameStep = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animVertices" ) ) { geWrapper.animVertices = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animDisplacement" ) ) { if ( theOption[1].asInt() == 1 ) geWrapper.vertexDisplacement = ge2Wrapper::kVDRelative; else geWrapper.vertexDisplacement = ge2Wrapper::kVDAbsolute; } else if ( theOption[0] == MString( "animTransforms" ) ) { geWrapper.animTransforms = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animShaders" ) ) { geWrapper.animShaders = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animLights" ) ) { geWrapper.animLights = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "animCamera" ) ) { geWrapper.animCamera = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "keyCurves" ) ) { geWrapper.keyCurves = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "keySample" ) ) { geWrapper.keySample = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "sampRate" ) ) { geWrapper.sampleRate = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "sampTol" ) ) { geWrapper.sampleTolerance = (float) ( theOption[1].asFloat() ); } else if ( theOption[0] == MString( "useGL" ) ) { geWrapper.useDomainGL = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "usePSX" ) ) { geWrapper.useDomainPSX = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "useN64" ) ) { geWrapper.useDomainN64 = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "useCustom" ) ) { geWrapper.useDomainCustom = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "hrcType" ) ) { geWrapper.hrcMode = static_cast <ge2Wrapper::GEHrcMode> ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "exportSel" ) ) { geWrapper.selType = static_cast <ge2Wrapper::GESelType> ( theOption[1].asInt() ); if ( (mode == MPxFileTranslator::kExportActiveAccessMode) && (geWrapper.selType == ge2Wrapper::kSelAll) ) { geWrapper.selType = ge2Wrapper::kSelActive; } } else if ( theOption[0] == MString( "exportLights" ) ) { geWrapper.outputLights = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "exportCamera" ) ) { geWrapper.outputCamera = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "exportJoints" ) ) { geWrapper.outputJoints = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "exportNormals" ) ) { geWrapper.outputNormals = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "opposite" ) ) { geWrapper.oppositeNormals = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "exportGeometry" ) ) { geWrapper.outputGeometry = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "reverse" ) ) { geWrapper.reverseWinding = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "exportTextures" ) ) { geWrapper.outputTextures = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "tesselation" ) ) { if ( theOption[1].asInt() == 2 ) DtExt_setTesselate( kTESSQUAD ); else DtExt_setTesselate( kTESSTRI ); } else if ( theOption[0] == MString( "texsample" ) ) { geWrapper.sampleTextures = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "texevaluate" ) ) { geWrapper.evalTextures = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "texOriginal" ) ) { geWrapper.useOriginalFileTextures = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "Xtexres" ) ) { geWrapper.xTexRes = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "Ytexres" ) ) { geWrapper.yTexRes = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "MaxXtexres" ) ) { geWrapper.xMaxTexRes = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "MaxYtexres" ) ) { geWrapper.yMaxTexRes = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "texType" ) ) { geWrapper.texType = theOption[1]; } else if ( theOption[0] == MString( "precision" ) ) { geWrapper.precision = (int) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "format" ) ) { geWrapper.useTabs = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "comments" ) ) { geWrapper.writeComments = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "verboseGeom" ) ) { geWrapper.verboseGeom = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "verboseLgt" ) ) { geWrapper.verboseLgt = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "verboseCam" ) ) { geWrapper.verboseCam = (bool) ( theOption[1].asInt() ); } else if ( theOption[0] == MString( "script" ) ) { geWrapper.userScript = theOption[1]; } else if ( theOption[0] == MString( "scriptAppend" ) ) { geWrapper.scriptAppendFileName = (int) ( theOption[1].asInt() ); } } } } #ifdef WIN32 #pragma warning ( default : 4800 ) #endif geWrapper.initScene(); // do some initialization geWrapper.writeScene(); // write it to the appropriate files geWrapper.killScene(); // clean-up return MS::kSuccess; }
MStatus AbcExport::doIt(const MArgList & args) { try { MStatus status; MTime oldCurTime = MAnimControl::currentTime(); MArgParser argData(syntax(), args, &status); if (argData.isFlagSet("help")) { MGlobal::displayInfo(util::getHelpText()); return MS::kSuccess; } bool verbose = argData.isFlagSet("verbose"); // If skipFrame is true, when going through the playback range of the // scene, as much frames are skipped when possible. This could cause // a problem for, time dependent solutions like // particle system / hair simulation bool skipFrame = true; if (argData.isFlagSet("dontSkipUnwrittenFrames")) skipFrame = false; double startEvaluationTime = DBL_MAX; if (argData.isFlagSet("preRollStartFrame")) { double startAt = 0.0; argData.getFlagArgument("preRollStartFrame", 0, startAt); startEvaluationTime = startAt; } unsigned int jobSize = argData.numberOfFlagUses("jobArg"); if (jobSize == 0) return status; // the frame range we will be iterating over for all jobs, // includes frames which are not skipped and the startAt offset std::set<double> allFrameRange; // this will eventually hold only the animated jobs. // its a list because we will be removing jobs from it std::list < AbcWriteJobPtr > jobList; for (unsigned int jobIndex = 0; jobIndex < jobSize; jobIndex++) { JobArgs jobArgs; MArgList jobArgList; argData.getFlagArgumentList("jobArg", jobIndex, jobArgList); MString jobArgsStr = jobArgList.asString(0); MStringArray jobArgsArray; { // parse the job arguments // e.g. -perFrameCallbackMel "print \"something\"" will be splitted to // [0] -perFrameCallbackMel // [1] print "something" enum State { kArgument, // parsing an argument (not quoted) kDoubleQuotedString, // parsing a double quoted string kSingleQuotedString, // parsing a single quoted string }; State state = kArgument; MString stringBuffer; for (unsigned int charIdx = 0; charIdx < jobArgsStr.numChars(); charIdx++) { MString ch = jobArgsStr.substringW(charIdx, charIdx); switch (state) { case kArgument: if (ch == " ") { // space terminates the current argument if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); stringBuffer.clear(); } // goto another argument state = kArgument; } else if (ch == "\"") { if (stringBuffer.length() > 0) { // double quote is part of the argument stringBuffer += ch; } else { // goto double quoted string state = kDoubleQuotedString; } } else if (ch == "'") { if (stringBuffer.length() > 0) { // single quote is part of the argument stringBuffer += ch; } else { // goto single quoted string state = kSingleQuotedString; } } else { stringBuffer += ch; } break; case kDoubleQuotedString: // double quote terminates the current string if (ch == "\"") { jobArgsArray.append(stringBuffer); stringBuffer.clear(); state = kArgument; } else if (ch == "\\") { // escaped character MString nextCh = (++charIdx < jobArgsStr.numChars()) ? jobArgsStr.substringW(charIdx, charIdx) : "\\"; if (nextCh == "n") stringBuffer += "\n"; else if (nextCh == "t") stringBuffer += "\t"; else if (nextCh == "r") stringBuffer += "\r"; else if (nextCh == "\\") stringBuffer += "\\"; else if (nextCh == "'") stringBuffer += "'"; else if (nextCh == "\"") stringBuffer += "\""; else stringBuffer += nextCh; } else { stringBuffer += ch; } break; case kSingleQuotedString: // single quote terminates the current string if (ch == "'") { jobArgsArray.append(stringBuffer); stringBuffer.clear(); state = kArgument; } else if (ch == "\\") { // escaped character MString nextCh = (++charIdx < jobArgsStr.numChars()) ? jobArgsStr.substringW(charIdx, charIdx) : "\\"; if (nextCh == "n") stringBuffer += "\n"; else if (nextCh == "t") stringBuffer += "\t"; else if (nextCh == "r") stringBuffer += "\r"; else if (nextCh == "\\") stringBuffer += "\\"; else if (nextCh == "'") stringBuffer += "'"; else if (nextCh == "\"") stringBuffer += "\""; else stringBuffer += nextCh; } else { stringBuffer += ch; } break; } } // the rest of the argument if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); } } // the frame range within this job std::vector< FrameRangeArgs > frameRanges(1); frameRanges.back().startTime = oldCurTime.value(); frameRanges.back().endTime = oldCurTime.value(); frameRanges.back().strideTime = 1.0; bool hasRange = false; bool hasRoot = false; bool sampleGeo = true; // whether or not to subsample geometry std::string fileName; bool asOgawa = true; unsigned int numJobArgs = jobArgsArray.length(); for (unsigned int i = 0; i < numJobArgs; ++i) { MString arg = jobArgsArray[i]; arg.toLowerCase(); if (arg == "-f" || arg == "-file") { if (i+1 >= numJobArgs) { MGlobal::displayError("File incorrectly specified."); return MS::kFailure; } fileName = jobArgsArray[++i].asChar(); } else if (arg == "-fr" || arg == "-framerange") { if (i+2 >= numJobArgs || !jobArgsArray[i+1].isDouble() || !jobArgsArray[i+2].isDouble()) { MGlobal::displayError("Frame Range incorrectly specified."); return MS::kFailure; } // this is not the first -frameRange argument, we are going // to add one more frame range to the frame range array. if (hasRange) { frameRanges.push_back(FrameRangeArgs()); } hasRange = true; frameRanges.back().startTime = jobArgsArray[++i].asDouble(); frameRanges.back().endTime = jobArgsArray[++i].asDouble(); // make sure start frame is smaller or equal to endTime if (frameRanges.back().startTime > frameRanges.back().endTime) { std::swap(frameRanges.back().startTime, frameRanges.back().endTime); } } else if (arg == "-frs" || arg == "-framerelativesample") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble()) { MGlobal::displayError( "Frame Relative Sample incorrectly specified."); return MS::kFailure; } frameRanges.back().shutterSamples.insert( jobArgsArray[++i].asDouble()); } else if (arg == "-nn" || arg == "-nonormals") { jobArgs.noNormals = true; } else if (arg == "-pr" || arg == "-preroll") { frameRanges.back().preRoll = true; } else if (arg == "-ro" || arg == "-renderableonly") { jobArgs.excludeInvisible = true; } else if (arg == "-s" || arg == "-step") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble()) { MGlobal::displayError("Step incorrectly specified."); return MS::kFailure; } frameRanges.back().strideTime = jobArgsArray[++i].asDouble(); } else if (arg == "-sl" || arg == "-selection") { jobArgs.useSelectionList = true; } else if (arg == "-sn" || arg == "-stripnamespaces") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isUnsigned()) { // the strip all namespaces case // so we pick a very LARGE number jobArgs.stripNamespace = 0xffffffff; } else { jobArgs.stripNamespace = jobArgsArray[++i].asUnsigned(); } } else if (arg == "-uv" || arg == "-uvwrite") { jobArgs.writeUVs = true; } else if (arg == "-wcs" || arg == "-writecolorsets") { jobArgs.writeColorSets = true; } else if (arg == "-wfs" || arg == "-writefacesets") { jobArgs.writeFaceSets = true; } else if (arg == "-wfg" || arg == "-wholeframegeo") { sampleGeo = false; } else if (arg == "-ws" || arg == "-worldspace") { jobArgs.worldSpace = true; } else if (arg == "-wuvs" || arg == "-writeuvsets") { jobArgs.writeUVSets = true; } else if (arg == "-wv" || arg == "-writevisibility") { jobArgs.writeVisibility = true; } else if (arg == "-as" || arg == "-autosubd") { jobArgs.autoSubd = true; } else if (arg == "-mfc" || arg == "-melperframecallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "melPerFrameCallback incorrectly specified."); return MS::kFailure; } jobArgs.melPerFrameCallback = jobArgsArray[++i].asChar(); } else if (arg == "-pfc" || arg == "-pythonperframecallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "pythonPerFrameCallback incorrectly specified."); return MS::kFailure; } jobArgs.pythonPerFrameCallback = jobArgsArray[++i].asChar(); } else if (arg == "-mpc" || arg == "-melpostjobcallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "melPostJobCallback incorrectly specified."); return MS::kFailure; } jobArgs.melPostCallback = jobArgsArray[++i].asChar(); } else if (arg == "-ppc" || arg == "-pythonpostjobcallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "pythonPostJobCallback incorrectly specified."); return MS::kFailure; } jobArgs.pythonPostCallback = jobArgsArray[++i].asChar(); } // geomArbParams - attribute filtering stuff else if (arg == "-atp" || arg == "-attrprefix") { if (i+1 >= numJobArgs) { MGlobal::displayError( "attrPrefix incorrectly specified."); return MS::kFailure; } jobArgs.prefixFilters.push_back(jobArgsArray[++i].asChar()); } else if (arg == "-a" || arg == "-attr") { if (i+1 >= numJobArgs) { MGlobal::displayError( "attr incorrectly specified."); return MS::kFailure; } jobArgs.attribs.insert(jobArgsArray[++i].asChar()); } // userProperties - attribute filtering stuff else if (arg == "-uatp" || arg == "-userattrprefix") { if (i+1 >= numJobArgs) { MGlobal::displayError( "userAttrPrefix incorrectly specified."); return MS::kFailure; } jobArgs.userPrefixFilters.push_back(jobArgsArray[++i].asChar()); } else if (arg == "-u" || arg == "-userattr") { if (i+1 >= numJobArgs) { MGlobal::displayError( "userAttr incorrectly specified."); return MS::kFailure; } jobArgs.userAttribs.insert(jobArgsArray[++i].asChar()); } else if (arg == "-rt" || arg == "-root") { if (i+1 >= numJobArgs) { MGlobal::displayError( "root incorrectly specified."); return MS::kFailure; } hasRoot = true; MString root = jobArgsArray[++i]; MSelectionList sel; if (sel.add(root) != MS::kSuccess) { MString warn = root; warn += " could not be select, skipping."; MGlobal::displayWarning(warn); continue; } unsigned int numRoots = sel.length(); for (unsigned int j = 0; j < numRoots; ++j) { MDagPath path; if (sel.getDagPath(j, path) != MS::kSuccess) { MString warn = path.fullPathName(); warn += " (part of "; warn += root; warn += " ) not a DAG Node, skipping."; MGlobal::displayWarning(warn); continue; } jobArgs.dagPaths.insert(path); } } else if (arg == "-ef" || arg == "-eulerfilter") { jobArgs.filterEulerRotations = true; } else if (arg == "-df" || arg == "-dataformat") { if (i+1 >= numJobArgs) { MGlobal::displayError( "dataFormat incorrectly specified."); return MS::kFailure; } MString dataFormat = jobArgsArray[++i]; dataFormat.toLowerCase(); if (dataFormat == "hdf") { asOgawa = false; } else if (dataFormat == "ogawa") { asOgawa = true; } } else { MString warn = "Ignoring unsupported flag: "; warn += jobArgsArray[i]; MGlobal::displayWarning(warn); } } // for i if (fileName == "") { MString error = "-file not specified."; MGlobal::displayError(error); return MS::kFailure; } { MString fileRule, expandName; MString alembicFileRule = "alembicCache"; MString alembicFilePath = "cache/alembic"; MString queryFileRuleCmd; queryFileRuleCmd.format("workspace -q -fre \"^1s\"", alembicFileRule); MString queryFolderCmd; queryFolderCmd.format("workspace -en `workspace -q -fre \"^1s\"`", alembicFileRule); // query the file rule for alembic cache MGlobal::executeCommand(queryFileRuleCmd, fileRule); if (fileRule.length() > 0) { // we have alembic file rule, query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } else { // alembic file rule does not exist, create it MString addFileRuleCmd; addFileRuleCmd.format("workspace -fr \"^1s\" \"^2s\"", alembicFileRule, alembicFilePath); MGlobal::executeCommand(addFileRuleCmd); // save the workspace. maya may discard file rules on exit MGlobal::executeCommand("workspace -s"); // query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } // resolve the expanded file rule if (expandName.length() == 0) { expandName = alembicFilePath; } // get the path to the alembic file rule MFileObject directory; directory.setRawFullName(expandName); MString directoryName = directory.resolvedFullName(); // make sure the cache folder exists if (!directory.exists()) { // create the cache folder MString createFolderCmd; createFolderCmd.format("sysFile -md \"^1s\"", directoryName); MGlobal::executeCommand(createFolderCmd); } // resolve the relative path MFileObject absoluteFile; absoluteFile.setRawFullName(fileName.c_str()); #if MAYA_API_VERSION < 201300 if (absoluteFile.resolvedFullName() != absoluteFile.expandedFullName()) { #else if (!MFileObject::isAbsolutePath(fileName.c_str())) { #endif // this is a relative path MString absoluteFileName = directoryName + "/" + fileName.c_str(); absoluteFile.setRawFullName(absoluteFileName); fileName = absoluteFile.resolvedFullName().asChar(); } else { fileName = absoluteFile.resolvedFullName().asChar(); } // check the path must exist before writing MFileObject absoluteFilePath; absoluteFilePath.setRawFullName(absoluteFile.path()); if (!absoluteFilePath.exists()) { MString error; error.format("Path ^1s does not exist!", absoluteFilePath.resolvedFullName()); MGlobal::displayError(error); return MS::kFailure; } // check the file is used by any AlembicNode in the scene MItDependencyNodes dgIter(MFn::kPluginDependNode); for (; !dgIter.isDone(); dgIter.next()) { MFnDependencyNode alembicNode(dgIter.thisNode()); if (alembicNode.typeName() != "AlembicNode") { continue; } MPlug abcFilePlug = alembicNode.findPlug("abc_File"); if (abcFilePlug.isNull()) { continue; } MFileObject alembicFile; alembicFile.setRawFullName(abcFilePlug.asString()); if (!alembicFile.exists()) { continue; } if (alembicFile.resolvedFullName() == absoluteFile.resolvedFullName()) { MString error = "Can't export to an Alembic file which is in use."; MGlobal::displayError(error); return MS::kFailure; } } std::ofstream ofs(fileName.c_str()); if (!ofs.is_open()) { MString error = MString("Can't write to file: ") + fileName.c_str(); MGlobal::displayError(error); return MS::kFailure; } ofs.close(); } // if -frameRelativeSample argument is not specified for a frame range, // we are assuming a -frameRelativeSample 0.0 for (std::vector<FrameRangeArgs>::iterator range = frameRanges.begin(); range != frameRanges.end(); ++range) { if (range->shutterSamples.empty()) range->shutterSamples.insert(0.0); } if (jobArgs.prefixFilters.empty()) { jobArgs.prefixFilters.push_back("ABC_"); } // the list of frame ranges for sampling std::vector<FrameRangeArgs> sampleRanges; std::vector<FrameRangeArgs> preRollRanges; for (std::vector<FrameRangeArgs>::const_iterator range = frameRanges.begin(); range != frameRanges.end(); ++range) { if (range->preRoll) preRollRanges.push_back(*range); else sampleRanges.push_back(*range); } // the list of frames written into the abc file std::set<double> geoSamples; std::set<double> transSamples; for (std::vector<FrameRangeArgs>::const_iterator range = sampleRanges.begin(); range != sampleRanges.end(); ++range) { for (double frame = range->startTime; frame <= range->endTime; frame += range->strideTime) { for (std::set<double>::const_iterator shutter = range->shutterSamples.begin(); shutter != range->shutterSamples.end(); ++shutter) { double curFrame = *shutter + frame; if (!sampleGeo) { double intFrame = (double)(int)( curFrame >= 0 ? curFrame + .5 : curFrame - .5); // only insert samples that are close to being an integer if (fabs(curFrame - intFrame) < 1e-4) { geoSamples.insert(curFrame); } } else { geoSamples.insert(curFrame); } transSamples.insert(curFrame); } } if (geoSamples.empty()) { geoSamples.insert(range->startTime); } if (transSamples.empty()) { transSamples.insert(range->startTime); } } bool isAcyclic = false; if (sampleRanges.empty()) { // no frame ranges or all frame ranges are pre-roll ranges hasRange = false; geoSamples.insert(frameRanges.back().startTime); transSamples.insert(frameRanges.back().startTime); } else { // check if the time range is even (cyclic) // otherwise, we will use acyclic // sub frames pattern std::vector<double> pattern( sampleRanges.begin()->shutterSamples.begin(), sampleRanges.begin()->shutterSamples.end()); std::transform(pattern.begin(), pattern.end(), pattern.begin(), std::bind2nd(std::plus<double>(), sampleRanges.begin()->startTime)); // check the frames against the pattern std::vector<double> timeSamples( transSamples.begin(), transSamples.end()); for (size_t i = 0; i < timeSamples.size(); i++) { // next pattern if (i % pattern.size() == 0 && i / pattern.size() > 0) { std::transform(pattern.begin(), pattern.end(), pattern.begin(), std::bind2nd(std::plus<double>(), sampleRanges.begin()->strideTime)); } // pattern mismatch, we use acyclic time sampling type if (timeSamples[i] != pattern[i % pattern.size()]) { isAcyclic = true; break; } } } // the list of frames to pre-roll std::set<double> preRollSamples; for (std::vector<FrameRangeArgs>::const_iterator range = preRollRanges.begin(); range != preRollRanges.end(); ++range) { for (double frame = range->startTime; frame <= range->endTime; frame += range->strideTime) { for (std::set<double>::const_iterator shutter = range->shutterSamples.begin(); shutter != range->shutterSamples.end(); ++shutter) { double curFrame = *shutter + frame; preRollSamples.insert(curFrame); } } if (preRollSamples.empty()) { preRollSamples.insert(range->startTime); } } if (jobArgs.dagPaths.size() > 1) { // check for validity of the DagPath relationships complexity : n^2 util::ShapeSet::const_iterator m, n; util::ShapeSet::const_iterator end = jobArgs.dagPaths.end(); for (m = jobArgs.dagPaths.begin(); m != end; ) { MDagPath path1 = *m; m++; for (n = m; n != end; n++) { MDagPath path2 = *n; if (util::isAncestorDescendentRelationship(path1,path2)) { MString errorMsg = path1.fullPathName(); errorMsg += " and "; errorMsg += path2.fullPathName(); errorMsg += " have an ancestor relationship."; MGlobal::displayError(errorMsg); return MS::kFailure; } } // for n } // for m } // no root is specified, and we aren't using a selection // so we'll try to translate the whole Maya scene by using all // children of the world as roots. else if (!hasRoot && !jobArgs.useSelectionList) { MSelectionList sel; #if MAYA_API_VERSION >= 201100 sel.add("|*", true); #else // older versions of Maya will not be able to find top level nodes // within namespaces sel.add("|*"); #endif unsigned int numRoots = sel.length(); for (unsigned int i = 0; i < numRoots; ++i) { MDagPath path; sel.getDagPath(i, path); jobArgs.dagPaths.insert(path); } } else if (hasRoot && jobArgs.dagPaths.empty()) { MString errorMsg = "No valid root nodes were specified."; MGlobal::displayError(errorMsg); return MS::kFailure; } else if (jobArgs.useSelectionList) { MSelectionList activeList; MGlobal::getActiveSelectionList(activeList); if (activeList.length() == 0) { MString errorMsg = "-selection specified but nothing is actively selected."; MGlobal::displayError(errorMsg); return MS::kFailure; } } AbcA::TimeSamplingPtr transTime, geoTime; if (hasRange) { if (isAcyclic) { // acyclic, uneven time sampling // e.g. [0.8, 1, 1.2], [2.8, 3, 3.2], .. not continuous // [0.8, 1, 1.2], [1.7, 2, 2.3], .. shutter different std::vector<double> samples( transSamples.begin(), transSamples.end()); std::transform(samples.begin(), samples.end(), samples.begin(), std::bind2nd(std::multiplies<double>(), util::spf())); transTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType( AbcA::TimeSamplingType::kAcyclic), samples)); } else { // cyclic, even time sampling between time periods // e.g. [0.8, 1, 1.2], [1.8, 2, 2.2], ... std::vector<double> samples; double startTime = sampleRanges[0].startTime; double strideTime = sampleRanges[0].strideTime; for (std::set<double>::const_iterator shutter = sampleRanges[0].shutterSamples.begin(); shutter != sampleRanges[0].shutterSamples.end(); ++shutter) { samples.push_back((startTime + *shutter) * util::spf()); } if (samples.size() > 1) { Alembic::Util::uint32_t numSamples = static_cast<Alembic::Util::uint32_t>(samples.size()); transTime.reset( new AbcA::TimeSampling(AbcA::TimeSamplingType( numSamples, strideTime * util::spf()), samples)); } // uniform sampling else { transTime.reset(new AbcA::TimeSampling( strideTime * util::spf(), samples[0])); } } } else { // time ranges are not specified transTime.reset(new AbcA::TimeSampling()); } if (sampleGeo || !hasRange) { geoTime = transTime; } else { // sampling geo on whole frames if (isAcyclic) { // acyclic, uneven time sampling std::vector<double> samples( geoSamples.begin(), geoSamples.end()); // one more sample for setup() if (*transSamples.begin() != *geoSamples.begin()) samples.insert(samples.begin(), *transSamples.begin()); std::transform(samples.begin(), samples.end(), samples.begin(), std::bind2nd(std::multiplies<double>(), util::spf())); geoTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType( AbcA::TimeSamplingType::kAcyclic), samples)); } else { double geoStride = sampleRanges[0].strideTime; if (geoStride < 1.0) geoStride = 1.0; double geoStart = *geoSamples.begin() * util::spf(); geoTime.reset(new AbcA::TimeSampling( geoStride * util::spf(), geoStart)); } } AbcWriteJobPtr job(new AbcWriteJob(fileName.c_str(), asOgawa, transSamples, transTime, geoSamples, geoTime, jobArgs)); jobList.push_front(job); // make sure we add additional whole frames, if we arent skipping // the inbetween ones if (!skipFrame && !allFrameRange.empty()) { double localMin = *(transSamples.begin()); std::set<double>::iterator last = transSamples.end(); last--; double localMax = *last; double globalMin = *(allFrameRange.begin()); last = allFrameRange.end(); last--; double globalMax = *last; // if the min of our current frame range is beyond // what we know about, pad a few more frames if (localMin > globalMax) { for (double f = globalMax; f < localMin; f++) { allFrameRange.insert(f); } } // if the max of our current frame range is beyond // what we know about, pad a few more frames if (localMax < globalMin) { for (double f = localMax; f < globalMin; f++) { allFrameRange.insert(f); } } } // right now we just copy over the translation samples since // they are guaranteed to contain all the geometry samples allFrameRange.insert(transSamples.begin(), transSamples.end()); // copy over the pre-roll samples allFrameRange.insert(preRollSamples.begin(), preRollSamples.end()); } // add extra evaluation run up, if necessary if (startEvaluationTime != DBL_MAX && !allFrameRange.empty()) { double firstFrame = *allFrameRange.begin(); for (double f = startEvaluationTime; f < firstFrame; ++f) { allFrameRange.insert(f); } } std::set<double>::iterator it = allFrameRange.begin(); std::set<double>::iterator itEnd = allFrameRange.end(); MComputation computation; computation.beginComputation(); // loop through every frame in the list, if a job has that frame in it's // list of transform or shape frames, then it will write out data and // call the perFrameCallback, if that frame is also the last one it has // to work on then it will also call the postCallback. // If it doesn't have this frame, then it does nothing for (; it != itEnd; it++) { if (verbose) { double frame = *it; MString info; info = frame; MGlobal::displayInfo(info); } MGlobal::viewFrame(*it); std::list< AbcWriteJobPtr >::iterator j = jobList.begin(); std::list< AbcWriteJobPtr >::iterator jend = jobList.end(); while (j != jend) { if (computation.isInterruptRequested()) return MS::kFailure; bool lastFrame = (*j)->eval(*it); if (lastFrame) { j = jobList.erase(j); } else j++; } } computation.endComputation(); // set the time back MGlobal::viewFrame(oldCurTime); return MS::kSuccess; } catch (Alembic::Util::Exception & e) { MString theError("Alembic Exception encountered: "); theError += e.what(); MGlobal::displayError(theError); return MS::kFailure; } catch (std::exception & e) { MString theError("std::exception encountered: "); theError += e.what(); MGlobal::displayError(theError); return MS::kFailure; } }
MStatus rtgTranslator::writer ( const MFileObject & fileObject, const MString & options, MPxFileTranslator::FileAccessMode mode) { char LTmpStr[MAXPATHLEN]; unsigned int i; int LN; const MString fname = fileObject.fullName (); MString extension; MString baseFileName; int TimeSlider = 0; int AnimEnabled = 0; // Lets strip off the known extension of .rtg if it is there. extension.set (".rtg"); int extLocation = fileObject.name ().rindex ('.'); if (extLocation > 0 && fileObject.name ().substring (extLocation, fileObject.name ().length () - 1) == extension) { baseFileName = fileObject.name ().substring (0, extLocation - 1); } else { baseFileName = fileObject.name (); extension.clear (); } DtExt_SceneInit( (char *)baseFileName.asChar() ); // Lets now do all of the option processing if (options.length () > 0) { //Start parsing. MStringArray optionList; MStringArray theOption; options.split (';', optionList); //break out all the options. for ( i = 0; i < optionList.length (); ++i) { theOption.clear (); optionList[i].split ('=', theOption); if (theOption.length () > 1) { if (theOption[0] == MString ("v18compatible")) { rtg_v18_compatible = (int) (theOption[1].asInt() ); } else if (theOption[0] == MString ("timeslider")) { TimeSlider = (int) (theOption[1].asInt ()); } else if (theOption[0] == MString ("animEnabled")) { AnimEnabled = (int) (theOption[1].asInt ()); } else if (theOption[0] == MString ("animStart")) { DtFrameSetStart( (int) (theOption[1].asInt ()) ); } else if (theOption[0] == MString ("animEnd")) { DtFrameSetEnd( (int) (theOption[1].asInt ()) ); } else if (theOption[0] == MString ("animStep")) { DtFrameSetBy( (int) (theOption[1].asInt ()) ); } else if (theOption[0] == MString ("hrcType")) { switch ( theOption[1].asInt () - 1) { case VRHRC_FLAT: DtExt_setOutputTransforms (kTRANSFORMMINIMAL); DtExt_setParents (0); break; case VRHRC_WORLD: DtExt_setOutputTransforms (kTRANSFORMNONE); DtExt_setParents (0); break; case VRHRC_FULL: default: DtExt_setOutputTransforms (kTRANSFORMALL); DtExt_setParents (1); break; } } else if (theOption[0] == MString ("joints")) { // Allow user to specify if the hierarchy should include // NULL geometry nodes - usually joints DtExt_setJointHierarchy( theOption[1].asInt() ); } else if (theOption[0] == MString ("exportSel")) { switch ( theOption[1].asInt () - 1) { case VRSEL_ALL: DtExt_setWalkMode (ALL_Nodes); break; case VRSEL_ACTIVE: DtExt_setWalkMode (ACTIVE_Nodes); break; case VRSEL_PICKED: DtExt_setWalkMode (PICKED_Nodes); break; } } else if (theOption[0] == MString ("texsample")) { // Allow user to specify if the textures should be sampled // with the Texture Placement options DtExt_setSoftTextures ( theOption[1].asInt() ); } else if (theOption[0] == MString ("texevaluate")) { // Allow the user to specify if the tex should be eval with // convertSolidTx command or read in if is a file texture. DtExt_setInlineTextures( theOption[1].asInt() ); } else if (theOption[0] == MString ("texoriginal")) { // Allow the user to specify if the tex should be eval at all. DtExt_setOriginalTexture( theOption[1].asInt() ); } else if (theOption[0] == MString ("Xtexres")) { // Set the X size of the texture swatches to use DtExt_setXTextureRes ( theOption[1].asInt () ); } else if (theOption[0] == MString ("Ytexres")) { // Set the Y size of the texture swatches to use DtExt_setYTextureRes ( theOption[1].asInt () ); } else if (theOption[0] == MString ("MaxXtexres")) { // Set the Max X size of the texture swatches to use DtExt_setMaxXTextureRes( theOption[1].asInt () ); } else if (theOption[0] == MString ("MaxYtexres")) { // Set the Max Y size of the texture swatches to use DtExt_setMaxYTextureRes( theOption[1].asInt () ); } else if (theOption[0] == MString ("precision")) { //VR_Precision = theOption[1].asInt (); } else if (theOption[0] == MString ("verbose")) { // DtExt_setDebug ( theOption[1].asInt () ); } else if (theOption[0] == MString ("debug")) { int levelG = DtExt_Debug(); if ( (int) (theOption[1].asInt () ) ) levelG |= DEBUG_GEOMAT; else levelG &= ~DEBUG_GEOMAT; DtExt_setDebug( levelG ); } else if (theOption[0] == MString ("debugC")) { int levelC = DtExt_Debug(); if ( (int) (theOption[1].asInt () ) ) levelC |= DEBUG_CAMERA; else levelC &= ~DEBUG_CAMERA; DtExt_setDebug( levelC ); } else if (theOption[0] == MString ("debugL")) { int levelL = DtExt_Debug(); if ( (int) (theOption[1].asInt () ) ) levelL |= DEBUG_LIGHT; else levelL &= ~DEBUG_LIGHT; DtExt_setDebug( levelL ); } else if (theOption[0] == MString ("reversed")) { DtExt_setWinding( theOption[1].asInt() ); } else if (theOption[0] == MString ("tesselation")) { if ( theOption[1].asInt() == 2 ) { DtExt_setTesselate( kTESSQUAD ); } else { DtExt_setTesselate( kTESSTRI ); } // // Now come the translator specific options // } else if (theOption[0] == MString ("imageformat")) { rtg_output_image_format = theOption[1].asInt(); } else if (theOption[0] == MString ("fileformat")) { rtg_output_file_format = theOption[1].asInt(); } else if (theOption[0] == MString ("vnormals")) { rtg_output_vert_norms = theOption[1].asInt(); } else if (theOption[0] == MString ("vcolors")) { rtg_output_vert_colors = theOption[1].asInt(); } else if (theOption[0] == MString ("tcoords")) { rtg_output_tex_coords = theOption[1].asInt(); } else if (theOption[0] == MString ("pnormals")) { rtg_output_poly_norms = theOption[1].asInt(); } else if (theOption[0] == MString ("idxcnt")) { rtg_show_index_counters = theOption[1].asInt(); } else if (theOption[0] == MString ("anglesdeg")) { rtg_output_degrees = theOption[1].asInt(); } else if (theOption[0] == MString ("materials")) { rtg_output_materials = theOption[1].asInt(); } else if (theOption[0] == MString ("multitexture")) { DtExt_setMultiTexture( theOption[1].asInt() ); } else if (theOption[0] == MString ("mdecomp")) { rtg_output_decomp = theOption[1].asInt(); } else if (theOption[0] == MString ("pivoth")) { rtg_output_pivots = theOption[1].asInt(); } else if (theOption[0] == MString ("transforms")) { rtg_output_transforms = theOption[1].asInt(); } else if (theOption[0] == MString ("ltransforms")) { rtg_output_local = theOption[1].asInt(); } else if (theOption[0] == MString ("animation")) { rtg_output_animation = theOption[1].asInt(); } else if (theOption[0] == MString ("allnodes")) { rtg_output_all_nodes = theOption[1].asInt(); } else if (theOption[0] == MString ("script")) { scriptToRun = theOption[1]; } else if (theOption[0] == MString ("scriptAppend")) { scriptAppend = (int)(theOption[1].asInt() ); } } } } // Lets see how we entered this plug-in, either with the export all // or export selection flag set. if ( mode == MPxFileTranslator::kExportActiveAccessMode ) { DtExt_setWalkMode ( ACTIVE_Nodes ); } // Lets check the TimeSlider control now: if ( TimeSlider ) { MTime start( MAnimControl::minTime().value(), MTime::uiUnit() ); DtFrameSetStart( (int) start.value() ); MTime end( MAnimControl::maxTime().value(), MTime::uiUnit() ); DtFrameSetEnd( (int) end.value() ); } // Now see if the animation is really enabled. // Else we will set the end frame to the beginning frame automatically if ( !AnimEnabled ) { DtFrameSetEnd( DtFrameGetStart() ); } // Find out where the file is supposed to end up. MDt_GetPathName ((char *) (fname.asChar ()), LTmpStr, MAXPATHLEN); LN = (int)strlen (LTmpStr); if (LTmpStr[LN - 1] == '/') LTmpStr[LN - 1] = '\0'; DtSetDirectory (LTmpStr); // Now lets setup some paths to do basic texture file searching // for those textures with relative paths MStringArray wSpacePaths; MStringArray rPaths; MString usePath; MString separator; MGlobal::executeCommand( "workspace -q -rd", wSpacePaths ); MGlobal::executeCommand( "workspace -q -rtl", rPaths ); if ( DtExt_getTextureSearchPath() ) separator.set( "|" ); else separator.set( "" ); for (i = 0; i < wSpacePaths.length (); ++i) { for ( unsigned int j = 0; j < rPaths.length(); j++ ) { usePath = usePath + separator + wSpacePaths[i] + MString( "/" ) + rPaths[j]; separator.set( "|" ); if ( rPaths[j] == MString( "sourceImages" ) ) usePath = usePath + separator + wSpacePaths[i] + MString( "/" ) + MString( "sourceimages" ); } } DtExt_addTextureSearchPath( (char *)usePath.asChar() ); // Now we can setup the database from the wire file geometry. // This is where all the Maya data are retrieved, cached, and processed. // // Say that we want to have camera info DtExt_setOutputCameras( 1 ); //Now we can setup the database from the wire file geometry DtExt_dbInit(); DtFrameSet( DtFrameGetStart() ); // Now do the export rtgExport(); // Now lets see if the user wants something else to be done if ( 0 < scriptToRun.length() ) { if ( scriptAppend ) { scriptToRun += MString( " " ) + MString( LTmpStr ); } system( scriptToRun.asChar() ); } // Clean house. // DtExt_CleanUp(); return MS::kSuccess; }