纳金网

标题: pythonInMaya_基本篇 [打印本页]

作者: 林伟贤    时间: 2013-9-12 14:47
标题: pythonInMaya_基本篇
【MEL和python的简介】
MEL(MayaEmbeddedLanguage),Maya的嵌入式编程语言,Maya的每一步操作都是执行一个MEL命令。MEL语法并不是很复杂,和C语言类似。虽然MEL是Maya中的重要构成,不过我个人一直没有系统的学习过。Python,Python……发音派森或者派索都可以,名称来源于语言开发者喜欢的电影――当然这不是研究蟒蛇的成果。Python是门强大的面向对象程序语言,至于它在强弱语言上的定位分歧不做讨论,对比多数编程语言,它的优势是显而易见的。通俗的说:它不需要用户输入变量类型,不需要分号结束符,不需要大括号终结语句,甚至条件也不需要小括号,跨平台,开源,易上手……
Python之所以不需要各种标识符来区分语句,是因为它使用了代码缩进的规则。这个规则,除了强制程序员保持语句的严谨美观,还提高了编写效率。Python没有数组的概念,不过它特有的列表,元组,字典功能是十分灵活的,具有意想不到的多数据管理效果。 2514978916927410397.jpg
Maya是从8.5版本开始支持Python语法的,将Maya中的Python和MEL比较的话,Python代码显得简洁直观,功能强大。MEL的很多功能都能通过Python语法直接应用。除了Maya,很多大型的图形软件都内嵌了Python(或类Python)语言,如:Nuke,fusion,Unity3D(类python语言boo),Houdini,Vue,Realflow,Cinema4D,poser等。所以相对局限于Maya框架中的MEL,学习Python显得前途无量。
【maya中的python】
一.MEL和python语法的一些简单区别。
maya中使用python前需要先通过import语句,将maya.cmds的模块导入到python环境,并赋予一个简单的名称替代;
在调用maya的内置命令时,需要使用【名称.命令】的格式。
MEL使用双反斜杠【//】来表示注释内容,而python使用的是【#】表示。注释是程序语言中常用的功能,起到提示的作用,它仅用于阅读,不会参与程序的执行过程。
MEL中一定要在变量前使用美元符号$标识,并使用分号来结束语句,否则会报错;python不需要设置变量类型,分号和大括号,并且同一个变量可以不同类型赋值。
MEL执行一个函数,要使用【``】(注意:是键盘左上角ESC键下方的~键)将函数包裹起来,函数中的参数使用【-】符号来标识,带数据的类型则后接【空格+数字】;python使用括号将参数包含,赋值是【参数=数字】的形式,并且python还可以通过maya.mel.eval函数直接执行MEL命令。
二.学习python。
学习maya中的Python需要先学习MEL吗?不需要。因为除了官方的python文档可参考,python的很多功能是MEL所不及的。当然,如果你具有一定的MEL基础,Python则会更快掌握(但不要被MEL的语法误导将其运用于Python之中,虽然有些情况下会被Python支持)。只要了解Python对应MEL函数的使用规则,很多时候我们还能通过maya脚本编辑器反馈的MEL语句来编写Python语句。
学习Python语言时有一点要注意,那就是你所选择的Python版本。
*Maya2013中的python版本是2.6.4
Python目前有2.X和3.X两个版本。相对于较新发布的3.X版本(2008年底),2.X版本更为流行,但3.X版本的发展将是未来的趋势。尽管3.X版本继承了2.X版本很多要素,不过由于3..X掘弃了很多2.X语法规则,并改进了不少函数特征,可以说是不向下兼容的。例如Python2.X版本常用的print语句:print 123,在Python3.X中将报错,因为print在3.X版本中作为函数而不是语句,你需要使用这样的规则:print(123)。
下图左边是python3.X的计算结果,右边则是python2.X的。
1021191215523955713.jpg
综上所述,个人的建议是,学习2.X版本的资料,同时认识3.X方面的改进。我们可以从Python官网获取Python的各种版本和学习资料。
*Python的官网被我国有关部门屏蔽,原因不详……
【入门实例】
【MEL内容】
跳过经典的HelloWorld,直接进行一个有趣的脚本编写:一个简单的线框变色脚本。
当使用Nurbs曲线作为绑定用的控制器时,除了改变其形状,将线条赋予一定色彩会更易于识别。在通常的maya操作中,我们是要进入物体的【shape形节点】,开启它的色彩覆写功能。
*不建议在物体的【变形节点】开启绘制覆写,因为这是存储动画信息用的。
2514978916927410408.jpg
首先了解maya中执行这个效果的步骤和MEL命令。
1. 选择场景中已经创建好的Nurbs曲线,然后按键盘的↓(向下)键。这是maya中选择物体形节点(nurbsCircleShape1)的一个操作步骤。
2. 在属性编辑器中,展开ObjectDisplay栏,勾选启用DrawingOverrides下展栏的EnableOverrides;
3. 拖动Color的滑动条到最右边改变默认的线框色彩。
6597283071911902922.jpg
前两个步骤中,我们能在脚本编辑器看到完整的MEL执行过程,但是第三步的色彩变色却没有任何的信息记录。勾选启用脚本编辑器History菜单下的EchoAllCommands,并不能看到真正的命令执行过程。不过这里可以得到一个有用的信息,那就是overrideColor属性。
2595480760266652178.jpg
选择Nurbs曲线的形节点后,Window->GeneralEditors->AttributeSpreadSheet,点击All栏,找到OverrideColor属性。通过测试可以发现,设置0到31的整数,可以选择maya允许的32种颜色变换线框色彩。关闭History的EchoAllCommands,手动改变AttributeSpreadSheet中OverrideColor的数值,可以在脚本编辑器中得到正确的MEL执行信息。
2620250558217200551.jpg

现在,将所执行过的MEL语句规整如下,可以得到“改变所选物体线框颜色”的命令。
3095098843928077232.jpg
//选择物体的形节点
pickWalk -d down;
//将场景选择的物体列表读取到一个名为mySel的变量中
$mySel=`ls -sl`;
//设置一个名为color的变量,它的值取自mySel变量中,可包含多个物体
for($color in $mySel)
{
    setAttr ($color+".overrideEnabled") 1;  //将color变量内容的覆写属性开启
    setAttr ($color+".overrideColor") 10; //设置color变量内容的颜色覆写数值。
   
}

虽然你可以将它设定多个颜色覆写数值,并用鼠标中键将代码拖放到工具架上作为快捷命令使用,但是这会占用很多的工具架空间。我们可以继续写入更多的MEL命令,创建窗口界面来执行功能。接下来,我将使用python来实现。 1299007017537372193.jpg

【Python内容】
上面提到的简单MEL语句,使用python的格式是这样的:

1355864962832922057.jpg
*可以看到,我重复使用了变量mySel,这在python中是没问题的。
以窗口来执行线条着色功能,我的思路是:
1.创建一个只读文本框,用于说明。
2.创建一个数值输入的文本框,用于设置色彩值。
3.创建按钮,执行线条上色功能。
--假如当前没有选择物体,则弹出提示的小窗口。
4.创建一个按钮,用于关闭色彩覆写功能。
Window和showWindow是maya中创建窗口的配套函数。在脚本编辑器的python栏输入window后,选择文字,右键:quickHelp,可以在右边的栏目中看到函数对应的内置参数。
2648961005841679255.jpg
*sys模块是python中一个用于获取它内置函数的模块,这里我导入,稍后用于获取maya中的python的版本信息。

先判断进程中是否存在一个同名的程序窗口,如果存在,则关闭它。因为Maya中,如果在执行一个窗口创建前已经存在同名窗口,软件会报错。对于Python,True/False和1/0都表示On/Off的意思,不过为了得到高亮显示和直观的理解,我建议使用True/False。*showWndow右边的括号内可以输入窗口名称(本例中名称为:'pyColor'),也可以不输入。
42502721500821902.jpg


我使用一个不可操作的按钮用于python版本信息的显示。首先定义一个名为version的全局变量,用于获取maya的python版本;然后在window和showWindow语句之间,建立一个button用于显示python版本信息(2.6.4)。
*ColumnLayout函数用于将内容排布于窗口中,需提前输入。这里我使用【adj=True】开启自动排布功能。
2554103938690195527.jpg

Python可以使用maya.mel.eval函数来直接执行MEL语句,不过为了发挥面向对象的好处,我打算使用“方法”将一个功能封装起来。“方法”就相当于用户的自定义函数(MEL中称为过程或函数),可以执行一个具体的命令,返回结果,python中使用def关键字来表示。方法可以是带参数进行,例如一个方法sphere()的作用是创建一个球体,带参数10的方法sphere(10)可以创建10个球体。
方法不同于局部变量,它可以放于类中其他方法之外的任意位置,你所要做的只是对它的名称进行调用。
和maya的MEL不同,python是将物体名称放于语句内容的最前面(MEL是放于最后面),在MEL中起到开关功能的布尔型参数,python是通过判断真假(True,False)来实现的。
2511038267253465670.jpg
以上,我定义了一个名为colorObject的“方法”,它的内容是使用一个value名称的变量获取窗口中内置名称为input的文本输入框的数值,并将数值传递到所选物体的色彩覆写属性上。最后,使用一个按钮来执行colorObject“方法”(maya按钮是以字符串来调用命令的,因此只需要输入方法的名称,不需要加小括号)。现在我们得到了一个点击按钮变色的功能,但是存在一个问题,那就是pickWalk命令会在没选择物体的情况下去拾取场景中的物体,接着继续完善代码。
*注意,使用maya的q参数获取文本输入内容时,得到的是字符串,如果要将它作为数值代入函数中,需要使用python的int()命令进行转换

定义一个名为note的“方法”,用于弹出提示小窗口。

6597399620144445531.jpg
Note方法中,len是python中获取变量中元素个数的命令:假如获取的数值是0,也就是没选择任何物体时,弹出提示窗口;否则,调用执行colorObject“方法”。然后,将“着色”按钮的命令调用改为note。
或许你注意到了,在note和colorObject方法的括号中,我添加了名为arg的参数。这其实是类似变量赋值一样,我们必须先给一个方法赋予一个具体参数才能被调用。这个具体参数并不会直接影响结果。
再定义一个名为reset的方法,用于去除颜色覆写。同样的,和note方法差不多,使用判断来执行setAttr命令,最后被新按钮调用。
2611524833939163572.jpg
【完整的语句如下】
6597255584121342346.jpg
import maya.cmds as py
import sys
if py.window('pyColor',ex=True):
    py.deleteUI('pyColor',wnd=True)
version=sys.version
def colorObject(arg):
    value=py.textField('input',q=True,tx=True)
    py.pickWalk(d='down')
    mySel=py.ls(sl=True)
    for mySel in mySel:
        py.setAttr (mySel+".overrideEnabled",1)
        py.setAttr (mySel+".overrideColor",int(value))      
def note(arg):
    mySel=py.ls(sl=True)
    if len(mySel)==0:
        py.confirmDialog(t='提示',m='No object is selected',b='OK')
    else:
        colorObject(arg)
        
def reset(arg):
    mySel=py.ls(sl=True)
    if len(mySel)==0:
        py.confirmDialog(t='提示',m='No object is selected',b='OK')
    else:
        py.pickWalk(d='down')
        mySel=py.ls(sl=True)
        for mySel in mySel:
            py.setAttr (mySel+".overrideEnabled",0)
            py.setAttr (mySel+".overrideColor",0)   
        
py.window('pyColor',t='colorCurve')
py.columnLayout(adj=True)
py.button(en=False,l='python '+version)
py.text(l='请输入0到31的整数值',fn='fixedWidthFont')
py.textField('input',tx='0',fn='fixedWidthFont',bgc=(0,0,0))
py.button(l='着色',c=note)
py.button(l='去除颜色覆写',c=reset)
py.showWindow()
【测试执行情况】

1580763469224739668.jpg
1332221064789240040.gif
如果觉得这个还不够直观,我们还可以写入滑动条或者带色彩的按钮组来执行功能,以及美化界面布局。这取决于每个人的灵感。






欢迎光临 纳金网 (http://c-www.narkii.com/club/) Powered by Discuz! X2.5