bool AbcWriteJob::checkInstance(MDagPath dag, MayaTransformWriterPtr iParent) { MFnDagNode fnDagNode(dag.node()); if (fnDagNode.isInstanced(false)) { MDagPathArray paths; fnDagNode.getAllPaths(paths); if (!(mCurDag == paths[0])) { MStringArray pathparts; paths[0].fullPathName().split('|', pathparts); Alembic::Abc::OObject rootobj = mRoot.getTop(); Alembic::Abc::OObject tmpobj(rootobj); std::string tmpstring; unsigned partscount = pathparts.length(); for (unsigned i(0); i < partscount; i++) { tmpstring = pathparts[i].asChar(); tmpobj = tmpobj.getChild(tmpstring); // for selections of non-root objects, the first parts of a dag will not be a child of mRoot // traverse hierarchy until valid matching child is found, break loop only if each part of dag is invalid if (!tmpobj.valid()) { if (i == (partscount - 1)) break; tmpobj = rootobj; } } if (tmpobj.valid()) { iParent->getObject().addChildInstance(tmpobj, fnDagNode.name().asChar()); return true; } } } return false; }
bool usdWriteJob::beginJob(const std::string &iFileName, bool append, double startTime, double endTime) { // Check for DAG nodes that are a child of an already specified DAG node to export // if that's the case, report the issue and skip the export PxrUsdMayaUtil::ShapeSet::const_iterator m, n; PxrUsdMayaUtil::ShapeSet::const_iterator endPath = mArgs.dagPaths.end(); for (m = mArgs.dagPaths.begin(); m != endPath; ) { MDagPath path1 = *m; m++; for (n = m; n != endPath; n++) { MDagPath path2 = *n; if (PxrUsdMayaUtil::isAncestorDescendentRelationship(path1,path2)) { MString errorMsg = path1.fullPathName(); errorMsg += " and "; errorMsg += path2.fullPathName(); errorMsg += " have an ancestor relationship. Skipping USD Export."; MGlobal::displayError(errorMsg); return false; } } // for n } // for m // Make sure the file name is a valid one with a proper USD extension. const std::string iFileExtension = TfStringGetSuffix(iFileName, '.'); if (iFileExtension == PxrUsdMayaTranslatorTokens->UsdFileExtensionDefault || iFileExtension == PxrUsdMayaTranslatorTokens->UsdFileExtensionASCII || iFileExtension == PxrUsdMayaTranslatorTokens->UsdFileExtensionCrate) { mFileName = iFileName; } else { mFileName = TfStringPrintf("%s.%s", iFileName.c_str(), PxrUsdMayaTranslatorTokens->UsdFileExtensionDefault.GetText()); } MGlobal::displayInfo("usdWriteJob::beginJob: Create stage file "+MString(mFileName.c_str())); ArResolverContext resolverCtx = ArGetResolver().GetCurrentContext(); if (append) { mStage = UsdStage::Open(SdfLayer::FindOrOpen(mFileName), resolverCtx); if (!mStage) { MGlobal::displayError("Failed to open stage file "+MString(mFileName.c_str())); return false; } } else { mStage = UsdStage::CreateNew(mFileName, resolverCtx); if (!mStage) { MGlobal::displayError("Failed to create stage file "+MString(mFileName.c_str())); return false; } } // Set time range for the USD file mStage->SetStartTimeCode(startTime); mStage->SetEndTimeCode(endTime); mModelKindWriter.Reset(); // Setup the requested render layer mode: // defaultLayer - Switch to the default render layer before exporting, // then switch back afterwards (no layer switching if // the current layer IS the default layer). // currentLayer - No layer switching before or after exporting. Just // use whatever is the current render layer for export. // modelingVariant - Switch to the default render layer before exporting, // and export each render layer in the scene as a // modeling variant, then switch back afterwards (no // layer switching if the current layer IS the default // layer). The default layer will be made the default // modeling variant. MFnRenderLayer currentLayer(MFnRenderLayer::currentLayer()); mCurrentRenderLayerName = currentLayer.name(); if (mArgs.renderLayerMode == PxUsdExportJobArgsTokens->modelingVariant) { // Handle usdModelRootOverridePath for USD Variants MFnRenderLayer::listAllRenderLayers(mRenderLayerObjs); if (mRenderLayerObjs.length() > 1) { mArgs.usdModelRootOverridePath = SdfPath("/_BaseModel_"); } } // Switch to the default render layer unless the renderLayerMode is // 'currentLayer', or the default layer is already the current layer. if (mArgs.renderLayerMode != PxUsdExportJobArgsTokens->currentLayer && MFnRenderLayer::currentLayer() != MFnRenderLayer::defaultRenderLayer()) { // Set the RenderLayer to the default render layer MFnRenderLayer defaultLayer(MFnRenderLayer::defaultRenderLayer()); MGlobal::executeCommand(MString("editRenderLayerGlobals -currentRenderLayer ")+ defaultLayer.name(), false, false); } // Pre-process the argument dagPath path names into two sets. One set // contains just the arg dagPaths, and the other contains all parents of // arg dagPaths all the way up to the world root. Partial path names are // enough because Maya guarantees them to still be unique, and they require // less work to hash and compare than full path names. TfHashSet<std::string, TfHash> argDagPaths; TfHashSet<std::string, TfHash> argDagPathParents; PxrUsdMayaUtil::ShapeSet::const_iterator end = mArgs.dagPaths.end(); for (PxrUsdMayaUtil::ShapeSet::const_iterator it = mArgs.dagPaths.begin(); it != end; ++it) { MDagPath curDagPath = *it; std::string curDagPathStr(curDagPath.partialPathName().asChar()); argDagPaths.insert(curDagPathStr); while (curDagPath.pop() && curDagPath.length() >= 0) { curDagPathStr = curDagPath.partialPathName().asChar(); if (argDagPathParents.find(curDagPathStr) != argDagPathParents.end()) { // We've already traversed up from this path. break; } argDagPathParents.insert(curDagPathStr); } } // Now do a depth-first traversal of the Maya DAG from the world root. // We keep a reference to arg dagPaths as we encounter them. MDagPath curLeafDagPath; for (MItDag itDag(MItDag::kDepthFirst, MFn::kInvalid); !itDag.isDone(); itDag.next()) { MDagPath curDagPath; itDag.getPath(curDagPath); std::string curDagPathStr(curDagPath.partialPathName().asChar()); if (argDagPathParents.find(curDagPathStr) != argDagPathParents.end()) { // This dagPath is a parent of one of the arg dagPaths. It should // be included in the export, but not necessarily all of its // children should be, so we continue to traverse down. } else if (argDagPaths.find(curDagPathStr) != argDagPaths.end()) { // This dagPath IS one of the arg dagPaths. It AND all of its // children should be included in the export. curLeafDagPath = curDagPath; } else if (!MFnDagNode(curDagPath).hasParent(curLeafDagPath.node())) { // This dagPath is not a child of one of the arg dagPaths, so prune // it and everything below it from the traversal. itDag.prune(); continue; } MayaPrimWriterPtr primWriter = nullptr; if (!createPrimWriter(curDagPath, &primWriter) && curDagPath.length() > 0) { // This dagPath and all of its children should be pruned. itDag.prune(); continue; } if (primWriter) { mMayaPrimWriterList.push_back(primWriter); // Write out data (non-animated/default values). if (UsdPrim usdPrim = primWriter->write(UsdTimeCode::Default())) { MDagPath dag = primWriter->getDagPath(); mDagPathToUsdPathMap[dag] = usdPrim.GetPath(); // If we are merging transforms and the object derives from // MayaTransformWriter but isn't actually a transform node, we // need to add its parent. if (mArgs.mergeTransformAndShape) { MayaTransformWriterPtr xformWriter = boost::dynamic_pointer_cast<MayaTransformWriter>( primWriter); if (xformWriter) { MDagPath xformDag = xformWriter->getTransformDagPath(); mDagPathToUsdPathMap[xformDag] = usdPrim.GetPath(); } } mModelKindWriter.OnWritePrim(usdPrim, primWriter); if (primWriter->shouldPruneChildren()) { itDag.prune(); } } } } // Writing Materials/Shading PxrUsdMayaTranslatorMaterial::ExportShadingEngines( mStage, mArgs.dagPaths, mArgs.shadingMode, mArgs.mergeTransformAndShape, mArgs.usdModelRootOverridePath); if (!mModelKindWriter.MakeModelHierarchy(mStage)) { return false; } // now we populate the chasers and run export default mChasers.clear(); PxrUsdMayaChaserRegistry::FactoryContext ctx(mStage, mDagPathToUsdPathMap, mArgs); for (const std::string& chaserName : mArgs.chaserNames) { if (PxrUsdMayaChaserRefPtr fn = PxrUsdMayaChaserRegistry::GetInstance().Create(chaserName, ctx)) { mChasers.push_back(fn); } else { std::string error = TfStringPrintf("Failed to create chaser: %s", chaserName.c_str()); MGlobal::displayError(MString(error.c_str())); } } for (const PxrUsdMayaChaserRefPtr& chaser : mChasers) { if (!chaser->ExportDefault()) { return false; } } return true; }
void AbcWriteJob::setup(double iFrame, MayaTransformWriterPtr iParent, GetMembersMap& gmMap) { MStatus status; // short-circuit if selection flag is on but this node isn't actively // selected if (mArgs.useSelectionList && !mSList.hasItem(mCurDag)) return; MObject ob = mCurDag.node(); // skip all intermediate nodes (and their children) if (util::isIntermediate(ob)) { return; } // skip nodes that aren't renderable (and their children) if (mArgs.excludeInvisible && !util::isRenderable(ob)) { return; } // look for riCurves flag for flattening all curve objects to a curve group MFnDependencyNode fnDepNode(ob, &status); MPlug riCurvesPlug = fnDepNode.findPlug("riCurves", &status); bool riCurvesVal = riCurvesPlug.asBool(); bool writeOutAsGroup = false; if (riCurvesVal) { writeOutAsGroup = checkCurveGrp(); if (writeOutAsGroup == false) { MString msg = "Curves have different degrees or close "; msg += "states, not writing out as curve group"; MGlobal::displayWarning(msg); } } if ( status == MS::kSuccess && riCurvesVal && writeOutAsGroup) { MayaNurbsCurveWriterPtr nurbsCurve; if (iParent == NULL) { Alembic::Abc::OObject obj = mRoot.getTop(); nurbsCurve = MayaNurbsCurveWriterPtr(new MayaNurbsCurveWriter( mCurDag, obj, mShapeTimeIndex, true, mArgs)); } else { Alembic::Abc::OObject obj = iParent->getObject(); nurbsCurve = MayaNurbsCurveWriterPtr(new MayaNurbsCurveWriter( mCurDag, obj, mShapeTimeIndex, true, mArgs)); } if (nurbsCurve->isAnimated() && mShapeTimeIndex != 0) { mCurveList.push_back(nurbsCurve); mStats.mCurveAnimNum++; mStats.mCurveAnimCurves += nurbsCurve->getNumCurves(); mStats.mCurveAnimCVs += nurbsCurve->getNumCVs(); } else { mStats.mCurveStaticNum++; mStats.mCurveStaticCurves += nurbsCurve->getNumCurves(); mStats.mCurveStaticCVs += nurbsCurve->getNumCVs(); } AttributesWriterPtr attrs = nurbsCurve->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else if (ob.hasFn(MFn::kTransform)) { MFnTransform fnTrans(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize transform node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } MayaTransformWriterPtr trans; // parented to the root case if (iParent == NULL) { Alembic::Abc::OObject obj = mRoot.getTop(); trans = MayaTransformWriterPtr(new MayaTransformWriter( obj, mCurDag, mTransTimeIndex, mArgs)); } else { trans = MayaTransformWriterPtr(new MayaTransformWriter( *iParent, mCurDag, mTransTimeIndex, mArgs)); } if (trans->isAnimated() && mTransTimeIndex != 0) { mTransList.push_back(trans); mStats.mTransAnimNum++; } else mStats.mTransStaticNum++; AttributesWriterPtr attrs = trans->getAttrs(); if (mTransTimeIndex != 0 && attrs->isAnimated()) mTransAttrList.push_back(attrs); // loop through the children, making sure to push and pop them // from the MDagPath unsigned int numChild = mCurDag.childCount(); for (unsigned int i = 0; i < numChild; ++i) { if (mCurDag.push(mCurDag.child(i)) == MS::kSuccess) { setup(iFrame, trans, gmMap); mCurDag.pop(); } } } else if (ob.hasFn(MFn::kLocator)) { MFnDependencyNode fnLocator(ob, & status); if (status != MS::kSuccess) { MString msg = "Initialize locator node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } if (iParent != NULL) { Alembic::Abc::OObject obj = iParent->getObject(); MayaLocatorWriterPtr locator(new MayaLocatorWriter( mCurDag, obj, mShapeTimeIndex, mArgs)); if (locator->isAnimated() && mShapeTimeIndex != 0) { mLocatorList.push_back(locator); mStats.mLocatorAnimNum++; } else { mStats.mLocatorStaticNum++; } AttributesWriterPtr attrs = locator->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else { MString err = "Can't translate "; err += fnLocator.name() + " since it doesn't have a parent."; MGlobal::displayError(err); } } else if (ob.hasFn(MFn::kParticle)) { MFnParticleSystem mFnParticle(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize particle system "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } if (iParent != NULL) { Alembic::Abc::OObject obj = iParent->getObject(); MayaPointPrimitiveWriterPtr particle(new MayaPointPrimitiveWriter( iFrame, mCurDag, obj, mShapeTimeIndex, mArgs)); if (particle->isAnimated() && mShapeTimeIndex != 0) { mPointList.push_back(particle); mStats.mPointAnimNum++; mStats.mPointAnimCVs += particle->getNumCVs(); } else { mStats.mPointStaticNum++; mStats.mPointStaticCVs += particle->getNumCVs(); } AttributesWriterPtr attrs = particle->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else { MString err = "Can't translate "; err += mFnParticle.name() + " since it doesn't have a parent."; MGlobal::displayError(err); } } else if (ob.hasFn(MFn::kMesh)) { MFnMesh fnMesh(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize mesh node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } if (iParent != NULL) { Alembic::Abc::OObject obj = iParent->getObject(); MayaMeshWriterPtr mesh(new MayaMeshWriter(mCurDag, obj, mShapeTimeIndex, mArgs, gmMap)); if (mesh->isAnimated() && mShapeTimeIndex != 0) { mMeshList.push_back(mesh); if (mesh->isSubD()) { mStats.mSubDAnimNum++; mStats.mSubDAnimCVs += mesh->getNumCVs(); mStats.mSubDAnimFaces += mesh->getNumFaces(); } else { mStats.mPolyAnimNum++; mStats.mPolyAnimCVs += mesh->getNumCVs(); mStats.mPolyAnimFaces += mesh->getNumFaces(); } } else { if (mesh->isSubD()) { mStats.mSubDStaticNum++; mStats.mSubDStaticCVs += mesh->getNumCVs(); mStats.mSubDStaticFaces += mesh->getNumFaces(); } else { mStats.mPolyStaticNum++; mStats.mPolyStaticCVs += mesh->getNumCVs(); mStats.mPolyStaticFaces += mesh->getNumFaces(); } } AttributesWriterPtr attrs = mesh->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else { MString err = "Can't translate "; err += fnMesh.name() + " since it doesn't have a parent."; MGlobal::displayError(err); } } else if (ob.hasFn(MFn::kCamera)) { MFnCamera fnCamera(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize camera node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } if (iParent != NULL) { Alembic::Abc::OObject obj = iParent->getObject(); MayaCameraWriterPtr camera(new MayaCameraWriter( mCurDag, obj, mShapeTimeIndex, mArgs)); if (camera->isAnimated() && mShapeTimeIndex != 0) { mCameraList.push_back(camera); mStats.mCameraAnimNum++; } else mStats.mCameraStaticNum++; AttributesWriterPtr attrs = camera->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else { MString err = "Can't translate "; err += fnCamera.name() + " since it doesn't have a parent."; MGlobal::displayError(err); } } else if (ob.hasFn(MFn::kNurbsSurface)) { MFnNurbsSurface fnNurbsSurface(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize nurbs surface "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } if (iParent != NULL) { Alembic::Abc::OObject obj = iParent->getObject(); MayaNurbsSurfaceWriterPtr nurbsSurface(new MayaNurbsSurfaceWriter( mCurDag, obj, mShapeTimeIndex, mArgs)); if (nurbsSurface->isAnimated() && mShapeTimeIndex != 0) { mNurbsList.push_back(nurbsSurface); mStats.mNurbsAnimNum++; mStats.mNurbsAnimCVs += nurbsSurface->getNumCVs(); } else { mStats.mNurbsStaticNum++; mStats.mNurbsStaticCVs += nurbsSurface->getNumCVs(); } AttributesWriterPtr attrs = nurbsSurface->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else { MString err = "Can't translate "; err += fnNurbsSurface.name() + " since it doesn't have a parent."; MGlobal::displayError(err); } } else if (ob.hasFn(MFn::kNurbsCurve)) { MFnNurbsCurve fnNurbsCurve(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize curve node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } if (iParent != NULL) { Alembic::Abc::OObject obj = iParent->getObject(); MayaNurbsCurveWriterPtr nurbsCurve(new MayaNurbsCurveWriter( mCurDag, obj, mShapeTimeIndex, false, mArgs)); if (nurbsCurve->isAnimated() && mShapeTimeIndex != 0) { mCurveList.push_back(nurbsCurve); mStats.mCurveAnimNum++; mStats.mCurveAnimCurves++; mStats.mCurveAnimCVs += nurbsCurve->getNumCVs(); } else { mStats.mCurveStaticNum++; mStats.mCurveStaticCurves++; mStats.mCurveStaticCVs += nurbsCurve->getNumCVs(); } AttributesWriterPtr attrs = nurbsCurve->getAttrs(); if (mShapeTimeIndex != 0 && attrs->isAnimated()) mShapeAttrList.push_back(attrs); } else { MString err = "Can't translate "; err += fnNurbsCurve.name() + " since it doesn't have a parent."; MGlobal::displayError(err); } } else { MString warn = mCurDag.fullPathName() + " is an unsupported type of "; warn += ob.apiTypeStr(); MGlobal::displayWarning(warn); } }
void AbcWriteJob::setup(double iFrame, MayaTransformWriterPtr iParent, util::GetMembersMap& gmMap) { MStatus status; // short-circuit if selection flag is on but this node isn't actively // selected if (mArgs.useSelectionList && !mSList.hasItem(mCurDag)) return; MObject ob = mCurDag.node(); MFnDependencyNode fnDepNode(ob, &status); bool bSolvedState = fnDepNode.typeName() == "bulletRigidCollection"; // skip all intermediate nodes (and their children) if (util::isIntermediate(ob)) { if (!bSolvedState) { return; } } // skip nodes that aren't renderable (and their children) if (mArgs.excludeInvisible && !util::isRenderable(ob)) { return; } if ( bSolvedState ) { // the motionstates are held on the initialstate node at the moment if (status != MS::kSuccess) { MString msg = "Initialize transform collection node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } MayaTransformCollectionWriterPtr transCol; // transformcollections always parented to the root case Alembic::Abc::OObject obj = mRoot.getTop(); transCol = MayaTransformCollectionWriterPtr(new MayaTransformCollectionWriter( obj, mCurDag, mTransTimeIndex, mArgs)); mTransColList.push_back(transCol); mStats.mTransColNum++; AttributesWriterPtr attrs = transCol->getAttrs(); if (attrs) { if (mTransTimeIndex != 0 && attrs->isAnimated()) mTransColAttrList.push_back(attrs); } } else if (ob.hasFn(MFn::kTransform)) { MFnTransform fnTrans(ob, &status); if (status != MS::kSuccess) { MString msg = "Initialize transform node "; msg += mCurDag.fullPathName(); msg += " failed, skipping."; MGlobal::displayWarning(msg); return; } MayaTransformWriterPtr trans; // parented to the root case if (iParent == NULL) { Alembic::Abc::OObject obj = mRoot.getTop(); trans = MayaTransformWriterPtr(new MayaTransformWriter( obj, mCurDag, mTransTimeIndex, mArgs)); } else { trans = MayaTransformWriterPtr(new MayaTransformWriter( *iParent, mCurDag, mTransTimeIndex, mArgs)); } if (trans->isAnimated() && mTransTimeIndex != 0) { mTransList.push_back(trans); mStats.mTransAnimNum++; } else mStats.mTransStaticNum++; AttributesWriterPtr attrs = trans->getAttrs(); if (mTransTimeIndex != 0 && attrs->isAnimated()) mTransAttrList.push_back(attrs); // loop through the children, making sure to push and pop them // from the MDagPath unsigned int numChild = mCurDag.childCount(); for (unsigned int i = 0; i < numChild; ++i) { mCurDag.push(mCurDag.child(i)); setup(iFrame, trans, gmMap); mCurDag.pop(); } } else { MString warn = mCurDag.fullPathName() + " is an unsupported type of "; warn += ob.apiTypeStr(); MGlobal::displayWarning(warn); } }