虚幻4渲染编程(DCC工具篇---Maya)【Maya Python Scripting(1)】

MY BLOG DIRECTORY:

YivanLee:专题概述及目录

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的设计思想就是节点式。

v2-c7e9080940b8698a3f20a241c0e554b1_b.jpg

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

Transform:

v2-732b2fa68580424b79ffdc1a37c96379_b.jpg

Shape:

v2-66740ff14120a1c281f1faeb3c48ea32_b.jpg

而一个Cube就是一个表,拿场景中的盒子为例

Cube = [CubeTransform, CubeShape]


【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

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

Cube = [CubeTransform, CubeShape]

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

        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

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


【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


【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


【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


【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


【10】Select Objects

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

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

        import maya.cmds as cmd

selectObjectList = cmd.ls(orderedSelection = True)

print selectObjectList
      
v2-79333da04a0827497f948592d7145275_b.jpg

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

        selectObjectList = cmd.ls(selection = True)
      
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

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

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

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

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


【15】Add UI Elements Into Window

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

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

创建按钮回调函数

        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

获取Attribute的方式如下

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


【18】Add Expression

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
        import maya.cmds as mc

pathToSave = 'D:\File'

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

      

可以多次调用write函数书写

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


【20】Get vertex array in mesh object mode

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

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
        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
        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
        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
        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
        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:

YivanLee:虚幻4渲染编程(DCC工具篇---Maya)【Maya Python Scripting(2)】

发布了384 篇原创文章 · 获赞 4 · 访问量 8055

猜你喜欢

转载自blog.csdn.net/cpongo10/article/details/100745178