"""
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 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 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 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 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 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]