Thursday, March 21, 2013

python variables into mel.eval


this is rather simple, but not necessarily easy to find.

when calling mel commands you might want to pass variables declared in python, without having to do so in the mel environment first.

the documentation suggests that you might be working on both and might to communicate in-between them (and you can do so only via global variables). in activities such as mine, this is rarely the case.
using the eval function is 99% of the time given by the need to call a mel only command or script not available in python.

to solve this one can use the python() function when opening a "mel statement" via eval, one can call python again.
import maya.cmds as mc
import maya.mel as mm   
collideMainGrp = 'ColisMain_grp', em=1)  
kONode, kOShape, kODrivenGrp = mm.eval('cMuscle_rigKeepOut(python("collideMainGrp"))')

easy! in this case cMuscle_rigKeepOut uses a python variable, instead of having to do stuff like using selection based commands such as cMuscle_rigKeepOutSel whilst selecting stuff in your script, which is a rather unclean alternative.

unfortunately because of the explained above, mel will not read the variable unless it is global. therefore if one where to pass it to a function: 

loc = 'locator1'

def makeKeepOut(obj):
    global keepOut
    keepOut = obj
    kONode, kOShape, kODrivenGrp = mm.eval('cMuscle_rigKeepOut(python("keepOut"))')
    del keepOut
    return kONode, kOShape, kODrivenGrp

this as you can see is not the cleanest way to call mel commands... but! thanks to python formatting we can avoid the variable smuggling and we can just pass stuff as strings. this will not only make for a cleaner and more pythonic code, but shorter too.

we can either use the old %s formatting or str.format(), like so:

collideMainGrp = 'ColisMain_grp', em=1)

# or 
#mm.eval('cMuscle_rigKeepOut("%s")' % collideMainGrp )

when in a function:

def makeKeepOut(obj):

    kONode, kOShape, kODrivenGrp = mm.eval('cMuscle_rigKeepOut("%s")' % obj)
    # or
    #kONode, kOShape, kODrivenGrp = mm.eval('cMuscle_rigKeepOut("{0}")'.format(obj))

    return kONode, kOShape, kODrivenGrp

no need for globals or other fluff... neat and easier to read. (cheers to jakub for suggesting a couple of things)

cMuscle_rigKeepOut, by the way is a maya muscle un-documented command. you can find it in /***/autodesk/maya2012sp1/scripts/muscle/cMuscle.mel , it creates a collision node with a collision vector. needs a muscle object to interact with. handy stuff!

for more information on python formatting and the old %.


No comments: