前言Abc助手其实最开始是师兄跟我提的。

我记得刚到公司的第一天,师兄就让我去研究如何实现批量将材质信息上到每个面上。

这就为这个插件的诞生慢下了伏笔。

其实就我自己而言,我当时并不太理解师兄想要实现的效果。

不过就是这么凑巧的,我们的三维动画实训也遇到了Alembic导出到Houdini的材质问题。

当时咨询了师兄之后才知道,原来问题都是一样的。

而这些信息从模型信息写为模型的面信息就是出于这个考虑。

师兄提供了一篇很好的推文,上面详细地说明了这个导出的解决方案。

我就是基于这篇推文的思路进行开发的。

界面开发这次是首次尝试使用 Qt Designer 来开完整的插件,不过之前也用PyQt开发软件也积累了不少的经验。

下面就是首次使用 Qt Designer 开发的插件界面

在Maya打开的界面是这个样子的

其实 Qt Designer 大大减低了界面开发的难度

UI功能开发这次我不仅开发出了可折叠式的UI按钮界面,还开发了可以存储最后一次设置的json功能。

折叠式UI开发其实原理很简单,我当时在制作PLB下载器的时候就有做过类似的效果。

原理就是点击按钮的时候将QWidget的setvisibled函数设置为False

如此一来按钮折叠式的内容就会消失。

然而因为消失的区域,会导致内容空缺,会导致按钮变得非常松散。

因此我想到的解决方案就是,每一次点击按钮都重置界面大小,如此一来就可以解决这个问题。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20class Interface(base_class,form_class):

def __init__(self):

"""

初始化相关的代码

"""

self.NameSapce_Toggle_Check = True

self.NameSpace_Toggle.clicked.connect(self.NameSapce_Toggle_Fun)

def NameSapce_Toggle_Fun(self):

if self.NameSapce_Toggle_Check:

self.NameSpace_Btn.setVisible(False)

self.NameSapce_Toggle_Check = False

self.NameSpace_Toggle.setText(u"■命名空间 - 修正")

else:

self.NameSpace_Btn.setVisible(True)

self.NameSapce_Toggle_Check = True

self.NameSpace_Toggle.setText(u"▼命名空间 - 修正")

self.adjustSize()

json存储记录功能我的出发点就是能够让插件记录上一次设置的选项。

于是我参考了 Python For Maya Artist Friendly Programming 教程的写法

每一次关闭窗口时候都会触发json数据的存储记录

而每一次打开窗口的时候都会读取相关的json,如果没有json数据就跳过。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51class Interface(base_class,form_class):

def __init__(self):

"""

初始化相关的代码

"""

# 判断当前路径是否存在json数据可以读取

if os.path.exists(GUI_state_PATH):

GUI_state = {}

with open(GUI_state_PATH,'r') as f:

GUI_state = json.load(f)

# 按照存储的json数据设置插件

self.Verbose_CheckBox.setChecked(GUI_state['Verbose_CheckBox'])

self.NM__CheckBox.setChecked(GUI_state['NM__CheckBox'])

self.Render_CheckBox.setChecked(GUI_state['Render_CheckBox'])

self.Namespace_CheckBox.setChecked(GUI_state['Namespace_CheckBox'])

self.UV_CheckBox.setChecked(GUI_state['UV_CheckBox'])

self.Color_CheckBox.setChecked(GUI_state['Color_CheckBox'])

self.Render_CheckBox.setChecked(GUI_state['Render_CheckBox'])

self.WS__CheckBox.setChecked(GUI_state['WS__CheckBox'])

self.Vis__CheckBox.setChecked(GUI_state['Vis__CheckBox'])

self.NameSapce_Toggle_Check = GUI_state['NameSapce_Toggle_Check']

self.Export_Toggle_Check = GUI_state['Export_Toggle_Check']

self.Convert_Toggle_Check = GUI_state['Convert_Toggle_Check']

# 切换到正确的按钮方式

self.NameSapce_Toggle_Fun()

self.Export_Toggle_Fun()

self.Convert_Toggle_Fun()

self.NameSapce_Toggle_Fun()

self.Export_Toggle_Fun()

self.Convert_Toggle_Fun()

# 关闭窗口时保存当前视窗选择

def closeEvent(self, event):

# 存储当前界面选择

GUI_state = {}

GUI_state['Verbose_CheckBox'] = self.Verbose_CheckBox.isChecked()

GUI_state['NM__CheckBox'] = self.NM__CheckBox.isChecked()

GUI_state['Render_CheckBox'] = self.Render_CheckBox.isChecked()

GUI_state['Namespace_CheckBox'] = self.Namespace_CheckBox.isChecked()

GUI_state['UV_CheckBox'] = self.UV_CheckBox.isChecked()

GUI_state['Color_CheckBox'] = self.Color_CheckBox.isChecked()

GUI_state['WS__CheckBox'] = self.WS__CheckBox.isChecked()

GUI_state['Vis__CheckBox'] = self.Vis__CheckBox.isChecked()

GUI_state['NameSapce_Toggle_Check'] = self.NameSapce_Toggle_Check

GUI_state['Export_Toggle_Check'] = self.Export_Toggle_Check

GUI_state['Convert_Toggle_Check'] = self.Convert_Toggle_Check

with open(GUI_state_PATH,'w') as f:

json.dump(GUI_state,f,indent=4)

主功能开发

按面给材质正如推文所说的,Houdini的Alembic需要保留Maya的面组信息来记录材质。

只要面组信息是对的,场景中有相关的材质,导入Alembic的时候,Maya会自动连接起来。

问题在于,如果某些材质是对物体进行着色的话,那么导入Maya是没有面组信息的。

因此解决方案就是将物体着色转为对物体的每个面进行着色。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40def Convert_Fun(self):

# 获取当前选择

sel = cmds.ls(sl=True,fl=True)

# 循环当前选择

for obj in sel:

# 获取SG节点

shapeNode = cmds.listRelatives(obj,children=True,shapes=True)

SGNodeList = cmds.listConnections(shapeNode[0],type="shadingEngine")

SGNodeList = list(set(SGNodeList))

# 循环SG节点

for SGNode in SGNodeList:

# 通过SG节点获取材质球

shader = cmds.listConnections(SGNode + ".surfaceShader")

cmds.select(cl=True)

# 选择材质球赋予的物体

cmds.hyperShade( objects=shader[0] )

# 将当前选择转换为面

cmds.ConvertSelectionToFaces()

faceList = cmds.ls(sl=True,fl=True)

cmds.sets(cl=(shader[0]+"SG"))

# 循环材质上的面重新赋予材质

for face in faceList :

if obj == face.split('.')[0]:

cmds.select(face)

cmds.sets(add=(shader[0]+"SG"))

mel.eval("maintainActiveChangeSelectMode " + sel[-1] + ";")

cmds.select(cl=True)

cmds.headsUpMessage( u'转换成功' )

模型材质传递这个功能是给现有的完全相同的来个物体传递两者的材质

这个写法其实参照公司之前写好的脚本修改的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30def Transfer_Fun(self):

sel = cmds.ls(sl=True,fl=True)

shapeNode = cmds.listRelatives(sel[0],children=True,shapes=True)

SGNodeList = cmds.listConnections(shapeNode[0],type="shadingEngine")

SGNodeList = list(set(SGNodeList))

for each in SGNodeList:

cmds.hyperShade(objects=each)

sel_mat_face=cmds.ls(sl=True)

##剔除不是本物体的面 (按材质组选的面,有可能选择其他物体)

mat_face_use=[]

for each_face in sel_mat_face:

if each_face.find(sel[0])!=-1: ##没有找到就返回-1

print each_face

mat_face_use.append(each_face)

print mat_face_use

##改为目标物体的面

mat_face_obj=[]

for each_new in mat_face_use:

mat_face_obj.append( each_new.replace(sel[0],sel[1]) )

cmds.select( mat_face_obj , r=True )

cmds.hyperShade( assign = each )

cmds.select(cl=True)

cmds.headsUpMessage( u'传递成功' )

Alembic 勾选相关参数导出要设置选项中的参数其实我是完全没有头绪的。

毕竟这个东西的勾选是没有任何命令回显的,所以最初完全没有头绪。

但是想起ADV5绑定的时候确实是可以设置相关的数据的。

于是我就参考了ADV5绑定设置中的源码,找到了蛛丝马迹。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31def Alembic_Export_Fun(self):

check = self.Check_CheckBox(self.UV_CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportUVWrite',check))

check = self.Check_CheckBox(self.Face_CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportWriteFaceSets',check))

check = self.Check_CheckBox(self.Verbose_CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportVerbose',check))

check = self.Check_CheckBox(self.Color_CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportWriteColorSets',check))

check = self.Check_CheckBox(self.Render_CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportRenderableOnly',check))

check = self.Check_CheckBox(self.WS__CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportWorldSpace',check))

check = self.Check_CheckBox(self.NM__CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportNoNormals',check))

check = self.Check_CheckBox(self.Vis__CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportWriteVisibility',check))

check = self.Check_CheckBox(self.Namespace_CheckBox.isChecked())

cmds.optionVar(iv=('Alembic_exportStripNamespaces',check))

# 触发 Alembic 导出

cmds.AlembicExportSelection()

使用 cmds.optionVar(l=True) 可以查看optionVar相关的属性变量

install.mel 的搭建鉴于对ADV5的安装方法的好奇,我也想开发出这种方便的安装方式。

本来我是想尝试直接将开发好的py文件扔进Maya,看看能不能如我所愿地执行插件。

经过测试,Maya2017是完全没问题的,但是Maya2015就无法这样直接执行了。

所以参考了ADV5的方法,我发现它是通过Mel来实现的

于是,对ADV5的install.mel进行魔改,成功实现了好ADV5差不多的效果。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64string $subDir = "abc_helper/";

string $scriptName="main";

string $scirptExt = "py";

string $ImagePath = "/icon/alembic_logo" ;

global string $gShelfTopLevel;

string $currentShelf = `tabLayout -query -selectTab $gShelfTopLevel`;

setParent $currentShelf;

string $asInstallScriptLocation=`asInstallScriptLocation`;

string $command="import sys\nsys.path.append(\"" + $asInstallScriptLocation + $subDir + "\")\nimport " + $scriptName + "\nreload(" + $scriptName + ") ";

string $sourceFile=$asInstallScriptLocation+ $subDir + $scriptName+"."+$scirptExt;

string $iconExt="jpg";

if (`asMayaVersionAsFloat`<2012)

$iconExt="xpm";

string $icon=$asInstallScriptLocation + $subDir + $ImagePath + "."+$iconExt;

if (!`file -q -ex $sourceFile`)

error ("Something went wrong, can not find: \""+$sourceFile+"\"");

shelfButton

-command $command

-annotation $scriptName

-label $scriptName

-image $icon

-image1 $icon

-sourceType "python"

;

global proc asInstallScriptLocator (){}

global proc string asInstallScriptLocation ()

{

string $whatIs=`whatIs asInstallScriptLocator`;

string $fullPath=`substring $whatIs 25 999`;

string $buffer[];

string $slash="/";

if (`gmatch $whatIs "*\\\\*"`)//sourced from ScriptEditor

$slash="\\";

int $numTok=`tokenize $fullPath $slash $buffer`;

int $numLetters=size($fullPath);

int $numLettersLastFolder=size($buffer[$numTok-1]);

string $scriptLocation=`substring $fullPath 1 ($numLetters-$numLettersLastFolder)`;

return $scriptLocation;

}

global proc float asMayaVersionAsFloat ()

{

float $version=2012;

if (`exists getApplicationVersionAsFloat`)

return `getApplicationVersionAsFloat`;

string $versionString=`about -v`;

string $tempString[];

string $char;

tokenize $versionString $tempString;

//default to 2012, if versionString is not all numbers

for ($i=0;$i

{

$char=`substring $tempString[0] ($i+1) ($i+1)`;

if (!`gmatch $char "[0-9]"`)

return 2012;

}

$version=$tempString[0];

return $version;

}

总结以上就是 Alembic导入导出助手 的核心源码了。

原理其实一点都不复杂,整个制作过程中最困难的是想出按面给材质的方法以及最后怎么实现设置导出选项。

这个插件开发奠定自己的插件开发风格,为后面的藤蔓生长工具的开发奠定了坚实的基础。

2018-11-30 更新借助UI2CG工具更新了基础界面和功能

这次删除了命名空间修改的功能,因为我发现Maya自带命名空间编辑器,比我自己的开发的小功能强多了。

这次当然也加入了UI2CG所带来的所有特性。

maya python插件_Maya Python - ALembic导入导出助手相关推荐

  1. python读取matlab矩阵_matlab、python中矩阵的互相导入导出方式

    还有一种最流行的h5py.. 过几天更新 ------------在python中导出矩阵至matlab------------ 如果矩阵是mxn维的. 那么可以用 : np.savetxt('dev ...

  2. UE4官方的Python插件(Python Editor Script Plugin)

    概要 UE4官方提供了使用Python脚本执行一些任务的插件:Python Editor Script Plugin. 本篇是对 <官方文档:Scripting the Editor using ...

  3. maya python插件_Maya动画批量重定向插件及Python开发插件笔记

    前言 前段时间研究使用Maya重定向动画,但一个一个手动操作还是有点心烦,所以我花了2天时间学习了Pyhton并写了这个插件(本人有c++.qt.JavaScript经验所以学的快),在这个过程也积累 ...

  4. maya python插件_Maya中Python代码插件编译技术视频教程

    本教程是关于Maya中Python代码插件编译技术视频教程,时长:16分,大小:45 MB,MP4高清视频格式,教程使用软件:Maya,附源文件,共1个章节,作者:Chayan Vinayak,语言: ...

  5. python基础-包文件批量导入导出

    当我们用Python写了项目时,需要给别的小伙伴使用.项目中有很多依赖包,如果每个使用项目的小伙伴都需要一个一个文件打开查看依赖包并一个一个安装,就需要耗费很多时间精力成本了.这时候pipreqs工具 ...

  6. maya python手册_maya python设置maya的渲染设置

    如何使用python去设置maya的渲染设置 通过改变某些渲染的设置值去获取命令 众所周知我们改变某些值的时候在maya的脚本编辑器里面会有命令返回,我们直接运行这些命令就可以了 这个我就不再细说了 ...

  7. Python数据处理016:Pandas 导入导出

    pandas可以读取与存取的资料格式有很多种,像csv.excel.json.html与pickle等-, 详细请看官方说明文件 一.读取csv 下面的例子假设当前路径中有xxx.csv文件: > ...

  8. nextcloud安装日历插件使用并设置导入导出和云端同步(安卓手机和ios手机)

    原文链接:https://dsx2016.com/?p=1718 公众号:大师兄2016 安装日历 点击右上角头衔 在下拉菜单中选择应用 选择办公&文本分类 安装Calendar插件 编辑日历 ...

  9. spss为什么有python插件_SPSS python插件和R插件安装详细流程

    注册后推荐绑定QQ,之后方才可以使用下方的"用QQ帐号登录". 您需要 登录 才可以下载或查看,没有帐号?立即注册 x IBM SPSS Statistics 21.0/AMOS ...

最新文章

  1. SQL Server中常用的SQL语句
  2. 别的程序员是怎么读你的简历的
  3. Java 自定义 ClassLoader 实现 JVM 类加载
  4. Intent对象详解(一)
  5. C 中的static关键字
  6. 联合索引使用规则(转载)
  7. OpenJudge计算概论-最长单词2
  8. *【CodeForces - 859C 】Pie Rules (博弈dp,时光倒流)
  9. LinkedList源码阅分析
  10. 在CentOS7上实现NFS共享
  11. 力扣算法题—069x的平方根
  12. FlinkWindow和水印
  13. ADS2015导入飞思卡尔元器件模型 安装DesignKit
  14. 2022制冷与空调设备运行操作考试模拟100题模拟考试平台操作
  15. python画聚类树状图_影像组学学习笔记(36)-聚类树状图Dendrogram的python实现
  16. ubuntu 下 ssd磁盘检测
  17. 怎么做GIF动画?怎样将图片合成gif动图
  18. Jest测试框架入门之匹配器与测试异步代码
  19. 深圳软件测试培训:移动测试ExpandableListView
  20. Swing版《房屋租赁合同》

热门文章

  1. 一名职业3D建模师的学习经历,月薪28K依然焦虑
  2. 数据结构之散列表(七)
  3. 【Matlab系列】常用模拟和数字通信系统仿真及Matlab实现
  4. lazada代运营-代运营服务平台
  5. c语言对于随机数的产生于应用,c语言之产生随机数详解
  6. 如何使用SQL批量替换数据库特定字段中部分特定数据
  7. VB/VBA,请让我点名表扬你
  8. 使用python批量提取txt中的数据并写入excel
  9. C# FileInfo类:文件操作
  10. 基于mbedtls的AES加密(C/C++)