参考学习链接 代码和上手难度比较简单,但是没有字幕…
18版的Maya官方API文档
关于python中的中文使用解决方法

写在最前面

干到啥就写点啥,不过也是从入门开始啦,暂定为第一篇吧。本次记录和往常一样用于自己复习,但如果能对别人有所帮助,那荣幸至极;

Maya默认的脚本支持Mel与python,写工具则需要使用C++或者C#或者Python,其中C++与C#不能直接使用,需要编译,且仅能写工具,但速度来说较Python好,但Python 上手简单且兼顾工具和脚本编写,故在此选择使用Python进行学习;

下面两张图大致讲了下关于各种API相关的介绍,看不懂可以使用有道翻译词典拍摄翻译!

另外,python对于格式的把握非常的严格,最好用Tab来控制缩进,否则一直报错,明明看起来写的一样,结果就是疯狂报错,调了一晚上,气的想骂人…

一.简单尝试及简单语法

1.使用Python脚本第一步,先在脚本里输入如下:

from maya import cmds

给我的感觉类似于#include的用法;

2.一串简易的代码,包括:创建物体,设置父子集,锁定

from maya import cmds
#创建物体
mysphere = cmds.polySphere()
mysphereShape = mysphere[0]

circle = cmds.circle()
circleShape   = circle[0]

#父子集
cmds.parent(mysphereShape,circleShape)

#锁定
cmds.setAttr(mysphereShape+".translate",lock=True)
cmds.setAttr(mysphereShape+".rotate",lock=True)
cmds.setAttr(mysphereShape+".scale",lock=True)

cmds.select(circleShape)

3.python中的if esle

如下图

下面的代码是通过判断是否选择了物体,如果选择物体的话,输出选择的物体名,否则,输出场景内所有物体,结果看下面的图;

from maya import cmds 

selection = cmds.ls(selection=True)

if len(selection) == 0:
    
    selection = cmds.ls(dag=True,long=True)

print selection

4.排序

sort排序,reverse用来倒序

from maya import cmds 

selection = cmds.ls(selection=True)

if len(selection) == 0:
    
    selection = cmds.ls(dag=True,long=True)

selection.sort(key=len,reverse=False)#sort排序,reverse用来倒序

print selection


5.for循环
下面两个代码的区别在于最后一句话,两个都是用来输出场景中物体的名称的

from maya import cmds 

selection = cmds.ls(selection=True)

if len(selection) == 0:
    
    selection = cmds.ls(dag=True,long=True)

selection.sort(key=len,reverse=True)

for obj in selection:
    print obj.split()

from maya import cmds 

selection = cmds.ls(selection=True)

if len(selection) == 0:
    
    selection = cmds.ls(dag=True,long=True)

selection.sort(key=len,reverse=True)

for obj in selection:
    print obj.split("|")[-1]

6.while循环


用于输出物体的属性

from maya import cmds 

selection = cmds.ls(selection=True)

if len(selection) == 0:
    
    selection = cmds.ls(dag=True,long=True)

selection.sort(key=len,reverse=True)

for obj in selection:
	shortName = obj.split("|")[-1]
	
children  = cmds.listRelatives(obj,children=True,fullPath=True)or[]

if len(children) == 1:
	child = children[0]
	objType = cmds.objectType(child)
else:
	objType = cmds.objectType(obj)

print objType


7.int to string,python中的强制转换
参考下图

8.另外三种字符串加减法

分别是创建字典和利用标识符%
以及.format,可以玩出很多花来

9.变量

全局变量,内部变量等,和往常其他语言一样就是了;

10.类

python中的类,和其他语言类似

python类的继承

当我们在子类里定义了新的同名函数,会覆盖原来的函数,否则就继承父类的其他函数


二.环境安装

1.pycharm安装第一步设置
百度直接搜索就好了,安装基本点下一步,完事后,需要改动的地方在设置里,如下图,找到Maya安装目录下的mayapy.exe;


2.pycharm安装第二步设置

需要我们先下载Devkit这个玩意,但是,根据视频里的git搜过去官方下载链接是404…然后,我是在csdn上找到的,可以搜下找找看别人整理好的;

下载好并解压后,我们将如下图的四个文件夹放入到Maya安装目录下,相同的文件我选择的是保留原来的,看了下大致应该不会有影响;

接下来在如下图的路径里手动添加devkit底下的py文件夹,并移除site-packages那个路径,之后就可以愉快的使用了!


三.物体重命名脚本

Python,当你会其他语言时,这个就感觉很容易了,省去了变量声明时要加变量类型等操作,写起来类似伪代码一样的,这就是Python,简单易懂,最主要的是跟着视频到这了…

1.根据物体属性重命名工具

逻辑较为简单,如果选中物体,就更改该物体的名字,如果没有选物体,则改变全体的名字,但存在问题是:没有判断是否已经改名,会存在二次命名的情况;

from maya import cmds 

selection = cmds.ls(selection=True)

if len(selection) == 0:
    
    selection = cmds.ls(dag=True,long=True)

selection.sort(key=len,reverse=True)

for obj in selection:
	shortName = obj.split("|")[-1]	
	children  = cmds.listRelatives(obj,children=True,fullPath=True) or []	
	if len(children) == 1:
		child = children[0]
		objType = cmds.objectType(child)
	else:		
		objType = cmds.objectType(obj)
	if objType=="mesh":
	 	suffix="geo"
	elif objType=="joint":
		suffix="jit"       
	elif objType=="camera":
	 	print "Skip!!" 
	 	continue
	else:
	 	suffix="grp"   
	newName=shortName+"_"+suffix

	cmds.rename(obj,newName)

2.在pycharm中写代码并在Maya中运用
还是之前的代码,稍微加了一句用于判断是否已经重命名过;同时定义了类;

from maya import cmds


def rename():
	selection = cmds.ls(selection=True)

	if len(selection) == 0:
		selection = cmds.ls(dag=True, long=True)

	selection.sort(key=len, reverse=True)

	for obj in selection:
		shortName = obj.split("|")[-1]
		children = cmds.listRelatives(obj, children=True, fullPath=True) or []
		if len(children) == 1:
			child = children[0]
			objType = cmds.objectType(child)
		else:
			objType = cmds.objectType(obj)
		if objType == "mesh":
			suffix = "geo"
		elif objType == "joint":
			suffix = "jit"
		elif objType == "camera":
			print "Skip!!"
			continue
		else:
			suffix = "grp"
		if obj.endswith(suffix):
			continue
		newName = shortName + "_" + suffix

		cmds.rename(obj, newName)

3.一个完整的代码
虽然写了中文注释,但是由于没有加字符转编码,直接复制到Maya的脚本编辑器是会报错的!!!使用时,删掉处理最合适!


from maya import cmds

SUFFIXES={
	"mesh":"geo",
	"joint":"jnt",
	"camera" : None,
	"ambientLight":"lgt"
}

DEFAULT_SUFFIX="grp"

def rename(isselection=False):
#总之用六个双引号隔开的是和#一样的注释
	"""
	This funcition is used to change objects name
	Args:
		isselection:Wheather use the orignl selection

	Returns:
         changed series of objects
	"""
	#获取当前选择
	objects = cmds.ls(selection=isselection,dag=True,long=True)

 # 如果没有选择任何东西 就报错“打咩达内”并停止代码
	if isselection and not objects:
		raise RuntimeError("Da! Me! Da! Ne!")

	if len(objects) == 0:
		objects = cmds.ls(dag=True, long=True)
		
#依靠长度对物体序列进行排序
	objects.sort(key=len, reverse=True)

	for obj in objects:
# 根据长度对选中的物体由长到短进行排序
		shortName = obj.split("|")[-1]
	  # 检查是否还有子对象
      # 如果有的话获取 当前对象类型
		children = cmds.listRelatives(obj, children=True, fullPath=True) or []
		if len(children) == 1:
			child = children[0]
			objType = cmds.objectType(child)
		else:
			objType = cmds.objectType(obj)
			
		 # 依据字典根据对象类型获取后缀名称 如果没有则获取默认名称
		suffix=SUFFIXES.get(objType,DEFAULT_SUFFIX)
	     # 如果 suffix 为空 跳过当前循环对象
		if not suffix:
			continue
		if obj.endswith('_'+suffix):
			continue
		 # 重新命名对象
		newName = "%s_%s"%(shortName,suffix)

		cmds.rename(obj, newName)
		#获取对象循环序号
		index=objects.index(obj)
		 # 将当前循环的对象的数组 替换为 新命名的名称
		objects[index] = obj.replace(shortName,newName)

	 # 返回数组 从而可以从外部获取到重命名的对象
	return objects

四.创建齿轮脚本

基于管道的模型,每隔一个面挤出一次,然后给定外围细分数以及挤出长度,根据该思路,获得一个简易的函数来创建齿轮

1.基础的创建齿轮

from maya import cmds

def creatGear(teeth=10,length=0.3):
    """
    This funcition weill create a gear
    Args:
        teeth: the number of teeth tocreate
        length: the length of the teeth

    Returns:
        A tuple of the transform,construct and extrude node
    """
    spans=teeth*2
    #create a pipe with spans
    transform,construct=cmds.polyPipe(subdivisionsAxis=spans)
    sideFaces = range(spans*2,spans*3,2)
    cmds.select(clear=True)
    for face in sideFaces:
    #'%s.f[%s]'%(transform,face)等价于transform.face
        cmds.select('%s.f[%s]'%(transform,face),add=True)
    extrude=cmds.polyExtrudeFacet(localTranslateZ=length)[0]
    return transform,construct,extrude

2.使用类

下面的类里定义了三个函数,第一个是用来初始化参数,第二个用来创建齿轮,第三个则用来改变参数;

from maya import cmds

class Gear(object):
    def __int__(self):

        self.transform=None
        self.extrude=None
        self.construct=None

    def createGear(self,teeth=10,length=0.3):
        spans=2*teeth
        self.transform,self.construct=cmds.polyPipe(subdivisionsAxis=spans)
        sideFaces=range(spans*2,spans*3,2)
        cmds.select(clear=True)
        for face in sideFaces:
            cmds.select('%s.f[%s]' % (self.transform, face), add=True)
        self.extrude = cmds.polyExtrudeFacet(localTranslateZ=length)[0]
        #return transform, construct, extrude

    def changeTeeth(self,teeth=10, length=0.2):
        spans = teeth * 2
        cmds.polyPipe(self.construct, edit=True,
                      subdivisionAxis=spans)
        sideFaces = range(spans * 2, spans * 3, 2)
        faceNames = []

        for face in sideFaces:
            faceName = 'f[%s]' % (face)
            faceNames.append(faceName)

        cmds.setAttr('%s.inputComponents' % (self.extrude), len(faceNames), *faceNames, type="componentList")
        cmds.polyExtrudeFacet(self.extrude, edit=True, ltz=length)

配套的Maya中的代码如下

import Class_CreateGear as GearCreator

reload(GearCreator)

gear=GearCreator.Gear()
gear.createGear()

print gear.extrude

五.时间轴插入脚本

1.Pycharm中的代码

from maya import cmds

def tween(percentage,obj=None,attrs=None,selection=True):
   """
   该函数根据前后帧以及占比,绘制中间帧
    Args:
        percentage:百分比占比

    Returns:
        设置中间关键帧
    """
    #若无参数且没有选择对象的话报错
    if not obj and not selection:
        raise ValueError("No object given to tween")
    #若无参数,选择当前所在的帧   
    if not obj:
        obj = cmds.ls(selection=True)[0]
        
    #若无参数列表,设置关键帧属性
    if not attrs:
        attrs=cmds.listAttr(obj,keyable=True)
    
    #获取当前帧
    currentTime=cmds.currentTime(query=True)
	
	#遍历参数列表
    for attr in attrs:
        #Construct the full name of the attribute with its object
        attrFull = '%s.%s'%(obj,attr)
        # Get the keyframes of yhe attribute on this object
        keyframes=cmds.keyframe(attrFull,query=True)
        #if there are no keyframes,then continue
        if not keyframes:
            continue
            
        #存储当前帧以前的帧
        previousKeyframes = []
        
        # 循环所有的关键帧 获取当前时间以前所有的关键帧
        for frame in keyframes:
            if frame<currentTime:
                previousKeyframes.append(frame)
        
        #简化写法,效果同上面的循环
        laterKeyframes = [frame for frame in keyframes if frame>currentTime]
		#获取离当前帧最近的前一个帧
        if not previousKeyframes and not laterKeyframes:
            continue
        if previousKeyframes:
            previousFrame=max(previousKeyframes)
        else:
            previousFrame=None

        nextFrame = min(laterKeyframes) if laterKeyframes else None

        if not previousFrame or not nextFrame:
            continue
       
       # 获取前后帧的关键帧信息
        previousValue=cmds.getAttr(attrFull,time=previousFrame)
        nextValue=cmds.getAttr(attrFull,time=nextFrame)

        difference=nextValue-previousValue
        weightDifference=(difference*percentage)/100.0
        currentValue = previousValue+weightDifference
		#根据前后帧设置当前帧
        cmds.setKeyframe(attrFull,time=currentTime,value=currentValue)

Maya中的代码

import twennerUI
reload(twennerUI)
#这里是设置百分比为20
twennerUI.tween(20)

2.Maya中的UI编写

下面的代码是从help里摘来的一段

import maya.cmds as cmds

#第一行用来创建窗口,窗口名称,icon和初始宽高
window = cmds.window( title="Long Name", iconName='Short Name', widthHeight=(200, 55) )
#用来设置排布的布局
cmds.columnLayout( adjustableColumn=True )
#设置按钮UI
cmds.button( label='Do Nothing' )
cmds.button( label='Close', command=('cmds.deleteUI(\"' + window + '\", window=True)') )
#设置父节点用‘..’表示
cmds.setParent( '..' )
#展示窗口
cmds.showWindow( window )

其效果如下:

3.创建时间轴脚本的UI

class TweenWindow(object):
    #定义窗口的名称
    windowName = "TweenWindow"
    #用于展示UI的函数
    def show(self):
        #判断是否存在该名称的窗口,有则删除
        if cmds.window(self.windowName, query=True, exists=True):
           cmds.deleteUI(self.windowName)
        #创建窗口
        cmds.window(self.windowName)
        #在窗口的面板里面添加一些其他UI
        self.buildUI()
        #展示UI
        cmds.showWindow()

    #构建其他UI的函数
    def buildUI(self):

        column=cmds.columnLayout()

        cmds.text(label="使用这个滑条来调节参数")

        row=cmds.rowLayout(numberOfColumns=2)

        self.slider=cmds.floatSlider(min=0,max=100,value=50,step=1,changeCommand=tween)

        cmds.button(label="重置",command=self.reset)

        cmds.setParent(column)
        cmds.button(label="关闭",command=self.close)

    #重置的函数
    def reset(self,*args):
       cmds.floatSlider(self.slider,edit=True,value=50)
       tween(50)
        
    #窗口关闭函数
    def close(self,*args):
        cmds.deleteUI(self.windowName)

效果如下图


六.工具保存

1.完善制作齿轮的工具

首先根据前面学到的UI的写法,完善了下之前的齿轮创建的工具,给它加上了UI相关的代码,效果如下

新建了一个管控UI的脚本,然后其主要代码如下,引用到了之前写的齿轮函数,然后比起视频稍微改了一部分,使得UI看起来舒服些,然后使效果更符合每个按钮,问题是在点击重置按钮后,再继续调节滑条好像变得容易闪退了:

还有就是参数由于添加了些,命名可能稍微有点乱(就那么一点点)

# coding=gbk
from maya import cmds
from Class_CreateGear import Gear


class GearUI(Basewindow):

    windowName = "齿轮制作"

    def __int__(self):
        self.gear= None


    def buildUI(self):

        column=cmds.columnLayout()
        cmds.text(label="使用该工具来设定齿轮")

        cmds.rowLayout(numberOfColumns=3)
        self.label1 = cmds.text(label="齿数")
        self.slider=cmds.intSlider(min=5,max=30,value=10,step=1,dragCommand=self.modifyGear)
        self.label = cmds.text(label="10")

        cmds.setParent(column)
        cmds.rowLayout(numberOfColumns=3)
        self.label1 = cmds.text(label="齿轮伸出长度")
        self.slider1 = cmds.floatSlider(min=0, max=10, value=0.2, step=0.01, dragCommand=self.modifyGear1)
        self.label2 = cmds.text(label="0.2")

        cmds.setParent(column)
        cmds.rowLayout(numberOfColumns=2)
        cmds.button(label="制作齿轮",command=self.makeGear)
        cmds.button(label="重置",command=self.reset)

        cmds.setParent(column)
        cmds.rowLayout(numberOfColumns=2)
        cmds.button(label="完成", command=self.finish)
        cmds.button(label="关闭", command=self.close)

    #根据滑条制作齿轮的函数
    def makeGear(self,*args):
        teeth = cmds.intSlider(self.slider, query=True, value=True)
        length = cmds.floatSlider(self.slider1, query=True, value=True)
        self.gear =Gear()
        self.gear.createGear(teeth=teeth,length=length)

    #修改齿轮齿数
    def modifyGear(self, teeth):
        cmds.text(self.label, edit=True, label=teeth)
        length = cmds.floatSlider(self.slider1, query=True, value=True)
        if self.gear:
            self.gear.changeTeeth(teeth=teeth,length=length)

    # 修改齿轮伸出长度
    def modifyGear1(self, length):
        teeth = cmds.intSlider(self.slider, query=True, value=True)
        cmds.text(self.label2, edit=True, label=length)
        if self.gear:
            self.gear.changeTeeth(teeth=teeth,length=length)


    #重置
    def reset(self,*args):
        #self.gear=None
        cmds.intSlider(self.slider,edit=True,value=10)
        cmds.floatSlider(self.slider1, edit=True, value=0.2)
        cmds.text(self.label,edit=True,label=10)
        cmds.text(self.label2, edit=True, label=0.2)
        self.gear.changeTeeth(teeth=10,length=0.2)

    def finish(self,*args):
        self.gear = None
        cmds.deleteUI(self.windowName)


2.保存到工具架

  • 首先文件->将脚本保存至工具架选项

  • 输入名称后,并选择Python保存后,它显示到了当前工具栏的最后面

  • 右键图标,选择编辑,进入面板,命令填对应的代码,其他设置则是在工具架那里进行编辑

  • 然后我们的第一个完整的工具就算完成了!

最后,在学习过程中也有看到有大佬早已完成的笔记,不过还是自己手过了一遍,自己再记录下比较能加深印象。如果感觉本篇有不足,可以参考下大佬的。
这里把链接贴到最后
https://blog.l0v0/posts/5c26d29c.html
https://wwwblogs/3lina/p/11727793.html

更多推荐

Python for Maya DCC工具插件开发学习记录(一)