scanDagSyntax.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.
// ==========================================================================
//+


#include <maya/MFnDagNode.h>
#include <maya/MItDag.h>
#include <maya/MObject.h>
#include <maya/MDagPath.h>
#include <maya/MPxCommand.h>
#include <maya/MSyntax.h>
#include <maya/MArgDatabase.h>
#include <maya/MStatus.h>
#include <maya/MString.h>
#include <maya/MFnPlugin.h>
#include <maya/MArgList.h>
#include <maya/MFnCamera.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MMatrix.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MFnLight.h>
#include <maya/MColor.h>
#include <maya/MFnNurbsSurface.h>
#include <maya/MIOStream.h>

#define kBreadthFlag            "-b"
#define kBreadthFlagLong        "-breadthFirst"
#define kDepthFlag              "-d"
#define kDepthFlagLong          "-depthFirst"
#define kCameraFlag             "-c"
#define kCameraFlagLong         "-cameras"
#define kLightFlag              "-l"
#define kLightFlagLong          "-lights"
#define kNurbsSurfaceFlag       "-n"
#define kNurbsSurfaceFlagLong   "-nurbsSurfaces"
#define kQuietFlag              "-q"
#define kQuietFlagLong          "-quiet"

class scanDagSyntax: public MPxCommand
{
public:
                    scanDagSyntax() {};
    virtual         ~scanDagSyntax();
    static void*    creator();
    static MSyntax  newSyntax();
    virtual MStatus doIt( const MArgList& );

private:
    MStatus         parseArgs( const MArgList& args,
                               MItDag::TraversalType& traversalType,
                               MFn::Type& filter, bool & quiet);
    MStatus         doScan( const MItDag::TraversalType traversalType,
                            MFn::Type filter, bool quiet);
    void            printTransformData(const MDagPath& dagPath, bool quiet);
};

scanDagSyntax::~scanDagSyntax() {}

void* scanDagSyntax::creator()
{
    return new scanDagSyntax;
}

MSyntax scanDagSyntax::newSyntax()
{
    MSyntax syntax;

    syntax.addFlag(kBreadthFlag, kBreadthFlagLong);
    syntax.addFlag(kDepthFlag, kDepthFlagLong);
    syntax.addFlag(kCameraFlag, kCameraFlagLong);
    syntax.addFlag(kLightFlag, kLightFlagLong);
    syntax.addFlag(kNurbsSurfaceFlag, kNurbsSurfaceFlagLong);
    syntax.addFlag(kQuietFlag, kQuietFlagLong);

    return syntax;
}


MStatus scanDagSyntax::doIt( const MArgList& args )
{
    MItDag::TraversalType   traversalType = MItDag::kDepthFirst;
    MFn::Type               filter        = MFn::kInvalid;
    MStatus                 status;
    bool                    quiet = false;

    status = parseArgs ( args, traversalType, filter, quiet );
    if (!status)
        return status;

    return doScan( traversalType, filter, quiet);
};

MStatus scanDagSyntax::parseArgs( const MArgList& args,
                                  MItDag::TraversalType& traversalType,
                                  MFn::Type& filter,
                                  bool & quiet)
{
    MStatus         stat;
    MArgDatabase    argData(syntax(), args);

    MString         arg;

    if (argData.isFlagSet(kBreadthFlag))
        traversalType = MItDag::kBreadthFirst;
    else if (argData.isFlagSet(kDepthFlag))
        traversalType = MItDag::kDepthFirst;

    if (argData.isFlagSet(kCameraFlag))
        filter = MFn::kCamera;
    else if (argData.isFlagSet(kLightFlag))
        filter = MFn::kLight;
    else if (argData.isFlagSet(kNurbsSurfaceFlag))
        filter = MFn::kNurbsSurface;
        
    if (argData.isFlagSet(kQuietFlag))
        quiet = true;
        
    return stat;
}

MStatus scanDagSyntax::doScan( const MItDag::TraversalType traversalType,
                               MFn::Type filter,
                               bool quiet)
{   
    MStatus status;

    MItDag dagIterator( traversalType, filter, &status);

    if ( !status) {
        status.perror("MItDag constructor");
        return status;
    }

    //  Scan the entire DAG and output the name and depth of each node

    if (traversalType == MItDag::kBreadthFirst)
    {
        if (!quiet)
            cout << endl << "Starting Breadth First scan of the Dag";
    } else {
        if (!quiet)
            cout << endl << "Starting Depth First scan of the Dag";
    }

    switch (filter) {
        case MFn::kCamera:
            if (!quiet)
                cout << ": Filtering for Cameras\n";
            break;
        case MFn::kLight:
            if (!quiet)
                cout << ": Filtering for Lights\n";
            break;
        case MFn::kNurbsSurface:
            if (!quiet)
                cout << ": Filtering for Nurbs Surfaces\n";
            break;
        default:
            cout << endl;
    }
    
    int objectCount = 0;
    for ( ; !dagIterator.isDone(); dagIterator.next() ) {

        MDagPath dagPath;

        status = dagIterator.getPath(dagPath);
        if ( !status ) {
            status.perror("MItDag::getPath");
            continue;
        }

        MFnDagNode dagNode(dagPath, &status);
        if ( !status ) {
            status.perror("MFnDagNode constructor");
            continue;
        }

        if (!quiet)
            cout << dagNode.name() << ": " << dagNode.typeName() << endl;

        if (!quiet)
            cout << "  dagPath: " << dagPath.fullPathName() << endl;

        objectCount += 1;
        if (dagPath.hasFn(MFn::kCamera)) {
            MFnCamera camera (dagPath, &status);
            if ( !status ) {
                status.perror("MFnCamera constructor");
                continue;
            }

            // Get the translation/rotation/scale data
            printTransformData(dagPath, quiet);

            // Extract some interesting Camera data
            if (!quiet)
            {
                cout << "  eyePoint: "
                     << camera.eyePoint(MSpace::kWorld) << endl;
                cout << "  upDirection: "
                     << camera.upDirection(MSpace::kWorld) << endl;
                cout << "  viewDirection: "
                     << camera.viewDirection(MSpace::kWorld) << endl;
                cout << "  aspectRatio: " << camera.aspectRatio() << endl;
                cout << "  horizontalFilmAperture: "
                     << camera.horizontalFilmAperture() << endl;
                cout << "  verticalFilmAperture: "
                     << camera.verticalFilmAperture() << endl;
            }
        } else if (dagPath.hasFn(MFn::kLight)) {
            MFnLight light (dagPath, &status);
            if ( !status ) {
                status.perror("MFnLight constructor");
                continue;
            }

            // Get the translation/rotation/scale data
            printTransformData(dagPath, quiet);

            // Extract some interesting Light data
            MColor color;

            color = light.color();
            if (!quiet)
            {
                cout << "  color: ["
                     << color.r << ", "
                     << color.g << ", "
                     << color.b << "]\n";
            }
            color = light.shadowColor();
            if (!quiet)
            {
                cout << "  shadowColor: ["
                     << color.r << ", "
                     << color.g << ", "
                     << color.b << "]\n";

                cout << "  intensity: " << light.intensity() << endl;
            }
        } else if (dagPath.hasFn(MFn::kNurbsSurface)) {
            MFnNurbsSurface surface (dagPath, &status);
            if ( !status ) {
                status.perror("MFnNurbsSurface constructor");
                continue;
            }

            // Get the translation/rotation/scale data
            printTransformData(dagPath, quiet);

            // Extract some interesting Surface data
            if (!quiet)
            {
                cout << "  numCVs: "
                     << surface.numCVsInU()
                     << " * "
                     << surface.numCVsInV()
                     << endl;
                cout << "  numKnots: "
                     << surface.numKnotsInU()
                     << " * "
                     << surface.numKnotsInV()
                     << endl;
                cout << "  numSpans: "
                     << surface.numSpansInU()
                     << " * "
                     << surface.numSpansInV()
                     << endl;
            }
        } else {
            // Get the translation/rotation/scale data
            printTransformData(dagPath, quiet);
        }
    }

    if (!quiet)
    {
        cout.flush();
    }
    setResult(objectCount);
    return MS::kSuccess;
}

void scanDagSyntax::printTransformData(const MDagPath& dagPath, bool quiet)
{
    MStatus     status;
    MObject     transformNode = dagPath.transform(&status);
    // This node has no transform - i.e., it's the world node
    if (!status && status.statusCode () == MStatus::kInvalidParameter)
        return;
    MFnDagNode  transform (transformNode, &status);
    if (!status) {
        status.perror("MFnDagNode constructor");
        return;
    }
    MTransformationMatrix   matrix (transform.transformationMatrix());

    if (!quiet)
    {
        cout << "  translation: " << matrix.translation(MSpace::kWorld)
             << endl;
    }
    double                                  threeDoubles[3];
    MTransformationMatrix::RotationOrder    rOrder;

    matrix.getRotation (threeDoubles, rOrder, MSpace::kWorld);
    if (!quiet)
    {
        cout << "  rotation: ["
             << threeDoubles[0] << ", "
             << threeDoubles[1] << ", "
             << threeDoubles[2] << "]\n";
    }
    matrix.getScale (threeDoubles, MSpace::kWorld);
    if (!quiet)
    {
        cout << "  scale: ["
             << threeDoubles[0] << ", "
             << threeDoubles[1] << ", "
             << threeDoubles[2] << "]\n";
    }
}

MStatus initializePlugin( MObject obj )
{ 
    MStatus status;

    MFnPlugin plugin ( obj, PLUGIN_COMPANY, "3.0", "Any" );
    status = plugin.registerCommand( "scanDagSyntax", 
                                     scanDagSyntax::creator,
                                     scanDagSyntax::newSyntax ); 
    
    return status;
}

MStatus uninitializePlugin( MObject obj )
{
    MStatus status;

    MFnPlugin plugin( obj );
    status = plugin.deregisterCommand( "scanDagSyntax" );

    return status;
}