技术标签: DCC工具插件开发学习
参考学习链接 代码和上手难度比较简单,但是没有字幕…
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.com/posts/5c26d29c.html
https://www.cnblogs.com/3lina/p/11727793.html
注册码云,因为github国内访问肥肠的慢。点击设置,添加ssh公钥,执行如下命令,连点击三次回车即可。生成的公钥默认在C盘用户目录下:用txt格式打开文件,复制公钥内容,到gitee上的添加公钥部分即可。大功告成!!!...
运行环境:Ubuntu 10.10软件版本:Qt Creator 2.4.1 、QT 4.7.0最后更新日期:2018年11月16日作者:Earvin·Jones//setAttribute基本上控件都可以用setAttribute(Qt::WA_TranslucentBackground);//窗体设置透明度setWindowOpacity(0.7);...
#include#define KEY 2 //定义 key_1 I/O number is 2 // 参考文件/* 28BYJ-48.pdf 该参数根据电机每一转的步数来修改*/const int stepsPerRevolution = 256;const int stepsDelay = 10000;int stepin=0;int coun
内容简介易到用车创始人/顺为资本投资合伙人周航,首度复盘20年创业经历,全方位坦陈创业得与失。这不是一本创业成功手册,却是思想的一次出走。20年创业经历的咀嚼与反思,从战略、品牌、竞争,到流量、领导力、团队管理等,多角度多维度的重新认知,如李开复所言,“都是真刀真枪打出来的经验,值得每一位创业者多读几遍,吸收内化”。雷军、李开复、徐小平作序,梁建章、张志东、曾鸣推荐。...
最近两天在研究研发部门如何进行绩效管理(其实一直都在思考,关注,实践,总感觉无从下手,也想求助咨询公司,无奈囊中羞涩)。查了两天的资料,主要的方向是KPI,OKR,谷歌等互联网公司的考核方法。这里做个简单的整理与总结,记录一些自己思考的结论。1、KPI万恶论说KPI毁了索尼都是扯淡,很多大公司如BAT都在用KPI,发展有目共睹,虽然网上曝出各种弊端,但是没有KPI可能更差。企业的生老病死也...
作为Linux程序员,在大多数情况,在终端下干活(编程),可能更方便一点。服务器在机房里,大家都连接到同一台服务器上,而本机在Windows下运行一个终端(如SecureCRT),这是典型的配置。 如果开发的软件是不带GUI界面的,一点问题也没有,至少我自己这样做了几年了。而最近要编写GTK+程序,麻烦就来了。先是尝试在VMWare运行Linux上,当然可以,不过编译太慢了。加上我...
树中两个结点的最低公共祖先问题(普通树)求树中两个结点的最低公共祖先,此树不是二叉树,并且没有指向父节点的指针。树的结点定义private static class TreeNode { int val; List<TreeNode> children = new LinkedList<&g...
Angular7父子组件以及父子组件之间的通信父组件给子组件传值[email protected]先在父组件ts中定义一个属性public title: string = '我是首页组件的标题';在父组件html页面元素中绑定属性<app-header [title]="title"></app-header>在子组件中引入Inputimport { Compon...
Properties类按顺序输出加载内容问题描述:因为读取配置文件来置文件来配置我们的service和dao的全限定类名,用来通过反射解耦。这里用到了Properties,但是用Properties获取的key集合是无序的,导致先创建Services,再创建Dao引起空指针异常,所以通过写一个Properties的子类来顺序读取配置文件里面的key-value来解决这个问题看了几个重写的发现一个大佬写的挺不错,又有注释的,这里推荐一下作者: 人之为言出处:https://www.cnblogs.co
用这个mediatek\custom\common\uboot\logo\tool\bmp_to_raw.exe工具
使用connect连接信号与槽函数时,附带了信号或者槽函数的参数。编译会通过,而运行不会通过。若信号函数void signal_1(int param);槽函数void function_1(int param);而connect写成connect(objectA,SIGNAL(signal_1(int param)),objectB,SLOT(slot_test(int param)));编译会通过,运行时会报错,并且无法触发槽函数QObject::connect: No such.
倒腾了两天终于能在cocos2dx的lua脚本中操作加密版的sqlite数据库了。趁还没忘记,赶紧记录一下步骤用到的资源:cocos2dx 3.0 beta2 lua 5.1wxsqlite3 V3.0.6(内含编译好的sqlite 3.8.2)LuaSQLite3 V0.9.1步骤:一、替换cocos2dx自带的sqlite3为加密的sqlite31) 解