Python has many useful built-in libraries and data structures. In most cases, there is an existing library that can be used for general programming tasks, which obviates the need to create custom utilities as in the case of MEL scripts. Documentation of the built-in Python libraries can be found at http://docs.python.org. This site also provides a good introductory tutorial for general Python programming.
One handy Python function is functools.partial, which can be used to pass extra information to a callback function. For example, the following class creates a window with several buttons that print a number when clicked on:
from functools import partial import maya.cmds as cmds class ButtonWin(object): def __init__(self): self.win = cmds.window() self.layout = cmds.columnLayout(parent=self.win) for x in range(10): cmds.button(label="Click Here %d"%x, parent=self.layout, command=partial(self.report,x)) cmds.showWindow() def report(self,buttonIndex,value): (print "button %d got %s"%(buttonIndex,value)) f = ButtonWin()
You can use any debugger to debug your Python scripts. Several IDEs, such as Eclipse and Wing IDE, come with their own debuggers. These have convenient graphical interfaces for debugging your scripts. See the documentation for your preferred IDE for information on how to start a debugging session.
Python also comes with its own built-in debugger, pdb. pdb has a text interface and can be invoked directly from within a script in the Script Editor. You will need to import the pdb module, then set a breakpoint using pdb.set_trace():
import pdb pdb.set_trace()
When execution reaches pdb.set_trace(), the input dialog will appear. You can use standard commands to continue, step-into, print values, or do other debugging operations. An input dialog box will appear whenever pdb needs input.
For more information on how to use pdb see The Python Debugger.
You can use the createMelWrapper function to register a Python function as a MEL procedure. Then, when the MEL procedure is invoked, it calls the Python function, passing any arguments it receives and returning the function's result.
For more information regarding this function, refer to the melutils.py file in the ..\Python\lib\site-packages\maya\mel folder of your Maya installation directory.
Or, execute the following in the Script Editor:
import maya.mel help(maya.mel.createMelWrapper)
Advantages of using this function:
The following is an example of how to use the createMelWrapper function to register a Python function as a MEL procedure in order to use the Rmb Command attribute in the asset (formerly container) node.
import maya.cmds as cmds import maya.mel as mel def exCoNotes(node): if(cmds.nodeType(node)=='container'): objCont = node else: objCont = cmds.container(q=True, findContainer=node) exec(cmds.getAttr(objCont+'.notes')) pyfunction = 'main("'+node+'","'+objCont+'")' exec(pyfunction) cmds.select(node, r=True) def setThisContainerCurrent(node): if(cmds.nodeType(node)=='container'): objCont = node else: objCont = cmds.container(q=True, findContainer=node) cmds.container(objCont, e=True, c=True) cmds.select(node, r=True) def rmbMyContainerScript(): return ("Execute Container Notes", "exCoNotes", "Set This Container Current", "setThisContainerCurrent")
from rmbScript import * import maya.cmds as cmds import maya.mel as mel mel.createMelWrapper(rmbMyContainerScript,retType='string[]') mel.createMelWrapper(exCoNotes) mel.createMelWrapper(setThisContainerCurrent)
You can also use this step with Assets with Transform; however, the node type would be dagContainer instead.
def main(node, container): print node print container
rehash;
You can use this Python example script to create an animated curve and set its key frames:
import maya.OpenMaya as om import maya.OpenMayaAnim as oma def addkeys(plugName, times, values, changeCache): # Get the plug to be animated. sel = om.MSelectionList() sel.add(plugName) plug = om.MPlug() sel.getPlug(0, plug) # Create the animCurve. animfn = oma.MFnAnimCurve() animCurve = animfn.create(plug, oma.MFnAnimCurve.kAnimCurveTL) # Copy the times into an MTimeArray and the values into an MDoubleArray. timeArray = om.MTimeArray() valueArray = om.MDoubleArray() for i in range(len(times)): timeArray.append(om.MTime(times[i], om.MTime.uiUnit())) valueArray.append(values[i]) # Add the keys to the animCurve. animfn.addKeys( timeArray, valueArray, oma.MFnAnimCurve.kTangentGlobal, oma.MFnAnimCurve.kTangentGlobal, False, changeCache )
The sample code above adds keyframe animation to a channel (in other words, a plug). If you do not need to be able to undo the change, you can call it as follows:
addkeys('pCube1.tx', [1.0, 3.0, 5.0], [0.6, 1.2, 2.4], None)
If, however, you want to be able to undo changes, then call it as follows:
changeCache = oma.MAnimCurveChange() addkeys('pCube1.tx', [1.0, 3.0, 5.0], [0.6, 1.2, 2.4], changeCache)
and then do the following to undo the changes:
changeCache.undoIt()
For simplicity, this function assumes the plug specified by plugName is not currently animated. It is left as an exercise for you to add the checks required to make that assumption unnecessary.
When using the dgInfo command to obtain information about the DG, you may see information messages such as DIRTY BLOCK, DIRTY PROP and so forth.
You can do this in a Python script using API calls. The following demonstrates how you would register a new user event type called myEvent:
import maya.OpenMaya as om om.MUserEventMessage.registerUserEvent('myEvent')
To have a function called myFunc execute whenever the event occurs, do as follows:
def myFunc(data): print('Got a myEvent event!') callbackId = om.MUserEventMessage.addUserEventCallback('myEvent', myFunc)
To send a myEvent event, do as follows:
om.MUserEventMessage.postUserEvent('myEvent')
To remove the callback function when done, do as follows:
om.MUserEventMessage.removeCallback(callbackId)