Maya parsing command arguments sample code

Handling a list of parameter:


MStatus MPxCommand::doIt(const MArgList& args)
{

    MString raw_command = MString("ComandName") + " " + to_str(args);

    MGlobal::displayInfo(raw_command);
    
    try {
        MStatus status;
        MSyntax syntax;
        
        syntax.addFlag("-ato", "-accordingTo", MSyntax::kString ); 
        syntax.addFlag("-sjt", "-sourceJoints", MSyntax::kString );
        
        syntax.addFlag("-fmt", "-forceMapTo", MSyntax::kString, MSyntax::kString);
        syntax.makeFlagMultiUse("-fmt");

        MArgParser parser(syntax, args, &status);
        if (!status) {
            MGlobal::displayError("Incorrect command! Check flags / arguments are valid: ");
            MGlobal::displayError(raw_command);
            return MS::kFailure;
        }

        if (parser.isFlagSet("-accordingTo")) {
            MString copy_options;
            mayaCheck(parser.getFlagArgument("-accordingTo", 0, copy_options));
        }

        if (parser.isFlagSet("-sourceJoints")) {
            MString joint_list;
            mayaCheck(parser.getFlagArgument("-sourceJoints", 0, joint_list));
            MStringArray joints = split(joint_list, ',');

            std::vector<std::string> source_joints;
            source_joints.resize(joints.length());
            for (int i = 0; i < source_joints.size(); ++i)
                source_joints[i] = to_str(joints[i]);
        }

        if (parser.isFlagSet("-copyWeights")) 
        {
            MString src_skincluster_name;
            MString dst_skincluster_name;
            mayaCheck(parser.getFlagArgument("-copyWeights", 0, src_skincluster_name));
            mayaCheck(parser.getFlagArgument("-copyWeights", 1, dst_skincluster_name));

            MObject src_skin_cluster = get_MObject(src_skincluster_name);
            MObject dst_skin_cluster = get_MObject(dst_skincluster_name);
            
            // look up -forceMapTo flags
            for(int i = 0; i < parser.numberOfFlagUses("-forceMapTo"); ++i)
            {
                MString src_joint_name, dst_joint_name;
                
                MArgList arg_list;
                mayaCheck( parser.getFlagArgumentList( "-forceMapTo", i, arg_list ) );
 
                src_joint_name = arg_list.asString( 0, &status );
                dst_joint_name = arg_list.asString( 1, &status );

                mayaCheck( status );
            }          
            
        }

        return redoIt();
    }
    catch (std::exception& e) {
        MGlobal::displayError("The command \"" + raw_command + "\" failed: ");
        MGlobal::displayError(e.what());
        MGlobal::displayError("Check input arguments or flags are valid.");
        std::cerr << e.what();
        return MS::kFailure;
    }
    return MS::kSuccess;
}


Raw parsing of the flags is what gives the most flexibility for the most work though:



char MpxCommand::_s_name[] = "MyCommandName";

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


MStatus MPxCommand::doIt(const MArgList& args)
{
    MStatus status;
    try
    {
        MString raw_command = MString(_s_name)+" "+to_str(args);
 

        // detect repeated occurrences of -fixValues
        // -fixValues double (min) double (max)
        std::vector<tbx::Vec2> constraints = get_flag_fix_values( args ); 

        // -nbIterations int
        int nb_iters = get_flag_int(args, "-nbIterations", /*default value:*/0);    
        
        // detect presence of -myFlag flag and ignores arguments
        bool has_my_flag = has_flag( args , "-myFlag");

        
        // flag with list of values (array of ints and floats)
        // -brushMask int (slot) int (length array) int[] (vert_ids) float[] (brush_values)
        std::vector<Brush> mask = get_flag_brush_mask( args ); 

        // -smoothCluster string
        MString skin_cluster_name;
        if( (skin_cluster_name = get_flag_string( args, "-smoothCluster")).length() > 0 ) 
            MObject skin_cluster = get_MObject( skin_cluster_name );            
       
        status = redoIt();
    }
    catch (std::exception& e)
    {
        MGlobal::displayError( e.what() );
        std::cerr << e.what();
        status = MS::kFailure;
    }

    return status;
}

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

static MString get_flag_string(const MArgList& args, const MString& str)
{
    MStatus status;
    unsigned len = args.length(&status);
    mayaCheck(status);
    MString name_arg;
    for(unsigned i = 0; i < len; ++i)
    {
        MString val = args.asString(i, &status);

        if( status == MS::kSuccess && str == val )
        {
            name_arg = args.asString(++i, &status);
            mayaCheck( status );
            break; // only one occurence is necessary.
        }
    }
    return name_arg;
}

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

/// fetch the argument "-fixValues" double (min) double (max)
static std::vector<tbx::Vec2> get_flag_fix_values(const MArgList& args)
{
    MStatus status;
    std::vector<tbx::Vec2> constraints;
    unsigned len = args.length(&status);
    mayaCheck(status);

    for(unsigned i = 0; i < len; ++i)
    {
        MString val = args.asString(i, &status);

        if( status == MS::kSuccess && MString("-fixValues") == val )
        {

            float min = float(args.asDouble(++i, &status));
            mayaCheck( status );
            float max = float(args.asDouble(++i, &status));
            mayaCheck( status );
            constraints.push_back( Vec2(min, max) );
        }
    }
    return constraints;
}

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

// 
static int get_flag_int(const MArgList& args,
                        const MString& str,
                        int default_value)
{
    MStatus status;
    unsigned len = args.length(&status);
    mayaCheck(status);
    int value = default_value;
    for(unsigned i = 0; i < len; ++i)
    {
        MString val = args.asString(i, &status);

        if( status == MS::kSuccess && str == val )
        {

            value = args.asInt(++i, &status);
            mayaCheck( status );
            break; // only one occurence is necessary.
        }
    }
    return value;
}


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

/// fetch the argument "-brushMask" int (slot) int (length array) int[] (vert_ids) float[] (brush_values)
/// @note the last two arguments are optional if length array is 0.
static std::vector<std::pair<int, float> > get_flag_brush_mask(const MArgList& args)
{
    MStatus status;
    std::vector<Brush> mask;
    unsigned len = args.length(&status);
    mayaCheck(status);

    for(unsigned i = 0; i < len; ++i)
    {
        MString val = args.asString(i, &status);

        if( status == MS::kSuccess && MString("-brushMask") == val )
        {
            // skip first int
            int slot = args.asInt(++i, &status);
            mayaCheck( status );

            int len = args.asInt(++i, &status);
            mayaCheck( status );

            MIntArray ints;
            MDoubleArray floats;
            if( len > 0 )
            {
                ints = args.asIntArray(++i, &status);
                mayaCheck( status );

                floats = args.asDoubleArray(++i, &status);
                mayaCheck( status );
            }

            mayaAssertMsg( ints.length() == floats.length(), 
                           "Invalid command flag for -brushMask" );

            for(unsigned j = 0; j < ints.length(); ++j)
                mask.push_back( make_pair(ints[j], float(floats[j])) );
        }
    }
    return mask;
}

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

static bool has_flag(const MArgList& args, const MString& flag_name)
{
    MStatus status;
    unsigned len = args.length(&status);
    mayaCheck(status);
    for(unsigned i = 0; i < len; ++i)
    {
        MString val = args.asString(i, &status);

        if( status == MS::kSuccess && flag_name == val ) {
            return true;
        }
    }
    return false;
}

No comments

(optional field, I won't disclose or spam but it's necessary to notify you if I respond to your comment)
All html tags except <b> and <i> will be removed from your comment. You can make links by just typing the url or mail-address.
Anti-spam question: