March 2019: ewertb.soundlinker.com is getting relocated to ewertb.mayasound.com, please update your bookmarks.

Maya API How-To #31

Back · Previous · Next Maya

How do I specify, and parse, a matrix, double array or double list for a MPxCommand argument?

#pragma warning( disable : 4786 )

#include "maya/MFnPlugin.h" // cannot put in header...declares global vars

#include "maya/MPxCommand.h"
#include "maya/MArgList.h"
#include "maya/MMatrix.h"
#include "maya/MDoubleArray.h"
#include "maya/MGlobal.h"

#include <iostream>

static const char* COMMAND_NAME = "matrixArg";

static const char* MATRIX_FLAG = "m";
static const char* MATRIX_FLAG_LONG = "matrix";

static const char* DOUBLE_ARRAY_FLAG = "da";
static const char* DOUBLE_ARRAY_FLAG_LONG = "doubleArray";

static const char* DOUBLE_LIST_FLAG = "dl";
static const char* DOUBLE_LIST_FLAG_LONG = "doubleList";

static const char* HELP_FLAG = "h";
static const char* HELP_FLAG_LONG = "help";

void print_maya_matrix( const MMatrix& m, const char* label = NULL )
{
    if ( NULL != label )
    {
        std::clog << label << std::endl;
    }
    
    char buf[128];
    sprintf( buf, "\t%4.4f %4.4f %4.4f %4.4f", m[0][0], m[0][1], m[0][2], m[0][3] );
    std::clog << buf << std::endl;
    sprintf( buf, "\t%4.4f %4.4f %4.4f %4.4f", m[1][0], m[1][1], m[1][2], m[1][3] );
    std::clog << buf << std::endl;
    sprintf( buf, "\t%4.4f %4.4f %4.4f %4.4f", m[2][0], m[2][1], m[2][2], m[2][3] );
    std::clog << buf << std::endl;
    sprintf( buf, "\t%4.4f %4.4f %4.4f %4.4f", m[3][0], m[3][1], m[3][2], m[3][3] );
    std::clog << buf << std::endl;
}

void print_double_array( const MDoubleArray& d, const char* label = NULL )
{
    if ( NULL != label )
    {
        std::clog << label << std::endl;
    }

    std::clog << "\t";
    
    char buf[16];
    unsigned int i;
    for ( i = 0; i < d.length(); i++ )
    {
        sprintf( buf, "%4.4f", d[i] );
        std::clog << buf;

        if ( i < ( d.length() - 1 ) ) std::clog << ", ";
    }

    std::clog << std::endl;
}

class SimpleCommand : public MPxCommand
{
    public:
        SimpleCommand();
        ~SimpleCommand() {}

        static void*        creator();

        virtual MStatus     doIt( const MArgList& args );

        MStatus             parseArgs( const MArgList& args );
        
        void                Help( void ) const;

    private:

        MMatrix             mMatrix;
        MDoubleArray        mDoubleArray;
        MDoubleArray        mDoubleList;

        bool                mHelp;   
};

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

SimpleCommand::SimpleCommand() :
    mHelp( false )
{
}

MStatus SimpleCommand::parseArgs( const MArgList& args )
{
    MStatus status;
    MStatus argStatus;

    unsigned int flagIndex = 0;

    flagIndex = args.flagIndex( HELP_FLAG, HELP_FLAG_LONG );
    if ( MArgList::kInvalidArgIndex != flagIndex )
    {
        mHelp = true;
        return MS::kSuccess;
    }

    flagIndex = args.flagIndex( MATRIX_FLAG, MATRIX_FLAG_LONG );
    if ( MArgList::kInvalidArgIndex != flagIndex )
    {
        flagIndex++;

        MMatrix m;
        status = args.get( flagIndex, m );
        if ( MS::kSuccess == status )
        {
            mMatrix = m;
        }
        else status.perror( "FAILED to get matrix." );
    }

    flagIndex = args.flagIndex( DOUBLE_ARRAY_FLAG, DOUBLE_ARRAY_FLAG_LONG );
    if ( MArgList::kInvalidArgIndex != flagIndex )
    {
        flagIndex++;

        MDoubleArray a;
        status = args.get( flagIndex, a );
        if ( MS::kSuccess == status )
        {
            mDoubleArray = a;
        }
        else status.perror( "FAILED to get double array." );
    }

    flagIndex = args.flagIndex( DOUBLE_LIST_FLAG, DOUBLE_LIST_FLAG_LONG );
    if ( MArgList::kInvalidArgIndex != flagIndex )
    {
        MString asString;

        // Keep popping arguments off the stack until 
        // we hit one that's not a number.
        //
        while ( ( MS::kSuccess == argStatus ) && 
                ( ++flagIndex < args.length() ) )
        {
            asString = args.asString( flagIndex, &argStatus );

            if ( ( MS::kSuccess != argStatus ) ||
                 !( asString.isDouble() || 
                    asString.isFloat() || 
                    asString.isInt() || 
                    asString.isShort() || 
                    asString.isUnsigned() ) )
                break;

            // If any of the numeric types, accept it as a double.
            //
            mDoubleList.append( args.asDouble( flagIndex, &argStatus ) );    
        }
    }

    return status;
}

MStatus SimpleCommand::doIt( const MArgList& args )
{
    MStatus status;

    status = parseArgs( args );

    if ( mHelp )
    {
        Help();
        return MS::kSuccess;
    }

    if ( MS::kSuccess == status )
    {
        print_maya_matrix( mMatrix, "Your matrix:" );
        print_double_array( mDoubleArray, "Your array:" );
        print_double_array( mDoubleList, "Your list:" );
    }

    return status;
}


void SimpleCommand::Help( void ) const
{
    MString help( "Example MPxCommand - by Bryan Ewert\n" );

    help += "//\t -m|-matrix                     [C]   Specify a matrix argument. Accepts sixteen float values only.\n";
    help += "//\t                                        e.g. 1.0 0.0 0.0 0.0  0.0 1.0 0.0 0.0  0.0 0.0 1.0 0.0  0.0 0.0 0.0 1.0\n";
    help += "//\t -da|-doubleArray               [C]   Specify a double array, enclosed in braces, comma-separated.\n";
    help += "//\t                                        e.g. { 1.1, 3.14, 0.707 }\n";
    help += "//\t -dl|-doubleList                [C]   Specify a list of doubles, separated by whitespace.\n";
    help += "//\t                                        e.g. 1.1 3.14 0.707\n";

    help += "//\t -h|-help                       [C]   Displays this help.\n";

    MGlobal::displayInfo( help );
}


//------------------------------------------------------------
//------------------------------------------------------------


//------------------------------------------------------------
// Plugin initialization. 
//
// All command objects need to be registered in this function
// before they can be called by a MEL script from within maya.
//------------------------------------------------------------
MStatus initializePlugin(MObject pluginObj)
{
    MStatus			status;
    MFnPlugin		plugin( pluginObj, COMMAND_NAME, "1.0", "Any" );

    // Register: simpleCommand
    status = plugin.registerCommand( COMMAND_NAME,
                                     SimpleCommand::creator );
    if ( MS::kSuccess != status)
    {
	    status.perror( MString( "FAILED to register '" ) + COMMAND_NAME + "'" );
	    return status;
    }

    return MS::kSuccess;
}

//------------------------------------------------------------
// Plugin uninitialization. 
//
// All command objects need to be deregistered in this function
// so that maya can clean up properly.
//------------------------------------------------------------
MStatus uninitializePlugin(MObject pluginObj)
{
    MStatus			status;
    MFnPlugin		plugin( pluginObj );

    status = plugin.deregisterCommand( COMMAND_NAME );

    return status;
}

21 Oct 2005