Friday, January 7, 2011

Passing Values Between Python and MEL

MEL to Python
MEL:
$foo="Hi"
Python:
import maya.mel as mel
foo=mel.eval("$temp=$foo")

Python to MEL
Python:
bar="Hi"
MEL:
$bar=python("bar") 

Python to/from MEL
Plugin:
import maya.OpenMaya as om
import maya.OpenMayaMPx as omMPx

nodeId = om.MTypeId(0x101118)

#node data
class user(omMPx.MPxNode):
 INPUT = om.MObject()

 def __init__(self):
  omMPx.MPxNode.__init__(self)
def userCreator():
 return omMPx.asMPxPtr( user() )
def userIniter():
 numAttr = om.MFnNumericAttribute()
 user.x = numAttr.create("x","x",om.MFnNumericData.kFloat,0.0)
 numAttr.setStorable(1)
 numAttr.setWritable(1)
 user.addAttribute(user.x)

#plugin requires
def initializePlugin(mobject):
 mplugin = omMPx.MFnPlugin(mobject)
 try:
  mplugin.registerNode("user", nodeId, userCreator, userIniter)
 except:
  print "Error loading"
  raise
def uninitializePlugin(mobject):
 mplugin = omMPx.MFnPlugin(mobject)
 try:
  mplugin.deregisterNode( nodeId )
 except:
  print "Error removing"
  raise
MEL:
if(!size(`ls "userData"`)){
    createNode "user" -name "userData";
}
setAttr "userData.x" 5;
getAttr "userData.x";
Python:
import maya.cmds as cmds
if not cmds.ls("userData"):
    myUser=cmds.createNode("user", name="userData")
cmds.setAttr("userData.x", 5)
print cmds.getAttr("userData.x")

Sunday, January 2, 2011

Useful Commands

whatIs
whatIs script;   //mel only
whatIs statusLineUpdateInputField;   
// Result: Mel procedure found in: C:/Program Files/Autodesk/Maya2009/scripts/startup/statusLine.mel // 

When you need to emulate a command from Maya and the script editor only gives feedback when Echo All Commands is checked.  Maya most likely echoed a built in mel procedure that runs multiple mel commands in the background. Just open the file, find the procedure, and begin sifting through Maya's internals. 

evalDeffered
cmds.evalDeferred("cmds.refresh(force=1)", lowestPriority=1) 
cmds.evalDeferred(lambda : localCommand, lowestPriority=1) 

Often a command will return a result before the intended process is complete.  This is often a result of commands firing idle scriptJobs.  The problem is your code continues while Maya is trying to play catch up.  evalDeferred will wait until Maya is completely idle (no more queued scriptJobs) before continuing.

Attributes and Values

Here is a simple script to list all the attributes, attributeType, and values.
selection=cmds.ls(sl=1)[0]
selection=cmds.ls(sl=1)[0]
attributes=cmds.listAttr(selection)
attributeList=[]
print "\n"
for eachAttr in attributes:
   name=eachAttr,
   try: type=cmds.nodeType(selection+"."+eachAttr),
   except: type="Error"
   try: value=cmds.getAttr(selection+"."+eachAttr)
   except: value="Cannot Read"
   attributeList.append([name[0], type[0], value])
col1length=max([len(str(item[0])) for item in attributeList])
col2length=max([len(str(item[1])) for item in attributeList])
col3length=max([len(str(item[2])) for item in attributeList])
print ("Attribute".ljust(col1length), 
       "Type".ljust(col2length), 
       "Value".ljust(col3length))
for eachAttr in attributeList:
   print str(eachAttr[0]).ljust(col1length),
   print str(eachAttr[1]).ljust(col2length),
   print str(eachAttr[2]).ljust(col3length)

materialInfo

Quite often, unintentionally, mesh will only display in wireframe. More than often it is from accidentally deleting the connection from the mesh to the shading group. However, if you are scripting a file translator or shader exporter you might have ignored the materialInfo node. Almost invisible to the user it is necessary for hardware rendering of any shader.

A: Correct Connections, B: MaterialInfo Error, C: Deleted ShadingGroup
As you can see the problem is indistinguishable in the hypershade.  The only way to tell if you've got this problem is to view B's material in the Attribute Editor.  If most of it's Hardware Texturing features are disabled try the following.
miNode=cmds.createNode("materialInfo")
cmds.connectAttr("phong1SG.message", "%s.shadingGroup"%miNode)
cmds.connectAttr("phong1.message", "%s.material"%miNode)