MY BLOG DIRECTORY:
YivanLee:专题概述及目录![图标](https://pic1.zhimg.com/v2-6933d2bef6307a7707847c405ef50634_180x120.jpg)
INTRODUCTION:
对于天天使用C++的人来说,学习和使用Maya脚本我觉得完全就像砍瓜切菜一般容易,唯一的难点在于记各种API以及熟练度上。下面我将记录一些maya里的脚本代码,也方便我日后Ctrl+C/V,我觉得三个小时学会Maya python脚本编程完全足够了。
C++派系出身的人写python的时候需要注意以下几点:
(1)请忘记类型这个概念,python中一切皆对象
(2)‘=’不是赋值,而是绑定一个名字
FORWARD DECLARATION:
下面是文章内容目录:
- Maya scripting basic concepts
- Create a poly
- Move, Scale, Rotate
- Create instance
- Loop Create Instance
- Random position
- Hide Object
- Group Objects
- Reset pivot
- Select Objects
- Object Type
- Create Constraint
- Animation key operations
- Create a window UI
- Add UI Elements Into Window
- Add/Get/Set Attribute
- Reconstruct Name String
- Add Expression
- Create a file or read write it
- Get vertex array in mesh object mode
- Write Vertex Data into file
- Save the file to the specified location and call out the selection path window
- Save maya file
- Snap shot
- Loop search Children or parent
MAIN CONTENT:
【1】Maya scripting basic concepts
在开始Maya编程之前一定要知道的是Maya的设计思想就是节点式。
![v2-c7e9080940b8698a3f20a241c0e554b1_b.jpg](https://pic2.zhimg.com/v2-c7e9080940b8698a3f20a241c0e554b1_b.jpg)
这个和Unity很类似,一个Transform下面装一个Shape,Transform节点里包含了物体的位置,缩放,旋转等信息。ShapeNode里包含了顶点,UV等模型形状信息。
Transform:
![v2-732b2fa68580424b79ffdc1a37c96379_b.jpg](https://pic2.zhimg.com/v2-732b2fa68580424b79ffdc1a37c96379_b.jpg)
Shape:
![v2-66740ff14120a1c281f1faeb3c48ea32_b.jpg](https://pic3.zhimg.com/v2-66740ff14120a1c281f1faeb3c48ea32_b.jpg)
而一个Cube就是一个表,拿场景中的盒子为例
【2】Create a poly
import maya.cmds as cmd
cubeList = cmd.ls('myCube')
if len(cubeList) > 0:
cmd.delete(cubeList)
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
![v2-cd1d6552f394b8c4686b3a049bb6dce4_b.jpg](https://pic1.zhimg.com/v2-cd1d6552f394b8c4686b3a049bb6dce4_b.jpg)
首先导入Maya的cmd然后从场景里找到是否存在一个叫myCube的Node列表。如果这个列表有长度,说明这个Cube已经创建了,需要先删除它然后重新创建。polyCube这个返回的是一个列表
创建求或者其它图形同理:
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
pSphere = cmd.polySphere(sx = 10, sy = 10, r = 5, name = 'mySphere')
pCylinder = cmd.polyCylinder(sx = 10, sy = 15, sz = 5, r = 5, h = 10, name = 'myCylinder')
pPolyTorus = cmd.polyTorus(r = 10, sr = 1, sx = 20, sy = 4, name = 'myTorus')
ls方法可以拿到Maya场景里的Node,并且把它存到一个列表里返回。因为Maya中物体的名字是唯一的所以上述代码是通过名字来拿物Node的。还可以通过物体类型来拿场景中的某一类物体,还可以通过选择列表拿物体,这些后面有论述。
【3】Move, Scale, Rotate
import maya.cmds as cmd
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
cmds.move(0, 10, 0, pCube)
cmds.scale(2, 2, 2, pCube)
cmds.rotate(45, 45, 0, pCube)
![v2-afdf78a96eda8d61099eca4d23a74647_b.jpg](https://pic4.zhimg.com/v2-afdf78a96eda8d61099eca4d23a74647_b.jpg)
也可以使用xform来设置一个transform node的属性。
【4】Create instance
import maya.cmds as cmd
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
pCubeTransform = pCube[0]
pCUbeIns = cmd.instance(pCubeTransform, name = pCubeTransform + '_Instance')
![v2-641531da578f542d51c377f64351c05c_b.jpg](https://pic1.zhimg.com/v2-641531da578f542d51c377f64351c05c_b.jpg)
【5】Loop Create Instance
import maya.cmds as cmd
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
pCubeTransform = pCube[0]
for i in range(0, 50):
pCubeIns = cmd.instance(pCubeTransform, name = pCubeTransform + '_Instance' + str(i))
cmd.move(0, 10 * i, 0, pCubeIns)
![v2-1858d744b461732fa3ccebf2049cc26a_b.jpg](https://pic3.zhimg.com/v2-1858d744b461732fa3ccebf2049cc26a_b.jpg)
【6】Random position
import maya.cmds as cmd
import random
random.seed(1234)
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
pCubeTransform = pCube[0]
for i in range(0, 50):
x = random.uniform(-100, 100)
y = random.uniform(0, 100)
z = random.uniform(-100, 100)
pCubeIns = cmd.instance(pCubeTransform, name = pCubeTransform + '_Instance' + str(i))
cmd.move(x, y, z, pCubeIns)
![v2-a03845707187d169a84baee2b3203784_b.jpg](https://pic1.zhimg.com/v2-a03845707187d169a84baee2b3203784_b.jpg)
【7】Hide Object
import maya.cmds as cmd
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
cmds.hide(pCube)
【8】Group Objects
import maya.cmds as cmd
import random
random.seed(1234)
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
pCubeTransform = pCube[0]
instGroup = cmd.group(empty = True, name = 'myInstGroup')
for i in range(0, 50):
x = random.uniform(-100, 100)
y = random.uniform(0, 100)
z = random.uniform(-100, 100)
pCubeIns = cmd.instance(pCubeTransform, name = pCubeTransform + '_Instance' + str(i))
cmd.parent(pCubeIns, instGroup)
cmd.move(x, y, z, pCubeIns)
![v2-a0498bddfc6943856f2d1b003500cef4_b.jpg](https://pic1.zhimg.com/v2-a0498bddfc6943856f2d1b003500cef4_b.jpg)
【9】Reset pivot
import maya.cmds as cmd
import random
random.seed(1234)
pCube = cmd.polyCube(w = 10, h = 10, d = 10, name = 'myCube')
pCubeTransform = pCube[0]
instGroup = cmd.group(empty = True, name = 'myInstGroup')
for i in range(0, 50):
x = random.uniform(-100, 100)
y = random.uniform(0, 100)
z = random.uniform(-100, 100)
pCubeIns = cmd.instance(pCubeTransform, name = pCubeTransform + '_Instance' + str(i))
cmd.parent(pCubeIns, instGroup)
cmd.move(x, y, z, pCubeIns)
cmd.xform(instGroup, centerPivots = True)
![v2-b9caf3a41502a437e24e812507eef402_b.jpg](https://pic3.zhimg.com/v2-b9caf3a41502a437e24e812507eef402_b.jpg)
【10】Select Objects
选择在Maya里要分为两部分作用,一个是从选择里获取,一个是把数据设置给当前选择的东西。
要想从外界传数据进脚本,方法之一就是从maya的选择列表里拿物体数据
import maya.cmds as cmd
selectObjectList = cmd.ls(orderedSelection = True)
print selectObjectList
![v2-79333da04a0827497f948592d7145275_b.jpg](https://pic2.zhimg.com/v2-79333da04a0827497f948592d7145275_b.jpg)
或者也可以使用,有一个fl标志用于展平列表。
selectObjectList = cmd.ls(selection = True)
![v2-9b66702ec2bbded3275f1617535adeec_b.jpg](https://pic1.zhimg.com/v2-9b66702ec2bbded3275f1617535adeec_b.jpg)
把属性设置给选择的物体,这时我们需要手动调用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)
【11】Object Type
import maya.cmds as cmd
selectObjectList = cmd.ls(selection = True)
for obj in selectObjectList:
objType = cmd.objectType(obj)
print objType
![v2-3920bbe9dd7fef48650e03c5c198c152_b.jpg](https://pic3.zhimg.com/v2-3920bbe9dd7fef48650e03c5c198c152_b.jpg)
在选择物体的时候可以加上Type作为过滤器
![v2-ed0e4d7c8f60ae79582cb6d1d5e79c02_b.jpg](https://pic3.zhimg.com/v2-ed0e4d7c8f60ae79582cb6d1d5e79c02_b.jpg)
import maya.cmds as cmd
selectObjectList = cmd.ls(selection = True, type = 'transform')
for obj in selectObjectList:
objType = cmd.objectType(obj)
print objType
还可以通过Type拿到场景中全部的模型
allMeshInScene = cmds.ls(type='mesh')
【12】Create Constraint
import maya.cmds as cmd
selectObjectList = cmd.ls(orderedSelection = True)
if len(selectObjectList) >=2:
target = selectObjectList[0]
object = selectObjectList[1]
cmd.aimConstraint(target, object, aimVector = [0, 1, 0])
![v2-9efb6ea658592dbfd94ba210ce1093b6_b.jpg](https://pic3.zhimg.com/v2-9efb6ea658592dbfd94ba210ce1093b6_b.jpg)
![v2-d204f09d4cd6ff97868a4c5b471f7d24_b.gif](https://pic1.zhimg.com/v2-d204f09d4cd6ff97868a4c5b471f7d24_b.gif)
如果为一群物体创建aimConstraint可以得到如下效果:
import maya.cmds as cmd
selectObjectList = cmd.ls(orderedSelection = True)
if len(selectObjectList) >=2:
target = selectObjectList[0]
selectObjectList.remove(target)
for object in selectObjectList:
cmd.aimConstraint(target, object, aimVector = [0, 1, 0])
![v2-467ed3f3bf1abaab2337f47cc77a95e4_b.gif](https://pic1.zhimg.com/v2-467ed3f3bf1abaab2337f47cc77a95e4_b.gif)
确保Target是第一个被选中的即可。
【13】Animation key operations
import maya.cmds as cmd
selectObjectList = cmd.ls(selection = True, type = 'transform')
if len(selectObjectList) >= 1:
startTime = cmd.playbackOptions(query = True, minTime = True)
endTime = cmd.playbackOptions(query = True, maxTime = True)
for obj in selectObjectList:
cmd.cutKey(obj, time = (startTime, endTime), attribute = 'rotateY')
cmd.setKeyframe(obj, time = startTime, attribute = 'rotateY', value = 0)
cmd.setKeyframe(obj, time = endTime, attribute = 'rotateY', value = 360)
cmd.selectKey(obj, time = (startTime, endTime), attribute = 'rotateY', keyframe = True)
cmd.keyTangent(inTangentType = 'linear', outTangentType = 'linear')
![v2-cf4055d6822c5b48c1c6c1b19fcddcf3_b.jpg](https://pic4.zhimg.com/v2-cf4055d6822c5b48c1c6c1b19fcddcf3_b.jpg)
cmd.selectKey会先选中一段时间内的关键帧的的某些属性,然后调用cmd.keyTangent。这个函数会对我们选中的属性进行修改。
【14】Create a window UI
import maya.cmds as cmd
def createWindow(pWindowTitle):
windowID = 'myWindowID'
if cmd.window(windowID, exists = True):
cmd.deleteUI(windowID)
cmd.window(windowID, title = pWindowTitle, sizeable = False, resizeToFitChildren = True)
cmd.showWindow()
createWindow('MyWindow')
![v2-c471d018dec7e108bfe7e5e5a515d75d_b.jpg](https://pic2.zhimg.com/v2-c471d018dec7e108bfe7e5e5a515d75d_b.jpg)
【15】Add UI Elements Into Window
创建一个窗口以后需要往里面加一些控件,但是在加空间之前需要先对Window进行布局
![v2-0ef1a1781b62e0932be1752c0c52d490_b.jpg](https://pic1.zhimg.com/v2-0ef1a1781b62e0932be1752c0c52d490_b.jpg)
import maya.cmds as cmd
def createWindow(pWindowTitle):
windowID = 'myWindowID'
if cmd.window(windowID, exists = True):
cmd.deleteUI(windowID)
cmd.window(windowID, title = pWindowTitle, sizeable = False, resizeToFitChildren = True)
cmd.rowColumnLayout(numberOfColumns = 3, columnWidth = {(1, 75), (2, 60), (3, 60)})
cmd.text(label = 'my text one')
cmd.text(label = 'my two')
cmd.text(label = 'my three')
cmd.text(label = 'my text Four')
cmd.intField('pIntInput')
cmd.separator(h = 10, style = 'none')
cmd.intField('pIntInput2')
cmd.showWindow()
createWindow('MyWindow')
rowColumnLayout命令会对窗口进行布局切割numberOfColumns = 3表示横向切三刀,控件会从左往右依次填充,如果横排填满了就自动换行继续填充。
![v2-d0916bcb0b76813c19ce11ac25e29692_b.jpg](https://pic3.zhimg.com/v2-d0916bcb0b76813c19ce11ac25e29692_b.jpg)
创建按钮回调函数
import maya.cmds as cmds
def create_window():
if cmds.window('mywindow', exists = True):
cmds.deleteUI('mywindow')
windowvar = cmds.window('mywindow')
cmds.columnLayout()
cmds.text(label = 'this is my window')
cmds.textField('pStatementInput')
cmds.floatField('pFloatInput')
cmds.intField('pIntInput')
cmds.button(label = 'print statement', command = 'printFunction()')
cmds.showWindow('mywindow')
def printFunction():
pStatement = cmds.textField('pStatementInput', q = True, text = True)
pInt = cmds.intField('pIntInput', q = True, value = True)
pFloat = cmds.floatField('pFloatInput', q = True, value = True)
print(pStatement + str(pInt) + str(pFloat))
create_window()
【16】Add/Get/Set Attribute
import maya.cmds as cmd
selectObjectList = cmd.ls(selection = True)
if len(selectObjectList) >= 1:
cmd.addAttr(longName = 'NewAttri', shortName = 'NewA', attributeType = 'double', min = 0, max = 100, defaultValue = 100, keyable = True)
![v2-d0344731ef7626e5e212b2274b901e24_b.jpg](https://pic1.zhimg.com/v2-d0344731ef7626e5e212b2274b901e24_b.jpg)
获取Attribute的方式如下
![v2-d1b0c2ddfebf8b2ca272a5b34ed9c5f1_b.jpg](https://pic2.zhimg.com/v2-d1b0c2ddfebf8b2ca272a5b34ed9c5f1_b.jpg)
import maya.cmds as cmds
MeshList = cmds.ls(sl = True, o = True)
Mesh = MeshList[0]
Loc = cmds.getAttr('%s.translate ' % (Mesh))
print Loc
设置方法如下
import maya.cmds as cmds
MeshList = cmds.ls(sl = True, o = True)
Mesh = MeshList[0]
cmds.setAttr('%s.translateX' % (Mesh), 10)
【17】Reconstruct Name String
import maya.cmds as cmd
selectObjectList = cmd.ls(selection = True)
objName = '%s.name' % selectObjectList[0]
print objName
![v2-adfaa11dff1d05292ffb1c27e6ed42ce_b.jpg](https://pic3.zhimg.com/v2-adfaa11dff1d05292ffb1c27e6ed42ce_b.jpg)
【18】Add Expression
![v2-6901a44f6ea87183fb15f39509180300_b.jpg](https://pic1.zhimg.com/v2-6901a44f6ea87183fb15f39509180300_b.jpg)
import maya.cmds as mc
mc.expression( s = 'pSphere1.translateX = cos(time/2)*10' )
在Maya中甚至可以给一个物体的一个属性在脚本里给它加上表达式,s是表达式的值,是字符串。time变量直接能获取滑杆的时间。
【19】Create a file or read write it
![v2-689726245b26df4a9a53818fef66008d_b.jpg](https://pic2.zhimg.com/v2-689726245b26df4a9a53818fef66008d_b.jpg)
import maya.cmds as mc
pathToSave = 'D:\File'
createTextFile = open(pathToSave + 'aaa.txt', 'w')
可以多次调用write函数书写
![v2-fc7475bc62eb2e65081bf7e8f3ad05db_b.jpg](https://pic4.zhimg.com/v2-fc7475bc62eb2e65081bf7e8f3ad05db_b.jpg)
最后close这个文件解除占用即可
import maya.cmds as mc
pathToSave = 'D:/'
createdTextFile = open(pathToSave + 'bbb.txt', 'w')
createdTextFile.write('this is my file\n')
createdTextFile.write('this is maya python\n')
createdTextFile.close()
读取文件也很简单
import maya.cmds as mc
pathToSave = 'D:/'
createdTextFile = open(pathToSave + 'bbb.txt', 'w')
createdTextFile.write('this is my file\n')
createdTextFile.write('this is maya python\n')
createdTextFile.close()
readFile = open(pathToSave + 'bbb.txt', 'r')
textVal = readFile.read()
print textVal
readFile.close()
![v2-83165a95004c6b697029963f4e364b09_b.jpg](https://pic2.zhimg.com/v2-83165a95004c6b697029963f4e364b09_b.jpg)
【20】Get vertex array in mesh object mode
上面的几个例子中都是在物体的顶点模式下先选中所有顶点完成的,下面通过脚本直接在顶层Node情况下访问顶点数组
![v2-cacb3641ba99e1e2edf177f3e33bab42_b.jpg](https://pic3.zhimg.com/v2-cacb3641ba99e1e2edf177f3e33bab42_b.jpg)
import maya.cmds as cmds
MeshList = cmds.ls(sl = True, o = True)
Mesh = MeshList[0]
VertexArray = cmds.ls('{}.vtx[:]'.format(Mesh), fl = True)
cmds.move(0, 20, sel_vtx[0])
【21】Write Vertex Data into file
在Maya中获取资源的数据实在太简单了,在引擎里想获得一点模型数据简直麻烦到爆炸。在maya中我们能轻松获取到我们想要的数据并且写入文件,这些数据我们可以到引擎去读取它们,这为我们写工具和自定义文件格式提供了方法。
![v2-2dd07c25cbd3c04e461e5099b2782699_b.jpg](https://pic2.zhimg.com/v2-2dd07c25cbd3c04e461e5099b2782699_b.jpg)
import maya.cmds as cmd
vertexes = cmd.ls(selection = True, fl = True)
File = open('D:/MyFile.txt', 'w')
for vet in vertexes:
pos = cmd.xform(vet, query = True, translation = True, worldSpace = True)
File.write(str(pos) + '\n')
File.close()
这里要开启flatten标志,这是为了让列表中的元素全部都有数值被初始化。
对代码稍作美化:
![v2-3f6212b2d557dfdbf25f511f048771b3_b.jpg](https://pic4.zhimg.com/v2-3f6212b2d557dfdbf25f511f048771b3_b.jpg)
import maya.cmds as cmd
MeshList = cmd.ls(selection = True, o = True)
Mesh = MeshList[0]
File = open("C:\Users\Yivanlee\Desktop/test.txt", 'w')
VertexArray = cmds.ls('{}.vtx[:]'.format(Mesh), fl = True)
for Vert in VertexArray:
pos = cmd.xform(Vert, query = True, translation = True, worldSpace = True)
X = str(pos[0])
Y = str(pos[1])
Z = str(pos[2])
File.write(X + "," + Y + "," + Z + "\n")
File.close()
ls的oflag是objectsOnly,当 objectsOnly打开时,只有物体的名字会被返回。物体的Components和Attribute都会被忽略
【22】Save the file to the specified location and call out the selection path window
![v2-e27589d3926b9ccb0d8a212dafc7fd63_b.jpg](https://pic4.zhimg.com/v2-e27589d3926b9ccb0d8a212dafc7fd63_b.jpg)
import maya.cmds as cmd
MeshList = cmd.ls(selection = True, o = True)
Mesh = MeshList[0]
FilePath = ""
FileFilter = "*.txt"
FilePath = cmd.fileDialog2(fileFilter = FileFilter, dialogStyle = 2)
File = open(FilePath[0], 'w')
VertexArray = cmds.ls('{}.vtx[:]'.format(Mesh), fl = True)
for Vert in VertexArray:
pos = cmd.xform(Vert, query = True, translation = True, worldSpace = True)
X = str(pos[0])
Y = str(pos[1])
Z = str(pos[2])
File.write(X + "," + Y + "," + Z + "\n")
File.close()
【23】Save maya file
import maya.cmds as cmds
cmds.file(rename="C:/Users/Temp/Desktop/test.ma")
cmds.file(save=True, type="mayaAscii")
【24】Snap shot
![v2-e00c0aa88aa04b92204f200ee305bcc4_b.jpg](https://pic1.zhimg.com/v2-e00c0aa88aa04b92204f200ee305bcc4_b.jpg)
import maya.cmds as cmd
cmds.sphere(n='sphere1')
cmds.currentTime('0')
cmds.setKeyframe('.t')
cmds.currentTime('30')
cmds.move(10,0,1)
cmds.setKeyframe('.t')
cmds.snapshot( 'sphere1', constructionHistory=True, startTime=0, endTime=30, increment=10 )
俗称快照,可以用于追踪顶点动画的每帧数据。顶点动画烘焙到纹理插件需要用到这个功能。
【25】Loop search Children or parent
![v2-88624acacf32e8fd080a33c26f5bf772_b.jpg](https://pic3.zhimg.com/v2-88624acacf32e8fd080a33c26f5bf772_b.jpg)
import maya.cmds as cmds
Root = cmds.ls("joint1")[0]
BoneList = []
BoneList.append(Root)
while True:
Root = cmds.listRelatives(Root)
if Root is None:
break
BoneList.append(Root)
print BoneList
SUMMARY AND OUTLOOK:
三个小时入门maya python编程完全够了,后面我会做一些高级插件。这篇文章我也会不断完善,插入各种短小代码的example方便我日后写工具的时候Ctrl+C/V,maya大神可以忽略
Enjoy it
NEXT: