Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
    }
}
Ejemplo n.º 4
0
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);
	}
}