BlueRoseNote/06-DCC/Maya/Maya Python笔记.md
2023-06-29 11:55:02 +08:00

312 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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: <drive>:\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 PySidepip install PySide2注意 python2.x 对应 PySidepython3.x 对应PySide2pyside-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")
```