BlueRoseNote/03-UnrealEngine/Plugins/使用Python开发Maya插件学习笔记.md
2023-06-29 11:55:02 +08:00

178 lines
8.8 KiB
Markdown
Raw Permalink 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: 使用Python开发Maya插件学习笔记
date: 2022-11-04 10:20:38
excerpt:
tags:
rating: ⭐
---
# 前言
前段时间研究使用Maya重定向动画但一个一个手动操作还是有点心烦所以我花了2天时间学习了Pyhton并写了这个插件本人有c++、qt、JavaScript经验所以学的快在这个过程也积累了一些心得在此分享给大家。另外祝大家劳动节快乐。
以下是我写的插件一个通过HumanIK批量重定向动画的工具
https://github.com/blueroseslol/DccTool
可以帮助动画公司将biped骨骼动画批量重定向到Ue4或者其他骨骼上。里面有很多HumanIK控制代码以及文件导入与导出代码可以参考。如果有什么问题欢迎交流。
# 前期准备
开发环境搭建推荐看这篇文章 https://www.jianshu.com/p/813b2cc71ca2
本人是通过《Maya Python游戏与影视编程指南》一书来学习实用Python开发Maya插件书中也介绍了Python的语法。使得没有Python基础的人也可以很好的学习。同时他也介绍了Maya插件开发的命令模式与API模式。通俗的说就是用Maya的内置命令与实用Maya的API。Maya API更加适合专业插件开发者使用。举个书中例子API中的基础对象MObject是一个指针对象。所以使用c#或者c++会更加适合API模式的开发吧。
不过这本书的很多翻译都感觉怪怪,这是它位移的缺点。
我使用Vscode进行开发除了必须的Python打开一个Py文件就会提示安装插件外我还使用**MayaPy**与**MayaCode**。为了能让MayaPy将代码发送到Maya中执行还需要再Maya中执行一段开启端口的命令
**Mel**
```
commandPort -name "localhost:7001" -sourceType "mel" -echoOutput;
```
**Python**
```
import maya.cmds as cmds
cmds.commandPort(name=":7001", sourceType="mel",echoOutput=True)
```
端口与MayaPy中设置的端口有关。如果你不想每次启动Maya都手动执行命令那么可以新建一个脚本文件并将代码填入。之后放到指定目录中
```
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路径设置及代码自动补全**<br>
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文件中每一项设置用","隔开,最后一项设置后面没有",",如果报错,检查一下是不是这里出现了问题。
# 编码篇
初次学习可以参考YivanLee的文章
https://zhuanlan.zhihu.com/p/76957745
我认为首先你需要了解Maya中的物体都是节点式的当然我个人认为Maya的节点更加偏向于组件而非Houdini那样的流程节点。
## 文档与搜索技巧
请使用谷歌进行搜索不推荐bing以及baidu包括搜索API这样可以节约大量时间。
**官方文档**http://help.autodesk.com/view/MAYAUL/2018/ENU/
>Pyside2是python版本的Qt库。你只要看一下它的模块数目就能明白它的强大。另外百度的时候请搜索PyQt5虽然Pyside才是官方正版。
**Pyside2**https://doc.qt.io/qtforpython/modules.html
>PyMel与maya.cmds不同在于它返回的不是字符串而是一个PyNode对象。它可以直接修改节点属性值无需调用getAttr与setAttr。更加适合于习惯了OOP语言人士使用。同时PyMel可以简化GUI的构建。但你看了文档就会明白这个玩意就是个残废。
**Pymel文档**http://help.autodesk.com/cloudhelp/2018/JPN/Maya-Tech-Docs/PyMel/modules.html
**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
# pyside2与GUI
实用Python构建Maya插件UI有3种方式
1. 调用Maya内置命令创建。
2. 直接调用Pyside2函数创建。
本人使用第三种使用Qt的界面设计师工具创建。虽然本质上就是第二种方法但效率高。需要注意的是maya目录下的designer.exe是不能直接使用的。需要将安装目录下的qt-plugins中的所有文件都复制到bin所在目录中。之后的步骤就是用Qt的界面设计师工具设计界面了。
但本人电脑上有Qt所有直接就用自己这个版本了。推荐还是用Maya目录下的版本自己去下个5.6版本的也是可以的)原因后面会说。
Qt的界面设计师工具可以输出*.ui文件但Python是无法直接使用的,(虽然可以通过loadUI载入但只能调用Mel命令无法关联python函数)所以之后需要安装Pyside2目的是为了使用 pyside-uic.exe工具它可以将 *.ui文件转化为python代码。
Pyside2对应python3.x所以你需要下载3.0的版本并安装。安装完之后打开CMD切换到安装目录下的script文件夹。执行
```
pip install PySide2
```
时候再执行
```
//请注意文件路径,推荐奖*.ui文件复制到script文件夹中
pyside-uic -o output.py input.ui
```
可能是我用的Qt版本与Maya的不同最后生成出来的python存在一些小错误按钮上的setText函数中会多出一个莫名其妙的函数。还有一个问题我倒最后也没搞懂Pyside2不是对应python3.x与Qt5么那为什么Maya使用python2.7却可以调用Pyside2呢是因为预编译了对应的库么
# 学习建议
我个人建议如果你想深入地使用pyside2开发插件强烈推荐先去学习一到两个月的Qt。之后再来学习pyside2你就会非常的顺利。尤其需要了解的是Qt的信号与槽机制、GUI绘制与线程、Qt事件传递机制。
# 实用代码
## 防止窗口重复创建
```
def main():
global win
try:
win.close() # 为了不让窗口出现多个因为第一次运行还没初始化所以要try在这里尝试先关闭再重新新建一个窗口
except:
pass
//MainWindow为窗口类
win = MainWindow()
win.show()
```
## 信号槽与解决生命周期问题
```
//其中SIGNAL需要先导入
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)
```
## python HumanIK
相关的控制代码可以在 安装目录\scripts\others下搜索hik找到主要在hikCharacterControlsUI.mel与hikGlobalUtils.mel文件中也可以参考我插件中的代码。
## FBX导出命令
导入文件可以只用cmds.file命令但是导出就不太好用了比如需要烘焙动画什么的所以需要调用以下Mel命令。
```
# 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")
```