scanDagCmd.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/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>

class scanDag: public MPxCommand
{
public:
                    scanDag() {};
    virtual         ~scanDag();
    static void*    creator();
    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);
};

scanDag::~scanDag() {}

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

MStatus scanDag::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 scanDag::parseArgs( const MArgList& args,
                          MItDag::TraversalType& traversalType,
                          MFn::Type& filter,
                          bool & quiet)
{
    MStatus         stat;
    MString         arg;
    const MString   breadthFlag             ("-b");
    const MString   breadthFlagLong         ("-breadthFirst");
    const MString   depthFlag               ("-d");
    const MString   depthFlagLong           ("-depthFirst");
    const MString   cameraFlag              ("-c");
    const MString   cameraFlagLong          ("-cameras");
    const MString   lightFlag               ("-l");
    const MString   lightFlagLong           ("-lights");
    const MString   nurbsSurfaceFlag        ("-n");
    const MString   nurbsSurfaceFlagLong    ("-nurbsSurfaces");
    const MString   quietFlag               ("-q");
    const MString   quietFlagLong           ("-quiet");

    // Parse the arguments.
    for ( unsigned int i = 0; i < args.length(); i++ ) {
        arg = args.asString( i, &stat );
        if (!stat)              
            continue;
                
        if ( arg == breadthFlag || arg == breadthFlagLong )
            traversalType = MItDag::kBreadthFirst;
        else if ( arg == depthFlag || arg == depthFlagLong )
            traversalType = MItDag::kDepthFirst;
        else if ( arg == cameraFlag || arg == cameraFlagLong )
            filter = MFn::kCamera;
        else if ( arg == lightFlag || arg == lightFlagLong )
            filter = MFn::kLight;
        else if ( arg == nurbsSurfaceFlag || arg == nurbsSurfaceFlagLong )
            filter = MFn::kNurbsSurface;
        else if ( arg == quietFlag || arg == quietFlagLong )
            quiet = true;
        else {
            arg += ": unknown argument";
            displayError(arg);
            return MS::kFailure;
        }
    }
    return stat;
}

MStatus scanDag::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 scanDag::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( "scanDag", scanDag::creator );
    if ( !status )
        status.perror("registerCommand");
    
    return status;
}

MStatus uninitializePlugin( MObject obj )
{
    MStatus status;

    MFnPlugin plugin( obj );
    status = plugin.deregisterCommand( "scanDag" );
    if ( ! status )
        status.perror("deregisterCommand");

    return status;
}