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

9.2 KiB
Raw Permalink Blame History

title, date, tags, rating
title date tags rating
Maya Python笔记 2022-08-09 13:55:15 Maya

前言

前期准备

开发环境搭建: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

import maya.cmds as cmds

cmds.commandPort(name=":7001", sourceType="mel",echoOutput=True)

建议建一个脚本文件这样就不用每次启动都手动开启端口了。以Python为例把上面Python代码复制到新建的.py文件中放到下面目录

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的选择列表里拿物体数据

import maya.cmds as cmd

selectObjectList = cmd.ls(orderedSelection = True)
print selectObjectList

把属性设置给选择的物体这时我们需要手动调用select命令因为有写操作是只能对选择物体生效的所以在执行这些操作之前需要在代码里先选中这个物体。如果场景里面有个pSphere1物体

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)

从列表中获取所有节点

nodes=cmds.ls();
print(nodes)

添加类型限制

nodes=cmds.ls(type='transform');
print(nodes)

字符串配合通配符*

nodes = cmds.ls('joint*');
print(nodes);

选中指定的物体

cmds.select('side*','top*');

select指令与ls指令可以结合使用例如

cmds.ls(sl=True);
cmds.select(cmds.ls('joint*'));

getAttr与setAttr

通过字符串获取属性,不容易报错。

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)  出现次数

可变参数的函数

def function1(*args):
    print(args[0],args[1:]);

两个**则代表Map

cmds.file

可以用于保存、新建、打开新场景。

模块

查看全局与本地队友对象globals()与locals()

__main__ #为当前MayaPython编辑器模块。
__file__ #文件绝对路径
__package__ #所在包名

在一个文件夹中放入一个__init__.py与其他*.py文件之后就可以

import 文件夹名;
文件夹名.py名.function()

调用函数

路径

import sys;
for p in sys.path:
    print(p)

class NewClass(object):
    pass;

实例化

instance1=NewClass();
instance2=NewClass();

构造函数

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

文档

Pyside2文档

百度的时候请搜索PyQt5 https://doc.qt.io/qtforpython/modules.html

信号槽与解决生命周期问题

其中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)

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")