Posts Tagged ‘ mel

Mel command argument passing in Python

From over on my mel wiki

Python has some shortcuts you can implement when passing arguments to mel commands (or other Python functions).
Take for example a sphere (named pSphere1) that you want to scale. Here is the basic mel to do so:

float $scaleVals[] = {1.0, 2.0, .5};
// optionA:
setAttr pSphere1.scale -type double3 $scaleVals[0] $scaleVals[1] $scaleVals[2];
// optionB also works:
setAttr pSphere1.scale $scaleVals[0] $scaleVals[1] $scaleVals[2];

Likewise in Python, you can do something very similar:

import maya.cmds as mc

scaleVals = [1, 2, .5]
# optionA:
mc.setAttr("pSphere1.scale", scaleVals[0], scaleVals[1], scaleVals[2], type="double3")
# optionB also works:
mc.setAttr("pSphere1.scale", scaleVals[0], scaleVals[1], scaleVals[2])

However, in Python you can pass all the args in as a list\tuple variable by prefixing the variable name with an asterisk ‘*’. The function (mel command) will unpack the variable as individual positional arguments. It’s important that the variable have the same number of items as the command expects argument values, or a Python RuntimeError exception will be raised:

# option C, much cleaner!:
mc.setAttr("pSphere1.scale", *scaleVals)

You can see more about how this argument system works over on my Python Wiki.

How does Maya populate its maya.cmds package?

From over on my Mel Wiki:

When using Python in Maya, to access the bulk of the mel commands via Python, you import the mel.cmds package, usually into a namespace, like so:

import maya.cmds as mc
print mc.ls()

But if you browse to that package on disk, you’ll find it empty, only containing an __init__.py file (required for package creation):

C:\Program Files\Autodesk\Maya<VERSION>\Python\Lib\site-packages\maya\cmds

So how are all the ‘mel commands’ added to that package for execution in Python?

There is a Maya startup Python module living here, that works the magic of populating that package:

C:\Program Files\Autodesk\Maya<VERSION>\Python\Lib\site-packages\maya\app\commands.py

It inspects a file called commandList (no extension, but it’s text) living here:

C:\Program Files\Autodesk\Maya<VERSION>\bin\commandList

You can open that file in a text editor, and what you’ll find are two columns: One with a ‘mel’ command name, and one with a .dll where that command ‘lives’. Those .dll’s live in the same dir as the commandList file. Here’s a sample:

TanimLayer AnimSlice.dll
about Shared.dll
addAttr Shared.dll
addDynamic DynSlice.dll
addPP DynSlice.dll
affectedNet Shared.dll
affects Shared.dll
agFormatIn Translators.dll
agFormatOut Translators.dll
aimConstraint AnimSlice.dll
air DynSlice.dll
aliasAttr Shared.dll
align Shared.dll

What commands.py does is parse the commandList file and append each command (via a Python command wrapper function) to maya.cmd‘s ‘__dict__‘ attribute (maya.cmds.__dict__), which is the lookup table users access when calling their favorite mel command via Python (like maya.cmds.ls())  It also passes the name of the .dll to the command wrapper function, so when the user executes the given command, it first loads the parental .dll.

Crack open commands.py for the nitty-gritty details.

If you want to see the end result of all this hard work, you can run this code in Maya. But it prints a *lot* of stuff:

import maya.cmds as mc

for k in sorted(mc.__dict__.keys()):
    print k, mc.__dict__[k]

Centering joints in edge loops

When I’m rigging, I will often create an initial ‘rig-skeleton’ that fits inside the mesh to be deformed. To speed things along, I first just rough in the joint positions by snapping them to verts.   But later I like to get them centered into a selection of verts, and usually that selection is some form of edge loop.

I wrote some mel that does this:

  • You pick a joint, and an edge on a mesh
  • The code detects the joint, and the edge
  • Based on the edge, find the edge loop
  • Convert the edge loop into a selection of verts
  • Find the average position of all the verts
  • Move the joint pivots to this new position
  • Reselect the joint, and the new vert selection.

You can find the mel code over on my Mel Wiki.