Source code for System.ART_RigModule

"""
Author: Jeremy Ernst

    This is the base class from which all modules are created. When creating a new module,
    your module class should inherit from this base class. Example:

|        class ART_Head(ART_RigModule)

    In the __init__ of your module class, you will want to also run the base class __init__
    at the end of your module class __init__:

|        ART_RigModule.__init__(self, "ART_Head_Module", "ART_Head", moduleUserName)

    This module has two file attributes set by default. Your module class will need many more
    file attributes set. Please see another module as an example.

########
Contents
########

|   **Module Creation Functions:**
|       :func:`addAttributes <System.ART_RigModule.ART_RigModule.addAttributes>`
|       :func:`buildNetwork <System.ART_RigModule.ART_RigModule.buildNetwork>`
|       :func:`createMirrorModule <System.ART_RigModule.ART_RigModule.createMirrorModule>`
|       :func:`jointMover_Build <System.ART_RigModule.ART_RigModule.jointMover_Build>`
|       :func:`skeletonSettings_UI <System.ART_RigModule.ART_RigModule.skeletonSettings_UI>`
|
|   **Module Update Functions:**
|       :func:`applyModuleChanges <System.ART_RigModule.ART_RigModule.applyModuleChanges>`
|       :func:`checkForDependencies <System.ART_RigModule.ART_RigModule.checkForDependencies>`
|       :func:`deleteModule <System.ART_RigModule.ART_RigModule.deleteModule>`
|
|   **Module Settings and Interface Functions:**
|       :func:`changeModuleName <System.ART_RigModule.ART_RigModule.changeModuleName>`
|       :func:`changeModuleParent <System.ART_RigModule.ART_RigModule.changeModuleParent>`
|       :func:`copySettings <System.ART_RigModule.ART_RigModule.copySettings>`
|       :func:`pasteSettings <System.ART_RigModule.ART_RigModule.pasteSettings>`
|       :func:`resetSettings <System.ART_RigModule.ART_RigModule.resetSettings>`
|       :func:`createContextMenu <System.ART_RigModule.ART_RigModule.createContextMenu>`
|       :func:`createMirrorOfModule_UI <System.ART_RigModule.ART_RigModule.createMirrorOfModule_UI>`
|       :func:`createScriptJob <System.ART_RigModule.ART_RigModule.createScriptJob>`
|       :func:`mirrorTransformations <System.ART_RigModule.ART_RigModule.mirrorTransformations>`
|       :func:`mirrorTransformations_Custom <System.ART_RigModule.ART_RigModule.mirrorTransformations_Custom>`
|       :func:`resetTransforms <System.ART_RigModule.ART_RigModule.resetTransforms>`
|       :func:`setMirrorModule <System.ART_RigModule.ART_RigModule.setMirrorModule>`
|       :func:`updateBoneCount <System.ART_RigModule.ART_RigModule.updateBoneCount>`
|       :func:`updatePreview <System.ART_RigModule.ART_RigModule.updatePreview>`
|       :func:`updateSettingsUI <System.ART_RigModule.ART_RigModule.updateSettingsUI>`
|
|   **Module Joint Mover Functions:**
|       :func:`addJointMoverToOutliner <System.ART_RigModule.ART_RigModule.addJointMoverToOutliner>`
|       :func:`aimMode <System.ART_RigModule.ART_RigModule.aimMode>`
|       :func:`aimMode_Setup <System.ART_RigModule.ART_RigModule.aimMode_Setup>`
|       :func:`bakeOffsets <System.ART_RigModule.ART_RigModule.bakeOffsets>`
|       :func:`createGlobalMoverButton <System.ART_RigModule.ART_RigModule.createGlobalMoverButton>`
|       :func:`createMeshMoverButton <System.ART_RigModule.ART_RigModule.createMeshMoverButton>`
|       :func:`createOffsetMoverButton <System.ART_RigModule.ART_RigModule.createOffsetMoverButton>`
|       :func:`pinModule <System.ART_RigModule.ART_RigModule.pinModule>`
|       :func:`selectMover <System.ART_RigModule.ART_RigModule.selectMover>`
|       :func:`selectScriptJob <System.ART_RigModule.ART_RigModule.selectScriptJob>`
|       :func:`toggleShapeVis <System.ART_RigModule.ART_RigModule.toggleShapeVis>`
|       :func:`updateOutliner <System.ART_RigModule.ART_RigModule.updateOutliner>`
|
|   **Module Publish Functions:**
|       :func:`cleanUpRigPose <System.ART_RigModule.ART_RigModule.cleanUpRigPose>`
|       :func:`createRigPoseSliderForJoint <System.ART_RigModule.ART_RigModule.createRigPoseSliderForJoint>`
|       :func:`getReferencePose <System.ART_RigModule.ART_RigModule.getReferencePose>`
|       :func:`matchModelPose <System.ART_RigModule.ART_RigModule.matchModelPose>`
|       :func:`mirrorTransformations_RigPose <System.ART_RigModule.ART_RigModule.mirrorTransformations_RigPose>`
|       :func:`resetRigPose <System.ART_RigModule.ART_RigModule.resetRigPose>`
|       :func:`resetRigPose_Part <System.ART_RigModule.ART_RigModule.resetRigPose_Part>`
|       :func:`rigPose_UI <System.ART_RigModule.ART_RigModule.rigPose_UI>`
|       :func:`setPosePercentage <System.ART_RigModule.ART_RigModule.setPosePercentage>`
|       :func:`setPosePercentage_Part <System.ART_RigModule.ART_RigModule.setPosePercentage_Part>`
|       :func:`setReferencePose <System.ART_RigModule.ART_RigModule.setReferencePose>`
|       :func:`setReferencePoseSlider <System.ART_RigModule.ART_RigModule.setReferencePoseSlider>`
|       :func:`setSkeletonPose <System.ART_RigModule.ART_RigModule.setSkeletonPose>`
|       :func:`setupForRigPose <System.ART_RigModule.ART_RigModule.setupForRigPose>`
|       :func:`setupModelPoseForRig <System.ART_RigModule.ART_RigModule.setupModelPoseForRig>`
|       :func:`skinProxyGeo <System.ART_RigModule.ART_RigModule.skinProxyGeo>`
|       :func:`updateRigPose <System.ART_RigModule.ART_RigModule.updateRigPose>`
|
|   **Module Rig Functions**
|       :func:`buildRig <System.ART_RigModule.ART_RigModule.buildRig>`
|       :func:`buildRigCustom <System.ART_RigModule.ART_RigModule.buildRigCustom>`
|       :func:`deleteRig <System.ART_RigModule.ART_RigModule.deleteRig>`
|       :func:`getControls <System.ART_RigModule.ART_RigModule.getControls>`
|       :func:`importFBX <System.ART_RigModule.ART_RigModule.importFBX>`
|       :func:`importFBX_pre <System.ART_RigModule.ART_RigModule.importFBX_pre>`
|       :func:`resetRigControls <System.ART_RigModule.ART_RigModule.resetRigControls>`
|       :func:`selectRigControls <System.ART_RigModule.ART_RigModule.selectRigControls>`
|       :func:`selectionScriptJob_animUI <System.ART_RigModule.ART_RigModule.selectionScriptJob_animUI>`
|
|   **Module Utility Functions**
|       :func:`getAllModules <System.ART_RigModule.ART_RigModule.getAllModules>`
|       :func:`getModules <System.ART_RigModule.ART_RigModule.getModules>`
|       :func:`removeSkeletalConstraints <System.ART_RigModule.ART_RigModule.removeSkeletalConstraints>`
|       :func:`returnCreatedJoints <System.ART_RigModule.ART_RigModule.returnCreatedJoints>`
|       :func:`returnJointMovers <System.ART_RigModule.ART_RigModule.returnJointMovers>`
|       :func:`returnMirrorModuleInst <System.ART_RigModule.ART_RigModule.returnMirrorModuleInst>`
|       :func:`returnNetworkNode <System.ART_RigModule.ART_RigModule.returnNetworkNode>`
|       :func:`returnPrefixSuffix <System.ART_RigModule.ART_RigModule.returnPrefixSuffix>`
|       :func:`returnRigNetworkNode <System.ART_RigModule.ART_RigModule.returnRigNetworkNode>`
|
|
#########
Class
#########
"""

# file imports
import json
import os
import traceback
from functools import partial

import System.interfaceUtils as interfaceUtils
import System.riggingUtils as riggingUtils
import System.utils as utils
import System.mathUtils as mathUtils
import maya.cmds as cmds
import maya.mel as mel
from ThirdParty.Qt import QtGui, QtCore, QtWidgets

# file attributes
fbxImport = ["None", "FK"]
matchData = [False, None]


[docs]class ART_RigModule():
[docs] def __init__(self, moduleName, moduleType, userCreatedName): """Initiate the class, taking in the instance to the interface and the user specified name. :param moduleName: This is the base name of the module, specified in the rig module. :param moduleType: This is the name of the module to create (the module class). :param userCreatedName: This is the name specified by the user on module creation. Instantiate the following class variables as well: * **self.modName:** Take the passed in moduleName and make it a class var * **self.moduleType:** Take the passed in moduleType and make it a class var * **self.rootMod:** The network node of the entire character asset * **self.name:** The user created name (prefix + baseName + suffix) passed in * **self.originalName:** Also the user created name, but we want to store what the original name was on creation, as the user can rename the module later. This will allow us to make the link between what the module's original name was and what the new name is. * **self.outlinerControls:** A list of the outliner controls created when adding module joint movers to the outliner. Also, read the QSettings to find out where needed paths are. """ # set class variables self.modName = moduleName self.moduleType = moduleType self.rootMod = None self.name = userCreatedName self.originalName = userCreatedName self.outlinerControls = [] self.controlTypes = [] # get the directory path of the tools settings = QtCore.QSettings("Epic Games", "ARTv2") self.toolsPath = settings.value("toolsPath") self.iconsPath = settings.value("iconPath")
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def buildNetwork(self): """ Build the network node for the module which will store all information needed by the module. Then, call on addAttributes to add the required module attributes to the network node. """ # create the network node for our module self.networkNode = cmds.createNode("network", name=self.modName) # create attributes self.addAttributes() return self.networkNode
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def addAttributes(self): """ Add attributes to the network node that all modules need. """ if self.moduleType == None: # add attributes specific to this module cmds.addAttr(self.networkNode, sn="rigModules", at="message") else: # add a rigging message attribute cmds.addAttr(self.networkNode, sn="parent", at="message") # add a module type attribute cmds.addAttr(self.networkNode, sn="moduleType", dt="string", keyable=False) cmds.setAttr(self.networkNode + ".moduleType", self.moduleType, type="string", lock=True) # and a module name attribute (used for skeleton settings UI groupbox label) cmds.addAttr(self.networkNode, sn="moduleName", dt="string", keyable=False) cmds.setAttr(self.networkNode + ".moduleName", self.name, type="string", lock=True) # add attr for parent module that user specfies cmds.addAttr(self.networkNode, sn="parentModuleBone", dt="string", keyable=False) # add attr for mirror module that user specfies cmds.addAttr(self.networkNode, sn="mirrorModule", dt="string", keyable=False) cmds.addAttr(self.networkNode, sn="pinned", at="bool", keyable=False) cmds.setAttr(self.networkNode + ".pinned", False, lock=True) # connect rigModule to root module node self.rootMod = self.getModules if self.rootMod != None: cmds.connectAttr(self.rootMod + ".rigModules", self.networkNode + ".parent")
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def skeletonSettings_UI(self, name, width, height, checkable): """ Build the framework for the skeleton settings that all modules need. :param name: user given name of module (prefix + base_name + suffix) :param width: width of the skeleton settings groupBox. 335 usually :param height: height of the skeleton settings groupBox. :param checkable: Whether or not the groupBox can be collapsed. """ # add the groupbox for this module with the module name and module settings self.groupBox = QtWidgets.QGroupBox(name) self.groupBox.setGeometry(QtCore.QRect(0, 0, width, height)) self.groupBox.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) if not checkable: self.groupBox.setMinimumSize(QtCore.QSize(width, height)) if checkable: self.groupBox.setMinimumSize(QtCore.QSize(width, 0)) self.groupBox.setMaximumSize(QtCore.QSize(width, height)) self.groupBox.setFlat(True) self.groupBox.setCheckable(checkable) self.lockButton = QtWidgets.QPushButton() self.lockButton.setMinimumSize(QtCore.QSize(20, 20)) self.lockButton.setMaximumSize(QtCore.QSize(20, 20)) # load style sheet file styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/skeletonSettings.qss") f = open(styleSheetFile, "r") style = f.read() f.close() self.groupBox.setStyleSheet(style) # set properties for filtering later self.groupBox.setObjectName(name) self.groupBox.setProperty("name", name) # set context menu policy on groupbox self.groupBox.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.groupBox.customContextMenuRequested.connect(self.createContextMenu)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def changeModuleName(self, baseName, moduleInst, rigUiInst): """ Launch the interface that allows users to change the module name. :param baseName: The module base name (head, torso, leg, etc) :param moduleInst: The specific instance of the module :param rigUiInst: The instance of the rig creator interface. This will call on a separate class in Core/Interfaces called ART_ChangeModuleNameUI.py """ # get prefix/suffix name = self.groupBox.title() prefix = name.partition(baseName)[0] suffix = name.partition(baseName)[2] # when pressing the change name button on the skeleton settings UI (if it exists): # delete the UI if it already exists mayaWindow = interfaceUtils.getMainWindow() mayaWindow = mayaWindow.objectName() if cmds.window(mayaWindow + "|pyArtChangeModuleNameUi", q=True, exists=True): cmds.deleteUI(mayaWindow + "|pyArtChangeModuleNameUi") # launch a UI for prefix/suffix/preview again import Interfaces.ART_ChangeModuleNameUI as ART_ChangeModuleNameUI reload(ART_ChangeModuleNameUI) inst = ART_ChangeModuleNameUI.ART_ChangeModuleName_UI(baseName, moduleInst, rigUiInst, prefix, suffix, interfaceUtils.getMainWindow()) inst.show()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def changeModuleParent(self, moduleInst, rigUiInst): """ Launch the interface that allows users to change the module's parent bone. :param moduleInst: The specific instance of the module :param rigUiInst: The instance of the rig creator interface. This will call on a separate class in Core/Interfaces called ART_ChangeModuleParentUI.py """ # get current parent value currentParent = self.currentParent.text() # when pressing the change parent button on the skeleton settings UI (if it exists): # delete the UI if it already exists mayaWindow = interfaceUtils.getMainWindow() mayaWindow = mayaWindow.objectName() if cmds.window(mayaWindow + "|pyArtChangeModuleParentUi", q=True, exists=True): cmds.deleteUI(mayaWindow + "|pyArtChangeModuleParentUi") # launch a UI for prefix/suffix/preview again import Interfaces.ART_ChangeModuleParentUI as ART_ChangeModuleParentUI reload(ART_ChangeModuleParentUI) inst = ART_ChangeModuleParentUI.ART_ChangeModuleParent_UI(currentParent, moduleInst, rigUiInst, interfaceUtils.getMainWindow()) inst.show()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setMirrorModule(self, moduleInst, rigUiInst): """ Launch the interface that allows users to change the module's mirror module. Meaning, the module that is linked as a mirror of this module. Only modules of the same type can be linked as mirrors. :param moduleInst: The specific instance of the module :param rigUiInst: The instance of the rig creator interface. This will call on a separate class in Core/Interfaces called ART_SetMirrorModuleUI.py """ # delete the UI if it already exists mayaWindow = interfaceUtils.getMainWindow() mayaWindow = mayaWindow.objectName() if cmds.window(mayaWindow + "|pyArtSetMirrorModuleUi", q=True, exists=True): cmds.deleteUI(mayaWindow + "|pyArtSetMirrorModuleUi") # launch a UI for prefix/suffix/preview again import Interfaces.ART_SetMirrorModuleUI as ART_SetMirrorModuleUI reload(ART_SetMirrorModuleUI) inst = ART_SetMirrorModuleUI.ART_SetMirrorModule_UI(moduleInst, rigUiInst, interfaceUtils.getMainWindow()) inst.show()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def jointMover_Build(self, path): """ Import the joint mover file with the given path. After importing the module's joint mover file, rename imported nodes to use module name. Then, assign existing matching materials to joint mover proxy geometry, deleting the imported materials if they were duplicates. Then parent into the main JointMover group. Lastly, hook up global scaling on the joint movers. :param path: Path of joint mover file to import """ # get the full path for the joint mover file fullPath = os.path.join(self.toolsPath, path) # import the file if os.path.exists(fullPath): nodes = cmds.file(fullPath, i=True, iv=True, type="mayaAscii", rnn=True) validTypes = ["transform", "joint", "ikHandle"] # loop through returned nodes from import, and find the mover_grp, renaming it and all # children to have user specified name as prefix for node in nodes: if node.find("|mover_grp") == 0: children = cmds.listRelatives(node, allDescendents=True, type="transform") moverGrp = node.partition("|")[2] movers = [moverGrp] for child in children: try: if cmds.nodeType(child) in validTypes: movers.append(child) except Exception, e: print e for mover in movers: try: cmds.rename(mover, self.name + "_" + mover) except Exception, e: print mover, self.name + "_" + mover print str(e) # exit loop break # assign materials if they exist, removing duplicate materials materials = [["*_blue_m", "blue_m"], ["*_green_m", "green_m"], ["*_red_m", "red_m"], ["*_white_m", "white_m"], ["*_proxy_shader_tan", "proxy_shader_tan"], ["*_proxy_shader_black", "proxy_shader_black"]] deleteMaterials = [] for material in materials: try: # select materials for the joint mover cmds.select(material[0]) foundMaterials = cmds.ls(sl=True) # loop through each color material (dupes) for mat in foundMaterials: cmds.hyperShade(objects=mat) assignedGeo = cmds.ls(sl=True) # select the geo and the original material, and assign originalMaterial = material[1] for geo in assignedGeo: cmds.select([geo, originalMaterial]) cmds.hyperShade(assign=originalMaterial) # delete the material no longer needed deleteMaterials.append(mat) except: pass # delete all deleteMaterials for mat in deleteMaterials: cmds.delete(mat) # add to JointMover grp cmds.refresh(force=True) if not cmds.objExists("JointMover"): cmds.group(empty=True, name="JointMover") try: cmds.parent("|" + self.name + "_mover_grp", "JointMover") except Exception, e: print str(e) globalMover = utils.findGlobalMoverFromName(self.name) cmds.select(globalMover) cmds.setToolTo("moveSuperContext") # obey visibility toggles self.rigUiInst.setMoverVisibility() # 1/13/16 Change # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # hook up global scale on joint movers try: movers = self.returnJointMovers for each in [movers[0], movers[1]]: for mover in each: if not cmds.objExists(mover + ".globalScale"): try: cmds.aliasAttr("globalScale", mover + ".scaleZ") cmds.connectAttr(mover + ".globalScale", mover + ".scaleX") cmds.connectAttr(mover + ".globalScale", mover + ".scaleY") cmds.setAttr(mover + ".scaleX", keyable=False) cmds.setAttr(mover + ".scaleY", keyable=False) except: pass # lock movers for each in movers: for mover in each: cmds.lockNode(mover, lock=True) except: pass # 1/13/16 Change # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # else: cmds.confirmDialog(title="Joint Mover", message="Could not find associated joint mover file.", icon="critical")
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def selectScriptJob(self, info): """ Change icon color of the given joint mover's button in the outliner to show selection status. :param info: This list contains the button object, the joint mover control, and the original color icon. If the control given is selected, the icon is switched to a white icon. If it is not selected, the icon is set back to the original passed in icon. """ pixmap = QtGui.QPixmap(20, 15) pixmap.fill(QtGui.QColor(255, 255, 255)) whiteIcon = QtGui.QIcon(pixmap) # for each item in the passed in info [outliner button, mover control, unselected stylesheet],check if # the control is in the selection, and color the button appropriately for item in info: button = item[0] control = item[1] icon = item[2] selected = cmds.ls(selection=True) if control not in selected: self.outlinerWidgets[button].setIcon(icon) if control in selected: self.outlinerWidgets[button].setIcon(whiteIcon)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createGlobalMoverButton(self, name, parent, uiInstance): """ Create the button in the outliner for the global mover control of a joint mover. :param name: The name of the joint mover control. :param parent: The outliner widget the created button will be parented to. :param uiInstance: The Rig Creator interface instance. """ part = name.partition(self.name)[2] # create the icon pixmap = QtGui.QPixmap(20, 15) pixmap.fill(QtGui.QColor("yellow")) icon = QtGui.QIcon(pixmap) # create the button self.outlinerWidgets[name + "_globalMoverBtn"] = QtWidgets.QPushButton(icon, "") self.outlinerWidgets[name + "_globalMoverBtn"].setMinimumSize(QtCore.QSize(20, 15)) self.outlinerWidgets[name + "_globalMoverBtn"].setMaximumSize(QtCore.QSize(20, 15)) uiInstance.treeWidget.setItemWidget(parent, 1, self.outlinerWidgets[name + "_globalMoverBtn"]) # connect and add to list self.outlinerWidgets[name + "_globalMoverBtn"].clicked.connect( partial(self.selectMover, part, True, False, False, self.outlinerWidgets[name + "_globalMoverBtn"])) self.outlinerControls.append([name + "_globalMoverBtn", name + "_mover", icon])
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createOffsetMoverButton(self, name, parent, uiInstance): """ Create the button in the outliner for the offset mover control of a joint mover. :param name: The name of the joint mover control. :param parent: The outliner widget the created button will be parented to. :param uiInstance: The Rig Creator interface instance. """ part = name.partition(self.name)[2] # create the icon pixmap = QtGui.QPixmap(20, 15) pixmap.fill(QtGui.QColor(100, 200, 255)) icon = QtGui.QIcon(pixmap) # create the button self.outlinerWidgets[name + "_offsetMoverBtn"] = QtWidgets.QPushButton(icon, "") self.outlinerWidgets[name + "_offsetMoverBtn"].setMinimumSize(QtCore.QSize(20, 15)) self.outlinerWidgets[name + "_offsetMoverBtn"].setMaximumSize(QtCore.QSize(20, 15)) uiInstance.treeWidget.setItemWidget(parent, 2, self.outlinerWidgets[name + "_offsetMoverBtn"]) # connect and add to list self.outlinerWidgets[name + "_offsetMoverBtn"].clicked.connect( partial(self.selectMover, part, False, True, False, self.outlinerWidgets[name + "_offsetMoverBtn"])) self.outlinerControls.append([name + "_offsetMoverBtn", name + "_mover_offset", icon])
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createMeshMoverButton(self, name, parent, uiInstance): """ Create the button in the outliner for the geometry mover control of a joint mover. :param name: The name of the joint mover control. :param parent: The outliner widget the created button will be parented to. :param uiInstance: The Rig Creator interface instance. Note: The geometry mover is purely for aesthetics and does not affect the rigging. """ part = name.partition(self.name)[2] # create the icon pixmap = QtGui.QPixmap(20, 15) pixmap.fill(QtGui.QColor(255, 176, 176)) icon = QtGui.QIcon(pixmap) # create the button self.outlinerWidgets[name + "_geoMoverBtn"] = QtWidgets.QPushButton(icon, "") self.outlinerWidgets[name + "_geoMoverBtn"].setMinimumSize(QtCore.QSize(20, 15)) self.outlinerWidgets[name + "_geoMoverBtn"].setMaximumSize(QtCore.QSize(20, 15)) uiInstance.treeWidget.setItemWidget(parent, 3, self.outlinerWidgets[name + "_geoMoverBtn"]) # connect and add to list self.outlinerWidgets[name + "_geoMoverBtn"].clicked.connect( partial(self.selectMover, part, False, False, True, self.outlinerWidgets[name + "_geoMoverBtn"])) self.outlinerControls.append([name + "_geoMoverBtn", name + "_mover_geo", icon])
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createScriptJob(self): """ Create the selection script job for the outliner buttons and their associated joint mover controls. This function purely creates the script job. The script job function that is run is called self.selectScriptJob. """ self.scriptJob = cmds.scriptJob( event=["SelectionChanged", partial(self.selectScriptJob, self.outlinerControls)], runOnce=False, parent="pyArtRigCreatorUi", kws=True, per=False) self.rigUiInst.scriptJobs.append(self.scriptJob)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def selectMover(self, part, globalMover, offsetMover, geoMover, button): """ Select the appropriate joint mover control based on the args passed in. Color the associated button white to show selection status. :param part: The name of the joint mover control. :param globalMover: Boolean of whether or not given control is a global mover. :param offsetMover: Boolean of whether or not given control is an offset mover. :param geoMover: Boolean of whether or not given control is a mesh mover. :param button: The button in the outliner associated with the given mover. """ # select mover and color button name = self.name + part # get modifiers toggle = False mods = cmds.getModifiers() if (mods & 1) > 0: toggle = True if globalMover: cmds.select(name + "_mover", tgl=toggle) selected = cmds.ls(sl=True) if name + "_mover" in selected: button.setStyleSheet('background-color: rgb(255, 255, 255);') else: button.setStyleSheet('background-color: rgb(255, 255, 0);') if offsetMover: cmds.select(name + "_mover_offset", tgl=toggle) selected = cmds.ls(sl=True) if name + "_mover_offset" in selected: self.outlinerWidgets[name + "_offsetMoverBtn"].setStyleSheet('background-color: rgb(255, 255, 255);') else: self.outlinerWidgets[name + "_offsetMoverBtn"].setStyleSheet('background-color: rgb(100, 220, 255);') if geoMover: cmds.select(name + "_mover_geo", tgl=toggle) selected = cmds.ls(sl=True) if name + "_mover_geo" in selected: self.outlinerWidgets[name + "_geoMoverBtn"].setStyleSheet('background-color: rgb(255, 255, 255);') else: self.outlinerWidgets[name + "_geoMoverBtn"].setStyleSheet('background-color: rgb(255, 176, 176);')
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createContextMenu(self, point): """ Create the right-click menu for the module. :param point: Point on monitor to spawn the right-click menu. Default menu actions created: * Copy Settings * Paste Settings * Reset Settings * Delete Module * Create Mirror of this Module * Mirror Transformations (only if a mirror is linked) """ networkNode = self.returnNetworkNode mirror = cmds.getAttr(networkNode + ".mirrorModule") # icons icon_copy = QtGui.QIcon(os.path.join(self.iconsPath, "System/copy.png")) icon_paste = QtGui.QIcon(os.path.join(self.iconsPath, "System/paste.png")) icon_reset = QtGui.QIcon(os.path.join(self.iconsPath, "System/reset.png")) icon_delete = QtGui.QIcon(os.path.join(self.iconsPath, "System/delete.png")) icon_mirror = QtGui.QIcon(os.path.join(self.iconsPath, "System/mirrorXforms.png")) icon_createMirror = QtGui.QIcon(os.path.join(self.iconsPath, "System/createMirror.png")) # create the context menu if networkNode != "ART_Root_Module": self.contextMenu = QtWidgets.QMenu() self.contextMenu.addAction(icon_copy, "Copy Settings", self.copySettings) self.contextMenu.addAction(icon_paste, "Paste Settings", self.pasteSettings) self.contextMenu.addAction(icon_reset, "Reset Settings", self.resetSettings) self.contextMenu.addSeparator() if mirror != None: self.contextMenu.addAction(icon_mirror, "Mirror Transformations to " + mirror, self.mirrorTransformations) self.contextMenu.addAction(icon_createMirror, "Create Mirror of this Module", self.createMirrorOfModule_UI) self.contextMenu.addSeparator() self.contextMenu.addAction(icon_delete, "Delete Module", self.deleteModule) self.contextMenu.exec_(self.groupBox.mapToGlobal(point))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def copySettings(self): """ Copy the values from the network node of the module and store them in a temp file on disk. This function is used in the right-click menu of the module on the skeleton settings interface. Occasionally, it is called outside of the menu. For example, when creating a mirror of the module, the settings are copied for the source module to then be later pasted on the mirror. """ networkNode = self.returnNetworkNode attrs = cmds.listAttr(networkNode, ud=True, hd=True) attrData = [] for attr in attrs: value = cmds.getAttr(networkNode + "." + attr) attrData.append([attr, value]) # write out attrData to a temp file tempDir = cmds.internalVar(userTmpDir=True) clipboardFile = os.path.normcase(os.path.join(tempDir, "ART_clipboard.txt")) f = open(clipboardFile, 'w') # dump the data with json json.dump(attrData, f) f.close()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def pasteSettings(self): """ Paste the settings from the temp file on disk to the module's network node. This function is used in the right-click menu of the module on the skeleton settings interface. Occasionally, it is called outside of the menu. For example, when creating a mirror of the module, the settings are copied for the source module to then be later pasted on the mirror. After settings are pasted, applyModuleChanges is called to update the joint mover in the scene with the latest values. updateSettingsUI is also called to update the outliner. """ # it does this 4 times because for some reason it would not grab everything one time through. Investigate for i in range(4): tempDir = cmds.internalVar(userTmpDir=True) clipboardFile = os.path.normcase(os.path.join(tempDir, "ART_clipboard.txt")) if os.path.exists(clipboardFile): # load the data json_file = open(clipboardFile) data = json.load(json_file) json_file.close() # attempt to paste data if module type is the same networkNode = self.returnNetworkNode moduleType = cmds.getAttr(networkNode + ".moduleType") if moduleType == data[0][1]: for each in data: attr = each[0] value = each[1] try: attrType = str(cmds.getAttr(networkNode + "." + attr, type=True)) if attrType != "string": cmds.setAttr(networkNode + "." + attr, lock=False) cmds.setAttr(networkNode + "." + attr, value, lock=True) except: pass else: cmds.warning("No data in clipboard") # relaunch the UI self.updateSettingsUI() self.applyModuleChanges(self)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def resetSettings(self): """ Reset the settings of the module's network node. This function is used in the right-click menu of the module on the skeleton settings interface. Occasionally, it is called outside of the menu. After settings are reset, applyModuleChanges is called to update the joint mover in the scene with the latest values. updateSettingsUI is also called to update the outliner. """ # it does this 4 times because for some reason it would not grab everything one time through. Investigate for i in range(4): networkNode = self.returnNetworkNode attrs = cmds.listAttr(networkNode, ud=True) for attr in attrs: attrType = str(cmds.getAttr(networkNode + "." + attr, type=True)) if attrType == "double": cmds.setAttr(networkNode + "." + attr, lock=False) cmds.setAttr(networkNode + "." + attr, 0, lock=True) if attrType == "bool": cmds.setAttr(networkNode + "." + attr, lock=False) cmds.setAttr(networkNode + "." + attr, True, lock=True) if attrType == "enum": cmds.setAttr(networkNode + "." + attr, lock=False) cmds.setAttr(networkNode + "." + attr, 0, lock=True) # relaunch the UI self.updateSettingsUI() self.applyModuleChanges(self)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def resetTransforms(self, translate, rotate, scale, name): """ Reset the given attributes of all movers in the module. :param translate: Boolean of whether or not to reset translation values. :param rotate: Boolean of whether or not to reset the rotation values. :param scale: Boolean of whether or not to reset the scale values. :param name: The module name. (prefix + basename + suffix) This function is mainly called from ART_ResetModeUI. """ cmds.select(name + "_mover_grp", hi=True) selection = cmds.ls(sl=True) globalMovers = [] offsetMovers = [] geoMovers = [] for each in selection: if each.find("_mover") != -1: if each.partition("_mover")[2] == "": globalMovers.append(each) if each.find("_mover_offset") != -1: if each.partition("_mover_offset")[2] == "": offsetMovers.append(each) if each.find("_mover_geo") != -1: if each.partition("_mover_geo")[2] == "": geoMovers.append(each) cmds.select(clear=True) for moverList in [globalMovers, offsetMovers, geoMovers]: for each in moverList: if translate: for attr in [".tx", ".ty", ".tz"]: try: cmds.setAttr(each + attr, 0) except: pass if rotate: for attr in [".rx", ".ry", ".rz"]: try: cmds.setAttr(each + attr, 0) except: pass if scale: for attr in [".sx", ".sy", ".sz"]: try: cmds.setAttr(each + attr, 1) except: pass if cmds.window("ART_ResetXformsModeWin", exists=True): cmds.deleteUI("ART_ResetXformsModeWin", wnd=True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def deleteModule(self): """ Delete the module and all associated nodes and interfaces. First, this will delete the joint mover, remove the entry from the outliner and the skeleton settings UI. Then, it has to deal with any connected modules or mirror modules and resolve any issues there. """ # delete the joint mover movers = self.returnJointMovers for moverGrp in movers: for mover in moverGrp: cmds.lockNode(mover, lock=False) cmds.delete(self.name + "_mover_grp") # remove the entry from the outliner index = self.rigUiInst.treeWidget.indexOfTopLevelItem(self.outlinerWidgets[self.name + "_treeModule"]) self.rigUiInst.treeWidget.takeTopLevelItem(index) # remove the groupbox self.groupBox.setParent(None) # deal with mirror module networkNode = self.returnNetworkNode mirrorModule = cmds.getAttr(networkNode + ".mirrorModule") if mirrorModule != None: if mirrorModule != "None": modules = utils.returnRigModules() for mod in modules: modName = cmds.getAttr(mod + ".moduleName") if modName == mirrorModule: # set the mirrored version cmds.setAttr(mod + ".mirrorModule", lock=False) cmds.setAttr(mod + ".mirrorModule", "None", type="string", lock=True) # get instance of mirror module's class modType = cmds.getAttr(mod + ".moduleType") modName = cmds.getAttr(mod + ".moduleName") module = __import__("RigModules." + modType, {}, {}, [modType]) # get the class name from that module file (returns Modules.ART_Root.ART_Root for example) moduleClass = getattr(module, module.className) # find the instance of that module and call on the skeletonSettings_UI function moduleInst = moduleClass(self.rigUiInst, modName) # find the current groupBox for this module for i in range(self.rigUiInst.moduleSettingsLayout.count()): if type(self.rigUiInst.moduleSettingsLayout.itemAt(i).widget()) == QtWidgets.QGroupBox: if self.rigUiInst.moduleSettingsLayout.itemAt(i).widget().title() == modName: self.rigUiInst.moduleSettingsLayout.itemAt(i).widget().setParent(None) # relaunch the skeleton settings UI with new info moduleInst.skeletonSettings_UI(modName) # check for any attached modules attachedModules = self.checkForDependencies() elementList = [] if len(attachedModules) > 0: for each in attachedModules: elementList.append([each[2], " -> parent changed from: ", each[1], " to: ", "root\n"]) cmds.parent(each[2] + "_mover_grp", "root_mover") cmds.setAttr(each[0] + ".parentModuleBone", lock=False) cmds.setAttr(each[0] + ".parentModuleBone", "root", type="string", lock=True) each[3].currentParent.setText("root") mover = "root_mover" # create the connection geo between the two childMover = utils.findOffsetMoverFromName(each[2]) riggingUtils.createBoneConnection(mover, childMover, each[2]) each[3].applyModuleChanges(each[3]) cmds.select(clear=True) # remove the network node cmds.delete(networkNode) # delete scriptJob cmds.scriptJob(kill=self.scriptJob, force=True) self.updateBoneCount() self.rigUiInst.moduleInstances.remove(self) # warn user about changes if len(attachedModules) > 0: winParent = interfaceUtils.getMainWindow() win = interfaceUtils.DialogMessage("Attention!", "The following modules have had their parent changed\ due to the change in this module's structure:", elementList, 5, winParent) win.show()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def checkForDependencies(self): """ This method will check modules for any attached modules or children modules. This method is generally called when deleting a module or when changing a module name so that any connected modules are updated accordingly. :return: attached modules """ # This method will check our module for any attached modules modules = self.getAllModules joints = self.returnCreatedJoints attachedMods = [] instances = {} for inst in self.rigUiInst.moduleInstances: networkNode = inst.returnNetworkNode instances[networkNode] = inst for module in modules: parentJoint = cmds.getAttr(module + ".parentModuleBone") moduleName = cmds.getAttr(module + ".moduleName") if parentJoint in joints: instance = instances.get(module) attachedMods.append([module, parentJoint, moduleName, instance]) return attachedMods
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createMirrorOfModule_UI(self): """ This method builds the interface for creating a mirror of a module. .. image:: /images/mirrorModule.png """ # copy the settings of the module self.copySettings() # get basename and classname networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") className = cmds.getAttr(networkNode + ".moduleType") # launch a UI to get the name information self.mirrorWindow = QtWidgets.QMainWindow() # load stylesheet styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss") f = open(styleSheetFile, "r") style = f.read() f.close() self.mirrorWindow.setStyleSheet(style) # size policies mainSizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) # create the main widget self.mainWidget = QtWidgets.QWidget() self.mirrorWindow.setCentralWidget(self.mainWidget) # set qt object name self.mirrorWindow.setObjectName("ART_createMirrorModuleUI") self.mirrorWindow.setWindowTitle("Create Mirror Module") # create the mainLayout for the rig creator UI self.mainLayout = QtWidgets.QVBoxLayout(self.mainWidget) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mirrorWindow.resize(300, 150) self.mirrorWindow.setSizePolicy(mainSizePolicy) self.mirrorWindow.setMinimumSize(QtCore.QSize(300, 150)) self.mirrorWindow.setMaximumSize(QtCore.QSize(300, 150)) # create the background image self.frame = QtWidgets.QFrame() self.mainLayout.addWidget(self.frame) # create the layout for the widgets self.widgetLayout = QtWidgets.QVBoxLayout(self.frame) # create the prefix pair of fields self.prefixForm = QtWidgets.QFormLayout() self.widgetLayout.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(partial(self.updatePreview, baseName)) # create the suffix pair of fields self.suffixForm = QtWidgets.QFormLayout() self.widgetLayout.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(partial(self.updatePreview, baseName)) # spacer spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.widgetLayout.addItem(spacerItem) # realtime preview of final module name self.previewForm = QtWidgets.QFormLayout() self.widgetLayout.addLayout(self.previewForm) self.previewLabel = QtWidgets.QLabel("Preview: ") self.previewName = QtWidgets.QLabel(baseName) self.previewName.setMinimumSize(QtCore.QSize(200, 20)) self.previewName.setMaximumSize(QtCore.QSize(200, 20)) self.previewName.setAlignment(QtCore.Qt.AlignHCenter) self.previewForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.previewLabel) self.previewForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, 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.widgetLayout.addItem(spacerItem1) # create button self.createButton = QtWidgets.QPushButton("CREATE") self.createButton.setObjectName("blueButton") self.widgetLayout.addWidget(self.createButton) self.createButton.setMinimumSize(QtCore.QSize(285, 40)) self.createButton.setMaximumSize(QtCore.QSize(285, 40)) self.createButton.setSizePolicy(mainSizePolicy) font = QtGui.QFont() font.setPointSize(12) self.createButton.setFont(font) # hookup signal/slot on create button self.createButton.clicked.connect(self.createMirrorModule) # show the window self.mirrorWindow.show()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def updatePreview(self, baseName, *args): """ This simple method updates the module preview field(QLineEdit) with the entered prefix and suffix. :param baseName: base name of the module (example: arm) """ prefix = str(self.prefix.text()) suffix = str(self.suffix.text()) string = "" if len(prefix) > 0: string += prefix + "_" string += baseName if len(suffix) > 0: string += "_" + suffix self.previewName.setText(string)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createMirrorModule(self): """ This method creates the mirror of a module and is called from createMirrorOfModule_UI. To create the mirror of a module, after a few checks are done, a module of the same type is created first. If that module type has a left/right version of a joint mover file, the opposite version is brought in. All the normal steps of module creation are then gone through and lastly, mirrorTransformations is called. """ userSpecName = str(self.previewName.text()) networkNode = self.returnNetworkNode parent = cmds.getAttr(networkNode + ".parentModuleBone") className = cmds.getAttr(networkNode + ".moduleType") # check to see if a module already has that name modules = utils.returnRigModules() mirrorModule = None moduleName = None 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 \ for the module", icon="critical") return # now check the modules that contain the parent bone for module in modules: bones = cmds.getAttr(module + ".Created_Bones") splitJoints = bones.split("::") createdJoints = [] # create a list of the created bones for bone in splitJoints: if bone != "": createdJoints.append(bone) # see if the parent bone is in that list if parent in createdJoints: mirrorModule = cmds.getAttr(module + ".mirrorModule") moduleName = cmds.getAttr(module + ".moduleName") # if our parent bone's module, has a mirror module, we need to create this new mirror module under that # parent instead (if parent = l_thigh, mirror parent should be r_thigh) if mirrorModule is not None: for module in modules: modName = cmds.getAttr(module + ".moduleName") if modName == mirrorModule: # find the parent's mover (if parent is l_thigh, mover would be l_leg_thigh_mover) networkNodes = utils.returnRigModules() mover = utils.findMoverNodeFromJointName(networkNodes, parent, False, True) # find mirror mover mirrorMover = mover.replace(moduleName, mirrorModule) baseName = cmds.getAttr(module + ".baseName") boneList = cmds.getAttr(module + ".Created_Bones") # now, we need to find the joint from the mirror mover, and once there is a match, the parent\ # var now becomes that joint if mirrorMover.find("_mover") != -1: jointName = mirrorMover.partition("_mover")[0] if jointName in boneList: parent = jointName else: # if removing _mover didn't yield a matching joint name, take out the baseName from\ # the mover name, and then remove the _mover jointName = jointName.replace(baseName + "_", "") if jointName in boneList: parent = jointName # arms and leg exception mirrorSide = None specialCaseModules = ["ART_Leg_Standard", "ART_Arm_Standard"] if className in specialCaseModules: side = cmds.getAttr(networkNode + ".side") if side == "Left": mirrorSide = "Right" if side == "Right": mirrorSide = "Left" # create an instance of the module mod = __import__("RigModules." + className, {}, {}, [className]) # get the class name from that module file (returns Modules.ART_Root.ART_Root for example) moduleClass = getattr(mod, mod.className) jmPath = mod.jointMover # call functions to create network node, skeleton settings UI moduleInst = moduleClass(self.rigUiInst, userSpecName) self.rigUiInst.moduleInstances.append(moduleInst) networkNodeInst = moduleInst.buildNetwork() # if mirrorSide exists if mirrorSide is not None: jmPath = jmPath.partition(".ma")[0] + "_" + mirrorSide + ".ma" if mirrorSide == "Left": cmds.setAttr(networkNodeInst + ".side", lock=False) cmds.setAttr(networkNodeInst + ".side", "Left", type="string", lock=True) if mirrorSide == "Right": cmds.setAttr(networkNodeInst + ".side", lock=False) cmds.setAttr(networkNodeInst + ".side", "Right", type="string", lock=True) # build the settings UI/joint mover/add to outliner 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: if prefix.find("_") == -1: prefix = prefix + "_" if len(suffix) > 0: if suffix.find("_") == -1: suffix = "_" + suffix createdBones = cmds.getAttr(networkNodeInst + ".Created_Bones") createdBones = createdBones.split("::") attrString = "" for bone in createdBones: if len(bone) > 1: attrString += prefix + bone + suffix + "::" cmds.setAttr(networkNodeInst + ".Created_Bones", lock=False) cmds.setAttr(networkNodeInst + ".Created_Bones", attrString, type="string", lock=True) # update the self.currentParent label and the parentModuleBone attr on the network node moduleInst.currentParent.setText(parent) cmds.setAttr(networkNodeInst + ".parentModuleBone", lock=False) cmds.setAttr(networkNodeInst + ".parentModuleBone", parent, type="string", lock=True) # find the current parent mover and its scale 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, userSpecName + "_mover_grp", mo=True) cmds.scaleConstraint(mover, userSpecName + "_mover_grp") # create the connection geo between the two childMover = utils.findOffsetMoverFromName(userSpecName) riggingUtils.createBoneConnection(offsetMover, childMover, userSpecName) globalMover = utils.findGlobalMoverFromName(userSpecName) cmds.select(globalMover) cmds.setToolTo("moveSuperContext") utils.fitViewAndShade() cmds.refresh(force=True) moduleInst.pasteSettings() moduleInst.aimMode(True) # delete UI cmds.deleteUI("ART_createMirrorModuleUI", wnd=True) # update the mirrorModule setting self.mirrorMod.setText(userSpecName) name = cmds.getAttr(networkNode + ".moduleName") moduleInst.mirrorMod.setText(name) cmds.setAttr(networkNode + ".mirrorModule", lock=False) cmds.setAttr(networkNode + ".mirrorModule", userSpecName, type="string", lock=True) cmds.setAttr(networkNodeInst + ".mirrorModule", lock=False) cmds.setAttr(networkNodeInst + ".mirrorModule", name, type="string", lock=True) # mirror transformations self.mirrorTransformations() self.rigUiInst.populateNetworkList()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def mirrorTransformations_RigPose(self): """ This method is used when creating rig poses for modules. If a module has a mirror, this method will mirror the rig pose transformations to that mirror module. """ # reset mirror module's rig pose mirrorModInst = self.returnMirrorModuleInst # ensure the mirrorModInst has a UI and is setup for rig pose creation mirrorModInst.setupForRigPose() # if not cmds.objExists(mirrorModInst.name + "_rigPose"): # mirrorModInst.getReferencePose("rigPose") # call on base mirror transformations method self.mirrorTransformations() mirrorModInst.getReferencePose("rigPose") # update the rig pose of the mirrorModInst mirrorModInst.updateRigPose(mirrorModInst.overallSlider) mirrorModInst.cleanUpRigPose()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def mirrorTransformations(self): """ This method mirrors transformations for the module's mirror module. """ currentSelection = cmds.ls(sl=True) # get the mirror module networkNode = self.returnNetworkNode mirrorModule = cmds.getAttr(networkNode + ".mirrorModule") moduleName = cmds.getAttr(networkNode + ".moduleName") parent = cmds.getAttr(networkNode + ".parentModuleBone") # get mirror module instance and information mirrorInst = self.returnMirrorModuleInst # turn off aim mode mirrorInst.aimMode_Setup(False) # turn off coplanar mode IF it exists on the module try: state = mirrorInst.coplanarBtn.isChecked() if state: mirrorInst.coplanarBtn.setChecked(False) mirrorInst.coplanarMode() except: pass moverTypes = self.returnJointMovers for moverType in moverTypes: for jointMover in moverType: attrs = cmds.listAttr(jointMover, keyable=True) for attr in attrs: value = cmds.getAttr(jointMover + "." + attr) mirrorMover = jointMover.partition(moduleName)[2] mirrorMover = mirrorModule + mirrorMover mirrorAttrs = ["translateX", "translateY", "translateZ"] if attr in mirrorAttrs: cmds.setAttr(mirrorMover + "." + attr, value * -1) else: cmds.setAttr(mirrorMover + "." + attr, value) cmds.select(clear=True) if len(currentSelection) > 0: cmds.select(currentSelection) # turn aim mode on mirrorInst.aimMode_Setup(True) # extend functionality self.mirrorTransformations_Custom()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def rigPose_UI(self, parentWidget): """ This method creates the UI widget that gets parented into the publish UI that handles rig pose creation. A slider gets created for the overall module that goes from current pose to ideal rig pose. Then a slider gets created for each joint in the module to allow for finer control over the rig pose creation. :param parentWidget: the widget the rig pose UI (QFrame) will get parented to """ # Add a QFrame for the widget self.rigPoseFrame = QtWidgets.QFrame() self.rigPoseFrame.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) self.rigPoseFrame.setMinimumWidth(310) self.rigPoseFrame.setMaximumWidth(310) # load stylesheet styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss") f = open(styleSheetFile, "r") self.style = f.read() f.close() # add the rig pose frame to the stackWidget parentWidget.addWidget(self.rigPoseFrame) numWidgetsInStack = parentWidget.count() parentWidget.setCurrentIndex(numWidgetsInStack - 1) # frame styling backgroundImg = utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/field_background.png")) self.rigPoseFrame.setStyleSheet("background-image: url(" + backgroundImg + ");") # create an overall layout self.rigPoseLayout = QtWidgets.QVBoxLayout(self.rigPoseFrame) label = QtWidgets.QLabel(self.name) self.rigPoseLayout.addWidget(label) # create a slider for the overall module rig pose hboxLayout = QtWidgets.QHBoxLayout() self.rigPoseLayout.addLayout(hboxLayout) image1 = QtWidgets.QFrame() image1.setMinimumSize(30, 30) image1.setMaximumSize(30, 30) modelPoseImg = utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/modelPose.png")) image1.setStyleSheet("background-image: url(" + modelPoseImg + ");") hboxLayout.addWidget(image1) image1.setToolTip("Model Pose") self.overallSlider = QtWidgets.QSlider() self.overallSlider.setProperty("name", self.name) hboxLayout.addWidget(self.overallSlider) self.overallSlider.setOrientation(QtCore.Qt.Horizontal) self.overallSlider.setRange(0, 100) self.overallSlider.setSingleStep(1) self.overallSlider.setTracking(False) image2 = QtWidgets.QFrame() image2.setMinimumSize(30, 30) image2.setMaximumSize(30, 30) rigPoseImg = utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/rigPose.png")) image2.setStyleSheet("background-image: url(" + rigPoseImg + ");") hboxLayout.addWidget(image2) image2.setToolTip("Rig Pose") # create hboxlayout for resetAll and update Rig Pose buttons buttonLayout = QtWidgets.QHBoxLayout() self.rigPoseLayout.addLayout(buttonLayout) self.rigPoseResetAllBtn = QtWidgets.QPushButton("Reset Rig Pose") buttonLayout.addWidget(self.rigPoseResetAllBtn) self.rigPoseResetAllBtn.clicked.connect(self.resetRigPose) self.rigPoseResetAllBtn.setToolTip("Reset the module to it's initial ideal rig pose.") self.rigPoseResetAllBtn.setObjectName("blueButton") self.rigPoseResetAllBtn.setStyleSheet(self.style) self.rigPoseUpdateAllBtn = QtWidgets.QPushButton("Update Rig Pose") self.rigPoseUpdateAllBtn.setStyleSheet(self.style) buttonLayout.addWidget(self.rigPoseUpdateAllBtn) self.rigPoseUpdateAllBtn.clicked.connect(partial(self.updateRigPose, self.overallSlider)) self.rigPoseUpdateAllBtn.setToolTip( "Update the rig pose if you've done any custom manipulations to the controls.") self.rigPoseUpdateAllBtn.setObjectName("blueButton") # create a frame for the advanced controls self.rigPose_advancedGroup = QtWidgets.QGroupBox("Advanced") self.rigPoseLayout.addWidget(self.rigPose_advancedGroup) self.rigPose_advancedLayout = QtWidgets.QVBoxLayout(self.rigPose_advancedGroup) # create a slider for each created joint joints = self.returnCreatedJoints networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") for joint in joints: if cmds.objExists(joint): self.createRigPoseSliderForJoint(joint) else: jointBaseName = joint if self.name != baseName: nameData = self.name.split(baseName) if nameData[0] != "": jointBaseName = jointBaseName.partition(nameData[0])[2] if nameData[1] != "": jointBaseName = jointBaseName.partition(nameData[1])[0] if cmds.objExists(self.name + "_" + jointBaseName + "_mover"): self.createRigPoseSliderForJoint(joint) # create mirror button if applicable if cmds.getAttr(networkNode + ".mirrorModule") != "": mirrorMod = cmds.getAttr(networkNode + ".mirrorModule") if mirrorMod != None: self.rigPoseMirrorBtn = QtWidgets.QPushButton("Mirror to: " + mirrorMod) self.rigPoseLayout.addWidget(self.rigPoseMirrorBtn) self.rigPoseMirrorBtn.clicked.connect(self.mirrorTransformations_RigPose) self.rigPoseMirrorBtn.setObjectName("blueButton") self.rigPoseMirrorBtn.setStyleSheet(self.style) self.rigPoseLayout.addSpacerItem( QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def buildRig(self, textEdit, uiInst): """ This method starts building the rig for a module. It will then call on buildRigCustom, which is implemented in each derived module class as an override function. :param textEdit: The text edit in the buildProgressUI that we output information to. :param uiInst: passed in instance of the buildProgressUI """ # get current nodes in scene currentNodes = cmds.ls("*", long=True) successfulBuild = True errorMessage = "" # run the instance build function try: self.buildRigCustom(textEdit, uiInst) except Exception, e: successfulBuild = False errorMessage = str(traceback.format_exc()) # get all nodes in scene and compare to original list allNodes = cmds.ls("*", long=True) newNodes = list(set(allNodes).difference(currentNodes)) for node in newNodes: if not cmds.objExists(node + ".sourceModule"): cmds.addAttr(node, ln="sourceModule", dt="string") try: cmds.setAttr(node + ".sourceModule", self.name, type="string") except: print node if not successfulBuild: print "Build Rig Failed: " + str(e) print errorMessage
# self.deleteRig() # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def buildRigCustom(self, textEdit, uiInst): """ This method is what truly builds the rig for each module. It is implemented in the derived module class. :param textEdit: The text edit in the buildProgressUI that we output information to. :param uiInst: passed in instance of the buildProgressUI """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def deleteRig(self): """ This method deletes all rigging for the module. """ allNodes = cmds.ls("*") for node in allNodes: if cmds.objExists(node + ".sourceModule"): cmds.lockNode(node, lock=False) source = cmds.getAttr(node + ".sourceModule") if source == self.name: try: cmds.delete(node) except: pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def mirrorTransformations_Custom(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def updateSettingsUI(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def applyModuleChanges(self, moduleInst): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def addJointMoverToOutliner(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def updateOutliner(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def skinProxyGeo(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def aimMode(self, state): """ This method toggles the aim mode state if the module can have aim mode. It then calls on each derived module's aimMode_Setup which defines how to setup aim mode for the module. """ networkNode = self.returnNetworkNode cmds.setAttr(networkNode + ".aimMode", lock=False) cmds.setAttr(networkNode + ".aimMode", state, lock=True) self.aimMode_Setup(state)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def aimMode_Setup(self, state): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setupModelPoseForRig(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def matchModelPose(self): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def pinModule(self, state): """ This method is implemented in the derived module class. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def bakeOffsets(self): """ This method bakes any transforms on the offset movers up to the global movers, and then zeroes out the offset movers. """ # get movers jointMovers = self.returnJointMovers # separate mover lists globalMovers = jointMovers[0] offsetMovers = jointMovers[1] constraints = [] locators = [] # create locators for the offsetMovers, then zero out offset mover for mover in offsetMovers: locatorName = mover.partition("_offset")[0] + "_loc" loc = cmds.spaceLocator(name=locatorName)[0] # constrain locator constraint = cmds.parentConstraint(mover, loc)[0] cmds.delete(constraint) # parent locator under a copy of the locatorName parentLoc = cmds.duplicate(loc)[0] cmds.parent(loc, parentLoc) locators.append(parentLoc) for mover in offsetMovers: for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]: try: cmds.setAttr(mover + attr, 0) except: pass # snap global movers to locators for mover in globalMovers: if cmds.objExists(mover + "_loc"): constraint = cmds.parentConstraint(mover + "_loc", mover)[0] constraints.append(constraint) # remove locs for const in constraints: cmds.delete(const) for loc in locators: cmds.delete(loc)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setupForRigPose(self): """ This method unhides the movers and constrains the joints to the movers for creating the rig pose. If the user wants to create a custom rig pose (instead of using the sliders), this method sets the module up for that functionality. """ # unlock joint movers cmds.select("JointMover", hi=True) jmNodes = cmds.ls(sl=True) for node in jmNodes: cmds.lockNode(node, lock=False) # find the mover shapes and set their visibility movers = self.returnJointMovers globalMovers = movers[0] shapes = [] for each in movers: for mover in each: 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", 0, lock=True) # show global movers shapes = [] for mover in globalMovers: 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", 1, lock=True) # unlock mover group for this module and make visible cmds.lockNode(self.name + "_mover_grp", lock=False) cmds.setAttr(self.name + "_mover_grp.v", lock=False) cmds.setAttr(self.name + "_mover_grp.v", 1) # hide the proxy geo cmds.select(self.name + "_mover_grp", hi=True) allNodes = cmds.ls(sl=True) for node in allNodes: if node.find("_proxy_geo") != -1: if cmds.nodeType(node) == "mesh": parent = cmds.listRelatives(node, parent=True)[0] cmds.lockNode(parent, lock=False) cmds.setAttr(parent + ".v", lock=False) cmds.setAttr(parent + ".v", 0) cmds.lockNode(parent, lock=True) # get the joints created by this module joints = self.returnCreatedJoints # create mover name networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") for joint in joints: if cmds.objExists(joint + "_mover_offset"): cmds.parentConstraint(joint + "_mover_offset", joint) else: jointBaseName = joint if self.name != baseName: nameData = self.name.split(baseName) if nameData[0] != "": jointBaseName = jointBaseName.partition(nameData[0])[2] if nameData[1] != "": jointBaseName = jointBaseName.partition(nameData[1])[0] if cmds.objExists(self.name + "_" + jointBaseName + "_mover_offset"): cmds.parentConstraint(self.name + "_" + jointBaseName + "_mover_offset", joint) # lock joint movers cmds.select("JointMover", hi=True) jmNodes = cmds.ls(sl=True) for node in jmNodes: cmds.lockNode(node, lock=True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setSkeletonPose(self, poseType): """ This method constrains the joints to the movers and then stores that pose data for those joints. This could be the model pose or the rig pose. :param poseType: whether to set the model pose or rig pose for the joints. """ # get the joints created by this module joints = self.returnCreatedJoints # create mover name networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") for joint in joints: if cmds.objExists(joint + "_mover_offset"): cmds.parentConstraint(joint + "_mover_offset", joint) else: jointBaseName = joint if self.name != baseName: nameData = self.name.split(baseName) if nameData[0] != "": jointBaseName = jointBaseName.partition(nameData[0])[2] if nameData[1] != "": jointBaseName = jointBaseName.partition(nameData[1])[0] if cmds.objExists(self.name + "_" + jointBaseName + "_mover_offset"): cmds.parentConstraint(self.name + "_" + jointBaseName + "_mover_offset", joint) # set pose self.setReferencePose(poseType)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def removeSkeletalConstraints(self): """ This method removes any constraints on the joints. This tends to get called by removing rigging. """ # get the joints created by this module and remove the constraints joints = self.returnCreatedJoints # create mover name networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") for joint in joints: if cmds.objExists(joint + "_mover_offset"): cmds.select(joint) cmds.delete(constraints=True) else: jointBaseName = joint if self.name != baseName: nameData = self.name.split(baseName) if nameData[0] != "": jointBaseName = jointBaseName.partition(nameData[0])[2] if nameData[1] != "": jointBaseName = jointBaseName.partition(nameData[1])[0] if cmds.objExists(self.name + "_" + jointBaseName + "_mover_offset"): cmds.select(joint) cmds.delete(constraints=True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def cleanUpRigPose(self): """ This method hides the joint movers and unconstrains the joints from the movers after setting a rig pose. """ # show the proxy geo cmds.select(self.name + "_mover_grp", hi=True) allNodes = cmds.ls(sl=True) for node in allNodes: if node.find("_proxy_geo") != -1: if cmds.nodeType(node) == "mesh": parent = cmds.listRelatives(node, parent=True)[0] cmds.lockNode(parent, lock=False) cmds.setAttr(parent + ".v", lock=False) cmds.setAttr(parent + ".v", 1) cmds.lockNode(parent, lock=True) # unlock mover group for this module and make invisible cmds.lockNode(self.name + "_mover_grp", lock=False) cmds.setAttr(self.name + "_mover_grp.v", lock=False) cmds.setAttr(self.name + "_mover_grp.v", 0) cmds.setAttr(self.name + "_mover_grp.v", lock=True) cmds.lockNode(self.name + "_mover_grp", lock=True) # get the joints created by this module and remove the constraints joints = self.returnCreatedJoints # create mover name networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") for joint in joints: if cmds.objExists(joint + "_mover_offset"): cmds.select(joint) cmds.delete(constraints=True) else: jointBaseName = joint if self.name != baseName: nameData = self.name.split(baseName) if nameData[0] != "": jointBaseName = jointBaseName.partition(nameData[0])[2] if nameData[1] != "": jointBaseName = jointBaseName.partition(nameData[1])[0] if cmds.objExists(self.name + "_" + jointBaseName + "_mover_offset"): cmds.select(joint) cmds.delete(constraints=True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def updateRigPose(self, slider): """ This method updates what the stored rig pose is for a module. The default rig pose tends to be zeroed out rotations, but this function can essentially update what the max value on the rig pose slider sets the pose to. :param slider: The rig pose slider where the min is the current model pose and the max is the rig pose. """ # get network node networkNode = self.returnNetworkNode # get pose data off networkNode originalData = json.loads(cmds.getAttr(networkNode + ".rigPose")) newPose = [] for data in originalData: moverData = {} mover = data.get("mover") moverData["mover"] = mover if cmds.objExists(mover): translate = cmds.getAttr(mover + ".translate")[0] rotate = cmds.getAttr(mover + ".rotate")[0] moverData["translate"] = translate moverData["rotate"] = rotate newPose.append(moverData) jsonString = json.dumps(newPose) cmds.setAttr(networkNode + ".rigPose", jsonString, type="string") slider.setValue(0) slider.setValue(100)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def resetRigPose(self): """ This method resets the module rig pose to be the default (zeroed rotations). """ # get the network node networkNode = self.returnNetworkNode # remove the rigPose attribute on the networkNode cmds.deleteAttr(networkNode, at="rigPose") # recreate rig pose node with defaults self.getReferencePose("rigPose") # set slider self.overallSlider.setValue(0) self.overallSlider.setValue(100)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def resetRigPose_Part(self, part): """ This method resets the given joint (part) rig pose to be zeroed rotations. This is for the part slider on the rig pose UI in the advanced section. :param part: The given joint name slider. """ # get the networkNode networkNode = self.returnNetworkNode # get the poseData poseData = json.loads(cmds.getAttr(networkNode + ".rigPose")) # find our part in the pose data for data in poseData: mover = data.get("mover") if mover == part: rotate = data.get("rotate") try: cmds.setAttr(mover + ".rotate", 0, 0, 0, type="double3") data["rotate"] = (0.0, 0.0, 0.0) except: pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def getReferencePose(self, poseType, zeroPose=True): """ This method gets the model pose or the rig pose (depending on poseType) and stores that data for the movers. :param poseType: Whether or not to get the model pose or rig pose. :param zeroPose: Whether or not the default rig pose should be set to zeroed rotations. """ # get movers jointMovers = self.returnJointMovers # separate mover lists globalMovers = jointMovers[0] offsetMovers = jointMovers[1] # get the network node networkNode = self.returnNetworkNode # if rigPose already exists, then do not set values if poseType == "rigPose": if cmds.objExists(networkNode + "." + poseType): return # create the pose data attr if needed if not cmds.objExists(networkNode + "." + poseType): cmds.addAttr(networkNode, sn=poseType, dt="string") # create reference pose data dict poseData = [] # loop through each mover, getting the translate and rotate values, creating an attribute on the network node # to store those values for moverList in [globalMovers, offsetMovers]: for mover in moverList: moverData = {} moverData["mover"] = mover for attr in ["translate", "rotate"]: value = cmds.getAttr(mover + "." + attr)[0] if zeroPose: if poseType == "rigPose": if attr == "rotate": value = (0.0, 0.0, 0.0) # add the data to the list moverData[attr] = value # add mover data to the pose data list poseData.append(moverData) # dump the pose data list onto the poseType attribute jsonString = json.dumps(poseData) cmds.setAttr(networkNode + "." + poseType, jsonString, type="string")
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setReferencePose(self, poseType): """ This method gets the data for the given pose type (rig or model) and sets the movers with those values. :param poseType: Whether to set the model pose or the rig pose on the movers. """ # get the network node networkNode = self.returnNetworkNode # get the pose data from the attribute if cmds.objExists(networkNode + "." + poseType): poseData = json.loads(cmds.getAttr(networkNode + "." + poseType)) for data in poseData: mover = data.get("mover") translate = data.get("translate") rotate = data.get("rotate") # if the mover exists, set the values if cmds.objExists(mover): # set translations for i in range(len(translate)): if i == 0: try: cmds.setAttr(mover + ".translateX", translate[i]) except: pass if i == 1: try: cmds.setAttr(mover + ".translateY", translate[i]) except: pass if i == 2: try: cmds.setAttr(mover + ".translateZ", translate[i]) except: pass # set rotations for i in range(len(rotate)): if i == 0: try: cmds.setAttr(mover + ".rotateX", rotate[i]) except: pass if i == 1: try: cmds.setAttr(mover + ".rotateY", rotate[i]) except: pass if i == 2: try: cmds.setAttr(mover + ".rotateZ", rotate[i]) except: pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setReferencePoseSlider(self, part, *args): """ This method takes the slider value of a given part and then calls on setPosePercentage, which will then find the values of the model pose and the rig pose and figure out based on the slider percentage what values to set on the mover. :param part: the joint mover which the slider is controlling. :param args: the values from the slider """ percent = float(args[0]) * .01 self.setPosePercentage(percent, part)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setPosePercentage(self, percent, part): """ This method takes the percent from setReferencePoseSlider, gets the values of the model pose and rig pose for the given part, then calls on setPosePercentage_Part to find and set the values on the mover that is the percentage between model and rig pose. Example: If the model pose is a value of 10 and the rig pose is a value of 0, and the slider is at .5, then the value to set is 5. (But this is done and found per attribute) :param percent: What percent of model and rig pose to set. :param part: What joint mover to set the values on. """ # get network node networkNode = self.returnNetworkNode # get reference pose attributes modelPoseData = json.loads(cmds.getAttr(networkNode + ".modelPose")) rigPoseData = json.loads(cmds.getAttr(networkNode + ".rigPose")) # get the data for each mover for poseData in modelPoseData: mover = poseData.get("mover") translate = poseData.get("translate") rotate = poseData.get("rotate") if part != None: if part == mover: self.setPosePercentage_Part(percent, mover, modelPoseData, rigPoseData, poseData, translate, rotate) else: self.setPosePercentage_Part(percent, mover, modelPoseData, rigPoseData, poseData, translate, rotate)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def setPosePercentage_Part(self, percent, mover, modelPoseData, rigPoseData, poseData, translate, rotate): """ This method takes the data from setPosePercentage and figures out what values to set on the given part (mover). Example: If the model pose is a value of 10 and the rig pose is a value of 0, and the slider is at .5, then the value to set is 5. (But this is done and found per attribute) :param percent: the percent value of the slider. What percentage of the model and rig pose to use. :param mover: the mover to set the values on. :param modelPoseData: all of the data for the model pose for this mover. :param rigPoseData: all of the data for the rig pose for this mover. :param poseData: a list which includes the mover and its translate and rotate values. :param translate: the translate values for the model pose :param rotate: the rotate values for the model pose """ # get the index of this entry in the rigPoseData list index = modelPoseData.index(poseData) # get the corresponding rig pose data rigData = rigPoseData[index] rigTranslate = rigData.get("translate") rigRotate = rigData.get("rotate") # find percentile between model and rig pose to set on each attribute for i in range(len(translate)): valueToSet = mathUtils.returnPercentile([translate[i], rigTranslate[i]], percent) if i == 0: cmds.setAttr(mover + ".translateX", valueToSet) if i == 1: cmds.setAttr(mover + ".translateY", valueToSet) if i == 2: cmds.setAttr(mover + ".translateZ", valueToSet) for i in range(len(rotate)): valueToSet = mathUtils.returnPercentile([rotate[i], rigRotate[i]], percent) if i == 0: cmds.setAttr(mover + ".rotateX", valueToSet) if i == 1: cmds.setAttr(mover + ".rotateY", valueToSet) if i == 2: cmds.setAttr(mover + ".rotateZ", valueToSet)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def createRigPoseSliderForJoint(self, joint): """ This method creates the rig pose slider widget for the given joint. (This shows up in the advanced section of the rig pose UI) :param joint: The joint that the slider will control. """ # load stylesheet styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss") f = open(styleSheetFile, "r") self.style = f.read() f.close() # create mover name networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") jointName = joint if cmds.objExists(joint + "_mover"): jointName = joint else: jointBaseName = joint if self.name != baseName: nameData = self.name.split(baseName) if nameData[0] != "": jointName = jointBaseName.partition(nameData[0])[2] if nameData[1] != "": jointName = jointName.partition(nameData[1])[0] jointName = self.name + "_" + jointName else: jointName = self.name + "_" + jointName # create a master vertical layout mainLayout = QtWidgets.QVBoxLayout() self.rigPose_advancedLayout.addLayout(mainLayout) # create a label for the joint font = QtGui.QFont() font.setPointSize(10) font.setBold(True) jointLabel = QtWidgets.QLabel(joint + ":") jointLabel.setFont(font) mainLayout.addWidget(jointLabel) # create layout for slider/button layout = QtWidgets.QHBoxLayout() mainLayout.addLayout(layout) # create slider for joint slider = QtWidgets.QSlider() layout.addWidget(slider) slider.setProperty("name", joint) slider.setOrientation(QtCore.Qt.Horizontal) slider.setRange(0, 100) slider.setSingleStep(1) slider.valueChanged.connect(partial(self.setReferencePoseSlider, jointName + "_mover")) slider.setTracking(False) self.overallSlider.valueChanged.connect(slider.setValue) # create reset button button = QtWidgets.QPushButton("Reset") button.setMinimumWidth(70) button.setMaximumWidth(70) layout.addWidget(button) button.setObjectName("blueButton") button.setStyleSheet(self.style) button.clicked.connect(partial(self.resetRigPose_Part, jointName + "_mover"))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def updateBoneCount(self): """ This method looks at the create bones attribute of the module and gets the number of bones in that list and appends it onto the total bone count for the bone counter interface. """ if cmds.window("ART_BoneCounterWin", exists=True): if self.rigUiInst.boneCounterInst is not None: self.rigUiInst.boneCounterInst.updateBoneCount()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def toggleShapeVis(self, transform, value): """ This method finds the shapes for the passed in transform and toggles the visibility based on the value. :param transform: the transform to get the shape nodes from. :param value: whether to show or hide the shape nodes. """ if cmds.objExists(transform): shape = cmds.listRelatives(transform, shapes=True) if shape is not None: cmds.setAttr(shape[0] + ".v", lock=False) cmds.setAttr(shape[0] + ".v", value) cmds.setAttr(shape[0] + ".v", lock=True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def selectionScriptJob_animUI(self, buttonData): """ This method is called from a scriptjob anytime a selection is changed. It's sole purpose it to update the button color on the anim picker to show if a control is selected or not. :param buttonData: pairings of button/control/brush. brush is the original color of the button. """ selection = mel.eval("ls -sl;") if selection is None: selection = [] for data in buttonData: control = data[1] button = data[0] brushColor = data[2] if control in selection: button.brush.setColor(QtCore.Qt.white) button.update() else: button.brush.setColor(brushColor) button.update()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def importFBX_pre(self, importMethod, character): """ This method runs before an fbx is imported onto the control rig. It cuts any keys on the controls and zeroes the controls out before importing the fbx (which is called in the derived module class) :param importMethod: Whether or not the FBX is getting imported as FK, IK, Both, or None :param character: The namespace of the rig. """ if importMethod != "None": controls = self.getControls() for control in controls: cmds.cutKey(character + ":" + control) self.resetRigControls(True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def importFBX(self, importMethod, character): """ This method is implemented in the derived module class and defines how mocap is imported onto the rig controls. :param importMethod: Whether or not the FBX is getting imported as FK, IK, Both, or None :param character: The namespace of the rig. """ pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def resetRigControls(self, resetAll): """ This method zeroes out control attributes. If resetAll is true, then it will zero out all rig controls for the module. Otherwise, it will only zero out the selected controls of the module. :param resetAll: Whether or not to reset only the selected controls or all controls of the module. """ # get namespace networkNode = self.returnRigNetworkNode characterNode = cmds.listConnections(networkNode + ".parent")[0] namespace = cmds.getAttr(characterNode + ".namespace") if resetAll: # list any attributes on the network node that contain "controls" controls = cmds.listAttr(networkNode, st="*Controls") # get that data on that attr for control in controls: data = json.loads(cmds.getAttr(networkNode + "." + control)) # reset the attr on each control nonZeroAttrs = ["scale", "globalScale", "scaleX", "scaleY", "scaleZ"] try: for each in data: attrs = cmds.listAttr(namespace + ":" + each, keyable=True) for attr in attrs: if attr not in nonZeroAttrs: cmds.setAttr(namespace + ":" + each + "." + attr, 0) else: cmds.setAttr(namespace + ":" + each + "." + attr, 1) except: cmds.warning("skipped " + str(control) + ". No valid controls found to reset.") if not resetAll: nonZeroAttrs = ["scale", "globalScale", "scaleX", "scaleY", "scaleZ"] selection = cmds.ls(sl=True) for each in selection: attrs = cmds.listAttr(each, keyable=True) for attr in attrs: if attr not in nonZeroAttrs: cmds.setAttr(each + "." + attr, 0) else: cmds.setAttr(each + "." + attr, 1)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def getControls(self): """ This method returns a list of all the rig controls of the module. :return: List of all rig controls in the module. """ # get namespace networkNode = self.returnRigNetworkNode if networkNode is None: winParent = interfaceUtils.getMainWindow() win = interfaceUtils.DialogMessage("Error", "This function does not work without a namespace.", [], 0, winParent) win.show() return None # list any attributes on the network node that contain "controls" controls = cmds.listAttr(networkNode, st="*Controls") returnControls = [] # get that data on that attr for control in controls: data = json.loads(cmds.getAttr(networkNode + "." + control)) # reset the attr on each control if data is not None: for each in data: returnControls.append(each) return returnControls
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs] def selectRigControls(self): """ This method calls on getControls to return a list of the controls and the selects them. """ controls = self.getControls() # get namespace networkNode = self.returnRigNetworkNode characterNode = cmds.listConnections(networkNode + ".parent")[0] namespace = cmds.getAttr(characterNode + ".namespace") for control in controls: cmds.select(namespace + ":" + control, add=True)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # PROPERTIES @property def getModules(self): """ This method finds the main "character" module that has connections to all of the rig modules :return: returns the character node. """ modules = cmds.ls(type="network") for module in modules: attrs = cmds.listAttr(module) if "rigModules" in attrs: return module @property def getAllModules(self): """ This method finds all connected rig modules to the main character network node. :return: returns a list of the rig modules """ modules = cmds.ls(type="network") returnMods = [] for module in modules: attrs = cmds.listAttr(module) if "parent" in attrs: returnMods.append(module) return returnMods @property def returnNetworkNode(self): """ This method returns the module's own network node. :return: the modules network node """ networkNodes = cmds.ls(type="network") for node in networkNodes: attrs = cmds.listAttr(node) if "moduleName" in attrs: if cmds.getAttr(node + ".moduleName") == self.name: networkNode = node return networkNode @property def returnRigNetworkNode(self): """ This method returns the module's own network node using the namespace on the main character network node. This is so that if there are multiple characters in a scene, we know which network node for which character we are trying to return. :return: returns this module's network node in a scene with references. """ modules = [] networkNodes = cmds.ls(type="network") for node in networkNodes: attrs = cmds.listAttr(node) if "moduleName" in attrs: if cmds.getAttr(node + ".moduleName") == self.name: characterNode = cmds.listConnections(node + ".parent")[0] if cmds.objExists(characterNode + ".namespace"): if cmds.getAttr(characterNode + ".namespace") == self.namespace.partition(":")[0]: networkNode = node return networkNode else: return None @property def returnClassObject(self): return self @property def returnCreatedJoints(self): """ This method loops through the Created Bones attribute on its network node and returns a list of the joints it will create given the current module settings. :return: A list of the created bones of the module. """ networkNode = self.returnNetworkNode joints = cmds.getAttr(networkNode + ".Created_Bones") splitJoints = joints.split("::") createdJoints = [] for bone in splitJoints: if bone != "": createdJoints.append(bone) return createdJoints @property def returnJointMovers(self): """ This method finds and returns all joint movers for the module. :return: a list of all global movers, offset movers, and geo movers for the module. """ name = self.groupBox.title() # select global movers cmds.select(name + "*_mover") globalMovers = cmds.ls(sl=True) # select offset movers cmds.select(name + "*_mover_offset") offsetMovers = cmds.ls(sl=True) # mesh movers cmds.select(name + "*_mover_geo") geoMovers = cmds.ls(sl=True) return [globalMovers, offsetMovers, geoMovers] @property def returnMirrorModuleInst(self): """ This method finds and returns the instance of a module's mirror module. :return: a pointer in memory to the instance of the mirror module. """ # get network node networkNode = self.returnNetworkNode mirrorModule = cmds.getAttr(networkNode + ".mirrorModule") # find instance through rig UI inst for inst in self.rigUiInst.moduleInstances: networkNode = inst.returnNetworkNode moduleName = cmds.getAttr(networkNode + ".moduleName") if moduleName == mirrorModule: return inst @property def returnPrefixSuffix(self): """ This method splits our module name by the base name and returns the prefix and suffix. :return: the user-defined prefix and suffix found by splitting the module name by the base name. """ prefix = None suffix = None networkNode = self.returnNetworkNode baseName = cmds.getAttr(networkNode + ".baseName") splitName = self.name.split(baseName) if splitName[0] != '': prefix = splitName[0] if splitName[1] != '': suffix = splitName[1] return [prefix, suffix]