MStatus replaceDagObject(MObject & oldObject, MObject & newObject, const MString & name) { MStatus status; MFnDagNode mFnOld(oldObject, &status); if (status == MS::kSuccess) { unsigned int numChild = mFnOld.childCount(); std::vector<MObject> children; children.reserve(numChild); for (unsigned int i = 0; i < numChild; i++) { MObject child = mFnOld.child(i, &status); if (status == MS::kSuccess) { children.push_back(child); } else { MString theError("Failed to get child "); theError += i; theError += " of "; theError += mFnOld.name(); theError += ", status = "; theError += status.errorString(); MGlobal::displayError(theError); } } MFnDagNode mFnNew(newObject, &status); if (status == MS::kSuccess) { for (unsigned int i = 0; i < numChild; i++) { status = mFnNew.addChild(children[i]); if (status != MS::kSuccess) { MString theError("Failed to add child "); theError += i; theError += " of "; theError += mFnOld.name(); theError += " to "; theError += name; theError += ", status = "; theError += status.errorString(); MGlobal::displayError(theError); } } } } return status; }
CGBLCOError CGBLLOArrayHandler::AddToSendArray(CGBLLOMessagePacket messagePacket) { // do something CGBLCOError theError(CGBLCOError::EGBLCOErrorType::GBLCO_OK); return theError; }
MStatus getDagPathListByName(const MString & objectNames, std::vector<MDagPath> & dagPathList) { MStatus status; MStringArray theArray; status = objectNames.split(' ', theArray); if (status == MS::kSuccess) { unsigned int len = theArray.length(); for (unsigned int i = 0; i < len; i++) { MDagPath dagPath; status = getDagPathByName(theArray[i], dagPath); if (status == MS::kSuccess) dagPathList.push_back(dagPath); else { MString theError(theArray[i]); theError += MString(" doesn't exist"); MGlobal::displayError(theError); } } } return status; }
MStatus disconnectAllPlugsTo(MPlug & dstPlug) { MStatus status = MS::kSuccess; MPlugArray array; dstPlug.connectedTo(array, true, false, &status); unsigned int arrayLength = array.length(); for (unsigned int i = 0; i < arrayLength; i++) { MPlug srcPlug = array[i]; if (status == MS::kSuccess) { MDGModifier modifier; status = modifier.disconnect(srcPlug, dstPlug); status = modifier.doIt(); if (status != MS::kSuccess) { MString theError("Disconnect "); theError += srcPlug.name(); theError += MString(" -> "); theError += dstPlug.name(); theError += MString(" failed, status = "); theError += status.errorString(); MGlobal::displayError(theError); return status; } } } return MS::kSuccess; }
void Melder_flushError () { /* "errors" has to be cleared *before* the message is put on the screen. This is because on some platforms the message dialog is synchronous (Melder_flushError will wait until the message dialog is closed), and some operating systems may force an immediate redraw event as soon as the message dialog is closed. We want "errors" to be empty when redrawing! */ static char32 temp [2000+1]; str32cpy (temp, errors); Melder_clearError (); theError (temp); }
MStatus setInitialShadingGroup(const MString & dagNodeName) { MObject initShader; MDagPath dagPath; if (getObjectByName("initialShadingGroup", initShader) == MS::kSuccess && getDagPathByName(dagNodeName, dagPath) == MS::kSuccess) { MFnSet set(initShader); set.addMember(dagPath); } else { MString theError("Error getting adding "); theError += dagNodeName; theError += MString(" to initalShadingGroup."); MGlobal::displayError(theError); return MS::kFailure; } return MS::kSuccess; }
MObject createShadingGroup(const MString& iName) { MStatus status; MFnSet fnSet; MSelectionList selList; MObject shadingGroup = fnSet.create(selList, MFnSet::kRenderableOnly, &status); if (status != MS::kSuccess) { MString theError("Could not create shading engine: "); theError += iName; MGlobal::displayError(theError); return shadingGroup; } fnSet.setName(iName); return shadingGroup; }
MStatus AlembicAssignInitialSGCommand::doIt(const MArgList& args) { MStatus status; MArgParser argData(syntax(), args, &status); if (argData.isFlagSet("help")) { MGlobal::displayInfo("[ExocortexAlembic]: ExocortexAlembic_assignFaceset command:"); MGlobal::displayInfo(" -m : mesh to assign the initialShadingGroup on"); return MS::kSuccess; } if (!argData.isFlagSet("mesh")) { MGlobal::displayError("No mesh/subdiv specified!"); return MS::kFailure; } MObject initShader; MDagPath dagPath; if (getObjectByName("initialShadingGroup", initShader) == MS::kSuccess && getDagPathByName(argData.flagArgumentString("mesh", 0), dagPath) == MS::kSuccess) { ESS_PROFILE_SCOPE("AlembicAssignInitialSGCommand::doIt::MFnSet"); MFnSet set(initShader); set.addMember(dagPath); } else { MString theError("Error getting adding "); theError += argData.flagArgumentString("mesh", 0); theError += MString(" to initalShadingGroup."); MGlobal::displayError(theError); return MS::kFailure; } return MS::kSuccess; }
MStatus AbcImport::doIt(const MArgList & args) { MStatus status; MArgParser argData(syntax(), args, &status); MString filename(""); MString connectRootNodes(""); MString filterString(""); MString excludeFilterString(""); MObject reparentObj = MObject::kNullObj; bool swap = false; bool createIfNotFound = false; bool removeIfNoUpdate = false; bool debugOn = false; if (argData.isFlagSet("help")) { MGlobal::displayInfo(usage); return status; } if (argData.isFlagSet("debug")) debugOn = true; if (argData.isFlagSet("reparent")) { MString parent(""); MDagPath reparentDagPath; status = argData.getFlagArgument("reparent", 0, parent); if (status == MS::kSuccess && getDagPathByName(parent, reparentDagPath) == MS::kSuccess) { reparentObj = reparentDagPath.node(); } else { MString theWarning = parent; theWarning += MString(" is not a valid DagPath"); printWarning(theWarning); } } if (!argData.isFlagSet("connect") && argData.isFlagSet("mode")) { MString modeStr; argData.getFlagArgument("mode", 0, modeStr); if (modeStr == "replace") deleteCurrentSelection(); else if (modeStr == "open") { MFileIO fileIo; fileIo.newFile(true); } } else if (argData.isFlagSet("connect")) { swap = true; argData.getFlagArgument("connect", 0, connectRootNodes); if (argData.isFlagSet("createIfNotFound")) { createIfNotFound = true; } if (argData.isFlagSet("removeIfNoUpdate")) removeIfNoUpdate = true; } if (argData.isFlagSet("filterObjects")) { argData.getFlagArgument("filterObjects", 0, filterString); } if (argData.isFlagSet("excludeFilterObjects")) { argData.getFlagArgument("excludeFilterObjects", 0, excludeFilterString); } // if the flag isn't specified we'll only do stuff marked with the Maya // meta data bool recreateColorSets = false; if (argData.isFlagSet("recreateAllColorSets")) { recreateColorSets = true; } status = argData.getCommandArgument(0, filename); MString abcNodeName; if (status == MS::kSuccess) { { 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); } // 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(); // resolve the relative path MFileObject absoluteFile; absoluteFile.setRawFullName(filename); absoluteFile.setResolveMethod(MFileObject::kInputFile); #if MAYA_API_VERSION < 201300 if (absoluteFile.resolvedFullName() != absoluteFile.expandedFullName()) { #else if (!MFileObject::isAbsolutePath(filename)) { #endif // this is a relative path MString absoluteFileName = directoryName + "/" + filename; absoluteFile.setRawFullName(absoluteFileName); filename = absoluteFile.resolvedFullName(); } else { filename = absoluteFile.resolvedFullName(); } } MFileObject fileObj; status = fileObj.setRawFullName(filename); if (status == MS::kSuccess && fileObj.exists()) { ArgData inputData(filename, debugOn, reparentObj, swap, connectRootNodes, createIfNotFound, removeIfNoUpdate, recreateColorSets, filterString, excludeFilterString); abcNodeName = createScene(inputData); if (inputData.mSequenceStartTime != inputData.mSequenceEndTime && inputData.mSequenceStartTime != -DBL_MAX && inputData.mSequenceEndTime != DBL_MAX) { if (argData.isFlagSet("fitTimeRange")) { MTime sec(1.0, MTime::kSeconds); setPlayback( inputData.mSequenceStartTime * sec.as(MTime::uiUnit()), inputData.mSequenceEndTime * sec.as(MTime::uiUnit()) ); } if (argData.isFlagSet("setToStartFrame")) { MTime sec(1.0, MTime::kSeconds); MGlobal::viewFrame( inputData.mSequenceStartTime * sec.as(MTime::uiUnit()) ); } } } else { MString theError("In AbcImport::doIt(), "); theError += filename; theError += MString(" doesn't exist"); printError(theError); } } MPxCommand::setResult(abcNodeName); return status; }
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; } }