Maya parsing command arguments sample code
How to parse list, tuples etc. - 10/2023 - #Jumble
Handling a list of parameter:
- Option1: -flag "elt0, elt1, elt2" having a flag with a single string and parsing the string for commas manually
- Option2: use MSyntax::makeFlagMultiUse() and MArgParser::getFlagArgumentList()
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