+ +

Source code for Interfaces.ART_AddModuleUI

+"""
+Author: Jeremy Ernst
+"""
+
+import maya.cmds as cmds
+
+import System.utils as utils
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+windowTitle = "Add Module"
+windowObject = "pyArtAddModuleUi"
+
+
+
[docs]class ART_AddModule_UI(QtWidgets.QMainWindow): + """ + This class builds a UI used by the rig creator, and is called when a user pushed a module button to add to their + rig. This UI presents options like prefix, suffix, and ability to specify the parent module bone. + + .. image:: /images/addModuleUI.png + + """ + +
[docs] def __init__(self, baseName, className, rigUiInst, parent=None): + """ + Initialize the class, taking in the base name of the module to be added, the name of the class of the module + to be added, and the instance of the rig creator UI. Then build the interface for the tool. + + :param baseName: The base name of the module to be added, defined in the module class file at the top. + :param className: The class name of the module to be added, so we can then initialize that module. + :param rigUiInst: The instance of the rig creator UI, from which this function was called. + + """ + + super(ART_AddModule_UI, self).__init__(parent) + + # get the directory path of the tools + settings = QtCore.QSettings("Epic Games", "ARTv2") + self.toolsPath = settings.value("toolsPath") + self.iconsPath = settings.value("iconPath") + + # create class variables + self.baseName = baseName + self.className = className + self.rigUiInst = rigUiInst + + # load stylesheet + styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss") + f = open(styleSheetFile, "r") + style = f.read() + f.close() + + self.setStyleSheet(style) + + # size policies + mainSizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + + # create the main widget + self.mainWidget = QtWidgets.QWidget() + self.setCentralWidget(self.mainWidget) + + # set qt object name + self.setObjectName(windowObject) + self.setWindowTitle(windowTitle) + + # create the mainLayout for the rig creator UI + self.mainLayout = QtWidgets.QHBoxLayout(self.mainWidget) + self.mainLayout.setContentsMargins(0, 0, 0, 0) + + self.setSizePolicy(mainSizePolicy) + self.setMinimumSize(QtCore.QSize(500, 220)) + self.setMaximumSize(QtCore.QSize(500, 520)) + + # create the background + self.frame = QtWidgets.QFrame() + self.frame.setObjectName("mid") + self.mainLayout.addWidget(self.frame) + + # create the layout for the widgets + self.column1layout = QtWidgets.QVBoxLayout(self.frame) + self.mainLayout.addLayout(self.column1layout) + + self.column2Layout = QtWidgets.QVBoxLayout() + self.mainLayout.addLayout(self.column2Layout) + + font = QtGui.QFont() + font.setBold(True) + + label = QtWidgets.QLabel("Choose Parent Bone") + label.setFont(font) + label.setAlignment(QtCore.Qt.AlignCenter) + self.column2Layout.addWidget(label) + + self.boneSearch = QtWidgets.QLineEdit() + self.column2Layout.addWidget(self.boneSearch) + self.boneSearch.setPlaceholderText("Search...") + self.boneSearch.textChanged.connect(self.searchList) + + self.hierarchyTree = QtWidgets.QListWidget() + self.column2Layout.addWidget(self.hierarchyTree) + + # add items to listWidget + parents = utils.getViableParents() + for bone in parents: + self.hierarchyTree.addItem(bone) + + if bone == "root": + index = parents.index(bone) + self.hierarchyTree.setCurrentRow(index) + + # create the prefix pair of fields + self.prefixForm = QtWidgets.QFormLayout() + self.column1layout.addLayout(self.prefixForm) + + self.prefixLabel = QtWidgets.QLabel("Prefix: ") + self.prefixForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.prefixLabel) + + self.prefix = QtWidgets.QLineEdit() + self.prefixForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.prefix) + + # hookup signal/slot connection + self.prefix.textChanged.connect(self.updatePreview) + + # create the suffix pair of fields + self.suffixForm = QtWidgets.QFormLayout() + self.column1layout.addLayout(self.suffixForm) + + self.suffixLabel = QtWidgets.QLabel("Suffix: ") + self.suffixForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.suffixLabel) + + self.suffix = QtWidgets.QLineEdit() + self.suffixForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.suffix) + + # hookup signal/slot connection + self.suffix.textChanged.connect(self.updatePreview) + + self.previewLabel = QtWidgets.QLabel("Module Name: ") + self.column1layout.addWidget(self.previewLabel) + + self.previewName = QtWidgets.QLabel(self.baseName) + self.previewName.setMinimumSize(QtCore.QSize(255, 25)) + self.previewName.setMaximumSize(QtCore.QSize(255, 25)) + self.previewName.setAlignment(QtCore.Qt.AlignHCenter) + self.column1layout.addWidget(self.previewName) + + # set preview font + font = QtGui.QFont() + font.setPointSize(12) + self.previewName.setFont(font) + + spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.column1layout.addItem(spacerItem1) + + # special cases (arms and legs) + specialCaseModules = ["ART_Leg_Standard", "ART_Arm_Standard"] + if className in specialCaseModules: + # spacer + groupBox = QtWidgets.QGroupBox("") + self.column1layout.addWidget(groupBox) + layout = QtWidgets.QVBoxLayout(groupBox) + + self.radioButtonLayout = QtWidgets.QHBoxLayout() + layout.addLayout(self.radioButtonLayout) + self.rightRadioBtn = QtWidgets.QRadioButton("Right Side") + self.leftRadioBtn = QtWidgets.QRadioButton("Left Side") + self.radioButtonLayout.addWidget(self.rightRadioBtn) + self.radioButtonLayout.addWidget(self.leftRadioBtn) + self.leftRadioBtn.setChecked(True) + + # spacer + spacerItem2 = QtWidgets.QSpacerItem(20, 80, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.column1layout.addItem(spacerItem2) + + # create button + self.createButton = QtWidgets.QPushButton("CREATE") + self.column1layout.addWidget(self.createButton) + self.createButton.setMinimumSize(QtCore.QSize(255, 40)) + self.createButton.setMaximumSize(QtCore.QSize(255, 40)) + self.createButton.setSizePolicy(mainSizePolicy) + self.createButton.setObjectName("blueButton") + font = QtGui.QFont() + font.setPointSize(12) + self.createButton.setFont(font) + + # hookup signal/slot on create button + self.createButton.clicked.connect(self.createModule) + + self.hierarchyTree.setFocus()
+ + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +
[docs] def updatePreview(self): + """ + Read the prefix and suffix QLineEdits, append an underscore, and update the previewName QLabel with the + prefix, basename, and suffix to show what the final module name will be. + + """ + + prefix = str(self.prefix.text()) + suffix = str(self.suffix.text()) + + string = "" + if len(prefix) > 0: + string += prefix + "_" + + string += self.baseName + + if len(suffix) > 0: + string += "_" + suffix + + self.previewName.setText(string)
+ + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +
[docs] def createModule(self): + """ + Instantiate our module class to create with the user specified name, creating the network node, building + the Skeleton Settings UI for the module, adding the joint mover for that module (importing the joint mover + file), and adding the joint mover to the outliner. + + """ + + mod = __import__("RigModules." + self.className, {}, {}, [self.className]) + reload(mod) + + # get the class name from that module file (returns RigModules.ART_Root.ART_Root for example) + moduleClass = getattr(mod, mod.className) + jmPath = mod.jointMover + + # find the instance of that module and call on the skeletonSettings_UI function + userSpecName = str(self.previewName.text()) + + # check to see if a module already has that name + modules = utils.returnRigModules() + validName = False + for module in modules: + name = cmds.getAttr(module + ".moduleName") + if name == userSpecName: + cmds.confirmDialog(title="Name Exists", + message="A module with that name already exists. Please enter a unique name.", + icon="critical") + return + + # call functions to create network node, skeleton settings UI + moduleInst = moduleClass(self.rigUiInst, userSpecName) + self.rigUiInst.moduleInstances.append(moduleInst) # add this instance to the ui's list of module instances + networkNode = moduleInst.buildNetwork() + + # figure out side + specialCaseModules = ["ART_Leg_Standard", "ART_Arm_Standard"] + if self.className in specialCaseModules: + side = "Left" + if self.rightRadioBtn.isChecked(): + side = "Right" + cmds.setAttr(networkNode + ".side", lock=False) + cmds.setAttr(networkNode + ".side", "Right", type="string", lock=True) + + # build new jmPath name + jmPath = jmPath.partition(".ma")[0] + "_" + side + ".ma" + + moduleInst.skeletonSettings_UI(userSpecName) + moduleInst.jointMover_Build(jmPath) + moduleInst.addJointMoverToOutliner() + + # update the created joints attribute on the network node with the new names + prefix = str(self.prefix.text()) + suffix = str(self.suffix.text()) + + if len(prefix) > 0: + prefix = prefix + "_" + if len(suffix) > 0: + suffix = "_" + suffix + + createdBones = cmds.getAttr(networkNode + ".Created_Bones") + createdBones = createdBones.split("::") + + attrString = "" + for bone in createdBones: + if len(bone) > 1: + attrString += prefix + bone + suffix + "::" + + cmds.setAttr(networkNode + ".Created_Bones", lock=False) + cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True) + + # update the self.currentParent label and the parentModuleBone attr on the network node + parent = (self.hierarchyTree.currentItem().text()) + moduleInst.currentParent.setText(parent) + + cmds.setAttr(networkNode + ".parentModuleBone", lock=False) + cmds.setAttr(networkNode + ".parentModuleBone", parent, type="string", lock=True) + + # parent the joint mover to the offset mover of the parent + mover = "" + + if parent == "root": + mover = "root_mover" + + else: + # find the parent mover name to parent to + networkNodes = utils.returnRigModules() + mover = utils.findMoverNodeFromJointName(networkNodes, parent, False, True) + + if mover is not None: + cmds.parentConstraint(mover, userSpecName + "_mover_grp", mo=True) + cmds.scaleConstraint(mover, userSpecName + "_mover_grp") + + # create the connection geo between the two + globalMover = utils.findGlobalMoverFromName(userSpecName) + cmds.select(globalMover) + cmds.setToolTo("moveSuperContext") + + utils.fitViewAndShade() + + # delete the UI + cmds.deleteUI(windowObject) + + # obey the current UI visibility toggles + self.rigUiInst.setMoverVisibility() + moduleInst.updateBoneCount() + self.rigUiInst.populateNetworkList() + + # turn on aim mode + moduleInst.aimMode(True)
+ + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +
[docs] def searchList(self): + """ + Get the search text from the QLineEdit and search the items in the QListWidget for any matches. Anything that + does not match will be hidden in the QListWidget. + + """ + + searchText = self.boneSearch.text() + + for i in range(self.hierarchyTree.count()): + lwItem = self.hierarchyTree.item(i) + if lwItem.text().find(searchText) != -1: + lwItem.setHidden(False) + else: + lwItem.setHidden(True)
+
+ +