aboutsummaryrefslogtreecommitdiff
path: root/Core/Scripts/Interfaces/ART_RigCreatorUI.py
diff options
context:
space:
mode:
authorMobileMachine\jeremy <[email protected]>2017-06-06 22:59:03 -0400
committerMobileMachine\jeremy <[email protected]>2017-06-06 22:59:03 -0400
commit24725fa8681f906ab44d80687c09fecc171a2896 (patch)
tree312a601df29aca7f8db9f44082d96ebc7a679138 /Core/Scripts/Interfaces/ART_RigCreatorUI.py
parentInitial commit (diff)
downloadartv2-24725fa8681f906ab44d80687c09fecc171a2896.tar.xz
artv2-24725fa8681f906ab44d80687c09fecc171a2896.zip
Initial Submission
First submission of current state of ARTv2. Currently considered to be in Alpha. There are a couple of animation tools not implemented yet, and one module not implemented yet, as well as incomplete documentation.
Diffstat (limited to 'Core/Scripts/Interfaces/ART_RigCreatorUI.py')
-rw-r--r--Core/Scripts/Interfaces/ART_RigCreatorUI.py1819
1 files changed, 1819 insertions, 0 deletions
diff --git a/Core/Scripts/Interfaces/ART_RigCreatorUI.py b/Core/Scripts/Interfaces/ART_RigCreatorUI.py
new file mode 100644
index 0000000..65a8d67
--- /dev/null
+++ b/Core/Scripts/Interfaces/ART_RigCreatorUI.py
@@ -0,0 +1,1819 @@
+# standard imports
+import json
+import os
+from functools import partial
+
+import maya.OpenMayaUI as mui
+import maya.cmds as cmds
+
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+# maya 2016< maya2017> compatability
+try:
+ import shiboken as shiboken
+except:
+ import shiboken2 as shiboken
+
+# external imports
+import System.utils as utils
+import System.riggingUtils as riggingUtils
+from System.ART_RigModule import ART_RigModule
+from RigModules.ART_Root import ART_Root
+import System.interfaceUtils as interfaceUtils
+
+windowTitle = "Rig_Creator"
+windowObject = "pyArtRigCreatorUi"
+
+
+class ART_RigCreator_UI(QtWidgets.QMainWindow):
+ # Original Author: Jeremy Ernst
+
+ def __init__(self, parent=None):
+
+ super(ART_RigCreator_UI, self).__init__(parent)
+
+ # clean up script jobs
+ jobs = cmds.scriptJob(lj=True)
+ for job in jobs:
+ if job.find("ART_") != -1:
+ jobNum = int(job.partition(":")[0])
+ cmds.scriptJob(kill=jobNum, force=True)
+
+ # get settings
+ settings = QtCore.QSettings("Epic Games", "ARTv2")
+ self.toolsPath = settings.value("toolsPath")
+ self.scriptPath = settings.value("scriptPath")
+ self.iconsPath = settings.value("iconPath")
+
+ # create a few lists/dicts to store info
+ self.outlinerWidgets = {}
+ self.outlinerControls = []
+
+ # this list will store module instances created by this UI or by any sub-UIs (like addModuleUI)
+ self.moduleInstances = []
+ self.scriptJobs = []
+ self.boneCounterInst = None
+
+ # build the UI
+ self.buildUI()
+
+ # tooltip style sheet
+ # write out qss based on user settings
+ stylesheetDir = utils.returnNicePath(self.scriptPath, "Interfaces/StyleSheets/")
+ stylesheets = os.listdir(stylesheetDir)
+
+ for sheet in stylesheets:
+ interfaceUtils.writeQSS(os.path.join(stylesheetDir, sheet))
+
+ # check to see if the root of our rig network exists
+ exists = False
+ networkNodes = cmds.ls(type="network")
+ for node in networkNodes:
+ attrs = cmds.listAttr(node)
+
+ if "rigModules" in attrs:
+ exists = True
+
+ # if the root of the rig network did not exist, create it now as well as our root module
+
+ if exists == False:
+
+ self.rigRootMod = ART_RigModule("ART_RIG_ROOT", None, None)
+ self.rigRootMod.buildNetwork()
+
+ # create a root module
+ self.rootMod = ART_Root(self, "root")
+ self.rootMod.buildNetwork()
+ self.rootMod.skeletonSettings_UI("Root")
+ self.rootMod.jointMover_Build("Core/JointMover/ART_Root.ma")
+ self.rootMod.addJointMoverToOutliner()
+ self.moduleInstances.append(self.rootMod)
+
+
+
+ # if module node network existed, create UI elements and do not create any new network nodes
+ else:
+ modules = utils.returnRigModules()
+
+ for module in modules:
+ modType = cmds.getAttr(module + ".moduleType")
+ modName = cmds.getAttr(module + ".moduleName")
+ mod = __import__("RigModules." + modType, {}, {}, [modType])
+ reload(mod)
+
+ # get the class name from that module file (returns Modules.ART_Root.ART_Root for example)
+ moduleClass = getattr(mod, mod.className)
+
+ # find the instance of that module and call on the skeletonSettings_UI function
+ moduleInst = moduleClass(self, modName)
+ moduleInst.skeletonSettings_UI(modName)
+ moduleInst.addJointMoverToOutliner()
+
+ self.moduleInstances.append(moduleInst)
+
+ # run toggleMoverVisibility
+ self.setMoverVisibility()
+
+ # clear selection
+ cmds.select(clear=True)
+
+ # unisolate selection if needed
+ try:
+ isoPnl = cmds.getPanel(wf=True)
+ isoCrnt = cmds.isolateSelect(isoPnl, q=True, s=True)
+ if isoCrnt:
+ cmds.isolateSelect(isoPnl, s=False)
+ except:
+ pass
+
+ utils.fitViewAndShade()
+
+ # set the UI to the correct state
+ if cmds.objExists("ART_RIG_ROOT.state"):
+ state = cmds.getAttr("ART_RIG_ROOT.state")
+ if state == 1:
+ self.toolModeStack.setCurrentIndex(1)
+
+ # remove outliner scriptJobs
+ for job in self.scriptJobs:
+ cmds.scriptJob(kill=job, force=True)
+
+ # build the scriptJob for the weight table
+ self.scriptJobs.append(self.skinToolsInst.weightTable_scriptJob())
+
+ if state == 2:
+ self.toolModeStack.setCurrentIndex(2)
+
+ # remove outliner scriptJobs
+ for job in self.scriptJobs:
+ cmds.scriptJob(kill=job, force=True)
+
+ self.populateNetworkList()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def populateNetworkList(self):
+
+ self.nodeNetworkList.clear()
+
+ # get network nodes and add to list widget
+ modules = cmds.ls(type="network")
+ returnMods = []
+ for module in modules:
+ attrs = cmds.listAttr(module)
+ if "parent" in attrs:
+ returnMods.append(module)
+
+ mainNode = cmds.listConnections(returnMods[0] + ".parent")[0]
+ self.nodeNetworkList.addItem(mainNode)
+
+ for mod in returnMods:
+ self.nodeNetworkList.addItem(mod)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def buildUI(self):
+ # Original Author: Jeremy Ernst
+
+ # load stylesheet
+ styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss")
+ f = open(styleSheetFile, "r")
+ self.style = f.read()
+ f.close()
+
+ self.setStyleSheet(self.style)
+
+ # size policies
+ mainSizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ scrollSizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
+
+ # create the main widget
+ self.mainWidget = QtWidgets.QWidget()
+ self.mainWidget.setObjectName("darkImg")
+ self.setCentralWidget(self.mainWidget)
+
+ # set qt object name
+ self.setObjectName(windowObject)
+ self.setWindowTitle(windowTitle)
+ self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
+
+ # create the mainLayout for the rig creator UI
+ self.layout = QtWidgets.QVBoxLayout(self.mainWidget)
+
+ self.setMinimumSize(QtCore.QSize(580, 400))
+ self.setMaximumSize(QtCore.QSize(580, 900))
+
+ self.resize(600, 450)
+
+ # Create a stackedWidget
+ self.toolModeStack = QtWidgets.QStackedWidget()
+ self.layout.addWidget(self.toolModeStack)
+ self.rigMode = QtWidgets.QWidget()
+ self.mainLayout = QtWidgets.QVBoxLayout(self.rigMode)
+ self.toolModeStack.addWidget(self.rigMode)
+
+ # create the menu bar
+ self.menuBar = QtWidgets.QMenuBar()
+ self.menuBar.setMaximumHeight(25)
+ self.mainLayout.addWidget(self.menuBar)
+
+ # create the toolbar layout
+ self.toolFrame = QtWidgets.QFrame()
+ self.toolFrame.setMinimumHeight(60)
+ self.toolFrame.setMaximumHeight(60)
+ self.toolFrame.setObjectName("dark2")
+ self.mainLayout.addWidget(self.toolFrame)
+ self.toolbarLayout = QtWidgets.QHBoxLayout(self.toolFrame)
+ self.toolbarLayout.setDirection(QtWidgets.QBoxLayout.RightToLeft)
+ self.toolbarLayout.addStretch(0)
+ self.toolbarLayout.setSpacing(10)
+
+ # toolbar buttons
+
+ self.pinModulesBtn = QtWidgets.QPushButton()
+ self.pinModulesBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.pinModulesBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/pin.png"))
+ self.pinModulesBtn.setIconSize(QtCore.QSize(30, 30))
+ self.pinModulesBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.pinModulesBtn)
+ self.pinModulesBtn.setToolTip("Pin a module in place so that moving a parent does not effect the module.")
+ self.pinModulesBtn.clicked.connect(self.pinModulesUI)
+ self.pinModulesBtn.setObjectName("toolbar")
+
+ self.bakeOffsetsBtn = QtWidgets.QPushButton()
+ self.bakeOffsetsBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.bakeOffsetsBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/bakeOffsets.png"))
+ self.bakeOffsetsBtn.setIconSize(QtCore.QSize(30, 30))
+ self.bakeOffsetsBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers.")
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsetsUI)
+ self.bakeOffsetsBtn.setObjectName("toolbar")
+
+ self.aimModeBtn = QtWidgets.QPushButton()
+ self.aimModeBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.aimModeBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/aim.png"))
+ self.aimModeBtn.setIconSize(QtCore.QSize(30, 30))
+ self.aimModeBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.aimModeBtn)
+ self.aimModeBtn.setToolTip("Toggle Aim mode for modules.")
+ self.aimModeBtn.clicked.connect(self.aimModeUI)
+ self.aimModeBtn.setObjectName("toolbar")
+
+ self.boneCountBtn = QtWidgets.QPushButton()
+ self.boneCountBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.boneCountBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/count.png"))
+ self.boneCountBtn.setIconSize(QtCore.QSize(30, 30))
+ self.boneCountBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.boneCountBtn)
+ self.boneCountBtn.setToolTip("Bring up a bone counter utility")
+ self.boneCountBtn.setCheckable(True)
+ self.boneCountBtn.clicked.connect(self.boneCounterUI)
+ self.boneCountBtn.setObjectName("toolbar")
+
+ self.resetBtn = QtWidgets.QPushButton()
+ self.resetBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.resetBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/reset.png"))
+ self.resetBtn.setIconSize(QtCore.QSize(30, 30))
+ self.resetBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.resetBtn)
+ self.resetBtn.setToolTip("Reset Joint Mover Modules Position and Rotation")
+ self.resetBtn.setCheckable(True)
+ self.resetBtn.clicked.connect(self.resetModeUI)
+ self.resetBtn.setObjectName("toolbar")
+
+ self.symmetryModeBtn = QtWidgets.QPushButton()
+ self.symmetryModeBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.symmetryModeBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/symmetryMode.png"))
+ self.symmetryModeBtn.setIconSize(QtCore.QSize(30, 30))
+ self.symmetryModeBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.symmetryModeBtn)
+ self.symmetryModeBtn.setToolTip("Brings up a new window to apply symmetry to the selected modules in the list.")
+ self.symmetryModeBtn.clicked.connect(self.symmetryModeUI)
+ self.symmetryModeBtn.setObjectName("toolbar")
+
+ self.geoDisplayBtn = QtWidgets.QPushButton()
+ self.geoDisplayBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.geoDisplayBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/geoDisplay_on.png"))
+ self.geoDisplayBtn.setIconSize(QtCore.QSize(30, 30))
+ self.geoDisplayBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.geoDisplayBtn)
+ self.geoDisplayBtn.setToolTip("Toggle the visibility of the proxy geometry")
+ self.geoDisplayBtn.setCheckable(True)
+ self.geoDisplayBtn.clicked.connect(partial(self.toggleMoverVisibility, "*_proxy_geo", self.geoDisplayBtn))
+ self.geoDisplayBtn.clicked.connect(
+ partial(self.toggleButtonIcon, self.geoDisplayBtn, "System/geoDisplay_on.png", "System/geoDisplay.png"))
+ self.geoDisplayBtn.setChecked(True)
+ self.geoDisplayBtn.setObjectName("toolbar")
+
+ self.lraDisplayBtn = QtWidgets.QPushButton()
+ self.lraDisplayBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.lraDisplayBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/lra_on.png"))
+ self.lraDisplayBtn.setIconSize(QtCore.QSize(30, 30))
+ self.lraDisplayBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.lraDisplayBtn)
+ self.lraDisplayBtn.setToolTip("Toggle the visibility of the local rotation axis display")
+ self.lraDisplayBtn.setCheckable(True)
+ self.lraDisplayBtn.clicked.connect(partial(self.toggleMoverVisibility, "*_lra", self.lraDisplayBtn))
+ self.lraDisplayBtn.clicked.connect(
+ partial(self.toggleButtonIcon, self.lraDisplayBtn, "System/lra_on.png", "System/lra.png"))
+ self.lraDisplayBtn.setChecked(True)
+ self.lraDisplayBtn.setObjectName("toolbar")
+
+ self.boneDisplayBtn = QtWidgets.QPushButton()
+ self.boneDisplayBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.boneDisplayBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/boneDisplay.png"))
+ self.boneDisplayBtn.setIconSize(QtCore.QSize(30, 30))
+ self.boneDisplayBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.boneDisplayBtn)
+ self.boneDisplayBtn.setToolTip("Toggle the visibility of the bone representations")
+ self.boneDisplayBtn.setCheckable(True)
+ self.boneDisplayBtn.clicked.connect(partial(self.toggleMoverVisibility, "*_bone_geo", self.boneDisplayBtn))
+ self.boneDisplayBtn.clicked.connect(
+ partial(self.toggleButtonIcon, self.boneDisplayBtn, "System/boneDisplay_on.png", "System/boneDisplay.png"))
+ self.boneDisplayBtn.setChecked(False)
+ self.boneDisplayBtn.setObjectName("toolbar")
+
+ self.meshMoverBtn = QtWidgets.QPushButton()
+ self.meshMoverBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.meshMoverBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/meshMover.png"))
+ self.meshMoverBtn.setIconSize(QtCore.QSize(30, 30))
+ self.meshMoverBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.meshMoverBtn)
+ self.meshMoverBtn.setToolTip("Toggle the visibility of the mesh mover controls")
+ self.meshMoverBtn.setCheckable(True)
+ self.meshMoverBtn.clicked.connect(partial(self.toggleMoverVisibility, "*_mover_geo", self.meshMoverBtn))
+ self.meshMoverBtn.clicked.connect(
+ partial(self.toggleButtonIcon, self.meshMoverBtn, "System/meshMover_on.png", "System/meshMover.png"))
+ self.meshMoverBtn.setChecked(False)
+ self.meshMoverBtn.setObjectName("toolbar")
+
+ self.offsetMoverBtn = QtWidgets.QPushButton()
+ self.offsetMoverBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.offsetMoverBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/offsetMover.png"))
+ self.offsetMoverBtn.setIconSize(QtCore.QSize(30, 30))
+ self.offsetMoverBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.offsetMoverBtn)
+ self.offsetMoverBtn.setToolTip("Toggle the visibility of the offset mover controls")
+ self.offsetMoverBtn.setCheckable(True)
+ self.offsetMoverBtn.clicked.connect(partial(self.toggleMoverVisibility, "*_mover_offset", self.offsetMoverBtn))
+ self.offsetMoverBtn.clicked.connect(
+ partial(self.toggleButtonIcon, self.offsetMoverBtn, "System/offsetMover_on.png", "System/offsetMover.png"))
+ self.offsetMoverBtn.setChecked(False)
+ self.offsetMoverBtn.setObjectName("toolbar")
+
+ self.globalMoverBtn = QtWidgets.QPushButton()
+ self.globalMoverBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.globalMoverBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/globalMover_on.png"))
+ self.globalMoverBtn.setIconSize(QtCore.QSize(30, 30))
+ self.globalMoverBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.globalMoverBtn)
+ self.globalMoverBtn.setToolTip("Toggle the visibility of the global mover controls")
+ self.globalMoverBtn.setCheckable(True)
+ self.globalMoverBtn.clicked.connect(partial(self.toggleMoverVisibility, "*_mover", self.globalMoverBtn))
+ self.globalMoverBtn.clicked.connect(
+ partial(self.toggleButtonIcon, self.globalMoverBtn, "System/globalMover_on.png", "System/globalMover.png"))
+ self.globalMoverBtn.setChecked(True)
+ self.globalMoverBtn.setObjectName("toolbar")
+
+ self.saveTemplateBtn = QtWidgets.QPushButton()
+ self.saveTemplateBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.saveTemplateBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/save.png"))
+ self.saveTemplateBtn.setIconSize(QtCore.QSize(30, 30))
+ self.saveTemplateBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.saveTemplateBtn)
+ self.saveTemplateBtn.setToolTip("Save current setup as template")
+ self.saveTemplateBtn.clicked.connect(self.saveTemplate)
+ self.saveTemplateBtn.setObjectName("toolbar")
+
+ self.loadTemplateBtn = QtWidgets.QPushButton()
+ self.loadTemplateBtn.setMinimumSize(QtCore.QSize(30, 30))
+ self.loadTemplateBtn.setMaximumSize(QtCore.QSize(30, 30))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/load.png"))
+ self.loadTemplateBtn.setIconSize(QtCore.QSize(30, 30))
+ self.loadTemplateBtn.setIcon(icon)
+ self.toolbarLayout.addWidget(self.loadTemplateBtn)
+ self.loadTemplateBtn.setToolTip("Load an existing template file")
+ self.loadTemplateBtn.clicked.connect(self.loadTemplate)
+ self.loadTemplateBtn.setObjectName("toolbar")
+
+ # Add Items to the Menu Bar
+ # icons
+ icon_saveTemplate = QtGui.QIcon(os.path.join(self.iconsPath, "System/save.png"))
+ icon_loadTemplate = QtGui.QIcon(os.path.join(self.iconsPath, "System/load.png"))
+ icon_exit = QtGui.QIcon(os.path.join(self.iconsPath, "System/exit.png"))
+ icon_viewToolbar = QtGui.QIcon(os.path.join(self.iconsPath, "System/toggleVis.png"))
+ icon_globalMover = QtGui.QIcon(os.path.join(self.iconsPath, "System/globalMover.png"))
+ icon_offsetMover = QtGui.QIcon(os.path.join(self.iconsPath, "System/offsetMover.png"))
+ icon_meshMover = QtGui.QIcon(os.path.join(self.iconsPath, "System/meshMover.png"))
+ icon_boneDisplay = QtGui.QIcon(os.path.join(self.iconsPath, "System/boneDisplay.png"))
+ icon_lraDisplay = QtGui.QIcon(os.path.join(self.iconsPath, "System/lra.png"))
+ icon_proxyGeo = QtGui.QIcon(os.path.join(self.iconsPath, "System/geoDisplay.png"))
+ icon_massMirrorMode = QtGui.QIcon(os.path.join(self.iconsPath, "System/symmetryMode.png"))
+ icon_resetModules = QtGui.QIcon(os.path.join(self.iconsPath, "System/reset.png"))
+ icon_boneCount = QtGui.QIcon(os.path.join(self.iconsPath, "System/count.png"))
+
+ # file
+ fileMenu = self.menuBar.addMenu("File")
+ fileMenu.addAction(icon_saveTemplate, "Save Template", self.saveTemplate)
+ fileMenu.addAction(icon_loadTemplate, "Load Template", self.loadTemplate)
+ fileMenu.addAction(icon_exit, "Exit")
+
+ # view
+ viewMenu = self.menuBar.addMenu("View")
+ viewMenu.addAction(icon_viewToolbar, "Toggle Toolbar Visibility", self.setToolbarVisibility)
+ viewMenu.addAction(icon_viewToolbar, "View Module Stats", self.moduleStatusUI)
+
+ # display
+ displayMenu = self.menuBar.addMenu("Display")
+ displayMenu.addAction(icon_globalMover, "Toggle Global Movers",
+ partial(self.toggleMoverVisibility_FromMenu, "*_mover", self.globalMoverBtn,
+ "System/globalMover_on.png", "System/globalMover.png"))
+ displayMenu.addAction(icon_offsetMover, "Toggle Offset Movers",
+ partial(self.toggleMoverVisibility_FromMenu, "*_mover_offset", self.offsetMoverBtn,
+ "System/offsetMover_on.png", "System/offsetMover.png"))
+ displayMenu.addAction(icon_meshMover, "Toggle Mesh Movers",
+ partial(self.toggleMoverVisibility_FromMenu, "*_mover_geo", self.meshMoverBtn,
+ "System/meshMover_on.png", "System/meshMover.png"))
+ displayMenu.addAction(icon_boneDisplay, "Toggle Joint Display",
+ partial(self.toggleMoverVisibility_FromMenu, "*_bone_geo", self.boneDisplayBtn,
+ "System/boneDisplay_on.png", "System/boneDisplay.png"))
+ displayMenu.addAction(icon_lraDisplay, "Toggle LRA Display",
+ partial(self.toggleMoverVisibility_FromMenu, "*_lra", self.lraDisplayBtn,
+ "System/lra_on.png", "System/lra.png"))
+ displayMenu.addAction(icon_proxyGeo, "Toggle Proxy Geo Display",
+ partial(self.toggleMoverVisibility_FromMenu, "*_proxy_geo", self.geoDisplayBtn,
+ "System/geoDisplay_on.png", "System/geoDisplay.png"))
+
+ # tools
+ toolsMenu = self.menuBar.addMenu("Tools")
+ toolsMenu.addAction(icon_massMirrorMode, "Mass Mirror Mode Tool", self.symmetryModeUI)
+ toolsMenu.addAction(icon_resetModules, "Reset Modules Tool", self.resetModeUI)
+ toolsMenu.addAction(icon_boneCount, "Bone Counter Tool", self.boneCounterUI)
+
+ # help
+ helpMenu = self.menuBar.addMenu("Help")
+ helpMenu.addAction("Documentation")
+ helpMenu.addAction("About")
+
+ # create the tabLayout (Skeleton Creation and Settings/Outliner)
+
+ # tab stylesheet (tab stylesheet via QSS doesn't seem to work for some reason
+ stylesheet = """
+ QTabBar::tab
+ {
+ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90,90,90), stop:1 rgb(30,30,30));
+ border: 2px solid black;
+ width: 180px;
+ padding-left: -10px;
+ font: 8pt;
+ }
+ QTabBar::tab:selected
+ {
+ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(255,174,0), stop:1 rgb(30,30,30));
+ border: 2px solid black;
+ font: bold 10pt;
+ }
+ QTabBar::tab:hover
+ {
+ background: rgb(132,95,16);
+ font: bold 10pt;
+ }
+ QTabBar::tab:!selected
+ {
+ margin-top: 5px;
+ }
+ QTabWidget::pane
+ {
+ border: 2px solid rgb(0,0,0);
+ }
+ """
+
+ self.tabWidget = QtWidgets.QTabWidget()
+ self.mainLayout.addWidget(self.tabWidget)
+ self.tabWidget.setMinimumSize(QtCore.QSize(545, 400))
+ self.tabWidget.setMaximumSize(QtCore.QSize(545, 900))
+ self.tabWidget.setSizePolicy(scrollSizePolicy)
+ self.tabWidget.setStyleSheet(stylesheet)
+
+ # Create our first tab
+ self.tab1 = QtWidgets.QFrame()
+ self.tab1.setObjectName("dark")
+ self.topLevelLayout = QtWidgets.QVBoxLayout(self.tab1)
+ self.tabWidget.addTab(self.tab1, "Creation/Settings")
+
+ # create the label layout
+ self.labelLayout = QtWidgets.QHBoxLayout()
+ self.topLevelLayout.addLayout(self.labelLayout)
+
+ # create a label for Modules and Installed Modules
+ self.modLabel = QtWidgets.QLabel("Rig Modules:")
+ font = QtGui.QFont()
+ font.setPointSize(12)
+ self.modLabel.setFont(font)
+ self.modLabel.setFrameShape(QtWidgets.QFrame.WinPanel)
+ self.modLabel.setAlignment(QtCore.Qt.AlignCenter)
+ self.modLabel.setSizePolicy(mainSizePolicy)
+ self.modLabel.setMinimumSize(QtCore.QSize(150, 30))
+ self.modLabel.setMaximumSize(QtCore.QSize(150, 30))
+ self.modLabel.setStyleSheet(
+ 'color: qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 rgba(25, 175, 255, 255), stop:1 rgba(25, 175, 255, 255));background-color: rgb(60,60,60);')
+ self.labelLayout.addWidget(self.modLabel)
+
+ # create the installed modules label
+ self.installedModLabel = QtWidgets.QLabel("Installed Modules:")
+ font = QtGui.QFont()
+ font.setPointSize(12)
+ self.installedModLabel.setFont(font)
+ self.installedModLabel.setFrameShape(QtWidgets.QFrame.WinPanel)
+ self.installedModLabel.setAlignment(QtCore.Qt.AlignCenter)
+ self.installedModLabel.setSizePolicy(mainSizePolicy)
+ self.installedModLabel.setMinimumSize(QtCore.QSize(360, 30))
+ self.installedModLabel.setMaximumSize(QtCore.QSize(360, 30))
+ self.installedModLabel.setStyleSheet(
+ 'color: qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 rgba(25, 175, 255, 255), stop:1 rgba(25, 175, 255, 255));background-color: rgb(60,60,60);')
+ self.labelLayout.addWidget(self.installedModLabel)
+
+ # create the search layout
+ self.searchLayout = QtWidgets.QHBoxLayout()
+ self.topLevelLayout.addLayout(self.searchLayout)
+
+ # create the search bars for both sides
+ self.moduleSearch = QtWidgets.QLineEdit()
+ self.moduleSearch.setPlaceholderText("Search...")
+ self.moduleSearch.setMinimumSize(QtCore.QSize(150, 20))
+ self.moduleSearch.setMaximumSize(QtCore.QSize(150, 20))
+ self.moduleSearch.setSizePolicy(mainSizePolicy)
+ self.searchLayout.addWidget(self.moduleSearch)
+ self.moduleSearch.textChanged.connect(self.searchModules)
+
+ self.installedSearch = QtWidgets.QLineEdit()
+ self.installedSearch.setPlaceholderText("Search...")
+ self.installedSearch.setMinimumSize(QtCore.QSize(150, 20))
+ self.installedSearch.setMaximumSize(QtCore.QSize(150, 20))
+ self.installedSearch.setSizePolicy(mainSizePolicy)
+ self.searchLayout.addWidget(self.installedSearch)
+ self.installedSearch.textChanged.connect(self.searchInstalled)
+
+ # add buttons (expand all, collapse all, sort by type, sort by ABC)
+ self.installed_ExpandAll = QtWidgets.QPushButton()
+ self.installed_ExpandAll.setSizePolicy(
+ QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.installed_ExpandAll.setMinimumSize(QtCore.QSize(40, 20))
+ self.installed_ExpandAll.setMaximumSize(QtCore.QSize(40, 20))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/expand_all.png"))
+ self.installed_ExpandAll.setIcon(icon)
+ self.installed_ExpandAll.setIconSize(QtCore.QSize(40, 20))
+ self.installed_ExpandAll.setToolTip("Expand all module settings")
+ self.searchLayout.addWidget(self.installed_ExpandAll)
+ self.installed_ExpandAll.clicked.connect(partial(self.expandAllSettings, True))
+ self.installed_ExpandAll.setObjectName("toolbar")
+
+ self.installed_CollapseAll = QtWidgets.QPushButton()
+ self.installed_CollapseAll.setSizePolicy(
+ QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.installed_CollapseAll.setMinimumSize(QtCore.QSize(40, 20))
+ self.installed_CollapseAll.setMaximumSize(QtCore.QSize(40, 20))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/collapse_all.png"))
+ self.installed_CollapseAll.setIcon(icon)
+ self.installed_CollapseAll.setIconSize(QtCore.QSize(40, 20))
+ self.installed_CollapseAll.setToolTip("Collapse all module settings")
+ self.searchLayout.addWidget(self.installed_CollapseAll)
+ self.installed_CollapseAll.clicked.connect(partial(self.expandAllSettings, False))
+ self.installed_CollapseAll.setObjectName("toolbar")
+
+ self.installed_sortByType = QtWidgets.QPushButton()
+ self.installed_sortByType.setSizePolicy(
+ QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.installed_sortByType.setMinimumSize(QtCore.QSize(40, 20))
+ self.installed_sortByType.setMaximumSize(QtCore.QSize(40, 20))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/sortByType.png"))
+ self.installed_sortByType.setIcon(icon)
+ self.installed_sortByType.setIconSize(QtCore.QSize(40, 20))
+ self.installed_sortByType.setToolTip("Sort modules by module type")
+ self.searchLayout.addWidget(self.installed_sortByType)
+ self.installed_sortByType.clicked.connect(partial(self.sortModules, "type"))
+ self.installed_sortByType.setObjectName("toolbar")
+
+ self.installed_sortByAlphabet = QtWidgets.QPushButton()
+ self.installed_sortByAlphabet.setSizePolicy(
+ QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.installed_sortByAlphabet.setMinimumSize(QtCore.QSize(40, 20))
+ self.installed_sortByAlphabet.setMaximumSize(QtCore.QSize(40, 20))
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, "System/sortByAlphabet.png"))
+ self.installed_sortByAlphabet.setIcon(icon)
+ self.installed_sortByAlphabet.setIconSize(QtCore.QSize(40, 20))
+ self.installed_sortByAlphabet.setToolTip("Sort modules by module alphabetical order")
+ self.searchLayout.addWidget(self.installed_sortByAlphabet)
+ self.installed_sortByAlphabet.clicked.connect(partial(self.sortModules, "abc"))
+ self.installed_sortByAlphabet.setObjectName("toolbar")
+
+ # create the layout for the main part of our UI
+ self.main = QtWidgets.QHBoxLayout()
+ self.topLevelLayout.addLayout(self.main)
+
+ # create the module scroll area and add it to the main layout
+ self.scrollAreaMods = QtWidgets.QScrollArea()
+ self.scrollAreaMods.setObjectName("epic")
+ self.main.addWidget(self.scrollAreaMods)
+ self.scrollAreaMods.setSizePolicy(mainSizePolicy)
+ self.scrollAreaMods.setMinimumSize(QtCore.QSize(150, 400))
+ self.scrollAreaMods.setMaximumSize(QtCore.QSize(150, 60000))
+ self.scrollAreaMods.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+
+ # Module scroll area contents
+ self.modScrollAreaContents = QtWidgets.QFrame()
+ self.modScrollAreaContents.setObjectName("epic")
+ self.modScrollAreaContents.setSizePolicy(scrollSizePolicy)
+ self.modScrollAreaContents.setMinimumSize(QtCore.QSize(150, 800))
+ self.modScrollAreaContents.setMaximumSize(QtCore.QSize(150, 60000))
+ self.scrollAreaMods.setWidget(self.modScrollAreaContents)
+
+ # add the vertical box layout for the module scroll area
+ self.moduleLayout = QtWidgets.QVBoxLayout(self.modScrollAreaContents)
+ self.moduleLayout.setDirection(QtWidgets.QBoxLayout.BottomToTop)
+ self.moduleLayout.setContentsMargins(5, 5, 0, 5)
+ self.moduleLayout.addStretch(2)
+ self.moduleLayout.setSpacing(5)
+
+ # create the scroll area for the module settings
+ self.scrollAreaSettings = QtWidgets.QScrollArea()
+ self.scrollAreaSettings.setObjectName("epic")
+ self.scrollAreaSettings.setWidgetResizable(True)
+ self.main.addWidget(self.scrollAreaSettings)
+ self.scrollAreaSettings.setSizePolicy(scrollSizePolicy)
+ self.scrollAreaSettings.setMinimumSize(QtCore.QSize(360, 400))
+ self.scrollAreaSettings.setMaximumSize(QtCore.QSize(360, 600000))
+ self.scrollAreaSettings.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+
+ # create the module settings scroll area contents widget
+ self.settingsScrollAreaContents = QtWidgets.QFrame()
+ self.settingsScrollAreaContents.setObjectName("dark")
+ self.settingsScrollAreaContents.setMinimumWidth(360)
+ self.settingsScrollAreaContents.setMaximumWidth(360)
+ self.settingsScrollAreaContents.setSizePolicy(scrollSizePolicy)
+ self.scrollAreaSettings.setWidget(self.settingsScrollAreaContents)
+
+ # add the vertical box layout for the module scroll area
+ self.moduleSettingsLayout = QtWidgets.QVBoxLayout(self.settingsScrollAreaContents)
+ self.moduleSettingsLayout.setDirection(QtWidgets.QBoxLayout.BottomToTop)
+ self.moduleSettingsLayout.setContentsMargins(0, 5, 0, 5)
+ self.moduleSettingsLayout.addStretch(2)
+ self.moduleSettingsLayout.setSpacing(10)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # SECOND TAB #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # Create the 2nd tab
+ self.tab2 = QtWidgets.QFrame(self.tabWidget)
+ self.tab2.setObjectName("mid")
+ self.tab2Layout = QtWidgets.QHBoxLayout(self.tab2)
+ self.tabWidget.addTab(self.tab2, "Outliner")
+
+ # create the treeView representing the outliner
+ self.treeWidget = QtWidgets.QTreeWidget()
+ self.treeWidget.setIndentation(10)
+ self.treeWidget.expandAll()
+
+ self.tab2Layout.addWidget(self.treeWidget)
+ self.treeWidget.setSizePolicy(mainSizePolicy)
+ self.treeWidget.setMinimumSize(QtCore.QSize(320, 500))
+ self.treeWidget.setMaximumSize(QtCore.QSize(320, 800))
+
+ # create columns
+ self.treeWidget.headerItem().setText(0, "Modules")
+ self.treeWidget.headerItem().setText(1, "G")
+ self.treeWidget.headerItem().setText(2, "O")
+ self.treeWidget.headerItem().setText(3, "M")
+
+ # set column widths
+ self.treeWidget.setColumnWidth(0, 240)
+ self.treeWidget.setColumnWidth(1, 20)
+ self.treeWidget.setColumnWidth(2, 20)
+ self.treeWidget.setColumnWidth(3, 20)
+ self.treeWidget.setObjectName("light")
+ self.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # CHANNEL BOX #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # add the channel box layout
+ self.channelBoxLayout = QtWidgets.QFrame()
+ self.channelBoxLayout.setObjectName("mid")
+
+ # set dimensions
+ self.channelBoxLayout.setSizePolicy(scrollSizePolicy)
+ self.channelBoxLayout.setGeometry(0, 0, 250, 500)
+ self.channelBoxLayout.setMinimumSize(QtCore.QSize(220, 500))
+ self.channelBoxLayout.setMaximumSize(QtCore.QSize(220, 800))
+ self.tab2Layout.addWidget(self.channelBoxLayout)
+
+ # create a VBoxLayout for the channelBox Layout
+ self.channelBoxVLayout = QtWidgets.QVBoxLayout(self.channelBoxLayout)
+
+ # create the QWidget to house the channelBox
+ self.channelBoxWidget = QtWidgets.QFrame()
+ self.channelBoxWidget.setObjectName("mid")
+
+ # set dimensions
+ self.channelBoxWidget.setSizePolicy(mainSizePolicy)
+ self.channelBoxWidget.setMinimumSize(QtCore.QSize(220, 470))
+ self.channelBoxWidget.setMaximumSize(QtCore.QSize(220, 770))
+
+ # add the channel box widget to the VBoxLayout
+ self.channelBoxVLayout.addWidget(self.channelBoxWidget)
+
+ # add the channel box VBoxLayout to the QFrame
+ self.channelBox_mainLayout = QtWidgets.QVBoxLayout(self.channelBoxWidget)
+
+ # add the channel box from Maya to the UI
+ channelBoxWidget = cmds.channelBox()
+ pointer = mui.MQtUtil.findControl(channelBoxWidget)
+ self.channelBox = shiboken.wrapInstance(long(pointer), QtWidgets.QWidget)
+ self.channelBox_mainLayout.addWidget(self.channelBox)
+ self.channelBox.setObjectName("dark")
+ self.channelBox.show()
+
+ # add network node info
+ self.nodeNetworkList = QtWidgets.QListWidget()
+ self.channelBox_mainLayout.addWidget(self.nodeNetworkList)
+ self.nodeNetworkList.setMinimumHeight(200)
+ self.nodeNetworkList.setMaximumHeight(200)
+ self.nodeNetworkList.itemClicked.connect(self.selectNetworkNode)
+
+ # add the "Finalize Setup" button
+ self.createSkeletonLayout = QtWidgets.QHBoxLayout()
+ self.createSkeletonLayout.setContentsMargins(25, 0, 0, 0)
+ self.createSkeletonBtn = QtWidgets.QPushButton("FINALIZE SETUP")
+ self.createSkeletonBtn.setObjectName("blueButtonSpecial")
+ self.createSkeletonBtn.setMinimumHeight(50)
+ self.createSkeletonBtn.setMaximumHeight(50)
+
+ self.createSkeletonBtn.clicked.connect(self.finalizeSetup_UI)
+ self.createSkeletonLayout.addWidget(self.createSkeletonBtn)
+ self.mainLayout.addLayout(self.createSkeletonLayout)
+
+ # build deformation UI
+ self.buildDeformation_UI()
+
+ # set the layout
+ self.setLayout(self.mainLayout)
+
+ # find and populate modules list
+ self.findRigModules()
+
+ # build lock page
+ self.rigLockedPage = QtWidgets.QFrame()
+ self.toolModeStack.addWidget(self.rigLockedPage)
+
+ self.rigLockedPage.setMinimumSize(QtCore.QSize(550, 500))
+ self.rigLockedPage.setMaximumSize(QtCore.QSize(550, 800))
+ image = utils.returnNicePath(self.iconsPath, "System/rigLockPage.png")
+ self.rigLockedPage.setStyleSheet("background-image: url(" + image + ");")
+
+ # add the layout to the lock page
+ self.lockLayout = QtWidgets.QVBoxLayout(self.rigLockedPage)
+ self.lockLayout.setContentsMargins(70, 500, 70, 160)
+
+ buttonLayout1 = QtWidgets.QHBoxLayout()
+ self.lockLayout.addLayout(buttonLayout1)
+
+ buttonLayout2 = QtWidgets.QHBoxLayout()
+ self.lockLayout.addLayout(buttonLayout2)
+
+ # add spacer and button
+ self.unlockBtn = QtWidgets.QPushButton("Remove Rig")
+ self.unlockBtn.clicked.connect(partial(self.removeRigging))
+ buttonLayout1.addWidget(self.unlockBtn)
+ self.unlockBtn.setMinimumSize(200, 40)
+ self.unlockBtn.setMaximumSize(200, 40)
+ self.unlockBtn.setFont(font)
+ self.unlockBtn.setStyleSheet(self.style)
+ self.unlockBtn.setObjectName("blueButton")
+
+ self.skinToolsBtn = QtWidgets.QPushButton("Deformation Toolkit")
+ self.skinToolsBtn.clicked.connect(partial(self.deformationTools))
+ buttonLayout2.addWidget(self.skinToolsBtn)
+ self.skinToolsBtn.setMinimumSize(200, 40)
+ self.skinToolsBtn.setMaximumSize(200, 40)
+ self.skinToolsBtn.setStyleSheet(self.style)
+ self.skinToolsBtn.setObjectName("blueButton")
+
+ self.exportMeshesBtn = QtWidgets.QPushButton("Export Skeletal Meshes")
+ self.exportMeshesBtn.clicked.connect(partial(self.exportMeshes))
+ buttonLayout2.addWidget(self.exportMeshesBtn)
+ self.exportMeshesBtn.setMinimumSize(200, 40)
+ self.exportMeshesBtn.setMaximumSize(200, 40)
+ self.exportMeshesBtn.setStyleSheet(self.style)
+ self.exportMeshesBtn.setObjectName("blueButton")
+
+ self.rigHistBtn = QtWidgets.QPushButton("Rig History")
+ self.rigHistBtn.clicked.connect(partial(self.rigHistoryUI))
+ buttonLayout1.addWidget(self.rigHistBtn)
+ self.rigHistBtn.setMinimumSize(200, 40)
+ self.rigHistBtn.setMaximumSize(200, 40)
+ self.rigHistBtn.setStyleSheet(self.style)
+ self.rigHistBtn.setObjectName("blueButton")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def setToolbarVisibility(self):
+ # Original Author: Jeremy Ernst
+ state = self.toolFrame.isVisible()
+ if state == True:
+ self.toolFrame.setVisible(False)
+ if state == False:
+ self.toolFrame.setVisible(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def setMoverVisibility(self):
+ # Original Author: Jeremy Ernst
+
+ movers = [["*_proxy_geo", self.geoDisplayBtn], ["*_lra", self.lraDisplayBtn],
+ ["*_bone_geo", self.boneDisplayBtn], ["*_mover_geo", self.meshMoverBtn],
+ ["*_mover_offset", self.offsetMoverBtn], ["*_mover", self.globalMoverBtn]]
+ for mover in movers:
+ self.toggleMoverVisibility(mover[0], mover[1])
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def sortModules(self, sortMethod):
+ # Original Author: Jeremy Ernst
+
+ modules = utils.returnRigModules()
+ modTypes = []
+ modNames = []
+ # get the module's type and name
+ for module in modules:
+ modType = cmds.getAttr(module + ".moduleType")
+ modName = cmds.getAttr(module + ".moduleName")
+ modTypes.append([modName, modType])
+ modNames.append(str(modName))
+
+ if sortMethod == "abc":
+ # create a sorted list of that info
+ modNames = sorted(modNames, key=str.lower)
+
+ # create a list of the groupbox widgets sorted by alphabetical order
+ groupBoxes = []
+ for i in range(self.moduleSettingsLayout.count()):
+ try:
+ groupBoxes.append([self.moduleSettingsLayout.itemAt(i).widget().title(),
+ self.moduleSettingsLayout.itemAt(i).widget()])
+ except:
+ pass
+
+ # re-sort the groupboxes in the layout
+ for each in modNames:
+ for box in groupBoxes:
+ if box[0] == each:
+ self.moduleSettingsLayout.insertWidget(1, box[1])
+ self.moduleSettingsLayout.setDirection(QtWidgets.QBoxLayout.BottomToTop)
+
+ if sortMethod == "type":
+ # create a sorted list of that info
+ sortedList = sorted(modTypes, key=lambda name: name[1])
+
+ # create a list of the groupbox widgets sorted by module type
+ groupBoxes = []
+ for i in range(self.moduleSettingsLayout.count()):
+ try:
+ groupBoxes.append([self.moduleSettingsLayout.itemAt(i).widget().title(),
+ self.moduleSettingsLayout.itemAt(i).widget()])
+ except:
+ pass
+ # compare the sorted list to the list of groupboxes and make a new list that has those groupboxes in the same order as the sorted list
+ newList = []
+ for item in sortedList:
+ name = item[0]
+ for box in groupBoxes:
+ title = box[0]
+ if title == name:
+ newList.append(box)
+
+ # re-sort the groupboxes in the layout
+ for i in range(len(newList)):
+ self.moduleSettingsLayout.insertWidget(1, newList[i][1])
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def expandAllSettings(self, doExpand):
+ # Original Author: Jeremy Ernst
+
+ modules = utils.returnRigModules()
+
+ for module in modules:
+ modType = cmds.getAttr(module + ".moduleType")
+ modName = cmds.getAttr(module + ".moduleName")
+ mod = __import__("RigModules." + modType, {}, {}, [modType])
+
+ # get the class name from that module file (returns Modules.ART_Root.ART_Root for example)
+ moduleClass = getattr(mod, mod.className)
+
+ # find the instance of that module and call on the skeletonSettings_UI function
+ moduleInst = moduleClass(self, modName)
+
+ if modType != "ART_Root":
+ for i in range(self.moduleSettingsLayout.count()):
+ if type(self.moduleSettingsLayout.itemAt(i).widget()) == QtWidgets.QGroupBox:
+ if self.moduleSettingsLayout.itemAt(i).widget().title() == modName:
+ self.moduleSettingsLayout.itemAt(i).widget().setChecked(doExpand)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def addModule(self, baseName, className):
+ # Original Author: Jeremy Ernst
+
+ # This function gets called when a module button is pushed. It will grab some information from the user and then add the network node, jointMover, and skelSettingsUI
+
+ # delete the UI if it already exists
+ mayaWindow = interfaceUtils.getMainWindow()
+ mayaWindow = mayaWindow.objectName()
+ if cmds.window(mayaWindow + "|pyArtAddModuleUi", q=True, exists=True):
+ cmds.deleteUI(mayaWindow + "|pyArtAddModuleUi")
+
+ # run the user interface to gather information
+ import ART_AddModuleUI as ART_AddModuleUI
+ reload(ART_AddModuleUI)
+ inst = ART_AddModuleUI.ART_AddModule_UI(baseName, className, self, interfaceUtils.getMainWindow())
+ inst.show()
+
+ return True
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleButtonIcon(self, button, onIcon, offIcon):
+ # Original Author: Jeremy Ernst
+
+ state = button.isChecked()
+
+ if state:
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, onIcon))
+ else:
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, offIcon))
+
+ button.setIcon(icon)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleMoverVisibility_FromMenu(self, searchKey, button, onIcon, offIcon):
+ # Original Author: Jeremy Ernst
+
+ state = button.isChecked()
+ if state:
+ button.setChecked(False)
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, offIcon))
+ button.setIcon(icon)
+
+ else:
+ button.setChecked(True)
+ icon = QtGui.QIcon(os.path.join(self.iconsPath, onIcon))
+ button.setIcon(icon)
+
+ self.toggleMoverVisibility(searchKey, button)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleMoverVisibility(self, searchKey, button):
+ # Original Author: Jeremy Ernst
+
+ try:
+ currentSelection = cmds.ls(sl=True)
+ # get current checkbox state
+ state = button.isChecked()
+
+ # get the list of movers
+ cmds.select(searchKey)
+ movers = cmds.ls(sl=True)
+
+ # find the mover shapes and set their visibility
+ shapes = []
+ for mover in movers:
+ child = cmds.listRelatives(mover, children=True, shapes=True)
+ if len(child) > 0:
+ shapes.append(mover + "|" + child[0])
+
+ for shape in shapes:
+ cmds.setAttr(shape + ".v", lock=False)
+ cmds.setAttr(shape + ".v", state, lock=True)
+
+ try:
+ cmds.select(currentSelection)
+ except:
+ pass
+
+ except:
+ pass
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def saveTemplate(self):
+ # Original Author: Jeremy Ernst
+
+ # find all modules in the scene
+ if cmds.objExists("ART_RIG_ROOT"):
+ modules = cmds.listConnections("ART_RIG_ROOT.rigModules")
+
+ # start creating the data list
+ data = []
+
+ # loop through each module, getting the required information
+ for module in modules:
+ moduleData = [str(module)]
+
+ # get the module attributes and their values
+ attrData = []
+ attrs = cmds.listAttr(module, ud=True, hd=True)
+ for attr in attrs:
+ value = cmds.getAttr(module + "." + attr)
+ attrData.append([str(attr), value])
+
+ # add the attrData to the moduleData
+ moduleData.append(attrData)
+
+ # get all movers and thier keyable values
+ moduleName = cmds.getAttr(module + ".moduleName")
+ moverTypes = ["_mover", "_mover_offset", "_mover_geo"]
+ allMoverData = []
+
+ for moverType in moverTypes:
+ try:
+ cmds.select(moduleName + "*" + moverType)
+ movers = cmds.ls(sl=True)
+ validMovers = []
+
+ # validate selection
+ for mover in movers:
+ moverGrp = moduleName + "_mover_grp"
+ validMovers.append(moverGrp)
+ children = cmds.listRelatives(moverGrp, ad=True)
+ if mover in children:
+ validMovers.append(str(mover))
+
+ # get mover values
+ for mover in validMovers:
+ moverData = []
+ attrs = cmds.listAttr(mover, keyable=True)
+
+ for attr in attrs:
+ value = cmds.getAttr(mover + "." + attr)
+ moverData.append([str(mover + "." + attr), value])
+ allMoverData.append(moverData)
+
+ except:
+ pass
+
+ # add all of the mover data to the moduleData list
+ moduleData.append(allMoverData)
+
+ # add the moduleData to data
+ data.append(moduleData)
+
+ # ask for the file name to give the template
+ startingDir = os.path.normcase(os.path.join(self.toolsPath, "Core/JointMover/Templates"))
+ if not os.path.exists(startingDir):
+ os.makedirs(startingDir)
+
+ filename = cmds.fileDialog2(fm=0, okc="Save Template", dir=startingDir, ff="*.template")[0]
+
+ # create the template file
+ f = open(filename, 'w')
+
+ # dump the data with json
+ json.dump(data, f)
+ f.close()
+
+ # print out confirmation
+ print "Template has been saved"
+ # inViewMessage only available in 2014 and up
+ try:
+ cmds.inViewMessage(amg=' <hl>Template has been saved.</hl>', pos='topCenter', fade=True)
+ except:
+ print "inViewMessage not supported"
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def loadTemplate(self):
+ # Original Author: Jeremy Ernst
+
+ # make sure scene is new, and refresh UI
+ if self.moduleSettingsLayout.count() > 2:
+ self.unsavedChanges()
+ return
+
+ # prompt for the file to load
+ startingDir = os.path.normcase(os.path.join(self.toolsPath, "Core/JointMover/Templates"))
+ if not os.path.exists:
+ startingDir = self.toolsPath
+ try:
+ filename = cmds.fileDialog2(fm=1, okc="Load Template", dir=startingDir, ff="*.template")[0]
+ except:
+ return
+
+ if filename is not None:
+
+ self.moduleInstances = []
+
+ # load the data
+ json_file = open(filename)
+ data = json.load(json_file)
+ json_file.close()
+
+ # clear out the scene of any network nodes, joint movers and relaunch the UI
+ modules = cmds.listConnections("ART_RIG_ROOT.rigModules")
+ modules.append("ART_RIG_ROOT")
+ cmds.delete(modules)
+
+ if cmds.objExists("JointMover"):
+ cmds.delete("JointMover")
+
+ for material in ["blue_m", "green_m", "red_m", "white_m"]:
+ if cmds.objExists(material):
+ cmds.delete(material)
+
+ # relaunch the UI
+ newUI = createUI()
+
+ # create a progress window
+ progWindow = cmds.progressWindow(title='Loading Template', progress=0)
+ amount = (100 / len(data)) / 5
+
+ # go through the template data, adding the modules, the settings UI, and the joint mover
+ solveLast = []
+ for each in data:
+ currentAmount = cmds.progressWindow(query=True, progress=True)
+ cmds.progressWindow(edit=True, progress=currentAmount + amount, status="Working on " + each[0])
+
+ module = each[0]
+ if module is not None:
+ moduleAttrData = each[1]
+ for attr in moduleAttrData:
+ if attr[0] == "moduleName":
+ moduleName = attr[1]
+ if attr[0] == "moduleType":
+ moduleClass = str(attr[1])
+ moduleType = str(attr[1])
+
+ # build the network node for the module
+ if module != "ART_Root_Module":
+ mod = __import__("RigModules." + moduleClass, {}, {}, [moduleClass])
+ moduleClass = getattr(mod, mod.className)
+ jmPath = mod.jointMover
+ moduleInst = moduleClass(newUI, moduleName)
+ networkNode = moduleInst.buildNetwork()
+
+ # set the attributes on the network node
+ for moduleAttr in moduleAttrData:
+ attr = moduleAttr[0]
+ value = moduleAttr[1]
+
+ try:
+ attrType = str(cmds.getAttr(networkNode + "." + attr, type=True))
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ if attrType == "string":
+ cmds.setAttr(networkNode + "." + attr, value, type=attrType, lock=True)
+ else:
+ cmds.setAttr(networkNode + "." + attr, value, lock=True)
+
+ except:
+ print attr, value, attrType
+
+ # arm/leg exceptions
+ specialCaseModules = ["ART_Leg_Standard", "ART_Arm_Standard"]
+ if moduleType in specialCaseModules:
+ side = cmds.getAttr(networkNode + ".side")
+ jmPath = jmPath.partition(".ma")[0] + "_" + side + ".ma"
+
+ # torso exception
+ if moduleType == "ART_Torso":
+ numSpine = int(cmds.getAttr(networkNode + ".spineJoints"))
+ jmPath = jmPath.partition(".ma")[0].rpartition("_")[0] + "_" + str(numSpine) + "Spine.ma"
+
+ # head exception
+ if moduleType == "ART_Head":
+ numNeck = int(cmds.getAttr(networkNode + ".neckJoints"))
+ jmPath = jmPath.partition(".ma")[0].rpartition("_")[0] + "_" + str(numNeck) + "Neck.ma"
+
+ # build settings UI/build JM/Add to Outliner
+ currentAmount = cmds.progressWindow(query=True, progress=True)
+ cmds.progressWindow(edit=True, progress=currentAmount + amount)
+
+ moduleInst.skeletonSettings_UI(moduleName)
+ moduleInst.jointMover_Build(jmPath)
+ moduleInst.addJointMoverToOutliner()
+ moduleInst.applyModuleChanges(moduleInst)
+
+ # copy, reset, and paste settings to update the UI/scene one last time
+ # this was initially put in to get leaf module proxy shape/control shape to actually load in
+ # properly without this, the settings would be correct, but the scene would not update, since
+ # the combo boxes had not been hooked up yet
+ skipModules = ["ART_Torso", "ART_Head"]
+ if moduleType not in skipModules:
+ moduleInst.copySettings()
+ moduleInst.resetSettings()
+ moduleInst.pasteSettings()
+ self.moduleInstances.append(moduleInst)
+
+ # position the movers according to the template
+ currentAmount = cmds.progressWindow(query=True, progress=True)
+ cmds.progressWindow(edit=True, progress=currentAmount + amount)
+
+ # Apply the positional data
+ movers = each[2]
+ for mover in movers:
+ for each in mover:
+
+ moduleAttr = each[0]
+ attrValue = each[1]
+
+ try:
+ cmds.setAttr(moduleAttr, attrValue)
+ except:
+ pass
+
+ # bake offsets
+ moduleInst.bakeOffsets()
+
+ # hook up mover to parent
+ currentAmount = cmds.progressWindow(query=True, progress=True)
+ cmds.progressWindow(edit=True, progress=currentAmount + amount)
+
+ parent = ""
+ for attr in moduleAttrData:
+ if attr[0] == "parentModuleBone":
+ parent = attr[1]
+
+ mover = ""
+ if parent == "root":
+ mover = "root_mover"
+ offsetMover = "root_mover"
+
+ else:
+ # find the parent mover name to parent to
+ networkNodes = utils.returnRigModules()
+ mover = utils.findMoverNodeFromJointName(networkNodes, parent, False, True)
+ offsetMover = utils.findMoverNodeFromJointName(networkNodes, parent)
+
+ if mover is not None:
+ cmds.parentConstraint(mover, moduleName + "_mover_grp", mo = True)
+ cmds.scaleConstraint(mover, moduleName + "_mover_grp", mo = True)
+
+ # create the connection geo between the two
+ currentAmount = cmds.progressWindow(query=True, progress=True)
+ cmds.progressWindow(edit=True, progress=currentAmount + amount)
+
+ childMover = utils.findOffsetMoverFromName(moduleName)
+ riggingUtils.createBoneConnection(offsetMover, childMover, moduleName)
+
+ globalMover = utils.findGlobalMoverFromName(moduleName)
+ cmds.select(globalMover)
+ cmds.setToolTo("moveSuperContext")
+
+ utils.fitViewAndShade()
+
+ else:
+ solveLast.append(each)
+
+ # solve root mover last
+ for each in solveLast:
+ # position the movers according to the template
+ currentAmount = cmds.progressWindow(query=True, progress=True)
+ cmds.progressWindow(edit=True, progress=currentAmount + amount)
+
+ movers = each[2]
+ for mover in movers:
+ for eachMover in mover:
+
+ moduleAttr = eachMover[0]
+ attrValue = eachMover[1]
+
+ try:
+ cmds.setAttr(moduleAttr, attrValue)
+ except:
+ pass
+
+ cmds.progressWindow(endProgress=1)
+ createUI()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def findRigModules(self):
+ # Original Author: Jeremy Ernst
+
+ # get rig module files
+ modulesLocation = os.path.normcase(os.path.join(self.toolsPath, "Core/Scripts/RigModules"))
+ files = os.listdir(modulesLocation)
+ modules = []
+
+ for f in files:
+ if f.rpartition(".")[2] == "py":
+ modules.append(f)
+
+ for mod in modules:
+ niceName = mod.rpartition(".")[0]
+ if niceName != "__init__" and niceName != "ART_Root":
+ # create the push button for the module and set the size
+ button = QtWidgets.QPushButton()
+ button.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ button.setMinimumSize(QtCore.QSize(125, 75))
+ button.setMaximumSize(QtCore.QSize(125, 75))
+
+ # get the icon path from the module and add the icon to the push button
+ module = __import__("RigModules." + niceName, {}, {}, [niceName])
+ reload(module)
+ icon = module.icon
+ hoverIcon = module.hoverIcon
+
+ searchTerm = module.search
+ className = module.className
+ baseName = module.baseName
+ iconFile = utils.returnFriendlyPath(os.path.join(self.iconsPath, icon))
+ hoverIcon = utils.returnFriendlyPath(os.path.join(self.iconsPath, hoverIcon))
+
+ # create stylesheet
+ style = """
+
+ QPushButton
+ {
+ background-image: url(iconfilepath);
+ }
+
+
+ QPushButton:hover
+ {
+ background-image: url(hoverfilepath);
+ margin-top: -2px;
+ }
+
+ """
+
+ buttonStyle = style.replace("iconfilepath", iconFile)
+ buttonStyle = buttonStyle.replace("hoverfilepath", hoverIcon)
+
+ # set properties for filtering later
+ button.setObjectName(searchTerm)
+ button.setProperty("name", searchTerm)
+ button.setStyleSheet(buttonStyle)
+ self.moduleLayout.addWidget(button)
+
+ # setup signal
+ button.clicked.connect(partial(self.addModule, baseName, className))
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def searchModules(self):
+ # Original Author: Jeremy Ernst
+
+ searchText = self.moduleSearch.text()
+
+ for i in range(self.moduleLayout.count()):
+ if type(self.moduleLayout.itemAt(i).widget()) == QtWidgets.QPushButton:
+ self.moduleLayout.itemAt(i).widget().setVisible(False)
+ moduleType = self.moduleLayout.itemAt(i).widget().property("name")
+ searchKeys = moduleType.split(":")
+
+ for key in searchKeys:
+ if key.find(searchText) != -1:
+ self.moduleLayout.itemAt(i).widget().setVisible(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def searchInstalled(self):
+ # Original Author: Jeremy Ernst
+
+ searchText = self.installedSearch.text()
+
+ for i in range(self.moduleSettingsLayout.count()):
+ if type(self.moduleSettingsLayout.itemAt(i).widget()) == QtWidgets.QGroupBox:
+ self.moduleSettingsLayout.itemAt(i).widget().setVisible(False)
+ title = self.moduleSettingsLayout.itemAt(i).widget().title()
+
+ if title.find(searchText) != -1:
+ self.moduleSettingsLayout.itemAt(i).widget().setVisible(True)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def editSetup(self):
+ # Original Author: Jeremy Ernst
+
+ # set model pose if exists
+ for inst in self.moduleInstances:
+ networkNode = inst.returnNetworkNode
+ if cmds.objExists(networkNode + ".modelPose"):
+ inst.setReferencePose("modelPose")
+
+ # remove weight table script job
+ cmds.scriptJob(kill=self.skinToolsInst.wtScriptJob)
+
+ # show index 0 of stacked widget
+ self.toolModeStack.setCurrentIndex(0)
+
+ # change state in network node
+ cmds.setAttr("ART_RIG_ROOT.state", 0)
+
+ # find meshes that are weighted
+ weightedMeshes = []
+ skinClusters = cmds.ls(type='skinCluster')
+
+ for cluster in skinClusters:
+ geometry = cmds.skinCluster(cluster, q=True, g=True)[0]
+ geoTransform = cmds.listRelatives(geometry, parent=True)[0]
+ if geoTransform.find("proxy_geo") == -1:
+ weightedMeshes.append([geoTransform, cluster])
+
+ # save out weights of meshes
+ for mesh in weightedMeshes:
+ filePath = utils.returnFriendlyPath(os.path.join(cmds.internalVar(utd=True), mesh[0] + ".WEIGHTS"))
+ print "saving out skin weights for " + mesh[0] + " at: " + filePath
+
+ # export skin weights
+ skin = riggingUtils.export_skin_weights(filePath, mesh[0])
+
+ # delete history of meshes
+ cmds.delete(mesh[0], ch=True)
+
+ # delete skeleton
+ cmds.delete("root")
+
+ # delete proxy geo grp if it exists
+ if cmds.objExists("skinned_proxy_geo"):
+ cmds.delete("skinned_proxy_geo")
+
+ # unhide/lock joint mover
+ cmds.select("JointMover", hi=True)
+ jmNodes = cmds.ls(sl=True)
+ for node in jmNodes:
+ cmds.lockNode(node, lock=False)
+
+ lockNodes = cmds.listRelatives("JointMover", children=True)
+ for node in lockNodes:
+ cmds.setAttr(node + ".v", lock=False)
+ cmds.setAttr(node + ".v", 1)
+
+ # clear selection
+ cmds.select(clear=True)
+
+ # recreate outliner scriptjobs
+ self.scriptJobs = []
+ for module in self.moduleInstances:
+ module.createScriptJob()
+
+
+ ##############################################################################################################
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # EXTERNAL FILE CALLS
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ ##############################################################################################################
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def buildDeformation_UI(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_SkinTools
+ reload(ART_SkinTools)
+ self.skinToolsInst = ART_SkinTools.ART_SkinTools(self, True, self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def deformationTools(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_SkinTools
+ reload(ART_SkinTools)
+ self.skinToolsInst = ART_SkinTools.ART_SkinTools(self, False, interfaceUtils.getMainWindow())
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def aimModeUI(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_AimModeUI
+ reload(ART_AimModeUI)
+ ART_AimModeUI.ART_AimMode(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pinModulesUI(self):
+ # Original Author: Jeremy Ernst
+ import ART_PinModules
+ reload(ART_PinModules)
+ ART_PinModules.ART_PinModules(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def bakeOffsetsUI(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_BakeOffsetsUI
+ reload(ART_BakeOffsetsUI)
+ ART_BakeOffsetsUI.ART_BakeOffsets(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def boneCounterUI(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_BoneCounter
+ reload(ART_BoneCounter)
+ inst = ART_BoneCounter.ART_BoneCounter(self)
+ self.boneCounterInst = inst
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def resetModeUI(self):
+
+ import ART_ResetModeUI
+ reload(ART_ResetModeUI)
+ ART_ResetModeUI.ART_ResetMode(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def symmetryModeUI(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_SymmetryModeUI
+ reload(ART_SymmetryModeUI)
+ ART_SymmetryModeUI.ART_SymmetryMode(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def finalizeSetup_UI(self):
+ # Original Author: Jeremy Ernst
+
+ import ART_FinalizeSetup
+ reload(ART_FinalizeSetup)
+ ART_FinalizeSetup.ART_FinalizeSetup(self, self.skinToolsInst)
+ # need to also pass in deformation ui instance
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRig(self):
+ # Original Author: Jeremy Ernst
+
+ # run publish process
+ import ART_Publish
+ reload(ART_Publish)
+ ART_Publish.ART_Publish(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def removeRigging(self):
+ # Original Author: Jeremy Ernst
+
+ # reset scale if needed
+ if cmds.objExists("master_anim.globalScale"):
+ cmds.setAttr("master_anim.globalScale", 1)
+ cmds.refresh()
+
+ # disconnect main deformation hiearchy
+ cmds.select("root", hi=True)
+ joints = cmds.ls(sl=True, type="joint")
+
+ for joint in joints:
+ attrs = ["translate", "rotate", "scale"]
+ for attr in attrs:
+ try:
+ cmds.disconnectAttr("driver_" + joint + "." + attr, joint + "." + attr)
+ except Exception, e:
+ print str(e)
+
+ # unlock nodes
+ cmds.select("rig_grp", hi=True)
+ rigNodes = cmds.ls(sl=True)
+ for node in rigNodes:
+ cmds.lockNode(node, lock=False)
+
+ # go through each rig and delete that module's rigging
+ for module in self.moduleInstances:
+ module.deleteRig()
+
+ # set the state of the character
+ self.toolModeStack.setCurrentIndex(1)
+ if cmds.objExists("ART_RIG_ROOT.state"):
+ cmds.setAttr("ART_RIG_ROOT.state", 1)
+
+ # remove outliner scriptJobs
+ for job in self.scriptJobs:
+ cmds.scriptJob(kill=job, force=True)
+
+ # build the scriptJob for the weight table
+ self.scriptJobs.append(self.skinToolsInst.weightTable_scriptJob())
+
+ # delete driver skeleton
+ if cmds.objExists("driver_root"):
+ cmds.delete("driver_root")
+
+ # set model pose
+ for inst in self.moduleInstances:
+ networkNode = inst.returnNetworkNode
+ if cmds.objExists(networkNode + ".modelPose"):
+ inst.setSkeletonPose("modelPose")
+
+ # remove the skeletal constraints
+ for inst in self.moduleInstances:
+ networkNode = inst.returnNetworkNode
+ if cmds.objExists(networkNode + ".modelPose"):
+ inst.removeSkeletalConstraints()
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ def rigHistoryUI(self):
+
+ import ART_RigHistoryUI as arh
+ reload(arh)
+ arh.ART_RigHistoryUI(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def moduleStatusUI(self):
+
+ import ART_ModuleStatus as ART_ModuleStatus
+ reload(ART_ModuleStatus)
+ ART_ModuleStatus.run(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def unsavedChanges(self):
+ # Original Author: Jeremy Ernst
+
+ # message box for letting user know current file has unsaved changes
+ msgBox = QtWidgets.QMessageBox()
+ msgBox.setIcon(QtWidgets.QMessageBox.Warning)
+ msgBox.setText("Current File Has Unsaved Changes!")
+ msgBox.setDetailedText("To load a template, please create a new file and re-launch the tool.")
+ ret = msgBox.exec_()
+
+ return ret
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def exportMeshes(self):
+ # Original Author: Jeremy Ernst
+
+ # run publish process
+ import ART_ExportMeshes
+ reload(ART_ExportMeshes)
+ inst = ART_ExportMeshes.ART_ExportMeshes(self, parent=interfaceUtils.getMainWindow())
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def selectNetworkNode(self):
+
+ selection = self.nodeNetworkList.currentItem()
+ cmds.select(selection.text())
+
+
+##############################################################################################################
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# NON-CLASS FUNCTIONS
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+##############################################################################################################
+
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+def createUI():
+ # Original Author: Jeremy Ernst
+
+ global parent
+ global gui
+
+ try:
+
+ gui.close()
+ gui.deleteLater()
+
+ except:
+ pass
+
+ # if the rigCreatorUI exists delete UI
+ if cmds.dockControl("pyArtRigCreatorDock", q=True, exists=True):
+ cmds.deleteUI(windowObject)
+ cmds.deleteUI("pyArtRigCreatorDock", control=True)
+
+ # create an instance of the UI and add it to a Maya dock
+ gui = ART_RigCreator_UI(interfaceUtils.getMainWindow())
+ allowedAreas = ["left", "right"]
+ dockControl = cmds.dockControl("pyArtRigCreatorDock", area="right", content=windowObject, allowedArea=allowedAreas,
+ label=windowTitle, w=450, h=500)
+ cmds.refresh(force=True)
+ cmds.dockControl("pyArtRigCreatorDock", e=True, r=True)
+ return gui