INTRODUCTION:

对于天天使用C++的人来说,学习和使用Maya脚本我觉得完全就像砍瓜切菜一般容易,唯一的难点在于记各种API以及熟练度上。下面我将记录一些maya里的脚本代码,也方便我日后Ctrl+C/V,我觉得三个小时学会Maya python脚本编程完全足够了。

C++派系出身的人写python的时候需要注意以下几点:

(1)请忘记类型这个概念,python中一切皆对象

(2)‘=’不是赋值,而是绑定一个名字

FORWARD DECLARATION:

下面是文章内容目录:

  1. Maya scripting basic concepts
  2. Create a poly
  3. Move, Scale, Rotate
  4. Create instance
  5. Loop Create Instance
  6. Random position
  7. Hide Object
  8. Group Objects
  9. Reset pivot
  10. Select Objects
  11. Object Type
  12. Create Constraint
  13. Animation key operations
  14. Create a window UI
  15. Add UI Elements Into Window
  16. Add/Get/Set Attribute
  17. Reconstruct Name String
  18. Add Expression
  19. Create a file or read write it
  20. Get vertex array in mesh object mode
  21. Write Vertex Data into file
  22. Save the file to the specified location and call out the selection path window
  23. Save maya file
  24. Snap shot
  25. Loop search Children or parent

MAIN CONTENT:

【1】Maya scripting basic concepts

在开始Maya编程之前一定要知道的是Maya的设计思想就是节点式。



c4dpython做树 c4d里面的python建模_控件

这个和Unity很类似,一个Transform下面装一个Shape,Transform节点里包含了物体的位置,缩放,旋转等信息。ShapeNode里包含了顶点,UV等模型形状信息。

Transform:



c4dpython做树 c4d里面的python建模_UI_02

Shape:



c4dpython做树 c4d里面的python建模_c4dpython做树_03

而一个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')





c4dpython做树 c4d里面的python建模_c4dpython做树_04

首先导入Maya的cmd然后从场景里找到是否存在一个叫myCube的Node列表。如果这个列表有长度,说明这个Cube已经创建了,需要先删除它然后重新创建。polyCube这个返回的是一个列表

c4dpython做树 c4d里面的python建模_控件_05

创建求或者其它图形同理:



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)





c4dpython做树 c4d里面的python建模_UI_06

也可以使用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')





c4dpython做树 c4d里面的python建模_ide_07

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





c4dpython做树 c4d里面的python建模_控件_08

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





c4dpython做树 c4d里面的python建模_c4dpython做树_09

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





c4dpython做树 c4d里面的python建模_控件_10

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





c4dpython做树 c4d里面的python建模_c4dpython做树_11

【10】Select Objects

选择在Maya里要分为两部分作用,一个是从选择里获取,一个是把数据设置给当前选择的东西。

要想从外界传数据进脚本,方法之一就是从maya的选择列表里拿物体数据



import maya.cmds as cmd

selectObjectList = cmd.ls(orderedSelection = True)

print selectObjectList





c4dpython做树 c4d里面的python建模_ide_12

或者也可以使用,有一个fl标志用于展平列表。



selectObjectList = cmd.ls(selection = True)





c4dpython做树 c4d里面的python建模_UI_13

把属性设置给选择的物体,这时我们需要手动调用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





c4dpython做树 c4d里面的python建模_ide_14

在选择物体的时候可以加上Type作为过滤器



c4dpython做树 c4d里面的python建模_UI_15

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





c4dpython做树 c4d里面的python建模_控件_16



c4dpython做树 c4d里面的python建模_c4dpython做树_17

如果为一群物体创建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])





c4dpython做树 c4d里面的python建模_ide_18

确保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')





c4dpython做树 c4d里面的python建模_ide_19

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





c4dpython做树 c4d里面的python建模_控件_20

【15】Add UI Elements Into Window

创建一个窗口以后需要往里面加一些控件,但是在加空间之前需要先对Window进行布局



c4dpython做树 c4d里面的python建模_控件_21

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表示横向切三刀,控件会从左往右依次填充,如果横排填满了就自动换行继续填充。



c4dpython做树 c4d里面的python建模_控件_22

创建按钮回调函数



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)





c4dpython做树 c4d里面的python建模_UI_23

获取Attribute的方式如下



c4dpython做树 c4d里面的python建模_ide_24

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





c4dpython做树 c4d里面的python建模_c4dpython做树_25

【18】Add Expression



c4dpython做树 c4d里面的python建模_UI_26

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



c4dpython做树 c4d里面的python建模_ide_27

import maya.cmds as mc

pathToSave = 'D:\File'

createTextFile = open(pathToSave + 'aaa.txt', 'w')



可以多次调用write函数书写



c4dpython做树 c4d里面的python建模_c4dpython做树_28

最后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()





c4dpython做树 c4d里面的python建模_控件_29

【20】Get vertex array in mesh object mode

上面的几个例子中都是在物体的顶点模式下先选中所有顶点完成的,下面通过脚本直接在顶层Node情况下访问顶点数组



c4dpython做树 c4d里面的python建模_控件_30

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中我们能轻松获取到我们想要的数据并且写入文件,这些数据我们可以到引擎去读取它们,这为我们写工具和自定义文件格式提供了方法。



c4dpython做树 c4d里面的python建模_c4dpython做树_31

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标志,这是为了让列表中的元素全部都有数值被初始化。

对代码稍作美化:



c4dpython做树 c4d里面的python建模_ide_32

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



c4dpython做树 c4d里面的python建模_c4dpython做树_33

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



c4dpython做树 c4d里面的python建模_c4dpython做树_34

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



c4dpython做树 c4d里面的python建模_控件_35

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