Python 类的自定义 UI

下面的类创建的窗口具有多个在单击时会输出数字的按钮

1
2
3
4
5
6
7
8
9
10
11
12
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会附带自己的调试器

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

1
2
import pdb
pdb.set_trace()

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

Python 函数注册为 MEL 程序

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

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

使用该函数的优点:

  • 通过将 Python 函数注册为 MEL 程序,您不需要获取 MEL 脚本的源代码(如果程序和脚本共享相同的名称)。相比之下,如果使用的是 Python,则必须先显式导入脚本,然后才能访问其包含的函数或类。使用该包裹器函数可以使 Maya 即时获得源代码,且不必始终加载每个脚本。
  • Maya 中的某些属性只接受 MEL 程序。例如,在“asset”(以前称为 container)节点中,“上下文特性”(Context Properties)区域下的“鼠标右键命令”(Rmb Command)属性只接受 MEL 程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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")

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

1
2
3
4
5
6
from rmbScript import *
import maya.cmds as cmds
import maya.mel as mel
mel.createMelWrapper(rmbMyContainerScript,retType='string[]')
mel.createMelWrapper(exCoNotes)
mel.createMelWrapper(setThisContainerCurrent)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import maya.OpenMaya as om
import maya.OpenMayaAnim as oma
def addkeys(plugName, times, values, changeCache):
# 设置动画。
sel = om.MSelectionList()
sel.add(plugName)
plug = om.MPlug()
sel.getPlug(0, plug)
#创建animCurve。
animfn = oma.MFnAnimCurve()
animCurve = animfn.create(plug, oma.MFnAnimCurve.kAnimCurveTL)

# 将时间复制到MTimeArray中,将值复制到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])
# 将关键帧添加到animCurve

animfn.addKeys(
timeArray,
valueArray,
oma.MFnAnimCurve.kTangentGlobal,
oma.MFnAnimCurve.kTangentGlobal,
False,
changeCache
)

以上示例代码会将关键帧动画添加到通道

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

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

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

执行以下脚本以撤消更改

1
changeCache.undoIt()

使用 ScriptJob 创建用户事件

1
2
import maya.OpenMaya as om
om.MUserEventMessage.registerUserEvent('myEvent')

在事件发生时执行称为 myFunc 的函数

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

要发送 myEvent 事件

1
om.MUserEventMessage.postUserEvent('myEvent')

完成后移除回调函数

1
om.MUserEventMessage.removeCallback(callbackId)