178 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
---
 | 
						||
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")
 | 
						||
```
 | 
						||
 |