面向初级 Python 脚本编写人员的提示和技巧

内置 Python 库

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

使用 Python 类的自定义 UI

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

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()

在 Maya 中调试 Python 脚本

可以使用任何调试器来调试 Python 脚本。一些 IDE(如 Eclipse 和 Wing IDE)会附带自己的调试器。它们具有便捷的图形界面,可用于调试脚本。有关如何启动调试会话的信息,请参见首选 IDE 对应的文档。

Python 还附带自己的内置调试器 pdbpdb 具有文本界面,可以直接从“脚本编辑器”(Script Editor)的脚本内调用。您需要导入 pdb 模块,然后使用 pdb.set_trace() 设置断点:

import pdb
pdb.set_trace()

当执行达到 pdb.set_trace() 时,将显示输入对话框。可以使用标准命令继续、单步执行、打印值或执行其他调试操作。只要 pdb 需要输入,就会显示输入对话框。

有关如何使用 pdb 的详细信息,请参见 Python 调试器

将 Python 函数注册为 MEL 程序

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

有关该函数的详细信息,请参见 Maya 安装目录的 ..\Python\lib\site-packages\maya\mel 文件夹中的 melutils.py 文件。

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

import maya.mel
help(maya.mel.createMelWrapper)

使用该函数的优点:

示例

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

  1. 将以下脚本另存为首选项文件夹的 scripts 目录中的 rmbScript.py
    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")
    
  2. “脚本编辑器”(Script Editor)中,从 Python 选项卡执行以下脚本。该操作将创建所需的 MEL 包裹器脚本:
    from rmbScript import *
    import maya.cmds as cmds
    import maya.mel as mel
    mel.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 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
   )

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

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 om
om.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)