exportJointClusterDataCmd/exportJointClusterDataCmd.cpp
 
 
 
exportJointClusterDataCmd/exportJointClusterDataCmd.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 exports rigid skin data from
//   maya to an alternate format.
//
//   To use, type the command:
//
//      exportJointClusterData -f <fileName>
//
//   For example:
//
//      exportJointClusterData -f "C:/temp/skinData"
//
//   The output format used is:
// 
//         jointName <skinCount>
//     skin_1 <weightCount>
//     <skin_1_component_index1> <skin_1_wt1>
//     <skin_1_component_index2> <skin_1_wt2>
//     <skin_1_component_index3> <skin_1_wt3>
//     ...
//     skin_2 <weightCount>
//     <skin_2_component_index1> <skin_2_wt1>
//     <skin_2_component_index2> <skin_2_wt2>
//     <skin_2_component_index3> <skin_2_wt3>
//     ...
//
//   
//

#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/MItSelectionList.h>
#include <maya/MSelectionList.h>
#include <maya/MFloatArray.h>
#include <maya/MObjectArray.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MItGeometry.h>
#include <maya/MFnWeightGeometryFilter.h>
#include <maya/MFnGeometryFilter.h>
#include <maya/MItGeometry.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MFnSet.h>


#include <maya/MIOStream.h>

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


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

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

    static      void* creator();

private:
        FILE*           file;
};

exportJointClusterData::exportJointClusterData():
file(NULL)
{
}

exportJointClusterData::~exportJointClusterData() {}

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

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

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

MStatus exportJointClusterData::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;
}

MObject exportJointClusterData::jointForCluster(MObject& jointCluster) const
//
// Given a jointCluster, return the joint that drives it
//
{
        MObject result;
        MFnDependencyNode fnNode(jointCluster);
        MObject attrJoint = fnNode.attribute("matrix");
        MPlug pJointPlug(jointCluster,attrJoint);
        MPlugArray conns;
        if (pJointPlug.connectedTo(conns,true,false)) {
                result = conns[0].node();
        }
        return result;
}

MStatus exportJointClusterData::doIt( const MArgList& args )
//
// Process the command  
// 1. parse the args
// 2. find the jointClusters in the scene
// 3. iterate over their members, writing their weight data out to file 
//
{
        // parse args to get the file name from the command-line
        //
        MStatus stat = parseArgs(args);
        if (stat != MS::kSuccess) {
                return stat;
        }

        // count the processed jointClusters
        //
        unsigned int jcCount = 0;

        // Iterate through graph and search for jointCluster nodes
        //
        MItDependencyNodes iter( MFn::kJointCluster);
        for ( ; !iter.isDone(); iter.next() ) {
                MObject object = iter.item();
                MFnWeightGeometryFilter jointCluster(object);

                // get the joint driving this cluster
                //
                MObject joint = jointForCluster(object);
                if (joint.isNull()) {
                        displayError("Joint is not attached to cluster.");
                        continue;
                }

                MObject deformSet = jointCluster.deformerSet(&stat);
                CheckError(stat,"Error getting deformer set.");
                        
                MFnSet setFn(deformSet, &stat); //need the fn to get the members
                CheckError(stat,"Error getting deformer set fn.");
                
                MSelectionList clusterSetList;

                //get all the members
                //
                stat = setFn.getMembers(clusterSetList, true);
                CheckError(stat,"Could not make member list with getMembers.");

                // print out the name of joint and the number of associated skins
                //
                MFnDependencyNode fnJoint(joint);
                fprintf(file,"%s %u\n",fnJoint.name().asChar(),
                                clusterSetList.length());
                
                for (unsigned int kk = 0; kk < clusterSetList.length(); ++kk) {
                        MDagPath skinpath;
                        MObject components;
                        MFloatArray weights;

                        clusterSetList.getDagPath(kk,skinpath,components);
                        jointCluster.getWeights(skinpath,components,weights);

                        // print out the path name of the skin & the weight count
                        //
                        fprintf(file,
                                        "%s %u\n",skinpath.partialPathName().asChar(),
                                        weights.length());

                        // loop through the components and print their index and weight
                        //
                        unsigned counter =0;
                        MItGeometry gIter(skinpath,components);
                        for (/* nothing */ ; !gIter.isDone() &&
                                                                   counter < weights.length(); gIter.next()) {
                                fprintf(file,"%d %f\n",gIter.index(),weights[counter]);
                                counter++;
                        }
                }
                jcCount++;
        }

        fclose(file);

        if (0 == jcCount) {
                displayError("No jointClusters found in this scene.");
                return MS::kFailure;
        }

        return MS::kSuccess;
}

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

    return status;
}

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

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