How to send python lists to a custom command

How to send python lists to a custom command

dneag
Explorer Explorer
1,388 Views
4 Replies
Message 1 of 5

How to send python lists to a custom command

dneag
Explorer
Explorer

Hello,

 

I'd like to be able to create a command that will accept from python a large list, or even better a list of tuples, as an argument. Just like the curve command for instance: cmds.curve( d=1, p= [ (x,y,z), (x,y,z), (x,y,z), ... ] ).  And then translate it into a multidimensional array.

I can use the addFlag and flagArgument functions to pass data through, but the data types seem limited.

 

Here is what I have:

 

MSyntax MyCommand::newSyntax()
{
    MSyntax syntax;
 
    syntax.addFlag( "-arg", "-argument", MSyntax::kDouble);
 
    return syntax;
}
 
MStatus MyCommand::doIt(const MArgList &argList)
{
    MStatus status;
 
    MArgDatabase argData(syntax(), argList, &status );
    CHECK_MSTATUS_AND_RETURN_IT(status);
 
    double arg1;
    arg1 = argData.flagArgumentDouble("-arg", 0);
}

How can I make a command that accepts lists as arguments?

0 Likes
1,389 Views
4 Replies
Replies (4)
Message 2 of 5

RFlannery1
Collaborator
Collaborator

I think you can get it to accept a list by using the "makeFlagMultiUse" command from the MSyntax class.  So if you wanted a list of strings, you would do the following:

MSyntax syntax;
syntax.addFlag( "-arg", "-argument", MSyntax::kString);
syntax.makeFlagMultiUse("argument");
 

Less sure about a list of tuples.  I would guess something like this:

MSyntax syntax;
syntax.addFlag( "-arg", "-argument", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble);
syntax.makeFlagMultiUse("argument");
0 Likes
Message 3 of 5

dneag
Explorer
Explorer

Well that does seem to allow the command to accept a list but I can't figure out how/if I can access all the elements on the other end.

 

I'm doing this:

 

MSyntax CreateMesh::newSyntax()
{
    MSyntax syntax;
    
    syntax.addFlag( "-arg", "-argument", MSyntax::kString);
    syntax.makeFlagMultiUse("-arg");
    
    return syntax;
}

MStatus CreateMesh::doIt(const MArgList &argList)
{

    MStatus status;

    MArgDatabase argData(syntax(), argList, &status );
    CHECK_MSTATUS_AND_RETURN_IT(status);

    MString arg1, arg2;
    arg1 = argData.flagArgumentString("-arg", 0);
    arg2 = argData.flagArgumentString("-arg", 1);
    MGlobal::displayInfo("Your list is: "+arg1+", "+arg2);
}

After running the command with a list of two strings ["a","b"], the arg1 variable will take the first element of the list, but arg2 remains empty.  I took a guess that the int parameter of flagArgumentString might correspond to the elements of the list but that doesn't seem to be working.

 

Thanks

0 Likes
Message 4 of 5

RFlannery1
Collaborator
Collaborator

Thanks for correcting my syntax.  I wasn't sure of the exact string to pass into the "makeFlagMultiUse" function.

 

Anyways, I found some examples in the devkit, AbcBullet.cpp and geometryCacheConverter.cpp.  Here is a slightly modified snippet of code from geometryCacheConverter:

#define SFLAG_FILE "-f"

MStatus convertGeometryCache::doIt( const MArgList& args ) MStatus status = MS::kSuccess; MArgDatabase argDb( syntax(), args, &status ); if( !status ) return status; bool hasFile = argDb.isFlagSet( SFLAG_FILE ); if( !hasFile ) { MGlobal::displayError( "Specify at least one file." ); return status; } // Iterate through all the files specified // uint numUses = argDb.numberOfFlagUses( SFLAG_FILE ); for( uint i = 0; i < numUses; i++ ) { MArgList argList; status = argDb.getFlagArgumentList( SFLAG_FILE, i, argList ); if( !status ) return status; MString name = argList.asString( 0, &status ); if( !status ) return status; } }

 

Message 5 of 5

dneag
Explorer
Explorer

Aha!  This is working.  Although I don't totally understand how.

I guess any list sent through has to be treated as a separate MArgList? 

 

Also, from there, a list of tuples is pretty straightforward:

MSyntax CreateMesh::newSyntax()
{
    MSyntax syntax;
  
    syntax.addFlag( "-arg", "-argument", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble );
    syntax.makeFlagMultiUse("-arg");
    
    return syntax;
}

MStatus CreateMesh::doIt(const MArgList &argList)
{
    
    MStatus status;

    MArgDatabase argData(syntax(), argList, &status );
    CHECK_MSTATUS_AND_RETURN_IT(status);

    uint numUses = argData.numberOfFlagUses("-arg");
    for( uint i = 0; i < numUses; i++ )
    {
        MArgList argList;
        status = argData.getFlagArgumentList( "-arg", i, argList );
        if( !status ) return status;
        
        double d1 = argList.asDouble( 0, &status );
        double d2 = argList.asDouble( 1, &status );
        double d3 = argList.asDouble( 2, &status );
        
        if( !status ) return status;
        
        MGlobal::displayInfo(MString()+d1+", "+d2+", "+d3);
    }
    
}

Not sure what a uint is or what its purpose here is.  Regular int seems to work as well.

 

Anyways, thank you very much.