半年没有更新了,我一切都好。这半年经历的事情很多:参加CAADRIA、拒掉留学Offer、做完毕设研究生毕业、搬到杭州、加入猪厂。一个新阶段的开始。

这一篇主要总结一下使用Python开发Maya插件的准备工作和基本工作流程。

1. 环境部署

开发之前需要进行一些准备工作。

1. devkit

就是Developer Kit啦。 有了它就可以用C++写maya插件了。不过这不是我们关心的,我们想用python快速开发插件。devkit里提供了一些示例,当然最重要的是自动补全的功能。这个下面配置编辑器时会用到。

2. Sublime Text部署

笔者用sublime text写代码的,毕竟原生的控制窗口太难用了。部署sublime环境的第一件事是装Package Control。有了它就可以方便快捷地安装sublime的插件了。

在这里可以找到Package Control的安装方法。因为电脑还没装python,所以笔者就手动装了一下。把package下下来放进目录就好啦。

然后装两个package。打开菜单Preferences>Package Control,输入install package回车,弹出的搜索框里找就好啦。装MayaSublime和Jedi两个包。MayaSublime这个包可以将Sublime里的代码传到maya执行。Jedi就是自动补全的插件。

MayaSublime装好要配置一下,在C:\Users\\Documents\maya\\scripts\里面新建一个userSetup.py,代码输入:

import maya.cmds as cmds
# Close ports if they were already open under another configuration
try:
cmds.commandPort(name=":7001", close=True)
except:
cmds.warning('Could not close port 7001 (maybe it is not opened yet...)')
try:
cmds.commandPort(name=":7002", close=True)
except:
cmds.warning('Could not close port 7002 (maybe it is not opened yet...)')
# Open new ports
cmds.commandPort(name=":7001", sourceType="mel")
cmds.commandPort(name=":7002", sourceType="python")

importmaya.cmdsascmds
# Close ports if they were already open under another configuration
try:
cmds.commandPort(name=":7001",close=True)
except:
cmds.warning('Could not close port 7001 (maybe it is not opened yet...)')
try:
cmds.commandPort(name=":7002",close=True)
except:
cmds.warning('Could not close port 7002 (maybe it is not opened yet...)')
# Open new ports
cmds.commandPort(name=":7001",sourceType="mel")
cmds.commandPort(name=":7002",sourceType="python")

其实就是创建端口啦。之后sublime会通过7002端口给maya发代码执行。设置好后,在sublime里写好代码敲Ctrl+Enter就能执行啦。

Jedi的配置要加一点:

"python_interpreter": "C:/Program Files/Autodesk/Maya2016.5/bin/mayapy.exe",
// Additional python package paths.
"python_package_paths": [
"C:/Program Files/Autodesk/Maya2016.5/devkit/other/pymel/extras/completion/py"
"python_interpreter":"C:/Program Files/Autodesk/Maya2016.5/bin/mayapy.exe",
// Additional python package paths.
"python_package_paths":[
"C:/Program Files/Autodesk/Maya2016.5/devkit/other/pymel/extras/completion/py"

做的事情是把python的解释器设为maya的python,然后自动补全包添加devkit里的这个东西,这样写pymel就有自动补全和说明了。

3. 安装外部包

就像python里面可以pip install一样,maya python也可以从PyPI上面下载外部包。

先要下一个ez_setup.py, 把它放到maya程序根目录,比如C:\Program Files\Autodesk\Maya2016.5\bin

之后开cmd,cd切到上面说的那个根目录比如

cd C:\Program Files\Autodesk\Maya2016.5\bin
1
cdC:\ProgramFiles\Autodesk\Maya2016.5\bin

执行mayapy ex_setup.py,安装这个包

安装完去maya的指令窗口检查一下,可以输入

from setuptools.command import easy_install
1
fromsetuptools.commandimporteasy_install

应该是没有报错的。

之后如果想安装任何的包,代码是:

from setuptools.command import easy_install
easy_install.main(["packagename"])

fromsetuptools.commandimporteasy_install
easy_install.main(["packagename"])

就在maya命令窗口执行就可以。

2. Pymel介绍

入门看Getting Start, 戳这里。

非常棒的一点是PyMel时面向对象的,可以链式调用,node.function1().function2().function3()这样。

用select()选物体,用ls()返回物体

用getShape()可以得到一个Mesh,再用.vtx,.f,.e之类就能取到MeshVertex MeshFace MeshEdge的数据。

笔者对RhinoCommon比较熟悉,二者非常像了。于是可以很快上手。

对于mesh还有很多乱七八槽的操作,熟悉建模的话在面板上点按钮就能看到命令窗口返回的mel指令,这些指令名字和PyMel里基本是一样的。比如PolyReduce, PolyCombine, PolyChipoff, PolySeperate等等很多。

详细的看Documentation就可以了 ,戳这里。

3. 加入界面

Maya Python自带PySide,就是Qt的一个封装。这意味着界面我们完全可以用Qt Designer来设计。可以参见之前一篇文章 PyQt+QtDesigner App Dev Workflow | PyQt + QtDesigner 小程序制作流程:

完全一样的啊在Qt Designer里设好UI元素,保存成.ui文件。

之后呢maya python自带pyside-uic生成UI的py文件。把刚才做的.ui文件放到maya根目录,然后cmd切到这个目录,执行指令

mayapy pyside-uic -o yourApp.py yourApp.ui
mayapypyside-uic-oyourApp.pyyourApp.ui


就会自动生成一个ui的.py文件。

之后的用法可以参考devkit给的例子,位置在C:\Program Files\Autodesk\Maya2016.5\devkit\pythonScripts

可以参考createNodeUI.py这个文件,不过这个里面调了那个.ui文件,而我们已经用.ui生成了一个.py文件

调用那个.py文件就跟一般的python qt开发一样的,只不过要参考一下createNodeUI.py里面把窗口挂到maya窗口下面的方法。

.......
mayaMainWindowPtr = omui.MQtUtil.mainWindow()
mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QWidget)
class MyApp(QWidget):
def __init__(self, *args, **kwargs):
super(MyApp,self).__init__(*args, **kwargs)
self.setParent(mayaMainWindow)
self.setWindowFlags( Qt.Window )
......
1


mayaMainWindowPtr=omui.MQtUtil.mainWindow()
mayaMainWindow=wrapInstance(long(mayaMainWindowPtr),QWidget)
classMyApp(QWidget):
def__init__(self,*args,**kwargs):
super(MyApp,self).__init__(*args,**kwargs)
self.setParent(mayaMainWindow)
self.setWindowFlags(Qt.Window)
......

4. 加入Shelf

如果脚本很短的话,直接在shelf上建一个按钮就好了,然后复制代码进去。但是我们这个插件可能是好几个.py文件呢。可能要用脚本创建按钮,

import maya.cmds as mc
mc.shelfLayout("Tools", p="ShelfLayout")
mc.setParent("Tools")
mc.shelfButton(l="atool", image="commandButton.png",imageOverlayLabel="aTool", command="import MyPlugin;ui = MyPlugin.MyApp();ui.show()")


importmaya.cmdsasmc
mc.shelfLayout("Tools",p="ShelfLayout")
mc.setParent("Tools")
mc.shelfButton(l="atool",image="commandButton.png",imageOverlayLabel="aTool",command="import MyPlugin;ui = MyPlugin.MyApp();ui.show()")

这样就创建了一个叫atool的按钮,在Shelf的Tools下面。当然需要调用一个MyPlugin的py文件,文件里有一个MyApp类是刚写的插件类。这个MyPlugin和它引用的文件要放在userSetup.py同一个目录的,或者放在maya根目录也行的。

至此,插件的工作环境、代码逻辑、UI设置应该都没有障碍了。