脚本 > Python > 

面向初级 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 脚本的一个优点是可以在开发过程中使用调试器。这在解决脚本问题时可以节省大量时间。

使用 PDB

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

import pdb
pdb.set_trace()

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

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

使用外部调试器

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

可以通过先在 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.1\wingdbstub.py 复制到 C:\Users\yourname\Documents\maya\scripts
  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 Files\Autodesk\Maya2014\Python\lib\site-packages\maya\mel

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

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

使用该函数的优点:

示例

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

  1. 将以下脚本另存为 rmbScript.py,并保存到 Maya2014/scripts 目录中:
    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)