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

//
// Description:
//   This is an example of a command that writes information about the
//   dag pose of selected joints out to a file.
//
//   To use the command, select the joints that you want data for and
//   then type the command, being sure to use the -f/-file flag to specify
//   the name of the file to write to.
//
//      dagPoseInfo -f <fileName>
//
//   For example:
//
//      dagPoseInfo -f "C:/temp/poseData"
//
//   The output format used is:
//      <jointName>
//      <poseName>
//      worldMatrix
//      1 0 0 0
//      0 1 0 0
//      0 0 1 0
//      0 0 0 1
//      matrix
//      1 0 0 0
//      0 1 0 0
//      0 0 1 0
//      0 0 0 1
// 
//   Note that the pose node stores the local matrix data in a transformation
//   matrix, so that if one wanted to extract only the rotation components
//   of the pose rather than the entire local matrix, one could do so using
//   the MTransformationMatrix function set.
//
//   Also note that if you want just the bindPose data, rather than data about
//   all of the poses on a joint, you could restrict the output to dagPose
//   nodes for which the "dagPose" attribute is true.
//

#include <math.h>
#include <maya/MPxCommand.h>
#include <maya/MStatus.h>
#include <maya/MArgList.h>
#include <maya/MFnPlugin.h>
#include <maya/MObject.h>
#include <maya/MGlobal.h>
#include <maya/MDagPath.h>
#include <maya/MDagPathArray.h>
#include <maya/MItSelectionList.h>
#include <maya/MSelectionList.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MMatrix.h>
#include <maya/MFnMatrixData.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnAttribute.h>

#include <maya/MIOStream.h>

#define CheckError(stat,msg)            \
        if ( MS::kSuccess != stat ) {   \
                displayError(msg);                      \
                continue;                                       \
        }


class dagPoseInfo : public MPxCommand
{
public:
                dagPoseInfo();
    virtual     ~dagPoseInfo();

        MStatus         parseArgs( const MArgList& args );
    MStatus     doIt ( const MArgList& args );
    MStatus     redoIt ();
    MStatus     undoIt ();
    bool        isUndoable() const;

    static      void* creator();

private:
        void            printDagPoseInfo(MObject& dagPoseNode, unsigned index);
        bool            findDagPose(MObject& jointNode);
        FILE*           file;
};

dagPoseInfo::dagPoseInfo():
file(NULL)
{
}

dagPoseInfo::~dagPoseInfo() {}

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

bool dagPoseInfo::isUndoable() const
{
    return false;
}

MStatus dagPoseInfo::undoIt()
{
    return MS::kSuccess;
}

MStatus dagPoseInfo::parseArgs( const MArgList& args )
//
// There is one mandatory flag: -f/-file <filename>
//
{
        MStatus         stat;
        MString         arg;
        MString                 fileName;
        const MString   fileFlag                        ("-f");
        const MString   fileFlagLong            ("-file");

        // Parse the arguments.
        for ( unsigned int i = 0; i < args.length(); i++ ) {
                arg = args.asString( i, &stat );
                if (!stat)              
                        continue;
                                
                if ( arg == fileFlag || arg == fileFlagLong ) {
                        // get the file name
                        //
                        if (i == args.length()-1) {
                                arg += ": must specify a file name";
                                displayError(arg);
                                return MS::kFailure;
                        }
                        i++;
                        args.get(i, fileName);
                }
                else {
                        arg += ": unknown argument";
                        displayError(arg);
                        return MS::kFailure;
                }
        }

        file = fopen(fileName.asChar(),"wb");
        if (!file) {
                MString openError("Could not open: ");
                openError += fileName;
                displayError(openError);
                stat = MS::kFailure;
        }
        
        return stat;
}

void dagPoseInfo::printDagPoseInfo(MObject& dagPoseNode, unsigned index)
//
// Description:
//   Given a dagPose and an index corresponding to a joint, print out
//   the matrix info for the joint.
// Return:
//       None.
//
{
        MFnDependencyNode nDagPose(dagPoseNode);
        fprintf(file,"%s\n",nDagPose.name().asChar());

        // construct plugs for this joints world and local matrices
        //
        MObject aWorldMatrix = nDagPose.attribute("worldMatrix");
        MPlug pWorldMatrix(dagPoseNode,aWorldMatrix);
        pWorldMatrix.selectAncestorLogicalIndex(index,aWorldMatrix);
        
        MObject aMatrix = nDagPose.attribute("xformMatrix");
        MPlug pMatrix(dagPoseNode,aMatrix);
        pMatrix.selectAncestorLogicalIndex(index,aMatrix);

        // get and print the world matrix data
        //
        MObject worldMatrix, xformMatrix;
        MStatus status = pWorldMatrix.getValue(worldMatrix);
        if (MS::kSuccess != status) {
                displayError("Problem retrieving world matrix.");
        } else {
                bool foundMatrix = 0;
                MFnMatrixData dMatrix(worldMatrix);
                MMatrix wMatrix = dMatrix.matrix(&status);
                if (MS::kSuccess == status) {
                        foundMatrix = 1;
                        unsigned jj,kk;
                        fprintf(file,"worldMatrix\n");
                        for (jj = 0; jj < 4; ++jj) {
                                for (kk = 0; kk < 4; ++kk) {
                                        double val = wMatrix(jj,kk);
                                        fprintf(file,"%f ",val);
                                }
                                fprintf(file,"\n");
                        }
                }
                if (!foundMatrix) {
                        displayError("Error getting world matrix data.");
                }
        }

        // get and print the local matrix data
        //
        status = pMatrix.getValue(xformMatrix);
        if (MS::kSuccess != status) {
                displayError("Problem retrieving xform matrix.");
        } else {
                bool foundMatrix = 0;
                MFnMatrixData dMatrix(xformMatrix);
                if (dMatrix.isTransformation()) {
                        MTransformationMatrix xform = dMatrix.transformation(&status);
                        if (MS::kSuccess == status) {
                                foundMatrix = 1;
                                MMatrix xformAsMatrix = xform.asMatrix();
                                unsigned jj,kk;
                                fprintf(file,"matrix\n");
                                for (jj = 0; jj < 4; ++jj) {
                                        for (kk = 0; kk < 4; ++kk) {
                                                double val = xformAsMatrix(jj,kk);
                                                fprintf(file,"%f ",val);
                                        }
                                        fprintf(file,"\n");
                                }
                        }
                }
                if (!foundMatrix) {
                        displayError("Error getting local matrix data.");
                }
        }
}

bool dagPoseInfo::findDagPose(MObject& jointNode)
//
// Description:
//   Given a joint, check for connected dag pose nodes.
//   For each pose found, write out the pose info.
// Return:
//       If one or more poses is found, return true, else return false.
//
{
        bool rtn = 0; // return 1 if we find a pose

        MStatus status;
        MFnDependencyNode fnJoint(jointNode);
        MObject aBindPose = fnJoint.attribute("bindPose",&status);

        if (MS::kSuccess == status) {
                unsigned connLength = 0;
                MPlugArray connPlugs;
                MPlug pBindPose(jointNode,aBindPose);
                pBindPose.connectedTo(connPlugs,false,true);
                connLength = connPlugs.length();
                for (unsigned ii = 0; ii < connLength; ++ii) {
                        if (connPlugs[ii].node().apiType() == MFn::kDagPose) {
                                MObject aMember = connPlugs[ii].attribute();
                                MFnAttribute fnAttr(aMember);
                                if (fnAttr.name() == "worldMatrix") {
                                        unsigned jointIndex = connPlugs[ii].logicalIndex();

                                        fprintf(file,"%s\n",fnJoint.name().asChar());
                                        MObject jointObject = connPlugs[ii].node();
                                        printDagPoseInfo(jointObject,jointIndex);
                                        rtn = 1;
                                }
                        }
                }
        }
        return rtn;
}

MStatus dagPoseInfo::doIt( const MArgList& args )
{
        // parse args to get the file name from the command-line
        //
        MStatus stat = parseArgs(args);
        if (stat != MS::kSuccess) {
                return stat;
        }
        
        unsigned int count = 0;

        // Get the selected joints/transforms, and for each of them print
        // out the dagPose info
        //
        MSelectionList slist;
        MGlobal::getActiveSelectionList( slist );
        MItSelectionList itr( slist );

        for (; !itr.isDone(); itr.next() )
        {
                MObject depNode;
                itr.getDependNode(depNode);
                if (depNode.apiType() == MFn::kJoint) {
                        if (findDagPose(depNode)) {
                                count++;
                        }
                }
        }

        fclose(file);
        if (0 == count) {
                displayError("No poses were found on the selected joints.");
                return MS::kFailure;
        }
        
        return MS::kSuccess;
}

MStatus dagPoseInfo::redoIt()
{
    clearResult();
        setResult( (int) 1);
    return MS::kSuccess;
}

MStatus initializePlugin( MObject obj )
{
        MStatus   status;
    MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

    status = plugin.registerCommand( "dagPoseInfo", dagPoseInfo::creator );
        if (!status) {
                status.perror("registerCommand");
                return status;
        }

    return status;
}

MStatus uninitializePlugin( MObject obj )
{
        MStatus   status;
    MFnPlugin plugin( obj );

    status = plugin.deregisterCommand( "dagPoseInfo" );
        if (!status) {
                status.perror("deregisterCommand");
        }
    return status;
}