BlueRose
文章97
标签28
分类7
Maya动画批量重定向插件及Python开发插件笔记

Maya动画批量重定向插件及Python开发插件笔记

前言

前段时间研究使用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文件就会提示安装)插件外,我还使用MayaPyMayaCode。为了能让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路径设置及代码自动补全

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才是官方正版。

Pyside2https://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")