polyExporter.cpp

//-
// ==========================================================================
// Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk
// license agreement provided at the time of installation or download,
// or which otherwise accompanies this software in either electronic
// or hard copy form.
// ==========================================================================
//+

//
//

//polyExporter.cpp
#include <maya/MStatus.h>
#include <maya/MString.h>
#include <maya/MObject.h>
#include <maya/MGlobal.h>
#include <maya/MItDag.h>
#include <maya/MDagPath.h>
#include <maya/MItSelectionList.h>
#include <maya/MPlug.h>

#include <maya/MIOStream.h>
#include <maya/MFStream.h>

#include "polyExporter.h"
#include "polyWriter.h"


polyExporter::polyExporter()
{
//Summary:  constructor method; does nothing
}


polyExporter::~polyExporter() 
{ 
//Summary:  destructor method; does nothing
//
}


MStatus polyExporter::writer(const MFileObject& file,
                             const MString& /*options*/,
                             MPxFileTranslator::FileAccessMode mode) 
//Summary:  saves a file of a type supported by this translator by traversing
//          the all or selected objects (depending on mode) in the current
//          Maya scene, and writing a representation to the given file
//Args   :  file - object containing the pathname of the file to be written to
//          options - a string representation of any file options 
//          mode - the method used to write the file - export, or export active
//                 are valid values; method will fail for any other values 
//Returns:  MStatus::kSuccess if the export was successful;
//          MStatus::kFailure otherwise
{
    #if defined (OSMac_)
        char nameBuffer[MAXPATHLEN];
        strcpy (nameBuffer, file.fullName().asChar());
        const MString fileName(nameBuffer);
    #else
        const MString fileName = file.fullName();
    #endif

    ofstream newFile(fileName.asChar(), ios::out);
    if (!newFile) {
        MGlobal::displayError(fileName + ": could not be opened for reading");
        return MS::kFailure;
    }
    newFile.setf(ios::unitbuf);

    writeHeader(newFile);

    //check which objects are to be exported, and invoke the corresponding
    //methods; only 'export all' and 'export selection' are allowed
    //
    if (MPxFileTranslator::kExportAccessMode == mode) {
        if (MStatus::kFailure == exportAll(newFile)) {
            return MStatus::kFailure;
        }
    } else if (MPxFileTranslator::kExportActiveAccessMode == mode) {
        if (MStatus::kFailure == exportSelection(newFile)) {
            return MStatus::kFailure;
        }
    } else {
        return MStatus::kFailure;
    }

    writeFooter(newFile);
    newFile.flush();
    newFile.close();

    MGlobal::displayInfo("Export to " + fileName + " successful!");
    return MS::kSuccess;
}


bool polyExporter::haveWriteMethod() const 
//Summary:  returns true if the writer() method of the class is implemented;
//          false otherwise
//Returns:  true since writer() is implemented in this class
{
    return true;
}


bool polyExporter::haveReadMethod() const 
//Summary:  returns true if the reader() method of the class is implemented;
//          false otherwise
//Returns:  false since reader() is not implemented in this class
{
    return false;
}


bool polyExporter::canBeOpened() const 
//Summary:  returns true if the translator can open and import files;
//          false if it can only import files
//Returns:  true
{
    return true;
}


MStatus polyExporter::exportAll(ostream& os) 
//Summary:  finds and outputs all polygonal meshes in the DAG
//Args   :  os - an output stream to write to
//Returns:  MStatus::kSuccess if the method succeeds
//          MStatus::kFailure if the method fails
{
    MStatus status;

    //create an iterator for only the mesh components of the DAG
    //
    MItDag itDag(MItDag::kDepthFirst, MFn::kMesh, &status);

    if (MStatus::kFailure == status) {
        MGlobal::displayError("MItDag::MItDag");
        return MStatus::kFailure;
    }

    for(;!itDag.isDone();itDag.next()) {
        //get the current DAG path
        //
        MDagPath dagPath;
        if (MStatus::kFailure == itDag.getPath(dagPath)) {
            MGlobal::displayError("MDagPath::getPath");
            return MStatus::kFailure;
        }

        MFnDagNode visTester(dagPath);

        //if this node is visible, then process the poly mesh it represents
        //
        if(isVisible(visTester, status) && MStatus::kSuccess == status) {
            if (MStatus::kFailure == processPolyMesh(dagPath, os)) {
                return MStatus::kFailure;
            }
        }
    }
    return MStatus::kSuccess;
}


MStatus polyExporter::exportSelection(ostream& os) 
//Summary:  finds and outputs all selected polygonal meshes in the DAG
//Args   :  os - an output stream to write to
//Returns:  MStatus::kSuccess if the method succeeds
//          MStatus::kFailure if the method fails
{
    MStatus status;

    //create an iterator for the selected mesh components of the DAG
    //
    MSelectionList selectionList;
    if (MStatus::kFailure == MGlobal::getActiveSelectionList(selectionList)) {
        MGlobal::displayError("MGlobal::getActiveSelectionList");
        return MStatus::kFailure;
    }

    MItSelectionList itSelectionList(selectionList, MFn::kMesh, &status);   
    if (MStatus::kFailure == status) {
        return MStatus::kFailure;
    }

    for (itSelectionList.reset(); !itSelectionList.isDone(); itSelectionList.next()) {
        MDagPath dagPath;

        //get the current dag path and process the poly mesh on it
        //
        if (MStatus::kFailure == itSelectionList.getDagPath(dagPath)) {
            MGlobal::displayError("MItSelectionList::getDagPath");
            return MStatus::kFailure;
        }

        if (MStatus::kFailure == processPolyMesh(dagPath, os)) {
            return MStatus::kFailure;
        }
    }
    return MStatus::kSuccess;
}


MStatus polyExporter::processPolyMesh(const MDagPath dagPath, ostream& os) 
//Summary:  processes the mesh on the given dag path by extracting its geometry
//          and writing this data to file
//Args   :  dagPath - the current dag path whose poly mesh is to be processed
//          os - an output stream to write to
//Returns:  MStatus::kSuccess if the polygonal mesh data was processed fully;
//          MStatus::kFailure otherwise
{
    MStatus status;
    polyWriter* pWriter = createPolyWriter(dagPath, status);
    if (MStatus::kFailure == status) {
        delete pWriter;
        return MStatus::kFailure;
    }
    if (MStatus::kFailure == pWriter->extractGeometry()) {
        delete pWriter;
        return MStatus::kFailure;
    }
    if (MStatus::kFailure == pWriter->writeToFile(os)) {
        delete pWriter;
        return MStatus::kFailure;
    }
    delete pWriter;
    return MStatus::kSuccess;
}


bool polyExporter::isVisible(MFnDagNode & fnDag, MStatus& status) 
//Summary:  determines if the given DAG node is currently visible
//Args   :  fnDag - the DAG node to check
//Returns:  true if the node is visible;        
//          false otherwise
{
    if(fnDag.isIntermediateObject())
        return false;

    MPlug visPlug = fnDag.findPlug("visibility", &status);
    if (MStatus::kFailure == status) {
        MGlobal::displayError("MPlug::findPlug");
        return false;
    } else {
        bool visible;
        status = visPlug.getValue(visible);
        if (MStatus::kFailure == status) {
            MGlobal::displayError("MPlug::getValue");
        }
        return visible;
    }
}


void polyExporter::writeHeader(ostream& os) 
//Summary:  outputs information that needs to appear before the main data
//Args   :  os - an output stream to write to
{
    os << "";
}


void polyExporter::writeFooter(ostream& os) 
//Summary:  outputs information that needs to appear after the main data
//Args   :  os - an output stream to write to
{
    os << "";
}