# -*-coding:utf-8-*-
from maya import cmds
# IO文件模块
import os
# json文件模块
import json
# 控制输出模块
import pprint
# 获取maya的位置
USERAPPDIR = cmds.internalVar(userAppDir=True)
DIRECTORY = os.path.join(USERAPPDIR, "controllerLibrary")
# 创建文件夹目录
def createDirectory(directory=DIRECTORY):
if not os.path.exists(directory):
os.mkdir(directory)
# 建立一个控制器库的类,以字典形式存储
class ControllerLibrary(dict):
def save(self, name, directory=DIRECTORY, screenshot=True, **info):
"""
将要存储的控制器存储在控制器库中
:param name: 控制器的名称
:param directory: 控制器存储的路径,有默认值
:param screenshot: 是否截屏存图
:param info: 需要存储的其他信息
"""
# 创建一个控制器库的目录
createDirectory(directory)
path = os.path.join(directory, "%s.ma" % name)
infoFile = os.path.join(directory, "%s.json" % name)
cmds.file(rename=path)
info["name"] = name
info["path"] = path
# 存储控制器
if cmds.ls(selection=True):
cmds.file(force=True, type="mayaAscii", exportSelected=True)
else:
cmds.file(save=True, type="mayaAscii", force=True)
# 截屏存图,并将存图信息存进info中
if screenshot:
info["screenshot"] = self.saveScreenshot(name, directory=directory)
# 将info中的信息写入到json文件中
with open(infoFile, "w") as f:
json.dump(info, f, indent=4)
# 将路径和对应名称以字典的形式存储在类中
self[name]=path
return path
def find(self, directory=DIRECTORY):
"""
在加载控制器前,需要调用find函数来查找目录中有什么控制器
:param directory: 路径
"""
self.clear()
# 如果路径不存在,则结束程序
if not os.path.exists(directory):
return
# 将目录中的文件列入列表中
files = os.listdir(directory)
# 找到里面的ma文件
mayaFiles = [f for f in files if f.endswith(".ma")]
for ma in mayaFiles:
name, ext = os.path.splitext(ma)
path = os.path.join(directory, ma)
# 找到ma文件对应名称的json文件
infoFile="%s.json" % name
# 获取json文件的信息
if infoFile in files:
infoFile=os.path.join(directory, infoFile)
with open(infoFile,"r") as f:
info = json.load(f)
else:
info = {}
"""screenshot="%s.jpg" % name
if screenshot in files:
info["screenshot"] = os.path.join(directory, name)
info["name"]=name
info["path"]=path"""
# 把json文件的信息输入到类的字典中
self[name]=info
# 输出类的字典
# pprint.pprint(self)
def load(self,name):
"""
加载控制器
:param name:需要加载的控制器名称
"""
# 获取需要加载的控制器的路径
path=self[name]["path"]
# 输入文件到场景中
cmds.file(path, i=True, usingNamespaces=False)
def saveScreenshot(self,name, directory=DIRECTORY):
"""
截图函数
:param name:需要截图的文件名称
:param directory: 存储的路径
:return: 返回存储的路径
"""
# 存储的路径名称
path = os.path.join(directory,"%s.jpg" % name)
# 让视图fit物体
cmds.viewFit()
# 设置需要存储的图片格式,8为jpg格式
cmds.setAttr("defaultRenderGlobals.imageFormat", 8)
# 进行拍屏
cmds.playblast(completeFilename=path, forceOverwrite=True,format="image", width=200,
height=200,showOrnaments=False,startTime=1,endTime=1,viewer=False)
return path
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UI部分
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# -*-coding:utf-8-*-
import pprint
from maya import cmds
import controlLibrary
reload(controlLibrary)
from PySide2 import QtWidgets, QtCore, QtGui
# 建立一个对话框类的UI程序
class ControllerLibraryUI(QtWidgets.QDialog):
def __init__(self):
# 调用QtWidget和QDialog的init方法
super(ControllerLibraryUI, self).__init__()
# 设置程序标题
self.setWindowTitle("Controller Library UI")
# 创建一个ControllerLibrary实例
self.library = controlLibrary.ControllerLibrary()
# 调用创建UI函数
self.buildUI()
# 调用刷新列表函数
self.populate()
def buildUI(self):
"""
创建UI函数,用于整个程序的UI创建
"""
# 设置一个layout层,模式为竖直排列
layout = QtWidgets.QVBoxLayout(self)
# 设置一个save层,模式为水平排列,并将其添加入layout层中
saveWidget = QtWidgets.QWidget()
saveLayout = QtWidgets.QHBoxLayout(saveWidget)
layout.addWidget(saveWidget)
# 创建一个行编辑器,将其添加入save层
self.saveNameField = QtWidgets.QLineEdit()
saveLayout.addWidget(self.saveNameField)
# 创建一个save按钮,用于save函数响应,将其添加进save层
saveBtn=QtWidgets.QPushButton("Save")
saveBtn.clicked.connect(self.save)
saveLayout.addWidget(saveBtn)
# 创建一个列表框,将其模式设置为图标模式显示,重设图标大小和每个列表框的大小,将列表变为可调整模式,将其加入layout层
size = 80
buffer = 12
self.listWidget = QtWidgets.QListWidget()
self.listWidget.setViewMode(QtWidgets.QListWidget.IconMode)
self.listWidget.setIconSize(QtCore.QSize(size, size))
self.listWidget.setGridSize(QtCore.QSize(size+buffer, size+buffer))
self.listWidget.setResizeMode(QtWidgets.QListWidget.Adjust)
layout.addWidget(self.listWidget)
# 创建一个btn层,模式设置为水平排列,将其添加进layout层中
btnWidget = QtWidgets.QWidget()
btnLayout = QtWidgets.QHBoxLayout(btnWidget)
layout.addWidget(btnWidget)
# 创建import按钮,响应load函数
importBtn = QtWidgets.QPushButton("import")
importBtn.clicked.connect(self.load)
btnLayout.addWidget(importBtn)
# 创建refresh按钮,响应populate函数
refreshBtn = QtWidgets.QPushButton("refresh")
refreshBtn.clicked.connect(self.populate)
btnLayout.addWidget(refreshBtn)
# 创建close按钮,响应QDialog自带的close函数
closeBtn = QtWidgets.QPushButton("close")
closeBtn.clicked.connect(self.close)
btnLayout.addWidget(closeBtn)
def populate(self):
"""
用于排列列表的刷新函数
"""
# 每一次刷新都删除上一次列表中的东西
self.listWidget.clear()
# 查找控制器库中有哪些控制器
self.library.find()
# name=key info=value
for name, info in self.library.items():
# 创建列表中的每个项目
item = QtWidgets.QListWidgetItem(name)
# 将项目添加进列表中
self.listWidget.addItem(item)
# 得到每个项目截图的路径
screenshot = info.get("screenshot")
# 如果路径存在,则添加图片
if screenshot:
icon = QtGui.QIcon(screenshot)
item.setIcon(icon)
# 设置鼠标移动时浮出的文档
item.setToolTip(pprint.pformat(info))
def save(self):
"""
保存控制器进入列表的函数
"""
# 获取行编辑器中用户输入的文字
name = self.saveNameField.text()
# 如果用户没有输入文字(或者只输入了空格),则弹出警告
if not name.strip():
cmds.warning("You must enter a name")
return
# 将用户输入的文字作为名字存储在库中
self.library.save(name)
# 刷新列表
self.populate()
# 将行编辑器中的文字设为空
self.saveNameField.setText("")
def load(self):
# 获取现在点击的项目
currentItem=self.listWidget.currentItem()
# 如果没有点击项目则结束函数
if not currentItem:
return
# 加载现在点击的项目的物体
name = currentItem.text()
self.library.load(name)
def showUI():
"""
主要要调用的函数,用于显示UI
:return: 返回ui实例,需要将其赋给一个变量,程序才不会闪退
"""
ui = ControllerLibraryUI()
ui.show()
return ui