如何成为一个TD 系列【5】--controller library

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值