--- title: Maya Python笔记 date: 2022-08-09 13:55:15 tags: Maya rating: ⭐️⭐️ --- # 前言 # 前期准备 开发环境搭建:https://www.jianshu.com/p/813b2cc71ca2 《Maya Python游戏与影视编程指南》这个书还是挺不错的。 # VSCode插件 除了必须的Python(打开一个Py文件就会提示安装),我使用的是MayaPy与MayaCode。 # Maya开启端口 在Maya中开启端口,这样就可以在VSCode中将代码直接发送到Maya中执行。 ## Mel commandPort -name "localhost:7001" -sourceType "mel" -echoOutput; ## Python ```python import maya.cmds as cmds cmds.commandPort(name=":7001", sourceType="mel",echoOutput=True) ``` 建议建一个脚本文件,这样就不用每次启动都手动开启端口了。以Python为例,把上面Python代码复制到新建的.py文件中,放到下面目录: ```s Windows: :\Documents and Settings\<你的windows用户名>\My Documents\maya\<你maya的版本号>\scripts (其实就是我的文档下面maya文件夹) MacOSX: ~/Library/Preferences/Autodesk/maya/<你maya的版本号>/scripts. Linux: ~/maya/<你maya的版本号>/scripts. ``` # Maya Python路径设置及代码自动补全 VS Code中按Ctrl+Shift+P,输入Settings打开settings.json配置文件,在大括号里加入下面代码: ``` //python.pythonPath是指定Python命令路径,请根据你maya的安装路径来做修改 "python.pythonPath": "C:/Program Files/Autodesk/Maya2019/bin/mayapy.exe", //python.autoComplete.extraPaths是代码自动补全路径,同样根据你自己的maya安装路径来写 "python.autoComplete.extraPaths": "C:/Program Files/Autodesk/Maya2019/devkit/other/pymel/extras/completion/py" ``` 注意:settings.json文件中,每一项设置用","隔开,最后一项设置后面没有",",如果报错,检查一下是不是这里出现了问题。 # Flag参数 ``` -e -edit -q -query -ax. -axis Length Length Length -cch -caching onloff -ch -constructionHistory onloff -cuv -createUVs Int -d -depth Length -h -height Length -n - name String - nds - nodeState Int -0 -object onlof f -sd -subdivisionsDepth Int -sh - subdivisionsHeight Int -sw -subdivis ionsWidth Int -SX -subdivisionsX Int -sy -subdivisionsY Int -sz - subdivisionsZ Int -tx -texture Int -W -width Length ``` ## 查询参数 使用以下命令可以查询具体函数的flag,例如polyCube: ``` print(cmds.help('polyCube')); ``` 结果为: ``` Synopsis: polyCube [flags] [String...] Flags: -e -edit -q -query -ax -axis Length Length Length -cch -caching on|off -ch -constructionHistory on|off -cuv -createUVs Int -d -depth Length -fzn -frozen on|off -h -height Length -n -name String -nds -nodeState Int -o -object on|off -sd -subdivisionsDepth Int -sh -subdivisionsHeight Int -sw -subdivisionsWidth Int -sx -subdivisionsX Int -sy -subdivisionsY Int -sz -subdivisionsZ Int -tx -texture Int -w -width Length ``` # 【10】Select Objects 选择在Maya里要分为两部分作用,一个是从选择里获取,一个是把数据设置给当前选择的东西。 要想从外界传数据进脚本,方法之一就是从maya的选择列表里拿物体数据 ```python import maya.cmds as cmd selectObjectList = cmd.ls(orderedSelection = True) print selectObjectList ``` 把属性设置给选择的物体,这时我们需要手动调用select命令,因为有写操作是只能对选择物体生效的,所以在执行这些操作之前需要在代码里先选中这个物体。如果场景里面有个pSphere1物体 ```python import maya.cmds as cmd cmd.select('pSphere1') 清除空选择列表: import maya.cmds as cmd cmd.select(clear = True) 加选 import maya.cmds as cmd cmd.select('pSphere1') cmd.select('pSphere2', add = True) ``` 从列表中获取所有节点 ```python nodes=cmds.ls(); print(nodes) ``` 添加类型限制 ```python nodes=cmds.ls(type='transform'); print(nodes) ``` 字符串配合通配符* ```python nodes = cmds.ls('joint*'); print(nodes); ``` 选中指定的物体 ```python cmds.select('side*','top*'); ``` select指令与ls指令可以结合使用,例如: ```python cmds.ls(sl=True); cmds.select(cmds.ls('joint*')); ``` # getAttr与setAttr 通过字符串获取属性,不容易报错。 ```python loc=cmds.spaceLocator()[0] sx=cmds.getAttr(loc+'.scaleX') print(sx) ``` 但注意,因为不确定类型,所以请注意数据格式 # 对应的容器 有数组、map与set ## 序列操作符 ``` x in s 如在在序列中则返回true x not in s 如果不在序列中则返回true s+t 串联 s[i] s序列中的第i项 s[i:j] 取得指定范围的成员 s[i:j:k] 取得指定范围的成员,k为步长 len(s) 长度 min(s) 最小项 max(s) 最大项 s.index(x) 第一次出现的index s.count(x) 出现次数 ``` # 可变参数的函数 ```python def function1(*args): print(args[0],args[1:]); ``` 两个**则代表Map # cmds.file 可以用于保存、新建、打开新场景。 # 模块 查看全局与本地队友对象:globals()与locals() ``` __main__ #为当前MayaPython编辑器模块。 __file__ #文件绝对路径 __package__ #所在包名 ``` 在一个文件夹中放入一个__init__.py与其他*.py文件,之后就可以 ```python import 文件夹名; 文件夹名.py名.function() ``` 调用函数 # 路径 ```python import sys; for p in sys.path: print(p) ``` # 类 ```python class NewClass(object): pass; ``` 实例化 ```python instance1=NewClass(); instance2=NewClass(); ``` 构造函数 ```python class Human(object): def __init__(self): self.first_name='aaaa'; self.last_name='bbbb'; ``` # PyMel PyMel与maya.cmds不同在于,它返回的不是字符串,而是一个PyNode对象。它可以直接修改节点属性值,无需调用getAttr与setAttr。更加适合于习惯了OOP语言人士使用。同时PyMel可以简化GUI的构建。 # GUI 开发包里有一些案例文件可以参考: - devkit\pythonScripts\widgetHierarchy.py 推荐使用Maya安装目录下的designer.exe 安装 PySide2:安装 python 后,在安装目录下有 /script 文件夹,里面有 pip.exe ,cmd执行:pip install PySide,pip install PySide2(注意: python2.x 对应 PySide,python3.x 对应PySide2)pyside-uic.exe 位于Python的安装目录下 ## python HumanIK 无效 https://forums.autodesk.com/t5/maya-programming/python-hik/td-p/4262564 https://forums.autodesk.com/t5/maya-animation-and-rigging/pythonic-mel-way-to-retarget-hik/td-p/7609798 ## 文档 - http://help.autodesk.com/view/MAYAUL/2018/ENU/?guid=GUID-CEC1D76B-7568-4DCA-B80B-1DE49362492C&pl=CHS - http://help.autodesk.com/cloudhelp/2018/JPN/Maya-Tech-Docs/PyMel/generated/pymel.core.animation.html ## Pyside2文档 百度的时候请搜索PyQt5 https://doc.qt.io/qtforpython/modules.html ## 信号槽与解决生命周期问题 其中SIGNAL需要先导入 ```python from PySide2.QtCore import SIGNAL, QObject class MainWindow(QWidget, Ui_Form): def slotBtnClicked(self): msgBox = QMessageBox(self) msgBox.setText(u"The document has been modified.") msgBox.setInformativeText(u"Do you want to save your changes?") msgBox.setStandardButtons(QMessageBox.Save) msgBox.setDefaultButton(QMessageBox.Save) msgBox.show() def __init__(self, parent=None): self.pushButton_stop.clicked.connect(self.slotBtnClicked) QObject.connect(self.pushButton_targetSkin,SIGNAL('clicked()'), self.slotBtnClicked) ``` # FBX Mel文档 https://knowledge.autodesk.com/zh-hans/support/maya/learn-explore/caas/CloudHelp/cloudhelp/2019/CHS/Maya-DataExchange/files/GUID-335F2172-DD4D-4D79-B969-55238C08F2EF-htm.html # FBX导出 ``` # FBX Exporter options. Set as required. # You can find a reference guide here: http://download.autodesk.com/us/fbx/20112/Maya/_index.html # Just add/change what you need. # Geometry mm.eval("FBXExportSmoothingGroups -v true") mm.eval("FBXExportHardEdges -v false") mm.eval("FBXExportTangents -v false") mm.eval("FBXExportSmoothMesh -v true") mm.eval("FBXExportInstances -v false") mm.eval("FBXExportReferencedContainersContent -v false") # Animation mm.eval("FBXExportBakeComplexAnimation -v true") mm.eval("FBXExportBakeComplexStart -v "+str(exportStartFrame[x])) mm.eval("FBXExportBakeComplexEnd -v "+str(exportEndFrame[x])) mm.eval("FBXExportBakeComplexStep -v 1") # mm.eval("FBXExportBakeResampleAll -v true") mm.eval("FBXExportUseSceneName -v false") mm.eval("FBXExportQuaternion -v euler") mm.eval("FBXExportShapes -v true") mm.eval("FBXExportSkins -v true") # Constraints mm.eval("FBXExportConstraints -v false") # Cameras mm.eval("FBXExportCameras -v false") # Lights mm.eval("FBXExportLights -v false") # Embed Media mm.eval("FBXExportEmbeddedTextures -v false") # Connections mm.eval("FBXExportInputConnections -v false") # Axis Conversion mm.eval("FBXExportUpAxis y") # Export! mm.eval("FBXExport -f "+exportNames[x]+".fbx -s") ```