maya python

胡泳滨MayaPython简易教程,如需转载,请标明出处地址:
http://huyongbin.blogbus.com/c3363976/
谢谢配合!
MayaPython第一篇 - 介绍
大家好,这是一个简易的MAYA PYTHON学习教程。简易教程的目的是可以让更多的人快速掌握这些知识,而不是拘泥于理论的研究。最好的学习方式无疑是实践,我会提供简单实用的代码来帮助学习者了解脚本的实际运用。如果你是初学MAYA PYTHON,特别是非程序员的初学者,不妨先看一下下面的内容,以帮助你对MAYA PYTHON有一个大致的了解。
为什么要学习简易教程?
简易教程的特点就是尽可能做到简单,容易理解。我的文档会涉及到尽可能多的内容,但不会说的很深。因为很多复杂的应用往往是许多简单部分的组合,学会如何组合是更重要的事情:)另外,任何学习都需要一个很好的getting started,好的入门,往往决定今后深入学习的质量。万事开头难,但是一个好的开始,就是成功的一半。希望我的简易教程可以带大家进入MAYA PYTHON的大门。
这个文档的适用人群是哪些?
·具有一定MAYA操作经验,但无编写脚本经验的用户
·具有一定MEL基础的用户
·始终徘徊在MAYA脚本门口,但找不到切入点的初级用户
什么是MAYA PYTHON?
简单来说,MAYA PYTHON就是用PYTHON语言包裹起来的MEL命令。
什么是PYTHON?
PYTHON是一门简单易学,但功能又非常强大的编程语言。(我会在下一篇中提供简单实用的PYTHON入门教程)
为什么要学习MAYA PYTHON?
大幅度地提高工作效率
挖掘MAYA隐藏功能,更全面地掌握MAYA
快速开发脚本插件
如何学习MAYA PYTHON?
最好的方法是学习别人写的源代码。而最好的代码资源其实就在你的电脑里:你的MAYA帮助文档。如果你有良好的英语阅读能力,这样你可以充分理解帮助文档里所说的内容。但是如果英语能力不是很理想的朋友也千万不要着急,我的文档会帮助你学习MAYA PYTHON。另外,MAYA的帮助文档中的脚本部分对每条命令的参数以及每个节点的属性解释的都非常详细,个人认为,学会使用MAYA的帮助文档是学习PYTHON脚本的制胜法宝。
---第一篇完---
MayaPython第二篇 - PYTHON (点击标题阅读全文)
如果你是PYTHON高手,可以跳过这篇:)因为节下来我要讲述PYTHON的基本应用。由于我的PYTHON教程主要是针对MAYA的应用,所以PYTHON基本应用的介绍主要会涵盖MAYA环境中经常会使用到的PYTHON功能。学习过程中,尽量运用已学到的知识自己也试着编写一些代码,发挥主观能动性。这样学习,效果会十分显著。该篇主要含盖以下内容:
2.1 脚本编辑器(Script Editor)
2.2 PYTHON常用数据类型和操作符
2.3 流程语句
2.4 定义函数
2.5 常用模块
2.1 脚本编辑器(Script Editor)
MAYA界面中有2处地方可以编辑PYTHON脚本,一处是左下角的快速命令行,这个命令行可以在PYTHON和MEL间快速切换,如下图:

一处是右下角的Script Editor按钮,点开窗口如下:

我们的PYTHON代码就是写在PYTHON选项卡中,如果PYTHON脚本在MEL选项卡中执行将会出错,vice versa。
我们在MAYA中执行的操作会通过MEL语言打印在上面灰色区域,也就是输出区域。这些MEL语言都可以非常快地转化成PYTHON代码。这个数据输出区域同时也会打印PYTOHN脚本的执行结果以及出错信息。
现在我们来执行一条简单的PYTHON语句,来一个初体验:PYTHON页面中输入print "hello maya",然后按数字键盘上的小回车(注意:小回车是执行代码,大回车是换行)。我们看到输出区域的打印结果如下:
print "hello! My name is Hu Yongbin"
hello! My name is Hu Yongbin

第一行是告诉用户,你执行了print "hello! My name is Hu Yongbin"这条命令,第二行hello! My name is Hu Yongbin是执行这条命令的结果,这里的执行结果就是:hello! My name is Hu Yongbin被打印出来了。命令执行成功。但是我们发觉PYTHON页面里的代码也消失了。如果需要反复执行代码,可以选中需要执行的代码,然后按小回车,这样,我们可以在执行代码的同时保留页面里的代码。(建议使用第二种方法执行代码)
接下来,再举个简单的例子来说明输出窗口中的报错信息。随意在命令行中输入一些字母HuYongbin,然后执行,出现如下信息:
HuYongbin
# Error: NameEror: name 'HuYongbin' is not defined #

这是个简单的报错信息,说明HuYongbin没有被定义,电脑无法识辨。这条命令是无效的。
最后就是#符号,#后的所有的代码(换行前)都被看作注释,不参与运算。例如:
# print "hellomaya" : )
虽然也是print命令,但是前面有#,所以无视。
现在我们终于知道如何在PYTHON中执行代码,以及辨别代码是否有效。在下面的教程中,我将会用一些简单的实例来展示PYTHON的常用功能!
2.2 PYTHON常用数据类型和操作符
数据类型就是数据的类型- -U,就是不同类型的数据,数据类型包括:整型,浮点,字符,列表,元组,字典。
整型(INT)就是整数,比如:1,3,21,1000……
浮点(FLOAT)就是带小数点的数字,比如:1.12,4.5……
字符(STRING)就是文字,需要用单或双引号,比如:"HuYongbin","12","3.1415","#_%)"
列表(LIST)就是一系列数据的组合,用中括号,比如:[2,3],["tom","jerry"],["marry",14]
元组(TUPLE)用小括号,和列表的区别是他是不可变的:(2,3),("tom","jerry"),("marry",14)
操作符,形象的说就是用来操作数据的工具,包括数学操作符,比较操作符,逻辑操作符。
数学操作符:+(加) -(减) *(乘) /(除)%(取除法余数)**(乘方)
比较操作符:<(小于)<=(小于等于)>(大于)>=(大于等于)==(等于)!=(不等于)
逻辑操作符:and or not
下面来做一些热身,在实际运用中体会不同数据类型之间的配合!
2.2.1 整数
a=1 # 定义变量a, 把整数1赋予给a
b=3 # 定义变量b, 把整数3赋予给b
a+b

运行结果为3,其他整数小数的加减乘除这里就不熬述了~
2.2.2 字符
name1="tom" # 定义变量name1,把字符tom赋予给name1,注意双引号
name2='jerry' # 定义变量name2,把字符jerry赋予给name2,注意这里是单引号,都可以表示
name1+name2

运行结果为"tomjerry",这里说明字符之间可以相加。但是不同数据类型之间不可以相加,变量a和变量name1就不可以相加,因为一个是整数,一个是字符。字符单引号和双引号的不同用法我会再之后的实例中写出。
2.2.3 列表
list1=[1,2,3] # 定义列表list1,包含3个整型数字
list2=["cube","sphere","plane"] #定义列表list2,包含3个字符
list=list1+list2 # 把list1和list2的相加结果赋予新的变量list
print list

运行结果为[1,2,3,"cube","sphere","plane"],可见,包含不同数据类型的列表之间可以相加
我们可以对列表中的数据进行访问操作。执行以下命令:
list[0]+list[2]
运行结果为4,因为list[0]指的是list列表中的第一项,list[2]指的是list列表中的第3项。(注意,PYTHON数数是用0开始的),依次类推,list[4]指的就是“sphere”。
list[3]*list[1]
运行结果为"cubecube",其效果等同于"cube"*2,可见,字符和整数间,可以做乘法运算。同样,如果"c"*5的运算结果就是"ccccc"。
user1=["tom","cat"]
user2=["jerry","mouse"]
userInfo=[user1,user2] # 定义列表userInfo,该列表内又嵌套了2个列表
print userInfo # 打印userInfo

运行结果为[ ["tom","cat"],["jerry","mouse"] ],我们看到大列表中包含了2个小列表
我们同样可以访问嵌套列表:
userInfo[0]表示userInfo中的第一个列表user1,userInfo[0][1]表示user1中的第2个值"cat"。同样,如果要访问"jerry",你可以通过userInfo[1][0]来访问。
我们还可以对列表里的内容进行添加或移除:
userInfo.append(["jack","male"])
这样我们再次打印userInfo的时候,得到的结果应该为[ ["tom","cat"],["jerry","mouse"],["jack","male"] ]
userInfo.remove(["tom","cat"])
这样我们再次打印userInfo的时候,得到的结果应该为[ ["jerry","mouse"],["jack","male"] ]
列表和字符还可以访问其区间的数据:
a=[1,2,3,4,5,6,7,8] # 定义列表a
b="abcdefg" # 定义字符b
a[3:5] # 返回的值是[4,5,6],是列表a的第4位到第6位
b[1:4] # 返回的值是"bcde"
a[3:] # 返回的值[4,5,6,7,8],从第4位一直到结尾
b[:-4] # 返回的值是"abc",从第1位到倒数第4位

2.2.4 常用工具
接下来,我给大家介绍一些不同数据类型中的常用工具!
2.2.4.1 +=操作符号
a=1
a+=1 # 等同于a=a+1

运行结果为2,因为a=1,a+1等于2,然后把2这个数字赋予给原来的a,这样,2就替换掉原来的1了,a就等于2
2.2.4.2 pow()乘方命令
x=pow(4,3) # 就是4的3次方
y=pow(4,-2) # 也就开根号

2.2.4.3 len()获取长度命令
len()命令能够返回字符和列表的长度,如下:
len("tommy") # 返回结果是5
len([1,2,6]) # 返回结果是3
len([[1,2,7],["lock","jack"],["bach","davinci","vivaldi"]]) # 返回结果为3,因为里面包含3个列表

2.2.4.4 int()str()数据类型转换命令
int()的str()是字符和整数转换的命令,非常实用:
a=256
b=int("256") # 把字符"256"转换成整数256
a-b # 运行结果为0
c="maya"
d=str(2011) # 把整数2011转换成字符"2011"
c+d # 运行结果是"maya2011"

2.2.4.5 max()min()最大值最小值命令
max()和min()可以用来比较数字的大小:
max(1,7) # 结果为7,两个取大的值
min(3,6) # 结果为3,两个取小的值

2.3 流程语句
2.3.1 if语句
if就是如果的意思,是条件判断语句的关键词,一般可以和elif或else语句结合使用。接下来我会用一些简单实用的例子来说明if语句的用法:
age=17 # 定义age等于17
if age<18: # 假设第一种情况,注意要用冒号
print "you are not adult" # 注意代码缩进
else: # 假设第二种情况,注意冒号
print "you are adult"

这里的运行结果是"you are nod adult",因为假设第一种情况是成立的。这里提一提代码缩进,缩进就相当于写作文时每小节开头要空2字;代码缩进,就是指被缩进的代码是上一行代码的子代码。
name="tom" # 定义name变量
if name=="tom": # 注意这里是“==”,不是“=”
print "Hello,tom"

运行结果是打印"Hello,tom"。“==”和“=”的区别是:“=”相当于是个动词,把"tom"这个字符值传递给变量name;“==”表示一种状态。if name=="tom"这句话翻译成人类的语言就是:假设name的值等于"tom"这个状态是成立的。(一旦成立就执行后面的语句……)
a=3
if a<1: # 假设1
print "a<1"
elif a==1: # 这里出现了假设2
print "a=1"
else: # 如果两种假设都不成立的话……就执行下面的语句
print "a>1"

运行结果是"a>1"。很显然,a不小于1,也不等于1,那就只有执行else后面的语句了。
2.3.2 for循环语句
for语句的操作对象一般是一个序列,对序列中的每一个成员进行操作,举例:
seq=[1,2,3] # 定义一个列表
for i in seq: # for即将对列表seq中的每个成员进行操作,成员我们用i来代替(这里成员变量可以自定义)
print i+1 # 操作的内容:给每个成员+1

执行结果如下:
2
3
4
我们给每个成员都+1了
说到for循环语句,我们不得不提一下range()内置函数。range()可以针对数字提供一个序列范围:
range(10)
运行结果就是:[0,1,2,3,4,5,6,7,8,9]
range(5,10)
运行结果就是:[5,6,7,8,9]
range(0,10,2)
运行结果就是:[0,2,4,6,8]
结合for语句,我们可以尝试执行以下代码:
x=["a","b","c","d","e","f","g","h"]
for i in range(0,10,2): # 操作范围:[0,2,4,6,8]
print x[i] # i 将会被[0,2,4,6,8]中的每一项依次替代,替代后再执行print语句。

运行结果:
a
c
e
g
2.4 定义函数
在PYTHON中,我们可以自己定义一个函数,定义函数的命令是def,如下:
def MyFirstFunction():
print "this is my first function"

这里我们用def命令定义了一个函数名字叫MyFirstFunction,后面括号里面是用来填写参数的,如果没参数,就留空。定义函数内的代码需要缩进。如果要执行函数,操作如下:
MyFirstFunction() # 这样输入,就可以执行函数,函数内的所有命令都会被执行
执行后,结果会打印"this is my first function",说明定义函数内的代码被正确执行了。
函数还有一种定义方式,就是在括号里加上一些参数:
def MySecondFunc(a, b): # 该函数包含了a和b两个参数
print a+b

然后我们来执行这个函数:
MySecondFunc(2, 5) # 把2和5分别代入a和b,然后执行,函数内的print命令会被执行。
运行结果为7
MySecondFunc("first","second")
运行结果为"firstsecond",两个字符串被相加了。
函数还可以签套函数,如下:
def func1():
a=1
print a
def func2():
b=2
print b
func1()

定义好func1和func2后,执行func2(),结果为:
2
1
因为func2先执行打印b,在执行func1,func1会打印a
2.5 常用模块
简单说,模块就是一个打包的命令集合,以文件的形式存在。模块的使用方法是“导入”。我们直接针对MAYA PYTHON的模块来具个简单的例子吧。
2.5.1 maya模块
import maya.cmds # 导入maya模块中的cmds命令集
这样,我们就在MAYA中导入了cmds命令集,里面包含了所有可以在PYTHON环境中使用的MAYA命令。现在我们来初试这个cmds命令集
import maya.cmds # 导入模块
maya.cmds.polyCube() # 调用模块中的polyCube()命令。

发觉场景里生成了一个方块,命令执行成功。
但是这样打命令太长了,我们在导入maya.cmds时加上:
import maya.cmds as mc
这样maya.cmds就作为mc导入了,我们就不用再打长长的maya.cmds了。我们再创建一个Cube:
mc.polyCube()
短很多了吧。接下来介绍几个常用的模块:
import maya.mel # 导入这个,可以调用所有的mel命令
2.5.2 os模块
import os 
os模块也是用的比较多的。我经常会使用os.system(),括号中间可以写一些DOS命令:
os.system("md c:\\MyFolder") 
这样就可以用PYTHON来调用DOS命令了。
os.listdir("C:\\")
listdir可以以列表的形式列出路径中的所有的文件和文件夹(注意:是列表的形式,像这样:['a.py', 'AUTOEXEC.BAT', 'boot.ini'])。
接下来再介绍一个re模块,我经常用它来做字符的切割工具:
2.5.3 re模块
import re
a="Hello_World"
re.split("_",a) # split就是切割工具,有2个参数 ,"_"就是切割的根据,a是我们定义的变量

返回结果是一个列表,["Hello","World"],还有个是替换命令re.sub():
a="my4name4is4HuYongbin"
re.sub("4","_",a) # 就是说把4替换成"_"

输出结果:"my_name_is_HuYongbin"
2.5.4 time模块
import time # 时间模块
time.ctime()

执行结果:# Result : Fri Jun 11 22:52:16 2010 # 。也就是当前的时间。
OK,PYTHON简易教程就写到这里,简易教程的内容肯定不是很完整,这里只是罗列出一些实战中比较常用的功能。(也是我比较常用的)初学者可以抛弃理论,先玩起来再说。实践太重要了。在下一篇中,我们将正式进入MAYA PYTHON实际应用。
---第二篇完---
MayaPython第三篇 - 实战演习 (点击标题阅读全文)
在上一篇中,我主要介绍PYTHON的一些基础知识以及常用语法。在这一篇中,我们要结合MAYA中的命令来编写一些基本PYTHON脚本。其实在上一篇接近尾声的时候,我已经举例了如何导入模块的方法,这是真正使用PYTHON在MAYA中编写脚本的第一步。
import maya.cmds as mc # 这里应该不用解释了吧,有疑问可以看第二篇的结尾“模块”部分。:)
这里顺便提一提,as mc可以用任何名词来代替,as cc也可以。这样,如果要调用polyCube()命令的话,就必须有cc.polyCube()作为前缀。基于笔者的个人习惯,我们这里还是用mc
3.1 MEL命令和PYTHON命令之间的转化
我们导入MAYA的模块,现在要运用模块中的命令编写一些东西了。但是大家可能会很疑惑,写什么呢?我们总不见得整天在MAYA里做小学数学题吧- -现在我们需要学习一些MAYA的实用命令(比如上一篇提到的polyCube()创建一个立方体),学习实用命令的最好的途径是通过执行手动操作命令来获取MEL命令语句,然后把MEL命令转换成PYTHON命令。比如我们在MAYA3D视图中用传统的方法建立一个polygon的立方体,我会在脚本编辑器的输出部分得到以下输出信息:
polyCube -ch on -o on -w 9.9 -h 7.1 -d 10 -cuv 4; //注意大小写
这是一句MEL命令,描述了如何创建一个Polycube。MEL命令的结构十分简单,开头的polyCube就是这句MEL命令的主命令,后面的部分全部是参数。其中,带“-”的,是参数名称;没有“-”的,是该参数的值。一般都是一个带“-”号的参数名称,后面再跟一个不带“-”的值。有时后面会不跟值,这说明这个参数不需要值,它只是一个开关,带这个参数,说明这个开关开着,不带说明关着。现在,我们就把这句MEL命令转换成PYTHON可以执行的命令(我们暂时不去理会具体参数的作用,只是学习一个转换过程):
mc.polyCube(ch=1, o=1, w=9.9, h=7.1, d=10, cuv=4)
执行代码后同样得到了一个立方体。我们对比一下,可以发现PYTHON可以完全把MEL的命令转化过来,只是格式不一样。格式不同体现在一下几点:
·有mc前缀(MEL没有前缀)
·所有的参数信息需要放在主命令后的括号中(MEL没有括号)
·参数名和它的值之间用等号隔开(MEL是用空格)
·每个参数之间用逗号隔开(MEL用空格)
·有些参数的值是1,而ME是on
关于最后一条,其实MEL的on也可以写成1,原因是,在PYTHON(包括其他程序语言),1这个值往往表示True,on等肯定意义的值,而0则表示False, off等否定意义的值。这样的值叫做布尔值(boolean),这种数据类型只有2种答案要么1,要么0;要么真,要么假;要么ON,要么OFF。例子中的1就是on,说明这个参数是可用的。
关于布尔值(其实你在MAYA中也可以把它理解成一个开关),以后还会讲到它的用法。节下来我们举一反三,熟练掌握MAYA命令转换的方法。
拖一个球出来,得到以下命令:
polySphere -ch on -o on -r 3;
转成PYTHON代码,就是:
mc.polySphere(ch=1, o=1, r=3)
还有一中转化形式:
我们如果在场景中选择了pCube1这个物体,会得到以下MEL命令:
select -r pCube1;
这里我们就不能写成mc.select(r=pCube1)了,因为现在这个命令基本上属于一个动作,一个动词,既然是动词,就必须有一个动作施与的对象,这里这个对象就是pCube1,而r这个参数其实replace的简写。注意这个r不是布尔值,它没有任何数据类型,只是一个开关而已。在MEL中,这个开关是不需要值的,但在PYTHON中,需要像布尔值那样给一个1的值,表示这个开关开启:
mc.select("pCube1", r=1) # 注意:PYTHON中,选择对象放在最前面。
# 注意名字的数据类型是字符,所以必须有双引号

如果要同时选择pCube1和pSphere1的话,需要用到列表,如下:
mc.select(["pCube1","pSphere"]) # 注意如果是选择集合的话,要用列表来表示
# r参数在这里我就不加了,但是不影响执行,体会下“可选”的作用

3.2 读取场景中信息的常用命令:
刚才我们知道了一些如何创建物体,以及如何选择物体的PYTHON命令。下面咱们要学习如何准确获取场景中你想要得到的信息,对于即将要编写的代码而言是十分重要的。比如,你要用命令对“所选的顶点”进行操作,那你就必须先要得到这些顶点信息,比如,这些点的ID号是那些?同样,如果要对“所选的MESH”进行操作,那你至少得让MAYA知道是哪些MESH。
3.2.1 得到所选物体的名字列表
那我们先来得到所选择的物体信息吧,这里用到一个新的命令ls(我这里提到命令绝对是常用的):
mc.select(["pCube1","pSphere"]) # 选择场景中的两个物体
mc.ls(sl=1) # ls就是list的简写,我们要list一些信息
# sl=1表示,我们要列出sl(select)的信息,“=1”就是一个开关,我们打开了它。

执行后,我们会从输出框中得到一个列表:["pCube1","pSphere"]。假如我们把第2行命令的结果赋予一个变量,那这个变量将继承这个命令执行的结果,如下:
sel=mc.ls(sl=1)
print sel

我们同样会得到["pCube1","pSphere"]这个结果,并且我们保存了这个列表结果到sel变量中去。假如你选择了N个物体,那你执行这句命令后会得到N个物体的列表。
3.2.1 得到和设置物体的属性getAttr()和setAttr()
下面再介绍2个非常有用的命令,getAttr()和setAttr()。前面那个是得到节点属性,后面那个是设置节点属性。我们同样可以借助MEL命令来获取一些命令信息。
3.2.1.1 setAttr()
我们选中刚才创建的pCube1,然后Ctrl+A打开属性窗口,找到pCube1节点中的Transform Attributes栏,我们把Translate行中的第一个值打成0,回车。现在我们在输出窗口中得到了一条MEL命令:
setAttr "pCube1.translateX" 0;
"pCube1.translateX"就是表示这个节点的TranslateX参数,后面的0表示它的值。这样我们也就可以把它转成PYTHON可以用的命令:
mc.setAttr("pCube1.translateX", 4) # 现学现用,我们把这个值再改成4
在PYTHON面板中执行后,发觉Translate行中的第一个值神奇地变成了4。同样,视图中的立方体也沿X轴平移了4个单位。同理,我们可以通过改变其他参数来获取其动作的MEL命令,然后把它转换成PYTHON可以用的命令。
3.2.1.2 getAttr()
下面,我给出如果获取属性值的命令:
mc.getAttr("pCube1.translateX") # 获取,pCube1的translateX参数的值。
执行后,我们得到4,也就是前面我们所设的那个数。同样,我们可以把这个值赋给一个变量:
a = mc.getAttr("pCube1.translateX")
print a

打印a的结果就是mc.getAttr("pCube1.translateX")的结果。
3.2.1.3 询问开关q
还有一种查寻其属性的方式,就是利用询问参数q。这里我们以xform命令来举例,如下:
mc.select("pCube1")
mc.xform(q=1, translation=1) 

执行结果,返回一个包含了pCube1的XYZ位置信息的列表。我们看到xform命令的参数表中有2个参数,一个是q,一个是translation。其中,q=1表示当前这个命令已经进入询问状态,改命令不会对所选的物体进行任何操作,只会询问;translation=1,表示我们要询问的参数是translation,“=1”相当于一个开关,说明我们要询问这个“=1”的参数值。假如,我们的命令是mc.xform(q=1, translation=1, rotation=1),这样会出错,因为询问状态下,只返回一个参数的值。相反,如果 mc.xform(q=1, translation=1, rotation=0),也就是把rotation改成0,返回结果仍然会正确。
3.3 帮助文档的使用(灰常重要!)
有的人可能回问:我如何才可以知道,一个操作命令有多少个参数可以使用?一个节点到底有多少个属性可以设置?接下来我会给大家介绍下MAYA帮助文档的使用方式。
按F1打开MAYA帮助文档。在Content中找到Technical Documentation(技术文档),在这个技术文档中,我们需要用到的,就是CommandsPython和Nodes。CommandsPython中包含了所有MAYA中的PYTHON命令以及其参数的使用方法;Nodes列出了MAYA中所有的节点以及其属性的用法。
现在我们列举一个xform命令来了解如何结合帮助文档来完成你的操作
3.3.1 Python命令
点CommandsPython进入页面,在By substring中输入xform命令,在下面出现的SubString列表中选择xform,我们就可以进入xform命令页面。我们把该页面往下拖,跳过Notes,Related的内容,在Flags下有个长长表格,表格由3列组成:Long name(short name)长名(缩写), Argument types(数据类型), Properties(属性)。
长名(缩写)的意思就是:比如mc.xform(q=1, translation=1) 这条语句中translation是一个参数,我们可以在Flags下的列表中找到这个参数,我们观察它的长名(缩写)一列,translation后有一个(t),这个(t)就是他的缩写,我们可以用缩写来替代长名,如:mc.xform(q=1, t=1),效果完全一样。
数据类型就是这个参数所支持的数据类型,如果它的数据类型是Int的话,说明它只能支持整数,你只能把整数作为它的参数,或者在询问时只能得到整数的输出。同样如果是个boolean值的话,它只能支持0或1。
属性指的是这个参数的性能。这里的性能有4种,在MAYA帮助文档中用这4个字母表示:       。其中C表示这个参数可以在该命令执行操作的时候使用;Q表示这个参数可以在询问状态下使用;E表示这个参数可以在编辑状态下使用;M表示这个参数可以拥有多种数据类型。一般情况下,C Q E用得最多。比如:mc.xform(q=1, t=1)这句命令就是典型的询问状态Q,询问内容是t,也就是translation。
3.3.2 Nodes信息
现在我们进入Nodes页面来了解下如何使用MAYA节点中的属性。
Nodes页面中所罗列出来的其实是MAYA中的所有节点类型。MAYA中充满着节点,我们任意选种场景中的某个节点,它都是属于某个Nodes页面中所罗列出来的类型。比如,我们选择之前在场景里创建的pCube1,它是属于什么类型的节点?是pCube节点吗?不是,我们无法在Nodes页面中搜索到。我们可以通过以下命令来询问节点的类型:
mc.objectType("pCube1") # objectType命令可以得到节点类型,实用推荐!
执行后,得到结果:transform。说明pCube1这个节点是transform节点。同样,我们询问:
mc.objectType("pSphere")
执行后,同样得到结果:transform。所以,虽然pCube1和pSphere节点名称不同,但是他们都是属于transform节点,千万不要认为他们是pCube类型或pSphere节点类型。
得到节点类型后,我们到Nodes页面,输入transform。找到transform,点入。找到Attributes下的长长列表。我们可以看到transform中有的参数。这些参数都可以通过getAttr()和setAttr()来获取和设置。我们来做下测试吧:)
mc.getAttr("pSphere.rz") # rz就是rotationZ的缩写
返回0.0,我们就得到了他的信息了。
关于文档使用的小结:其实我平时用的比较多的还是CommandsPython命令查询页面,因为在场景中很难找到命令及其参数的完整信息(当然,我们可以通过输出窗口中的MEL记录,但这些信息远远不够……)。关于Nodes,当我们需要知道某个节点的类型时,可以用到objectType来查询;或者当我们需要得到节点中某些属性的时候,也会用的到这个页面。
3.4 一个简单的脚本实例
这一节中,我要结合前三篇所讲的一些知识来作一个综合的小范例,并加上适当的注解,以便学习。
import maya.cmds as mc # 导入MAYA模块
def height(h): # 定义函数height,h为这个函数的一个参数
sel=mc.ls(sl=1) # 定义变量sel,把当前所选的内容赋予这个变量
for i in range(0,len(sel)): # 在sel这个选集范围里,对其中的每一个对象进行操作
mc.setAttr(sel[i]+".ty", h*i) # 所做的操作是:把每个对象的Y轴移动一个量。
# 这个量是这个函数的h参数乘以这个for循环的成员变量i
先执行以上这写代码。现在我们在场景中创建一个立方体,然后按Ctrl+D水平复制出若干个成一直线,全部选中这些立方体。如下图:

然后执行:
height(2)

执行height函数后,发现这些立方体的高度会发生一些变化,形成一斜线。并且,height的斜率会根据h的值的不同而不同。
代码的简单分析:
代码的结构不是很复杂,只有5行,前面3行应该不用作过多的解释,应该是很好理解的。我主要分析下最后的2行for循环语句。(看下面的文字时请注意对照源代码)
第一行for:假设我的场景里有5个pCube,分别叫pCube1, pCube2, pCube3, pCube4, pCube5,如果我选择的他们的话,那么sel变量会是这样一个列表:["pCube1", "pCube2", "pCube3", "pCube4", "pCube5"];len(sel)的值就是5;range(0,len(sel)) 就等于range(0,5),也就是[0,1,2,3,4]这样一个列表。所以说成员变量i的取值范围就在这个列表中,i将逐个被列表中的每一个成员替代。
第二行for:由于i有5个值可以取,所以setAttr会执行5次,每次执行时,就会把range范围列表中的值代入i。比如,当i=0的时候,sel[0]就是指范围列表中的第一个值,也就是"pCube1",sel[i]+".ty"指的就是"pCUbe1.ty",也就是pCube1的Y轴的移动值;h*i指的就是这个移动值的具体数字,其中i是在这里就是0,h的值取决于你在调用函数时在参数中所输入的数字,把整句话连接起来就是:当i=0时,并且h=2时(h值在我们调用函数时得到),执行mc.setAttr("pCube1.ty", 2*0),pCube1的Y的位移值等于0;以次类推,当i=4时,并且h=2时,执行mc.setAttr("pCube5.ty", 2*5),pCube5的Y的位移值等于10。
如果你有一定编程经验,相信这些代码理解起来不会很困难。如果你是初学着,建议多练习for循环语句的使用,多尝试自己写一些代码,得以巩固。在下一篇中,我们会有更多的代码演示及其分析,进入实战。
---第三篇完---
MayaPython第四篇 - 实战篇 (点击标题阅读全文)
上一篇,我们结束了演习,在这一篇中,我们将进入实战!我们将学习写一些实用的代码,以使我们的工作高效化。作为简易教程,我的范例代码的难度不会很大,学习者也可以触类旁通,重组这些简单的“零件”,发挥自己的“组合能力”。其实这个世界上真正复杂的“东西”很少,但是复杂的“组合”却是很多。复杂的“组合”往往需要自己创造,发挥自己的想象力吧。
4.1 自制吸附工具
事实上,MAYA自己也有吸附工具,可以吸附很多场景中的元素。我们下面的代码的主要是用来吸附中心点位置的。在MAYA场景中,如果遇到有很多物体时,MAYA自带吸附功能可能会有点不太好使(会吸到别的物体)。但也有可能是我MAYA掌握不全面- -U。(事实上,操作上我更习惯MAX,因为学的比较早,但从软件结构上,更偏爱MAYA)OK,不废话了,先看看下面的代码吧:
# 执行代码前,请大家在自己的场景里建2个物体(任意),我这里是pCube1和pSphere1
def snap():
selection=mc.ls(sl=1) # 把所选的物体命令存入变量selection
pos=mc.xform(selection[1], q=1, t=1, ws=1) # 询问所选的第2个物体的位置信息,并存入变量pos
mc.xform(selection[0], t=pos, ws=1) # 把这个pos变量的值给所选的第一个物体
先执行以上代码,什么也不会发生,因为我们现在已经定义了一个函数,这个函数叫snap,接下来,我们要执行这个函数了。先选pCube1,然后按Shift加选pSphere1,执行函数:
snap()
我们看到,pCube1的位置完全移到pSphere1的位置上去了。如果我们撤消操作,先选pSphere1,再加选pCube1,执行函数后结果就成了pSphere1的位置完全移到pCube1的位置上去了。这里我们看到选择的顺序对最终的执行结果形成了直接的影响。所以我们先要测试MAYA中的选择顺序和mc.ls(sl=1)命令之间的关系。再次选pCube1,然后按Shift加选pSphere1,然后执行:
mc.ls(sl=1)
我们看到MAYA返回了一个列表["pCube1","pSphere1"]。然后同样反过来操作,先选pSphere1,再加选pCube1,执行mc.ls(sl=1),得到的列表结果是["pSphere1","pCube1"]。所以得出结论:加选的物体,会追加到列表的结尾。selection[0]就是先选的物体,selection[1]就是后选的物体。
如果我们想要把后选的物体作为目标位置的话,那我们就要获取后选物体的位置信息:pos=mc.xform(selection[1], q=1, t=1, ws=1)。我们再次用到了询问开关q;t就不用多说了吧,如有疑问可以参考上一篇3.3.1;ws(worldspace)是世界空间的意思,打开ws说明你所要获取或设置的参数是基于世界坐标的,而不是局部坐标(可以在帮助文档中找到)。这样我们就把后选的那个物体selection[1]的位置信息记录到了pos变量里。
随后我们把这个位置信息用mc.xform(selection[0], t=pos, ws=1)命令赋予给先选的物体selection[0],这样selection[0]的位置就看上去像“吸”到selection[1]上去了。
扩展:
由于字数限制,扩展部分介绍请参阅我的博客:
http://huyongbin.blogbus.com/logs/66196527.html
4.2 自制重命名工具:
MAYA自带也有类似的工具。但是功能比较简陋,我们可以自制一个功能更强的重命名工具。先看下代码吧:
def addpre(pre):
selection=mc.ls(sl=1)
for i in selection:
mc.rename(i, pre+i)

我们先执行以上代码,这样就定义了addpre()函数,然后我们选中刚才创建的pCube1和pSphere1,执行该函数,如下:
addpre("prefix_")
执行后,看到我们所选择的物体名字前就加上了前缀,变成了prefix_pCube1和prefix_pSphere1。现在我来解释代码。
定义函数中,我们增加了pre变量作为该函数的参数,用来输入你需要的前缀字符。函数主体中第一行大家应该明白,这里就不多说了,主要还是稍微解释下for循环。
for循环的范围是你的选择范围selection,不管selection列表里多少值,都是循环范围。每次循环所执行的语句是mc.rename(i, pre+i),其中rename是重命名的命令,我们可以通过手动给物体重命名,在MEL输出窗口得到MEL命令,然后转成PYTHON;或者到帮助里查找,这里我推荐第一个方法,因为比较快捷。rename中有2个参数,第一个是要rename的原始名字,第二个是修改后的名字。i是selection列表里的的每个成员,也就是你所选择的物体。
执行命令后,for循环会逐个对你所选的每一个物体执行rename命令:把i(原始名字)变成pre+i。其中pre是一个预设的变量,在调用函数的时候pre需要被设定成一个字符,比如:addpre("prefix_"),这样pre就等于"prefix_"了,那pre+i就等于在原始名字前加上一个叫做"prefix_"的字符。
扩展:
由于字数限制,扩展部分介绍请参阅我的博客:
http://huyongbin.blogbus.com/logs/66196527.html
4.3 对文本进行操作
这里我写个小小的实例,这个实例可以将当前所选择的物体的位置坐标导出成文本文件。接下来,我们在脚本编辑器中输入以下代码:
import maya.cmds as mc
sel=mc.ls(sl=1)
info=[]
for i in sel: #获取每个选择物体的名字和它的位置信息
posx=mc.getAttr(i+".tx")
posy=mc.getAttr(i+".ty")
posz=mc.getAttr(i+".tz")
iposInfo=[i,posx,posy,posz]
info.append(iposInfo)
info_str=""
for i in info:
info_str=info_str+i[0]+"\r\nposX: "+str(i[1])+"\r\nposY: "+str(i[2])+"\r\nposZ: "+str(i[3])+"\r\n\r\n"
f=open("D:\\posInfo.txt","w") # "w"表示写入
f.write(info_str) # 把info_str写入文件
f.close()

然后我们在视图中创建3个立方体,然后随意放置他们的位置,如下图:

最后全选上面的代码,按小回车执行它们,完了我们打开资源管理器,找到D盘的根目录下,多了一个叫posInfo.txt的文件,打开它,可以看到文本文件的内容,如下:

这个文件记录了我们所选择的物体的坐标位置信息。现在我为大家分析以下这段脚本,谈谈我对写类似脚本的思路:
首先我先要想,我如果要记录一个文本文件要记录哪些信息?这里作为范例,我只记录最简单的信息,那就是:所选物体的名字,以及该物体的XYZ位置信息。所以这里创建了一个空的列表Info,然后使用for循环对每一个所选择的物体进行getAttr(),以获得它的XYZ位置坐标,然后把[物体的名字,坐标X,坐标Y,坐标Z]以列表的形式给一个临时的变量iposInfo,把每个物体的iposInfo再添加给Info列表。这个时候,Info得到的数据应该是这样的:
[[立方体1,POSX,POSY,POSZ],[立方体2,POSX,POSY,POSZ],[立方体3,POSX,POSY,POSZ]]
现在我们以列表的形式暂时保存了想要储存的数据,这个列表叫做Info。
然后我们需要用到PYTHON的文件读写命令open()和写入命令write()。但是写入文本文件的数据类型是字符,所以我们需要把列表转成字符,而且是带格式的字符,因为带格式的字符可以方便我们浏览文件。这里我们再次使用了for循环,我们对Info列表进行循环,把列表中的信息以特定的格式累积到空字符info_str中去,最后把info_str写入文本。
扩展:
由于字数限制,扩展部分介绍请参阅我的博客:
http://huyongbin.blogbus.com/logs/66196527.html
一些隐藏的命令
由于字数限制,部分内容介绍请参阅我的博客:
http://huyongbin.blogbus.com/logs/66196527.html
在PYTHON中使用MEL语句
由于字数限制,部分内容介绍请参阅我的博客:
http://huyongbin.blogbus.com/logs/66196527.html
---第四篇完---
MayaPython第五篇 - 界面篇 (点击标题阅读全文)
学习写界面的最好方法是看帮助文档,帮助文档里拥有大量的学习资源!并且大多都很实用。我基本就是直接把帮助文档里的范例直接拿过来用,然后修改其中的参数,边改边学。这里我基本也是拿来主义,在接下来的篇幅中,我会选择性地解释一些基本控件的用法。
5.1 按钮和文字
按钮和文字是界面中常用的元素,接下来我们先尝试用最简单的代码来生成一个带按钮的界面。
5.1.1 按钮
import maya.cmds as mc
mc.window()
mc.columnLayout()
mc.button()
mc.showWindow()

执行后看到一个只有一个按钮的窗口

点击按钮什么也不会发生。接下来我们在mc.button()中添加一些参数:
mc.button(label="Hu Yongbin") # 添加按钮标签
再次执行所有代码

看到窗口中按钮上的文字变成了label参数后的值。接下来我们继续添加参数:
mc.button(label="Hu Yongbin", w=100, h=100) # 添加宽度和高度参数
执行后,看到按钮变成100*100的方形

接下来,我们要让这个按钮执行些命令,比如打印一句话:
mc.button(label="Hu Yongbin", w=100, h=100, command="print 'hello, my name is Hu Yongbin'") # command 参数
执行所有代码,点Hu Yongbin按钮,观察输出窗口,看到了hello, my name is Hu Yongbin。我们看到command参数其实包含的是命令。同样,我们也可以定义一个函数:
def printer(whatever):
print whatever

然后把函数放在command参数后:
mc.button(label="Hu Yongbin", w=100, h=100, command="printer(12312)'")
执行后,点Press Me,看到输出窗口返回12312这个值。
mc.button(label="Hu Yongbin", w=100, h=100,bgc=[1,0,1] ) # bgc就是backgroundcolor
执行后,看到按钮变成了难看的粉红色。更多的参数请参考帮助文档:)

5.1.2 文字
文字在UI中起着说明解释的作用
import maya.cmds as mc
mc.window()
mc.columnLayout()
mc.text(label="welcome to Hu Yongbin blog - http://huyongbin.blogbus.com")
mc.button()
mc.showWindow()

执行代码后

看到按钮上方出现welcome to Hu Yongbin blog - http://huyongbin.blogbus.com,如果把mc.text(label="welcome to Hu Yongbin blog - http://huyongbin.blogbus.com")放到mc.button()下面的话,welcome to Hu Yongbin blog -  http://huyongbin.blogbus.com就会在按钮的下面。我们还可以改变字体:
mc.text(label="welcome to Hu Yongbin blog - http://huyongbin.blogbus.com", fn="boldLabelFont" )
执行后看到字体变成了黑体。更多的参数请参考帮助文档:)
5.2 输入框
输入框也是一个非常实用的功能,我们可以在框中输入一些文本,然后再执行相关的命令,我们可以把上一篇的简单命名工具拿来扩展一下:
def addpre(pre): # 定义加前缀函数
sel=mc.ls(sl=1)
for i in sel:
mc.rename(i, pre+i)
mc.window()
mc.columnLayout()
a = mc.textField(tx="default") # 文本输入框,我们定义了默认文本default
mc.button(label="Press Me", w=100, h=100, command="b=mc.textField(a, q=1, tx=1); addpre(b)")
mc.showWindow()

执行以上代码

看到按钮上方多了一个文本输入框,里面有个默认的文本内容default,这个值是我们在创建时定义的。现在我们在场景中随意创建一些几何体,然后全部选中,点Press Me按钮,看到所选的几何体的名字前全部自己加上了default。当然你也可以把默认defualt删除,打入任何字符,这些字符将成为所选物体的前缀。
-->
相信addpre()函数大家应该很熟悉了吧,在上一篇中我介绍过,接下来我分析一下textField命令的用法。
a = mc.textField(tx="default")就是创建一个文本输入框,其默认值是一个字符"default"。我们把定义了的输入框赋予一个具体实例a,因为我们在之后要用到这个实例。一般来说,如果控件需要用到询问模式(q)和编辑模式(e),都要指定一个具体实例,这个具体实例为之后的编辑提供了具体的操作对象。
我们看到button行的command参数里包含了这个实例对象a,mc.textField(a, q=1, tx=1)表示询问实例对象a关于参数tx的值(这里tx是默认的,你也可以通过改变输入窗口中的默认值来得到新的tx值);然后我们把这个值赋给了变量b;最后把这个得到的变量b的值填入addpre()函数的pre预设变量,并且执行addpre()函数。这样我们就把tx的值加在了所选物体的前面。
所以整体流程就是:在输入窗口输入文本;按Press Me后,通过询问得到文本信息tx,然后传给b,把b填如addpre(pre),这样就得到了最后的结果。
5.3 选项菜单
选项菜单是一个菜单,并且是可选的。
import maya.cmds as mc
mc.window()
mc.columnLayout()
o=mc.optionMenu( label='test') # 创建菜单
mc.menuItem( label='cat' ) # 加入菜单内容cat
mc.menuItem( label='dog' ) # 加dog
mc.button(label="Press Me", command="a=mc.optionMenu(o, q=1, v=1);print a")
mc.showWindow()

执行后,得到一个窗口

上面是一个选项菜单,下面是一个按钮。点Press Me,看到输出窗口返回cat;我们把选项菜单中的选项改成dog,再点Press Me,看到输出窗口返回dog。可见,选项菜单中选什么,点Press Me后就打印什么。
原理很简单,和上文提到的输入窗口类似,我们在定义选项菜单时要注意设置一个实例o,以便之后再获取菜单中的值。
点PressMe后,执行a=mc.optionMenu(o, q=1, v=1);mc.optionMenu(o, q=1, v=1)的意思就是询问实例o的v参数,v参数就是value的意思,也就是指当前optionMenu的值。把获得的值给a,然后打印a。
5.4 列表框
接下来,我结合选项菜单来写一段简单的有关列表框的代码:
import maya.cmds as mc
import os # 导入OS模块,常用功能见第二篇。
def changeList():
cdir=mc.optionMenu(op, v=1,q=1)
myls=os.listdir(cdir)
mc.textScrollList(directoryList , e=1, removeAll=1)
mc.textScrollList(directoryList , e=1, append=myls)
mc.window()
mc.columnLayout()
op=mc.optionMenu( label='Directory', cc="changeList()") # 定义选项菜单
mc.menuItem( label='C:\\' )
mc.menuItem( label='D:\\' )
directoryList = mc.textScrollList(numberOfRows=8, append=os.listdir("C:\\"))
mc.showWindow()

执行后,看到一个窗口

上边是选项菜单,里面有C:\和D:\两个选项。如果你切换盘附,你的列表会显示该盘附里的所有文件和文件夹。如何实现?我慢慢道来...
由于字数限制,列表框的分析内容介绍请参阅我的博客:
http://huyongbin.blogbus.com/logs/66230999.html
5.5 进度条
进度条主要用在脚本运算量很大的情况下的,为了避免用户以为死机,进度条可以很好的让脚本使用者了解到当前脚本执行的进度。这里我引用了文档里的一个例子:
import maya.cmds as cmds
window = cmds.window()
cmds.columnLayout()
progressControl = cmds.progressBar(maxValue=10, width=300)
cmds.button(label='Make Progress!',command='cmds.progressBar(progressControl,edit=True, step=1)')
cmds.showWindow( window )

执行后,看到一个窗口,里面有一个进度条和一个按钮

每点下按钮,进度条会升10%,点10下,进度条就满了。

进度条命令其实很简单。progressControl = cmds.progressBar(maxValue=10, width=300)定义了一个进度条:最大值10,宽300。
按钮命令中,command参数里cmds.progressBar(progressControl, edit=True, step=1)表示对进度条值的修改,注意edit=True,等同于e=1;step=1表示,每执行一次,进度条前进一格。
一般在for循环里用进度条比较多,我一般惯用格式如下:
for i in alist: # 假定有个列表叫alist
执行命令 # 这只是一个例子,大家可以自己代命令进去
cmds.progressBar(progressControl, edit=True, step=1)

这样,每作一次循环,进度条就会前进。
5.6 勾选框
勾选框是可以任意勾选自己想要的选项这么一个UI控件,示范代码如下:
import maya.cmds as cmds
#以下定义3个初始值
v1=0
v2=0
v3=0
def test():
print "value 1 is "+str(v1)
print "value 2 is "+str(v2)
print "value 3 is "+str(v3)
print "---"
window = cmds.window()
cmds.columnLayout( adjustableColumn=True )
#三个勾选框
cmds.checkBox( label='value 1', align='left', v=v1, onCommand="v1=1", offCommand="v1=0")
cmds.checkBox( label='value 2', align='left', v=v2, onCommand="v2=1", offCommand="v2=0")
cmds.checkBox( label='value 3', align='left', v=v3, onCommand="v3=1", offCommand="v3=0")
cmds.button( label="Press Me", command="test()") # 定义按钮
cmds.showWindow( window )

执行后,看到一个窗口有3个勾选框,分别叫做value 1,value 2,value 3,还有一个按钮

勾选1、3项,2项不要勾选,点press me,看到输出窗口输出信息如下:
value 1 is 1
value 2 is 0
value 3 is 1
---

如果勾2、3项,关闭1项,再点press me,输出如下:
value 1 is 0
value 2 is 1
value 3 is 1
---

可见,打印结果的0和1取决于勾选框是否被勾上,勾上的为1,否则为0。这段代码,我将不再作过多的分析,希望大家可以自己理解其运作原理。:)
界面篇的内容就到此为止,更多的界面元素以及其用法我不一一熬述,大家要多参考帮助文档,多分析。发挥主观能动性才是学习的王道。
(本教程完)

 

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值