内置 Python 库

Python 具有许多有用的内置库和数据结构。大多数情况下,可以使用一个现有的库来完成常规的编程任务,这样不必与 MEL 脚本一样创建自定义工具。可在 http://docs.python.org 中找到内置 Python 库的文档。该网站还针对常规 Python 编程提供了一个很好的初级教程。

使用 Python 类的自定义 UI

其中一个方便的 Python 函数是 functools.partial,该函数可用于将附加信息传递到回调函数。例如,下面的类创建的窗口具有多个在单击时会输出数字的按钮:

from functools import partialimport maya.cmds as cmdsclass 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()

在 Maya 中调试 Python 脚本

使用 Python 脚本的一个优点是可以在开发过程中使用调试器。这在解决脚本问题时可以节省大量时间。

使用 PDB              

Python 在 PDB 模块中附带一个内置的调试器。PDB 的文本界面适用于快速调试会话。如果在从“脚本编辑器”(Script Editor)调用的脚本中使用 PDB,则每当 PDB 需要输入时都会出现输入对话框。使用 PDB 与导入 PDB 并按如下方式设定断点一样简单:

import pdbpdb.set_trace()

执行达到第二行时,将显示输入对话框,您可以使用标准命令来继续、跳过、输出值等。                

可以在 http://docs.python.org/library/pdb.html 上找到 PDB 的完整文档。

使用外部调试器              

对于复杂调试任务,可能更易于使用外部图形调试器。存在多个免费的和商业的 IDE,例如:  

  • Wing IDE http://www.wingware.com                  

  • Winpdb http://winpdb.org                  

  • Eclipse http://eclipse.org                  

可以通过先在 Maya 中导入一个工具模块来使用外部调试器,导入该模块会打开到 IDE 的通信套接字。IDE 连接到 Maya 后,即可打开脚本文件来设定断点、检查变量值等。每个 IDE 都将具有其自己所需的工作流;有关详细信息,请参见相应的文档。                                

将 Wing IDE 与 Maya 结合使用

若要在 Windows 中使用 Wing IDE 3.1 启动 Maya Python 脚本的调试会话,请执行以下操作:

  1. wingdbstub.py 从 Wing IDE 安装目录复制到 Maya Python 脚本路径。例如,将 C:Program Files (x86) Wing IDE 3.1wingdbstub.py 复制到 C:UsersyournameDocumentsmayascripts                

  2. 确保已在“Wing IDE > 编辑 > 首选项 > 调试器”中选中“启用被动侦听”,以便允许从外部进程进行连接。Windows 可能会弹出一个对话框,请求授权以打开通信端口。您应该允许此种情况。

  3. 启动 Maya,并确保 Python 脚本可以成功导入并运行。

  4. 在 Wing IDE 中,打开相同的脚本。使用 F9 键或通过单击最左边来设定断点。

  5. 在 Maya 中,执行 Python 语句                  

    import wingdbstub

    Windows 可能会弹出另一个授权对话框,请求通过授权。您应该允许此种情况。        

  6. 在 Wing IDE 中进行检查;Wing IDE 主窗口左下方的状态指示器应为绿色。这表示已建立远程调试连接,且 Maya 正在运行。

  7. 在 Maya 中,调用包含断点的 Python 函数。在到达该断点时,状态指示器会变为黄色以表明 Maya 已暂停。要执行的下一行代码将通过红线亮显。

  8. 现在,您可以使用 Wing IDE 的所有调试功能检查程序的状态。按 F5 键或绿色播放按钮将控制权返还给 Maya。

注意: 有关如何使用 Wing IDE 的更多详细信息,请参见其帮助文档。                  

将 Python 函数注册为 MEL 程序

可以使用 createMelWrapper 函数将 Python 函数注册为 MEL 程序。然后,在调用 MEL 程序时,会调用 Python 函数,从而传递收到的任何参数并返回函数的结果。

有关该函数的详细信息,请参见 melutils.py 文件,路径为:

C:Program FilesAutodeskMaya2014Pythonlibsite-packagesmayamel

或者,在脚本编辑器中执行以下命令:

import maya.melhelp(maya.mel.createMelWrapper)

使用该函数的优点:

  • 通过将 Python 函数注册为 MEL 程序,您不需要获取 MEL 脚本的源代码(如果程序和脚本共享相同的名称)。相比之下,如果使用的是 Python,则必须先显式导入脚本,然后才能访问其包含的函数或类。使用该包裹器函数可以使 Maya 即时获得源代码,且不必始终加载每个脚本。                                

  • Maya 中的某些属性只接受 MEL 程序。例如,在“asset”(以前称为 container)节点中,“上下文特性”(Context Properties)区域下的“鼠标右键命令”(Rmb Command)属性只接受 MEL 程序。                

示例              

以下示例说明如何使用 createMelWrapper 函数将 Python 函数注册为 MEL 程序,以便使用“asset”(以前称为 container)节点中的“鼠标右键命令”(Rmb Command)属性。                

  1. 将以下脚本另存为 rmbScript.py,并保存到 Maya2014/scripts 目录中:                      

    import maya.cmds as cmdsimport maya.mel as meldef 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")

  2. “脚本编辑器”(Script Editor)中,从 Python 选项卡执行以下脚本。该操作将创建所需的 MEL 包裹器脚本:                      

    from rmbScript import *import maya.cmds as cmdsimport maya.mel as melmel.createMelWrapper(rmbMyContainerScript,retType='string[]')mel.createMelWrapper(exCoNotes)mel.createMelWrapper(setThisContainerCurrent)

  3. 创建一个对象。

  4. 选择“资源 > 高级资源 > 创建”(Assets > Advanced Assets > Create),然后将 rmbMyContainerScript 添加到资源的“鼠标右键命令”(Rmb Command)属性。                      

    注意:还可以借助变换资源使用该步骤;但是,节点类型将为 dagContainer。                          

  5. 将类似如下的脚本添加到“asset”节点的“注释”(Notes)部分:                      

    def main(node, container):    print node    print container

  6. “脚本编辑器”(Script Editor)的 MEL 选项卡中,输入以下脚本:                      

    rehash;

  7. 在对象上单击鼠标右键 ( ),并从标记菜单中选择“自定义”(Custom)。您现在可以查看自定义鼠标右键菜单。有关详细信息,请参见为资源指定自定义命令或菜单。                  

为已设置动画的曲线创建关键帧

可以使用以下 Python 示例脚本来创建已设置动画的曲线并设定其关键帧:

import maya.OpenMaya as omimport maya.OpenMayaAnim as omadef 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   )

以上示例代码会将关键帧动画添加到通道(即栓)。如果不需要具有撤消更改的能力,则可以按以下方式进行调用:

addkeys('pCube1.tx', [1.0, 3.0, 5.0], [0.6, 1.2, 2.4], None)

但是,如果需要具有撤消更改的能力,那么请按以下方式进行调用:

changeCache = oma.MAnimCurveChange()addkeys('pCube1.tx', [1.0, 3.0, 5.0], [0.6, 1.2, 2.4], changeCache)

然后执行以下脚本以撤消更改:

changeCache.undoIt()

注意:为简便起见,该函数假定由 plugName 指定的栓当前未设置动画。这种情况作为练习,以便您添加使假设不必要所需的检查。                  

常见信息消息

在使用 dgInfo 命令获取有关 DG 的信息时,您可能会看到诸如 DIRTY BLOCK、DIRTY PROP 等信息消息。有关这些消息的定义列表,请参见常见信息消息

使用 ScriptJob 创建用户事件

可以在 Python 脚本中使用 API 调用执行该操作。以下脚本演示了如何注册称为 myEvent 的新用户事件类型:

import maya.OpenMaya as omom.MUserEventMessage.registerUserEvent('myEvent')

若要在事件发生时执行称为 myFunc 的函数,请执行以下脚本:

def myFunc(data):    print('Got a myEvent event!')callbackId = om.MUserEventMessage.addUserEventCallback('myEvent', myFunc)

若要发送 myEvent 事件,请执行以下脚本:

om.MUserEventMessage.postUserEvent('myEvent')

若要在完成后移除回调函数,请执行以下脚本:

om.MUserEventMessage.removeCallback(callbackId)

,