aboutsummaryrefslogtreecommitdiff
path: root/Core/Scripts/RigModules
diff options
context:
space:
mode:
authorMobileMachine\jeremy <[email protected]>2017-06-06 22:59:03 -0400
committerMobileMachine\jeremy <[email protected]>2017-06-06 22:59:03 -0400
commit24725fa8681f906ab44d80687c09fecc171a2896 (patch)
tree312a601df29aca7f8db9f44082d96ebc7a679138 /Core/Scripts/RigModules
parentInitial commit (diff)
downloadartv2-24725fa8681f906ab44d80687c09fecc171a2896.tar.xz
artv2-24725fa8681f906ab44d80687c09fecc171a2896.zip
Initial Submission
First submission of current state of ARTv2. Currently considered to be in Alpha. There are a couple of animation tools not implemented yet, and one module not implemented yet, as well as incomplete documentation.
Diffstat (limited to 'Core/Scripts/RigModules')
-rw-r--r--Core/Scripts/RigModules/ART_Arm_Standard.py4863
-rw-r--r--Core/Scripts/RigModules/ART_Chain.py294
-rw-r--r--Core/Scripts/RigModules/ART_Head.py1068
-rw-r--r--Core/Scripts/RigModules/ART_Leaf.py1414
-rw-r--r--Core/Scripts/RigModules/ART_Leg_Standard.py3758
-rw-r--r--Core/Scripts/RigModules/ART_Root.py246
-rw-r--r--Core/Scripts/RigModules/ART_Torso.py2394
-rw-r--r--Core/Scripts/RigModules/__init__.py0
8 files changed, 14037 insertions, 0 deletions
diff --git a/Core/Scripts/RigModules/ART_Arm_Standard.py b/Core/Scripts/RigModules/ART_Arm_Standard.py
new file mode 100644
index 0000000..a0e82ec
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Arm_Standard.py
@@ -0,0 +1,4863 @@
+import json
+import os
+import time
+import weakref
+from functools import partial
+
+import maya.cmds as cmds
+
+import System.interfaceUtils as interfaceUtils
+import System.riggingUtils as riggingUtils
+import System.utils as utils
+from System.ART_RigModule import ART_RigModule
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+# file attributes
+icon = "Modules/armStandard.png"
+hoverIcon = "Modules/hover_armStandard.png"
+search = "biped:arm"
+className = "ART_Arm_Standard"
+jointMover = "Core/JointMover/ART_Arm_Standard.ma"
+baseName = "arm"
+rigs = ["FK::IK"]
+fbxImport = ["None", "FK", "IK", "Both"]
+matchData = [True, ["Match FK to IK", "Match IK to FK"]]
+controlTypes = [["fkControls", "FK"], ["ikControls", "IK"], ["upArmTwistControls", "FK"], ["loArmTwistControls", "FK"],
+ ["fkFingerControls", "FK"], ["ikFingerControls", "IK"], ["clavControls", "FK"], ["clavControls", "IK"]]
+sorting = 0
+
+# begin class
+class ART_Arm_Standard(ART_RigModule):
+ _instances = set()
+
+ def __init__(self, rigUiInst, moduleUserName):
+
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+
+ self.__class__._instances.add(weakref.ref(self))
+
+ ART_RigModule.__init__(self, "ART_Arm_Standard_Module", "ART_Arm_Standard", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ # call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ # add custom attributes for this specific module
+ bones = "clavicle::upperarm::lowerarm::hand::thumb_metacarpal::thumb_proximal::thumb_distal::index_proximal::"
+ bones += "index_middle::index_distal::middle_proximal::middle_middle::middle_distal::ring_proximal::"
+ bones += "ring_middle::ring_distal::pinky_proximal::pinky_middle::pinky_distal::"
+
+ cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", bones, type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".canAim", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".aimMode", False, lock=True)
+
+ # joint mover settings
+ cmds.addAttr(self.networkNode, sn="armTwists", keyable=False)
+ cmds.setAttr(self.networkNode + ".armTwists", 0, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="forearmTwists", keyable=False)
+ cmds.setAttr(self.networkNode + ".forearmTwists", 0, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="thumbJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".thumbJoints", 2, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="thumbMeta", keyable=False, at="bool")
+ cmds.setAttr(self.networkNode + ".thumbMeta", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="indexJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".indexJoints", 3, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="indexMeta", keyable=False, at="bool")
+ cmds.setAttr(self.networkNode + ".indexMeta", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="middleJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".middleJoints", 3, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="middleMeta", keyable=False, at="bool")
+ cmds.setAttr(self.networkNode + ".middleMeta", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="ringJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".ringJoints", 3, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="ringMeta", keyable=False, at="bool")
+ cmds.setAttr(self.networkNode + ".ringMeta", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="pinkyJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".pinkyJoints", 3, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="pinkyMeta", keyable=False, at="bool")
+ cmds.setAttr(self.networkNode + ".pinkyMeta", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="side", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".side", "Left", type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="includeClavicle", keyable=False, at="bool")
+ cmds.setAttr(self.networkNode + ".includeClavicle", True, lock=True)
+
+ # rig creation settings
+ cmds.addAttr(self.networkNode, sn="buildFK", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".buildFK", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="buildIK_V1", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".buildIK_V1", True, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+ networkNode = self.returnNetworkNode
+
+ # groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 500, True)
+
+ font = QtGui.QFont()
+ font.setPointSize(8)
+
+ headerFont = QtGui.QFont()
+ headerFont.setPointSize(8)
+ headerFont.setBold(True)
+
+ # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot
+ self.layout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.frame = QtWidgets.QFrame(self.groupBox)
+ self.layout.addWidget(self.frame)
+
+ self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.frame.setMinimumSize(QtCore.QSize(320, 465))
+ self.frame.setMaximumSize(QtCore.QSize(320, 465))
+
+ # add layout for custom settings
+ self.customSettingsLayout = QtWidgets.QVBoxLayout(self.frame)
+
+ # mirror module
+ self.mirrorModLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.mirrorModLayout)
+ self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ")
+ self.mirrorModuleLabel.setFont(font)
+ self.mirrorModLayout.addWidget(self.mirrorModuleLabel)
+
+ mirror = cmds.getAttr(networkNode + ".mirrorModule")
+ if mirror == "":
+ mirror = "None"
+ self.mirrorMod = QtWidgets.QLabel(mirror)
+ self.mirrorMod.setFont(font)
+ self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter)
+ self.mirrorModLayout.addWidget(self.mirrorMod)
+
+ # current parent
+ self.currentParentMod = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.currentParentMod)
+ self.currentParentLabel = QtWidgets.QLabel("Current Parent: ")
+ self.currentParentLabel.setFont(font)
+ self.currentParentMod.addWidget(self.currentParentLabel)
+
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.currentParent = QtWidgets.QLabel(parent)
+ self.currentParent.setFont(font)
+ self.currentParent.setAlignment(QtCore.Qt.AlignHCenter)
+ self.currentParentMod.addWidget(self.currentParent)
+
+ # button layout for name/parent
+ self.buttonLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.buttonLayout)
+ self.changeNameBtn = QtWidgets.QPushButton("Change Name")
+ self.changeParentBtn = QtWidgets.QPushButton("Change Parent")
+ self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module")
+ self.buttonLayout.addWidget(self.changeNameBtn)
+ self.buttonLayout.addWidget(self.changeParentBtn)
+ self.buttonLayout.addWidget(self.mirrorModuleBtn)
+ self.changeNameBtn.setObjectName("blueButton")
+ self.changeParentBtn.setObjectName("blueButton")
+ self.mirrorModuleBtn.setObjectName("blueButton")
+
+ # add side settings
+ self.sideLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.sideLayout)
+ self.sideLabel = QtWidgets.QLabel("Side: ")
+ self.sideLabel.setFont(font)
+ self.leftSideBtn = QtWidgets.QRadioButton("Left Side")
+ self.rightSideBtn = QtWidgets.QRadioButton("Right Side")
+ self.sideLayout.addWidget(self.sideLabel)
+ self.sideLayout.addWidget(self.leftSideBtn)
+ self.sideLayout.addWidget(self.rightSideBtn)
+
+ # get current side
+ if cmds.getAttr(networkNode + ".side") == "Left":
+ self.leftSideBtn.setChecked(True)
+ if cmds.getAttr(networkNode + ".side") == "Right":
+ self.rightSideBtn.setChecked(True)
+
+ self.leftSideBtn.clicked.connect(self.changeSide)
+ self.rightSideBtn.clicked.connect(self.changeSide)
+
+ # coplanar mode and bake offsets layout
+ self.armToolsLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.armToolsLayout)
+
+ # Coplanar mode
+ self.coplanarBtn = QtWidgets.QPushButton("Coplanar Mode")
+ self.coplanarBtn.setFont(headerFont)
+ self.armToolsLayout.addWidget(self.coplanarBtn)
+ self.coplanarBtn.setCheckable(True)
+ self.coplanarBtn.clicked.connect(self.coplanarMode)
+ self.coplanarBtn.setToolTip("[EXPERIMENTAL] Forces arm joints to always be planar for best IK setup")
+
+ # Bake OFfsets
+ self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets")
+ self.bakeOffsetsBtn.setFont(headerFont)
+ self.armToolsLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync")
+
+ self.coplanarBtn.setObjectName("blueButton")
+ self.bakeOffsetsBtn.setObjectName("blueButton")
+
+ # Clavicle Settings
+ spacerItem = QtWidgets.QSpacerItem(200, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ self.clavicleCB = QtWidgets.QCheckBox("Include Clavicle?")
+ self.clavicleCB.setChecked(True)
+ self.customSettingsLayout.addWidget(self.clavicleCB)
+
+ spacerItem = QtWidgets.QSpacerItem(200, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ # Twist Bone Settings
+ self.twistSettingsLabel = QtWidgets.QLabel("Twist Bone Settings: ")
+ self.twistSettingsLabel.setFont(headerFont)
+ self.twistSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);")
+ self.customSettingsLayout.addWidget(self.twistSettingsLabel)
+
+ self.separatorA = QtWidgets.QFrame()
+ self.separatorA.setFrameShape(QtWidgets.QFrame.HLine)
+ self.separatorA.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.customSettingsLayout.addWidget(self.separatorA)
+
+ self.twistBonesLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.twistBonesLayout)
+
+ self.twistForm = QtWidgets.QFormLayout()
+ self.upperarmTwistLabel = QtWidgets.QLabel("UpperArm: ")
+ self.upperarmTwistLabel.setFont(font)
+ self.twistForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.upperarmTwistLabel)
+ self.upperarmTwistNum = QtWidgets.QSpinBox()
+ self.upperarmTwistNum.setMaximum(3)
+ self.twistForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.upperarmTwistNum)
+ self.twistBonesLayout.addLayout(self.twistForm)
+
+ self.lowerArmTwistForm = QtWidgets.QFormLayout()
+ self.lowerarmTwistLabel = QtWidgets.QLabel("LowerArm: ")
+ self.lowerarmTwistLabel.setFont(font)
+ self.lowerArmTwistForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.lowerarmTwistLabel)
+ self.lowerarmTwistNum = QtWidgets.QSpinBox()
+ self.lowerarmTwistNum.setMaximum(3)
+ self.lowerArmTwistForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lowerarmTwistNum)
+ self.twistBonesLayout.addLayout(self.lowerArmTwistForm)
+
+ # Hand Settings Section
+ self.handSettingsLabel = QtWidgets.QLabel("Hand Settings: ")
+ self.handSettingsLabel.setFont(headerFont)
+ self.handSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);")
+ self.customSettingsLayout.addWidget(self.handSettingsLabel)
+
+ self.separatorB = QtWidgets.QFrame()
+ self.separatorB.setFrameShape(QtWidgets.QFrame.HLine)
+ self.separatorB.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.customSettingsLayout.addWidget(self.separatorB)
+
+ # Thumb Settings: add VBoxLayout
+ self.fingerVBoxLayout = QtWidgets.QVBoxLayout()
+ self.customSettingsLayout.addLayout(self.fingerVBoxLayout)
+
+ # THUMB
+ self.thumbLayout = QtWidgets.QHBoxLayout()
+
+ self.thumbLabel = QtWidgets.QLabel("Thumb Joints: ")
+ self.thumbLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.thumbLabel.setMinimumSize(QtCore.QSize(100, 20))
+ self.thumbLabel.setMaximumSize(QtCore.QSize(100, 20))
+ self.thumbLayout.addWidget((self.thumbLabel))
+
+ self.thumbNum = QtWidgets.QSpinBox()
+ self.thumbNum.setMaximum(2)
+ self.thumbNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.thumbNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.thumbNum.setValue(2)
+ self.thumbNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.thumbLayout.addWidget(self.thumbNum)
+
+ self.thumbMeta = QtWidgets.QCheckBox("Include Metacarpal")
+ self.thumbMeta.setChecked(True)
+ self.thumbMeta.setMinimumSize(QtCore.QSize(150, 20))
+ self.thumbMeta.setMaximumSize(QtCore.QSize(150, 20))
+ self.thumbLayout.addWidget(self.thumbMeta)
+ self.fingerVBoxLayout.addLayout(self.thumbLayout)
+
+ # INDEX
+ self.indexLayout = QtWidgets.QHBoxLayout()
+
+ self.indexLabel = QtWidgets.QLabel("Index Joints: ")
+ self.indexLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.indexLabel.setMinimumSize(QtCore.QSize(100, 20))
+ self.indexLabel.setMaximumSize(QtCore.QSize(100, 20))
+ self.indexLayout.addWidget((self.indexLabel))
+
+ self.indexNum = QtWidgets.QSpinBox()
+ self.indexNum.setMaximum(3)
+ self.indexNum.setValue(3)
+ self.indexNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.indexNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.indexNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.indexLayout.addWidget(self.indexNum)
+
+ self.indexMeta = QtWidgets.QCheckBox("Include Metacarpal")
+ self.indexMeta.setMinimumSize(QtCore.QSize(150, 20))
+ self.indexMeta.setMaximumSize(QtCore.QSize(150, 20))
+ self.indexLayout.addWidget(self.indexMeta)
+ self.fingerVBoxLayout.addLayout(self.indexLayout)
+
+ # MIDDLE
+ self.middleLayout = QtWidgets.QHBoxLayout()
+
+ self.middleLabel = QtWidgets.QLabel("Middle Joints: ")
+ self.middleLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.middleLabel.setMinimumSize(QtCore.QSize(100, 20))
+ self.middleLabel.setMaximumSize(QtCore.QSize(100, 20))
+ self.middleLayout.addWidget((self.middleLabel))
+
+ self.middleNum = QtWidgets.QSpinBox()
+ self.middleNum.setMaximum(3)
+ self.middleNum.setValue(3)
+ self.middleNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.middleNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.middleNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.middleLayout.addWidget(self.middleNum)
+
+ self.middleMeta = QtWidgets.QCheckBox("Include Metacarpal")
+ self.middleMeta.setMinimumSize(QtCore.QSize(150, 20))
+ self.middleMeta.setMaximumSize(QtCore.QSize(150, 20))
+ self.middleLayout.addWidget(self.middleMeta)
+ self.fingerVBoxLayout.addLayout(self.middleLayout)
+
+ # RING
+ self.ringLayout = QtWidgets.QHBoxLayout()
+
+ self.ringLabel = QtWidgets.QLabel("Ring Joints: ")
+ self.ringLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.ringLabel.setMinimumSize(QtCore.QSize(100, 20))
+ self.ringLabel.setMaximumSize(QtCore.QSize(100, 20))
+ self.ringLayout.addWidget((self.ringLabel))
+
+ self.ringNum = QtWidgets.QSpinBox()
+ self.ringNum.setMaximum(3)
+ self.ringNum.setValue(3)
+ self.ringNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.ringNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.ringNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.ringLayout.addWidget(self.ringNum)
+
+ self.ringMeta = QtWidgets.QCheckBox("Include Metacarpal")
+ self.ringMeta.setMinimumSize(QtCore.QSize(150, 20))
+ self.ringMeta.setMaximumSize(QtCore.QSize(150, 20))
+ self.ringLayout.addWidget(self.ringMeta)
+ self.fingerVBoxLayout.addLayout(self.ringLayout)
+
+ # PINKY
+ self.pinkyLayout = QtWidgets.QHBoxLayout()
+
+ self.pinkyLabel = QtWidgets.QLabel("Pinky Joints: ")
+ self.pinkyLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.pinkyLabel.setMinimumSize(QtCore.QSize(100, 20))
+ self.pinkyLabel.setMaximumSize(QtCore.QSize(100, 20))
+ self.pinkyLayout.addWidget((self.pinkyLabel))
+
+ self.pinkyNum = QtWidgets.QSpinBox()
+ self.pinkyNum.setMaximum(3)
+ self.pinkyNum.setValue(3)
+ self.pinkyNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.pinkyNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.pinkyNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.pinkyLayout.addWidget(self.pinkyNum)
+
+ self.pinkyMeta = QtWidgets.QCheckBox("Include Metacarpal")
+ self.pinkyMeta.setMinimumSize(QtCore.QSize(150, 20))
+ self.pinkyMeta.setMaximumSize(QtCore.QSize(150, 20))
+ self.pinkyLayout.addWidget(self.pinkyMeta)
+ self.fingerVBoxLayout.addLayout(self.pinkyLayout)
+
+ # rebuild button
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ self.applyButton = QtWidgets.QPushButton("Apply Changes")
+ self.customSettingsLayout.addWidget(self.applyButton)
+ self.applyButton.setFont(headerFont)
+ self.applyButton.setMinimumSize(QtCore.QSize(300, 40))
+ self.applyButton.setMaximumSize(QtCore.QSize(300, 40))
+ self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.applyButton.setEnabled(False)
+
+ # button signal/slots
+ self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst))
+ self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst))
+ self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst))
+ self.applyButton.clicked.connect(partial(self.applyModuleChanges, self))
+
+ # signal slot for groupbox checkbox
+ QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible)
+ self.groupBox.setChecked(False)
+
+ # spinBox & checkbox signal/slots
+ self.upperarmTwistNum.valueChanged.connect(self.toggleButtonState)
+ self.lowerarmTwistNum.valueChanged.connect(self.toggleButtonState)
+ self.thumbNum.valueChanged.connect(self.toggleButtonState)
+ self.indexNum.valueChanged.connect(self.toggleButtonState)
+ self.middleNum.valueChanged.connect(self.toggleButtonState)
+ self.ringNum.valueChanged.connect(self.toggleButtonState)
+ self.pinkyNum.valueChanged.connect(self.toggleButtonState)
+
+ self.pinkyMeta.stateChanged.connect(self.toggleButtonState)
+ self.ringMeta.stateChanged.connect(self.toggleButtonState)
+ self.middleMeta.stateChanged.connect(self.toggleButtonState)
+ self.indexMeta.stateChanged.connect(self.toggleButtonState)
+ self.thumbMeta.stateChanged.connect(self.toggleButtonState)
+
+ self.clavicleCB.stateChanged.connect(self.toggleButtonState)
+
+ # add custom skeletonUI settings name, parent, rig types to install, mirror module, thigh twist, calf twists,
+ # ball joint, toes,
+ # add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+ # Populate the settings UI based on the network node attributes
+ self.updateSettingsUI()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pickerUI(self, center, animUI, networkNode, namespace):
+
+ self.namespace = namespace
+
+ # create qBrushes
+ yellowBrush = QtCore.Qt.yellow
+ blueBrush = QtGui.QColor(100, 220, 255)
+ purpleBrush = QtGui.QColor(111, 48, 161)
+ greenBrush = QtGui.QColor(0, 255, 30)
+ clearBrush = QtGui.QBrush(QtCore.Qt.black)
+ clearBrush.setStyle(QtCore.Qt.NoBrush)
+ side = cmds.getAttr(networkNode + ".side")
+
+ # create the picker border item
+ if networkNode.find(":") != -1:
+ moduleNode = networkNode.partition(":")[2]
+ else:
+ moduleNode = networkNode
+
+ borderItem = interfaceUtils.pickerBorderItem(center.x() - 80, center.y() - 130, 110, 260, clearBrush,
+ moduleNode)
+
+ # get controls
+ ikControls = json.loads(cmds.getAttr(networkNode + ".ikControls"))
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ upArmTwistControls = json.loads(cmds.getAttr(networkNode + ".upArmTwistControls"))
+ loArmTwistControls = json.loads(cmds.getAttr(networkNode + ".loArmTwistControls"))
+ clavControls = []
+
+ if cmds.objExists(networkNode + ".clavControls"):
+ clavControls = json.loads(cmds.getAttr(networkNode + ".clavControls"))
+
+ buttonData = []
+ controls = []
+
+ # =======================================================================
+ # ik buttons
+ # =======================================================================
+ ikHandButton = interfaceUtils.pickerButton(20, 20, [50, 190], namespace + ikControls[0], yellowBrush,
+ borderItem)
+ buttonData.append([ikHandButton, namespace + ikControls[0], yellowBrush])
+ controls.append(namespace + ikControls[0])
+
+ ikElbowButton = interfaceUtils.pickerButton(20, 20, [50, 100], namespace + ikControls[1], yellowBrush,
+ borderItem)
+ buttonData.append([ikElbowButton, namespace + ikControls[1], yellowBrush])
+ controls.append(namespace + ikControls[0])
+
+ if len(clavControls) > 0:
+ ikClavButton = interfaceUtils.pickerButton(20, 20, [50, 10], namespace + clavControls[1], yellowBrush,
+ borderItem)
+ buttonData.append([ikClavButton, namespace + clavControls[1], yellowBrush])
+ controls.append(namespace + clavControls[1])
+
+ # =======================================================================
+ # fk buttons
+ # =======================================================================
+ fkArmBtn = interfaceUtils.pickerButton(20, 60, [50, 35], namespace + fkControls[2], blueBrush, borderItem)
+ buttonData.append([fkArmBtn, namespace + fkControls[2], blueBrush])
+ controls.append(namespace + fkControls[2])
+
+ fkElbowBtn = interfaceUtils.pickerButton(20, 60, [50, 125], namespace + fkControls[1], blueBrush, borderItem)
+ buttonData.append([fkElbowBtn, namespace + fkControls[1], blueBrush])
+ controls.append(namespace + fkControls[1])
+
+ fkHandBtn = interfaceUtils.pickerButton(40, 40, [40, 215], namespace + fkControls[0], blueBrush, borderItem)
+ buttonData.append([fkHandBtn, namespace + fkControls[0], blueBrush])
+ controls.append(namespace + fkControls[0])
+
+ if len(clavControls) > 0:
+ fkClavButton = interfaceUtils.pickerButton(20, 20, [25, 10], namespace + clavControls[0], blueBrush,
+ borderItem)
+ buttonData.append([fkClavButton, namespace + clavControls[0], blueBrush])
+ controls.append(namespace + clavControls[0])
+
+ # =======================================================================
+ # twist bones
+ # =======================================================================
+ if upArmTwistControls != None:
+ if len(upArmTwistControls) > 0:
+ y = 35
+ for i in range(len(upArmTwistControls)):
+ button = interfaceUtils.pickerButton(15, 15, [75, y], namespace + upArmTwistControls[i],
+ purpleBrush, borderItem)
+ buttonData.append([button, namespace + upArmTwistControls[i], purpleBrush])
+ controls.append(namespace + upArmTwistControls[i])
+ y = y + 22
+
+ if loArmTwistControls != None:
+ if len(loArmTwistControls) > 0:
+ y = 170
+ for i in range(len(loArmTwistControls)):
+ button = interfaceUtils.pickerButton(15, 15, [75, y], namespace + loArmTwistControls[i],
+ purpleBrush, borderItem)
+ buttonData.append([button, namespace + loArmTwistControls[i], purpleBrush])
+ controls.append(namespace + loArmTwistControls[i])
+ y = y - 22
+
+ # =======================================================================
+ # settings button
+ # =======================================================================
+ settingsBtn = interfaceUtils.pickerButton(20, 20, [85, 235], namespace + self.name + "_settings", greenBrush,
+ borderItem)
+ buttonData.append([settingsBtn, namespace + ":" + self.name + "_settings", greenBrush])
+ controls.append(namespace + ":" + self.name + "_settings")
+ interfaceUtils.addTextToButton("S", settingsBtn)
+
+ # =======================================================================
+ # #FINGERS !!!! THIS IS A SUB-PICKER !!!!
+ # =======================================================================
+
+ # if there are fingers, create a finger picker
+ fingerControls = json.loads(cmds.getAttr(networkNode + ".fkFingerControls"))
+ ikFingerControls = json.loads(cmds.getAttr(networkNode + ".ikFingerControls"))
+
+ if len(fingerControls) > 0:
+
+ name = cmds.getAttr(networkNode + ".moduleName")
+ fingerBorder = interfaceUtils.pickerBorderItem(center.x() + 35, center.y() - 75, 100, 100, clearBrush,
+ moduleNode, name + "_fingers")
+ fingerBorder.setParentItem(borderItem)
+ interfaceUtils.addTextToButton(side[0] + "_Fingers", fingerBorder, False, False, True)
+
+ # create selection set lists
+ thumbFingers = []
+ indexFingers = []
+ middleFingers = []
+ ringFingers = []
+ pinkyFingers = []
+
+ metaCarpals = []
+ distalKnuckles = []
+ middleKnuckles = []
+ proximalKnuckles = []
+ fkFingerControls = []
+
+ fingerButtonData = []
+ # =======================================================================
+ # THUMB
+ # =======================================================================
+ for finger in fingerControls:
+ if finger.find("thumb_metacarpal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20, 40], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ thumbFingers.append(namespace + finger)
+
+ if finger.find("thumb_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20, 55], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ thumbFingers.append(namespace + finger)
+
+ if finger.find("thumb_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20, 75], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ thumbFingers.append(namespace + finger)
+
+ # =======================================================================
+ # INDEX
+ # =======================================================================
+ if finger.find("index_metacarpal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35, 25], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ indexFingers.append(namespace + finger)
+ metaCarpals.append(namespace + finger)
+
+ if finger.find("index_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35, 40], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ indexFingers.append(namespace + finger)
+ proximalKnuckles.append(namespace + finger)
+
+ if finger.find("index_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35, 55], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ indexFingers.append(namespace + finger)
+ middleKnuckles.append(namespace + finger)
+
+ if finger.find("index_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35, 75], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ indexFingers.append(namespace + finger)
+ distalKnuckles.append(namespace + finger)
+
+ # =======================================================================
+ # MIDDLE
+ # =======================================================================
+ if finger.find("middle_metacarpal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50, 25], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ middleFingers.append(namespace + finger)
+ metaCarpals.append(namespace + finger)
+
+ if finger.find("middle_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50, 40], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ middleFingers.append(namespace + finger)
+ proximalKnuckles.append(namespace + finger)
+
+ if finger.find("middle_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50, 55], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ middleFingers.append(namespace + finger)
+ middleKnuckles.append(namespace + finger)
+
+ if finger.find("middle_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50, 75], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ middleFingers.append(namespace + finger)
+ distalKnuckles.append(namespace + finger)
+
+ # =======================================================================
+ # RING
+ # =======================================================================
+ if finger.find("ring_metacarpal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65, 25], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ ringFingers.append(namespace + finger)
+ metaCarpals.append(namespace + finger)
+
+ if finger.find("ring_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65, 40], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ ringFingers.append(namespace + finger)
+ proximalKnuckles.append(namespace + finger)
+
+ if finger.find("ring_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65, 55], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ ringFingers.append(namespace + finger)
+ middleKnuckles.append(namespace + finger)
+
+ if finger.find("ring_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65, 75], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ ringFingers.append(namespace + finger)
+ distalKnuckles.append(namespace + finger)
+
+ # =======================================================================
+ # PINKY
+ # =======================================================================
+ if finger.find("pinky_metacarpal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80, 25], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ pinkyFingers.append(namespace + finger)
+ metaCarpals.append(namespace + finger)
+
+ if finger.find("pinky_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80, 40], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ pinkyFingers.append(namespace + finger)
+ proximalKnuckles.append(namespace + finger)
+
+ if finger.find("pinky_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80, 55], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ pinkyFingers.append(namespace + finger)
+ middleKnuckles.append(namespace + finger)
+
+ if finger.find("pinky_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80, 75], namespace + finger, blueBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, blueBrush])
+ fingerButtonData.append([button, namespace + finger, blueBrush])
+ controls.append(namespace + finger)
+ fkFingerControls.append(namespace + finger)
+ pinkyFingers.append(namespace + finger)
+ distalKnuckles.append(namespace + finger)
+
+ # =======================================================================
+ # IK FINGERS
+ # =======================================================================
+ for finger in ikFingerControls:
+
+ if finger.find("index_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35, 88], namespace + finger, yellowBrush,
+ fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("index_pv") != -1:
+ button = interfaceUtils.pickerButton(10, 6, [35, 67], namespace + finger, yellowBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("middle_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50, 88], namespace + finger, yellowBrush,
+ fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("middle_pv") != -1:
+ button = interfaceUtils.pickerButton(10, 6, [50, 67], namespace + finger, yellowBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("ring_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65, 88], namespace + finger, yellowBrush,
+ fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("ring_pv") != -1:
+ button = interfaceUtils.pickerButton(10, 6, [65, 67], namespace + finger, yellowBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("pinky_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80, 88], namespace + finger, yellowBrush,
+ fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("pinky_pv") != -1:
+ button = interfaceUtils.pickerButton(10, 6, [80, 67], namespace + finger, yellowBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("thumb_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20, 88], namespace + finger, yellowBrush,
+ fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("thumb_pv") != -1:
+ button = interfaceUtils.pickerButton(10, 6, [20, 67], namespace + finger, yellowBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ if finger.find("hand_global") != -1:
+ button = interfaceUtils.pickerButton(5, 98, [94, 2], namespace + finger, yellowBrush, fingerBorder)
+ buttonData.append([button, namespace + finger, yellowBrush])
+ fingerButtonData.append([button, namespace + finger, yellowBrush])
+ controls.append(namespace + finger)
+ button.setToolTip(finger)
+
+ # =======================================================================
+ # FINGER MASS SELECT BUTTONS
+ # =======================================================================
+ metaCarpalAll_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 25], metaCarpals, greenBrush, fingerBorder)
+ metaCarpalAll_btn.setToolTip("select all metacarpal controls")
+
+ proxiKnuckle_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 40], proximalKnuckles, greenBrush,
+ fingerBorder)
+ proxiKnuckle_btn.setToolTip("select all proximal knuckles")
+ midKnuckle_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 55], middleKnuckles, greenBrush, fingerBorder)
+ midKnuckle_btn.setToolTip("select all middle knuckles")
+ distKnuckle_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 75], distalKnuckles, greenBrush, fingerBorder)
+ distKnuckle_btn.setToolTip("select all distal knuckles")
+
+ thumbs_btn = interfaceUtils.pickerButtonAll(10, 10, [20, 5], thumbFingers, greenBrush, fingerBorder)
+ thumbs_btn.setToolTip("select all thumb controls")
+ indexes_btn = interfaceUtils.pickerButtonAll(10, 10, [35, 5], indexFingers, greenBrush, fingerBorder)
+ indexes_btn.setToolTip("select all index finger controls")
+ middles_btn = interfaceUtils.pickerButtonAll(10, 10, [50, 5], middleFingers, greenBrush, fingerBorder)
+ middles_btn.setToolTip("select all middle finger controls")
+ rings_btn = interfaceUtils.pickerButtonAll(10, 10, [65, 5], ringFingers, greenBrush, fingerBorder)
+ rings_btn.setToolTip("select all ring finger controls")
+ pinkys_btn = interfaceUtils.pickerButtonAll(10, 10, [80, 5], pinkyFingers, greenBrush, fingerBorder)
+ pinkys_btn.setToolTip("select all pinky finger controls")
+
+ allFinger_btn = interfaceUtils.pickerButtonAll(12, 12, [5, 8], fkFingerControls, greenBrush, fingerBorder)
+ allFinger_btn.setToolTip("select all fk finger controls")
+
+ # =======================================================================
+ # go through button data, adding menu items
+ # =======================================================================
+ for each in buttonData:
+ if each not in fingerButtonData:
+ button = each[0]
+
+ fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png"))))
+ ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png"))))
+ zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png"))))
+ zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png"))))
+ selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png"))))
+
+ switchAction = QtWidgets.QAction('Match when Switching', button.menu)
+ switchAction.setCheckable(True)
+ switchAction.setChecked(True)
+
+ button.menu.addAction(selectIcon, "Select All Arm Controls", partial(self.selectRigControls, "all"))
+ button.menu.addAction(selectIcon, "Select FK Arm Controls", partial(self.selectRigControls, "fk"))
+ button.menu.addAction(selectIcon, "Select IK Arm Controls", partial(self.selectRigControls, "ik"))
+ button.menu.addSeparator()
+
+ if len(clavControls) > 0:
+ if each[1] == namespace + clavControls[0] or each[1] == namespace + clavControls[1]:
+ button.menu.addAction(fkIcon, "(Clav) FK Mode",
+ partial(self.switchClavMode, "FK", switchAction))
+ button.menu.addAction(ikIcon, "(Clav) IK Mode",
+ partial(self.switchClavMode, "IK", switchAction))
+
+ else:
+ button.menu.addAction(fkIcon, "(Arm) FK Mode", partial(self.switchMode, "FK", switchAction))
+ button.menu.addAction(ikIcon, "(Arm) IK Mode", partial(self.switchMode, "IK", switchAction))
+
+ else:
+ button.menu.addAction(fkIcon, "(Arm) FK Mode", partial(self.switchMode, "FK", switchAction))
+ button.menu.addAction(ikIcon, "(Arm) IK Mode", partial(self.switchMode, "IK", switchAction))
+
+ button.menu.addAction(switchAction)
+
+ button.menu.addSeparator()
+
+ button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True))
+ button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False))
+
+ for each in fingerButtonData:
+ button = each[0]
+
+ fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png"))))
+ ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png"))))
+ zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png"))))
+ zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png"))))
+
+ button.menu.addAction(fkIcon, "FK Mode (Finger)", partial(self.switchFingerMode, "FK", each[1]))
+ button.menu.addAction(ikIcon, "IK Mode (Finger)", partial(self.switchFingerMode, "IK", each[1]))
+
+ button.menu.addSeparator()
+ button.menu.addAction(fkIcon, "FK Mode (All Fingers)", partial(self.switchFingerMode, "FK", "All"))
+ button.menu.addAction(ikIcon, "IK Mode (All Fingers)", partial(self.switchFingerMode, "IK", "All"))
+
+ button.menu.addSeparator()
+ button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True))
+ button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False))
+
+ # =======================================================================
+ # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5)
+ # =======================================================================
+ scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)],
+ kws=True)
+ borderItem.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ # return data and set to mirror if side is right
+ if side == "Right":
+ return [borderItem, True, scriptJob]
+ else:
+ return [borderItem, False, scriptJob]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleButtonState(self):
+
+ state = self.applyButton.isEnabled()
+ if state == False:
+ self.applyButton.setEnabled(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addJointMoverToOutliner(self):
+
+ index = self.rigUiInst.treeWidget.topLevelItemCount()
+ self.outlinerWidgets = {}
+
+ # Add the module to the tree widget in the outliner tab of the rig creator UI
+ self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget)
+ self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name)
+ foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255))
+ self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground)
+
+ # add the clavicle
+ self.outlinerWidgets[self.name + "_clavicle"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_clavicle"].setText(0, self.name + "_clavicle")
+ self.createGlobalMoverButton(self.name + "_clavicle", self.outlinerWidgets[self.name + "_clavicle"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_clavicle", self.outlinerWidgets[self.name + "_clavicle"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_clavicle", self.outlinerWidgets[self.name + "_clavicle"],
+ self.rigUiInst)
+
+ # add the upperarm
+ self.outlinerWidgets[self.name + "_upperarm"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_upperarm"].setText(0, self.name + "_upperarm")
+ self.createGlobalMoverButton(self.name + "_upperarm", self.outlinerWidgets[self.name + "_upperarm"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_upperarm", self.outlinerWidgets[self.name + "_upperarm"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_upperarm", self.outlinerWidgets[self.name + "_upperarm"],
+ self.rigUiInst)
+
+ # add the upperarm twists
+ self.outlinerWidgets[self.name + "_upperarm_twist_01"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_upperarm"])
+ self.outlinerWidgets[self.name + "_upperarm_twist_01"].setText(0, self.name + "_upperarm_twist_01")
+ self.createOffsetMoverButton(self.name + "_upperarm_twist_01",
+ self.outlinerWidgets[self.name + "_upperarm_twist_01"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_upperarm_twist_01"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_upperarm_twist_02"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_upperarm"])
+ self.outlinerWidgets[self.name + "_upperarm_twist_02"].setText(0, self.name + "_upperarm_twist_02")
+ self.createOffsetMoverButton(self.name + "_upperarm_twist_02",
+ self.outlinerWidgets[self.name + "_upperarm_twist_02"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_upperarm_twist_02"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_upperarm_twist_03"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_upperarm"])
+ self.outlinerWidgets[self.name + "_upperarm_twist_03"].setText(0, self.name + "_upperarm_twist_03")
+ self.createOffsetMoverButton(self.name + "_upperarm_twist_03",
+ self.outlinerWidgets[self.name + "_upperarm_twist_03"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_upperarm_twist_03"].setHidden(True)
+
+ # add the lowerarm
+ self.outlinerWidgets[self.name + "_lowerarm"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_upperarm"])
+ self.outlinerWidgets[self.name + "_lowerarm"].setText(0, self.name + "_lowerarm")
+ self.createGlobalMoverButton(self.name + "_lowerarm", self.outlinerWidgets[self.name + "_lowerarm"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_lowerarm", self.outlinerWidgets[self.name + "_lowerarm"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_lowerarm", self.outlinerWidgets[self.name + "_lowerarm"],
+ self.rigUiInst)
+
+ # add the lowerarm twists
+ self.outlinerWidgets[self.name + "_lowerarm_twist_01"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_lowerarm"])
+ self.outlinerWidgets[self.name + "_lowerarm_twist_01"].setText(0, self.name + "_lowerarm_twist_01")
+ self.createOffsetMoverButton(self.name + "_lowerarm_twist_01",
+ self.outlinerWidgets[self.name + "_lowerarm_twist_01"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_lowerarm_twist_01"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_lowerarm_twist_02"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_lowerarm"])
+ self.outlinerWidgets[self.name + "_lowerarm_twist_02"].setText(0, self.name + "_lowerarm_twist_02")
+ self.createOffsetMoverButton(self.name + "_lowerarm_twist_02",
+ self.outlinerWidgets[self.name + "_lowerarm_twist_02"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_lowerarm_twist_02"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_lowerarm_twist_03"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_lowerarm"])
+ self.outlinerWidgets[self.name + "_lowerarm_twist_03"].setText(0, self.name + "_lowerarm_twist_03")
+ self.createOffsetMoverButton(self.name + "_lowerarm_twist_03",
+ self.outlinerWidgets[self.name + "_lowerarm_twist_03"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_lowerarm_twist_03"].setHidden(True)
+
+ # add the hand
+ self.outlinerWidgets[self.name + "_hand"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_lowerarm"])
+ self.outlinerWidgets[self.name + "_hand"].setText(0, self.name + "_hand")
+ self.createGlobalMoverButton(self.name + "_hand", self.outlinerWidgets[self.name + "_hand"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_hand", self.outlinerWidgets[self.name + "_hand"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_hand", self.outlinerWidgets[self.name + "_hand"], self.rigUiInst)
+
+ # add the thumb
+ self.outlinerWidgets[self.name + "_thumb_metacarpal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_thumb_metacarpal"].setText(0, self.name + "_thumb_metacarpal")
+ self.createGlobalMoverButton(self.name + "_thumb_metacarpal",
+ self.outlinerWidgets[self.name + "_thumb_metacarpal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thumb_metacarpal",
+ self.outlinerWidgets[self.name + "_thumb_metacarpal"], self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_thumb_proximal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_thumb_proximal"].setText(0, self.name + "_thumb_proximal")
+ self.createGlobalMoverButton(self.name + "_thumb_proximal", self.outlinerWidgets[self.name + "_thumb_proximal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thumb_proximal", self.outlinerWidgets[self.name + "_thumb_proximal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_thumb_proximal", self.outlinerWidgets[self.name + "_thumb_proximal"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_thumb_distal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_thumb_proximal"])
+ self.outlinerWidgets[self.name + "_thumb_distal"].setText(0, self.name + "_thumb_distal")
+ self.createGlobalMoverButton(self.name + "_thumb_distal", self.outlinerWidgets[self.name + "_thumb_distal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thumb_distal", self.outlinerWidgets[self.name + "_thumb_distal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_thumb_distal", self.outlinerWidgets[self.name + "_thumb_distal"],
+ self.rigUiInst)
+
+ # add the index finger
+ self.outlinerWidgets[self.name + "_index_metacarpal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_index_metacarpal"].setText(0, self.name + "_index_metacarpal")
+ self.createGlobalMoverButton(self.name + "_index_metacarpal",
+ self.outlinerWidgets[self.name + "_index_metacarpal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_metacarpal",
+ self.outlinerWidgets[self.name + "_index_metacarpal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_index_metacarpal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_index_proximal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_index_proximal"].setText(0, self.name + "_index_proximal")
+ self.createGlobalMoverButton(self.name + "_index_proximal", self.outlinerWidgets[self.name + "_index_proximal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_proximal", self.outlinerWidgets[self.name + "_index_proximal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_index_proximal", self.outlinerWidgets[self.name + "_index_proximal"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_index_middle"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_index_proximal"])
+ self.outlinerWidgets[self.name + "_index_middle"].setText(0, self.name + "_index_middle")
+ self.createGlobalMoverButton(self.name + "_index_middle", self.outlinerWidgets[self.name + "_index_middle"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_middle", self.outlinerWidgets[self.name + "_index_middle"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_index_middle", self.outlinerWidgets[self.name + "_index_middle"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_index_distal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_index_middle"])
+ self.outlinerWidgets[self.name + "_index_distal"].setText(0, self.name + "_index_distal")
+ self.createGlobalMoverButton(self.name + "_index_distal", self.outlinerWidgets[self.name + "_index_distal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_distal", self.outlinerWidgets[self.name + "_index_distal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_index_distal", self.outlinerWidgets[self.name + "_index_distal"],
+ self.rigUiInst)
+
+ # add the middle finger
+ self.outlinerWidgets[self.name + "_middle_metacarpal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_middle_metacarpal"].setText(0, self.name + "_middle_metacarpal")
+ self.createGlobalMoverButton(self.name + "_middle_metacarpal",
+ self.outlinerWidgets[self.name + "_middle_metacarpal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_metacarpal",
+ self.outlinerWidgets[self.name + "_middle_metacarpal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_middle_metacarpal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_middle_proximal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_middle_proximal"].setText(0, self.name + "_middle_proximal")
+ self.createGlobalMoverButton(self.name + "_middle_proximal",
+ self.outlinerWidgets[self.name + "_middle_proximal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_proximal",
+ self.outlinerWidgets[self.name + "_middle_proximal"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_middle_proximal", self.outlinerWidgets[self.name + "_middle_proximal"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_middle_middle"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_middle_proximal"])
+ self.outlinerWidgets[self.name + "_middle_middle"].setText(0, self.name + "_middle_middle")
+ self.createGlobalMoverButton(self.name + "_middle_middle", self.outlinerWidgets[self.name + "_middle_middle"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_middle", self.outlinerWidgets[self.name + "_middle_middle"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_middle_middle", self.outlinerWidgets[self.name + "_middle_middle"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_middle_distal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_middle_middle"])
+ self.outlinerWidgets[self.name + "_middle_distal"].setText(0, self.name + "_middle_distal")
+ self.createGlobalMoverButton(self.name + "_middle_distal", self.outlinerWidgets[self.name + "_middle_distal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_distal", self.outlinerWidgets[self.name + "_middle_distal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_middle_distal", self.outlinerWidgets[self.name + "_middle_distal"],
+ self.rigUiInst)
+
+ # add the ring finger
+ self.outlinerWidgets[self.name + "_ring_metacarpal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_ring_metacarpal"].setText(0, self.name + "_ring_metacarpal")
+ self.createGlobalMoverButton(self.name + "_ring_metacarpal",
+ self.outlinerWidgets[self.name + "_ring_metacarpal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_metacarpal",
+ self.outlinerWidgets[self.name + "_ring_metacarpal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_ring_metacarpal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_ring_proximal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_ring_proximal"].setText(0, self.name + "_ring_proximal")
+ self.createGlobalMoverButton(self.name + "_ring_proximal", self.outlinerWidgets[self.name + "_ring_proximal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_proximal", self.outlinerWidgets[self.name + "_ring_proximal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ring_proximal", self.outlinerWidgets[self.name + "_ring_proximal"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_ring_middle"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_ring_proximal"])
+ self.outlinerWidgets[self.name + "_ring_middle"].setText(0, self.name + "_ring_middle")
+ self.createGlobalMoverButton(self.name + "_ring_middle", self.outlinerWidgets[self.name + "_ring_middle"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_middle", self.outlinerWidgets[self.name + "_ring_middle"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ring_middle", self.outlinerWidgets[self.name + "_ring_middle"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_ring_distal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_ring_middle"])
+ self.outlinerWidgets[self.name + "_ring_distal"].setText(0, self.name + "_ring_distal")
+ self.createGlobalMoverButton(self.name + "_ring_distal", self.outlinerWidgets[self.name + "_ring_distal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_distal", self.outlinerWidgets[self.name + "_ring_distal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ring_distal", self.outlinerWidgets[self.name + "_ring_distal"],
+ self.rigUiInst)
+
+ # add the pinky finger
+ self.outlinerWidgets[self.name + "_pinky_metacarpal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_pinky_metacarpal"].setText(0, self.name + "_pinky_metacarpal")
+ self.createGlobalMoverButton(self.name + "_pinky_metacarpal",
+ self.outlinerWidgets[self.name + "_pinky_metacarpal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_metacarpal",
+ self.outlinerWidgets[self.name + "_pinky_metacarpal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_pinky_metacarpal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_pinky_proximal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_hand"])
+ self.outlinerWidgets[self.name + "_pinky_proximal"].setText(0, self.name + "_pinky_proximal")
+ self.createGlobalMoverButton(self.name + "_pinky_proximal", self.outlinerWidgets[self.name + "_pinky_proximal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_proximal", self.outlinerWidgets[self.name + "_pinky_proximal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pinky_proximal", self.outlinerWidgets[self.name + "_pinky_proximal"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_pinky_middle"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_pinky_proximal"])
+ self.outlinerWidgets[self.name + "_pinky_middle"].setText(0, self.name + "_pinky_middle")
+ self.createGlobalMoverButton(self.name + "_pinky_middle", self.outlinerWidgets[self.name + "_pinky_middle"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_middle", self.outlinerWidgets[self.name + "_pinky_middle"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pinky_middle", self.outlinerWidgets[self.name + "_pinky_middle"],
+ self.rigUiInst)
+
+ self.outlinerWidgets[self.name + "_pinky_distal"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_pinky_middle"])
+ self.outlinerWidgets[self.name + "_pinky_distal"].setText(0, self.name + "_pinky_distal")
+ self.createGlobalMoverButton(self.name + "_pinky_distal", self.outlinerWidgets[self.name + "_pinky_distal"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_distal", self.outlinerWidgets[self.name + "_pinky_distal"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pinky_distal", self.outlinerWidgets[self.name + "_pinky_distal"],
+ self.rigUiInst)
+
+ # create selection script job for module
+ self.createScriptJob()
+
+ # update based on spinBox values
+ self.updateOutliner()
+ self.updateBoneCount()
+ self.rigUiInst.treeWidget.expandAll()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def aimMode_Setup(self, state):
+
+ # get attributes needed
+ name = self.groupBox.title()
+ networkNode = self.returnNetworkNode
+ side = cmds.getAttr(networkNode + ".side")
+
+ # setup aim vector details per side
+ armAim = [1, 0, 0]
+ armUp = [0, 0, 1]
+ handAim = [1, 0, 0]
+ handUp = [0, -1, 0]
+
+ if side == "Right":
+ armAim = [-1, 0, 0]
+ armUp = [0, 0, -1]
+ handAim = [-1, 0, 0]
+ handUp = [0, 1, 0]
+
+ # if passed in state is True:
+ if state:
+ # setup aim constraints
+
+ # clavicle
+ cmds.aimConstraint(name + "_upperarm_lra", name + "_clavicle_mover_geo", aimVector=armAim, upVector=armUp,
+ wut="scene", wu=[0, 0, 1], mo=True)
+ cmds.aimConstraint(name + "_upperarm_lra", name + "_clavicle_mover_offset", aimVector=armAim,
+ upVector=armUp, wut="scene", wu=[0, 0, 1], mo=True)
+
+ # upperarm
+ cmds.aimConstraint(name + "_lowerarm_lra", name + "_upperarm_mover_geo", aimVector=armAim, upVector=armUp,
+ skip="x", wut="scene", wu=[0, 0, 1], mo=True)
+ cmds.aimConstraint(name + "_lowerarm_lra", name + "_upperarm_mover_offset", aimVector=armAim,
+ skip="x", upVector=armUp, wut="scene", wu=[0, 0, 1], mo=True)
+
+ # lowerarm
+ cmds.aimConstraint(name + "_hand_lra", name + "_lowerarm_mover_offset", aimVector=armAim, upVector=armUp,
+ wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ # index finger
+ if cmds.getAttr(name + "_index_metacarpal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_index_proximal_lra", name + "_index_metacarpal_mover_offset",
+ aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_index_proximal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_index_middle_lra", name + "_index_proximal_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_index_middle_lra", name + "_index_proximal_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_index_middle_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_index_distal_lra", name + "_index_middle_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_index_distal_lra", name + "_index_middle_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ # middle finger
+ if cmds.getAttr(name + "_middle_metacarpal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_middle_proximal_lra", name + "_middle_metacarpal_mover_offset",
+ aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_middle_proximal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_middle_middle_lra", name + "_middle_proximal_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_middle_middle_lra", name + "_middle_proximal_mover_offset",
+ aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_middle_middle_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_middle_distal_lra", name + "_middle_middle_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_middle_distal_lra", name + "_middle_middle_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ # ring finger
+ if cmds.getAttr(name + "_ring_metacarpal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ring_proximal_lra", name + "_ring_metacarpal_mover_offset",
+ aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_ring_proximal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ring_middle_lra", name + "_ring_proximal_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_ring_middle_lra", name + "_ring_proximal_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_ring_middle_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ring_distal_lra", name + "_ring_middle_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_ring_distal_lra", name + "_ring_middle_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ # pinky finger
+ if cmds.getAttr(name + "_pinky_metacarpal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_pinky_proximal_lra", name + "_pinky_metacarpal_mover_offset",
+ aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_pinky_proximal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_pinky_middle_lra", name + "_pinky_proximal_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_pinky_middle_lra", name + "_pinky_proximal_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_pinky_middle_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_pinky_distal_lra", name + "_pinky_middle_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_pinky_distal_lra", name + "_pinky_middle_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ # thumb finger
+ if cmds.getAttr(name + "_thumb_metacarpal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_thumb_proximal_lra", name + "_thumb_metacarpal_mover_offset",
+ aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ if cmds.getAttr(name + "_thumb_proximal_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_thumb_distal_lra", name + "_thumb_proximal_mover_geo", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+ cmds.aimConstraint(name + "_thumb_distal_lra", name + "_thumb_proximal_mover_offset", aimVector=handAim,
+ upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"])
+
+ # if passed in state is False:
+ if not state:
+ cmds.select(name + "_mover_grp", hi=True)
+ aimConstraints = cmds.ls(sl=True, exactType="aimConstraint")
+
+ for constraint in aimConstraints:
+ cmds.lockNode(constraint, lock=False)
+ cmds.delete(constraint)
+
+ self.bakeOffsets()
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def coplanarMode(self):
+
+ # current selection
+ currentSelection = cmds.ls(sl=True)
+
+ # get the state of the button
+ state = self.coplanarBtn.isChecked()
+
+ # write the attribute on the module
+ networkNode = self.returnNetworkNode
+
+ import System.utils as utils
+ aimState = cmds.getAttr(networkNode + ".aimMode")
+ if state:
+
+ # lock out offset movers as they aren't to be used in coplanar mode
+ offsetMovers = self.returnJointMovers[1]
+ for mover in offsetMovers:
+ cmds.lockNode(mover, lock=False)
+ for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]:
+ try:
+ cmds.setAttr(mover + attr, lock=True)
+ except:
+ pass
+
+ # fire script job that watches the coplanarIkHandle attributes, and when they change, snap to IK knee in tz
+ self.coplanarScriptJob1 = cmds.scriptJob(attributeChange=[self.name + "_coplanarIkHandle.translate",
+ partial(riggingUtils.coPlanarModeSnap, self,
+ self.name + "_coplanar_lowerarm",
+ self.name + "_lowerarm_mover_offset",
+ [self.name + "_coplanar_upperarm",
+ self.name + "_coplanar_lowerarm"],
+ [self.name + "_upperarm_mover_offset",
+ self.name + "_lowerarm_mover_offset"],
+ self.name + "_lowerarm_mover_offset",
+ [])], kws=True)
+
+ # make sure aim mode is on
+ if not aimState:
+ self.aimMode_Setup(True)
+
+ # reselect current selection
+ if len(currentSelection) > 0:
+ cmds.select(currentSelection)
+
+ if not state:
+ # unlock all offset movers
+ offsetMovers = self.returnJointMovers[1]
+ for mover in offsetMovers:
+ for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]:
+ try:
+ cmds.setAttr(mover + attr, lock=False)
+ except:
+ pass
+
+ cmds.lockNode(mover, lock=True)
+
+ cmds.scriptJob(kill=self.coplanarScriptJob1)
+ self.aimMode_Setup(False)
+
+ if aimState:
+ self.aimMode_Setup(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateSettingsUI(self):
+
+ # this function will update the settings UI when the UI is launched based on the network node settings
+ # in the scene
+ networkNode = self.returnNetworkNode
+
+ upperarmTwists = cmds.getAttr(networkNode + ".armTwists")
+ lowerarmTwists = cmds.getAttr(networkNode + ".forearmTwists")
+ thumbJoints = cmds.getAttr(networkNode + ".thumbJoints")
+ indexJoints = cmds.getAttr(networkNode + ".indexJoints")
+ middleJoints = cmds.getAttr(networkNode + ".middleJoints")
+ ringJoints = cmds.getAttr(networkNode + ".ringJoints")
+ pinkyJoints = cmds.getAttr(networkNode + ".pinkyJoints")
+ includeClav = cmds.getAttr(networkNode + ".includeClavicle")
+ thumbMeta = cmds.getAttr(networkNode + ".thumbMeta")
+ indexMeta = cmds.getAttr(networkNode + ".indexMeta")
+ middleMeta = cmds.getAttr(networkNode + ".middleMeta")
+ ringMeta = cmds.getAttr(networkNode + ".ringMeta")
+ pinkyMeta = cmds.getAttr(networkNode + ".pinkyMeta")
+
+ # update UI elements
+ self.upperarmTwistNum.setValue(upperarmTwists)
+ self.lowerarmTwistNum.setValue(lowerarmTwists)
+ self.clavicleCB.setChecked(includeClav)
+
+ self.thumbNum.setValue(thumbJoints)
+ self.indexNum.setValue(indexJoints)
+ self.middleNum.setValue(middleJoints)
+ self.ringNum.setValue(ringJoints)
+ self.pinkyNum.setValue(pinkyJoints)
+
+ self.thumbMeta.setChecked(thumbMeta)
+ self.indexMeta.setChecked(indexMeta)
+ self.middleMeta.setChecked(middleMeta)
+ self.ringMeta.setChecked(ringMeta)
+ self.pinkyMeta.setChecked(pinkyMeta)
+
+ # apply changes
+ self.applyButton.setEnabled(False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateOutliner(self):
+
+ # whenever changes are made to the module settings, update the outliner to show the new or removed movers
+
+ # CLAVICLE
+
+ if not self.clavicleCB.isChecked():
+ self.outlinerWidgets[self.originalName + "_clavicle"].setHidden(True)
+ else:
+ self.outlinerWidgets[self.originalName + "_clavicle"].setHidden(False)
+
+ # UPPERARM TWISTS
+ armTwists = self.upperarmTwistNum.value()
+ if armTwists == 0:
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(True)
+ if armTwists == 1:
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(True)
+ if armTwists == 2:
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(True)
+ if armTwists == 3:
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(False)
+
+ # LOWERARM TWISTS
+ lowerarmTwists = self.lowerarmTwistNum.value()
+ if lowerarmTwists == 0:
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(True)
+ if lowerarmTwists == 1:
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(True)
+ if lowerarmTwists == 2:
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(True)
+ if lowerarmTwists == 3:
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(False)
+
+ # THUMB
+ thumbBones = self.thumbNum.value()
+ thumbMeta = self.thumbMeta.isChecked()
+
+ if thumbBones == 0:
+ self.outlinerWidgets[self.originalName + "_thumb_proximal"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_thumb_distal"].setHidden(True)
+ if thumbBones == 1:
+ self.outlinerWidgets[self.originalName + "_thumb_proximal"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thumb_distal"].setHidden(True)
+ if thumbBones == 2:
+ self.outlinerWidgets[self.originalName + "_thumb_proximal"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thumb_distal"].setHidden(False)
+
+ if thumbMeta:
+ self.outlinerWidgets[self.originalName + "_thumb_metacarpal"].setHidden(False)
+ if not thumbMeta:
+ self.outlinerWidgets[self.originalName + "_thumb_metacarpal"].setHidden(True)
+
+ # FINGERS
+ fingers = [[self.indexNum, "index", self.indexMeta], [self.middleNum, "middle", self.middleMeta],
+ [self.ringNum, "ring", self.ringMeta], [self.pinkyNum, "pinky", self.pinkyMeta]]
+
+ for finger in fingers:
+ value = finger[0].value()
+ meta = finger[2].isChecked()
+
+ if value == 0:
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(True)
+ if value == 1:
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(True)
+ if value == 2:
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(True)
+ if value == 3:
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(False)
+
+ if meta:
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_metacarpal"].setHidden(False)
+ if not meta:
+ self.outlinerWidgets[self.originalName + "_" + finger[1] + "_metacarpal"].setHidden(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def applyModuleChanges(self, moduleInst):
+
+ # get prefix/suffix
+ name = self.groupBox.title()
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ if len(prefix) > 0:
+ if prefix.find("_") == -1:
+ prefix = prefix + "_"
+ if len(suffix) > 0:
+ if suffix.find("_") == -1:
+ suffix = "_" + suffix
+
+ # create list of the new created bones
+ armJoints = []
+
+ if self.clavicleCB.isChecked():
+ armJoints.append(prefix + "clavicle" + suffix)
+ armJoints.append(prefix + "upperarm" + suffix)
+ else:
+ armJoints.append(prefix + "upperarm" + suffix)
+
+ # upperarm twists
+ upperarmTwists = self.upperarmTwistNum.value()
+ for i in range(upperarmTwists):
+ armJoints.append(prefix + "upperarm_twist_0" + str(i + 1) + suffix)
+
+ armJoints.append(prefix + "lowerarm" + suffix)
+
+ # lowerarm twists
+ lowerarmTwists = self.lowerarmTwistNum.value()
+ for i in range(lowerarmTwists):
+ armJoints.append(prefix + "lowerarm_twist_0" + str(i + 1) + suffix)
+
+ armJoints.append(prefix + "hand" + suffix)
+
+ # FINGERS
+ thumbJoints = ["proximal", "distal"]
+ fingerJoints = ["proximal", "middle", "distal"]
+
+ # thumb
+ thumbs = self.thumbNum.value()
+ thumbMeta = self.thumbMeta.isChecked()
+ if thumbMeta:
+ armJoints.append(prefix + "thumb_metacarpal" + suffix)
+ for i in range(thumbs):
+ armJoints.append(prefix + "thumb_" + thumbJoints[i] + suffix)
+
+ # index
+ indexFingers = self.indexNum.value()
+ indexMeta = self.indexMeta.isChecked()
+ if indexMeta:
+ armJoints.append(prefix + "index_metacarpal" + suffix)
+ for i in range(indexFingers):
+ armJoints.append(prefix + "index_" + fingerJoints[i] + suffix)
+
+ # middle
+ middleFingers = self.middleNum.value()
+ middleMeta = self.middleMeta.isChecked()
+ if middleMeta:
+ armJoints.append(prefix + "middle_metacarpal" + suffix)
+ for i in range(middleFingers):
+ armJoints.append(prefix + "middle_" + fingerJoints[i] + suffix)
+
+ # ring
+ ringFingers = self.ringNum.value()
+ ringMeta = self.ringMeta.isChecked()
+ if ringMeta:
+ armJoints.append(prefix + "ring_metacarpal" + suffix)
+ for i in range(ringFingers):
+ armJoints.append(prefix + "ring_" + fingerJoints[i] + suffix)
+
+ # pinky
+ pinkyFingers = self.pinkyNum.value()
+ pinkyMeta = self.pinkyMeta.isChecked()
+ if pinkyMeta:
+ armJoints.append(prefix + "pinky_metacarpal" + suffix)
+ for i in range(pinkyFingers):
+ armJoints.append(prefix + "pinky_" + fingerJoints[i] + suffix)
+
+ # build attrString
+ attrString = ""
+ for bone in armJoints:
+ attrString += bone + "::"
+
+ networkNode = self.returnNetworkNode
+ cmds.setAttr(networkNode + ".Created_Bones", lock=False)
+ cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True)
+
+ # reset button
+ self.applyButton.setEnabled(False)
+
+ # update joint mover
+ self.editJointMoverViaSpinBox(self.thumbNum, "thumb", True)
+ self.editJointMoverViaSpinBox(self.indexNum, "index", False)
+ self.editJointMoverViaSpinBox(self.middleNum, "middle", False)
+ self.editJointMoverViaSpinBox(self.ringNum, "ring", False)
+ self.editJointMoverViaSpinBox(self.pinkyNum, "pinky", False)
+
+ self.editJointMoverTwistBones(self.upperarmTwistNum, "upperarm")
+ self.editJointMoverTwistBones(self.lowerarmTwistNum, "lowerarm")
+
+ self.editJointMoverMetaCarpals(self.thumbMeta, "thumb")
+ self.editJointMoverMetaCarpals(self.indexMeta, "index")
+ self.editJointMoverMetaCarpals(self.middleMeta, "middle")
+ self.editJointMoverMetaCarpals(self.ringMeta, "ring")
+ self.editJointMoverMetaCarpals(self.pinkyMeta, "pinky")
+
+ self.includeClavicle()
+
+ # set network node attributes
+ cmds.setAttr(networkNode + ".armTwists", lock=False)
+ cmds.setAttr(networkNode + ".armTwists", upperarmTwists, lock=True)
+
+ cmds.setAttr(networkNode + ".forearmTwists", lock=False)
+ cmds.setAttr(networkNode + ".forearmTwists", lowerarmTwists, lock=True)
+
+ cmds.setAttr(networkNode + ".thumbJoints", lock=False)
+ cmds.setAttr(networkNode + ".thumbJoints", thumbs, lock=True)
+
+ cmds.setAttr(networkNode + ".indexJoints", lock=False)
+ cmds.setAttr(networkNode + ".indexJoints", indexFingers, lock=True)
+
+ cmds.setAttr(networkNode + ".middleJoints", lock=False)
+ cmds.setAttr(networkNode + ".middleJoints", middleFingers, lock=True)
+
+ cmds.setAttr(networkNode + ".ringJoints", lock=False)
+ cmds.setAttr(networkNode + ".ringJoints", ringFingers, lock=True)
+
+ cmds.setAttr(networkNode + ".pinkyJoints", lock=False)
+ cmds.setAttr(networkNode + ".pinkyJoints", pinkyFingers, lock=True)
+
+ cmds.setAttr(networkNode + ".includeClavicle", lock=False)
+ cmds.setAttr(networkNode + ".includeClavicle", self.clavicleCB.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".thumbMeta", lock=False)
+ cmds.setAttr(networkNode + ".thumbMeta", self.thumbMeta.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".indexMeta", lock=False)
+ cmds.setAttr(networkNode + ".indexMeta", self.indexMeta.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".ringMeta", lock=False)
+ cmds.setAttr(networkNode + ".ringMeta", self.ringMeta.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".middleMeta", lock=False)
+ cmds.setAttr(networkNode + ".middleMeta", self.middleMeta.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".pinkyMeta", lock=False)
+ cmds.setAttr(networkNode + ".pinkyMeta", self.pinkyMeta.isChecked(), lock=True)
+
+ # update outliner
+ self.updateOutliner()
+ self.updateBoneCount()
+
+ # clear selection
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def editJointMoverViaSpinBox(self, uiWidget, searchKey, isThumb, *args):
+
+ # uiWidget is the spinBox
+ # isThumb will be the special case, since there are only the three joints instead of the 4
+ # searchKey is the basname (thumb, middle, ring, etc)
+
+ # unlock bone representations
+ cmds.select(self.name + "_bone_representations", hi=True)
+ selection = cmds.ls(sl=True, type="transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock=False)
+
+ # check number in spinBox
+ num = uiWidget.value()
+
+ # set visibility on movers and geo depending on the value of num
+ for i in range(num + 1):
+ # purely for fanciness
+ time.sleep(.05)
+ cmds.refresh(force=True)
+
+ if isThumb == False:
+
+ moverList = ["_proximal", "_middle", "_distal"]
+ for mover in moverList:
+ if moverList.index(mover) <= i - 1:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1)
+
+ if i == 0:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0)
+
+ if isThumb == True:
+
+ moverList = ["_proximal", "_distal"]
+ for mover in moverList:
+ if moverList.index(mover) <= i - 1:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1)
+
+ if i == 0:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0)
+
+ # relock bone representations
+ cmds.select(self.name + "_bone_representations", hi=True)
+ selection = cmds.ls(sl=True, type="transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock=True)
+
+ # toggle mover vis
+ self.rigUiInst.setMoverVisibility()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def editJointMoverTwistBones(self, uiWidget, searchKey, *args):
+
+ # check number in spinBox
+ num = uiWidget.value()
+
+ for i in range(num + 1):
+
+ if i == 0:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 0, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock=True)
+
+ if i == 1:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock=True)
+
+ if i == 2:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock=True)
+
+ if i == 3:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 1, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def editJointMoverMetaCarpals(self, uiWidget, searchKey, *args):
+
+ # uiWidget is the spinBox
+ # searchKey is the basname (index, middle, ring, etc)
+
+ # unlock bone representations
+ cmds.select(self.name + "_bone_representations", hi=True)
+ selection = cmds.ls(sl=True, type="transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock=False)
+
+ # toggle visibility
+ if uiWidget.isChecked():
+ try:
+ cmds.parent(self.name + "_" + searchKey + "_proximal_mover_grp",
+ self.name + "_" + searchKey + "_metacarpal_mover")
+ except Exception, e:
+ print e
+
+ cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", 1, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_bone_geo.v", 1)
+
+ if not uiWidget.isChecked():
+ try:
+ cmds.parent(self.name + "_" + searchKey + "_proximal_mover_grp", self.name + "_hand_mover")
+ except Exception, e:
+ print e
+
+ cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", 0, lock=True)
+ cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_bone_geo.v", 0)
+
+ # relock bone representations
+ cmds.select(self.name + "_bone_representations", hi=True)
+ selection = cmds.ls(sl=True, type="transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock=True)
+
+ # toggle mover vis
+ self.rigUiInst.setMoverVisibility()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def includeClavicle(self, *args):
+ state = self.clavicleCB.isChecked()
+
+ if state == False:
+
+ # hide clavicle mover controls
+ cmds.setAttr(self.name + "_clavicle_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_clavicle_mover_grp.v", 0, lock=True)
+
+ # parent upperarm to mover_grp
+ try:
+ cmds.parent(self.name + "_upperarm_mover_grp", self.name + "_mover_grp")
+ except Exception, e:
+ print e
+
+ if state == True:
+
+ # show clavicle mover controls
+ cmds.setAttr(self.name + "_clavicle_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_clavicle_mover_grp.v", 1, lock=True)
+
+ # parent upperarm to mover_grp
+ try:
+ cmds.parent(self.name + "_upperarm_mover_grp", self.name + "_clavicle_mover")
+ except Exception, e:
+ print e
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def changeSide(self):
+
+ # gather information (current name, current parent, etc)
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ currentSide = cmds.getAttr(networkNode + ".side")
+
+ if cmds.getAttr(networkNode + ".aimMode") == True:
+ self.aimMode_Setup(False)
+
+ # call on base class delete
+ movers = self.returnJointMovers
+
+ for moverGrp in movers:
+ for mover in moverGrp:
+ cmds.lockNode(mover, lock=False)
+
+ cmds.delete(self.name + "_mover_grp")
+
+ # figure out side
+ if currentSide == "Left":
+ cmds.setAttr(networkNode + ".side", lock=False)
+ cmds.setAttr(networkNode + ".side", "Right", type="string", lock=True)
+ side = "Right"
+ if currentSide == "Right":
+ cmds.setAttr(networkNode + ".side", lock=False)
+ cmds.setAttr(networkNode + ".side", "Left", type="string", lock=True)
+ side = "Left"
+
+ # build new jmPath name
+ jmPath = jointMover.partition(".ma")[0] + "_" + side + ".ma"
+ self.jointMover_Build(jmPath)
+
+ # parent the joint mover to the offset mover of the parent
+ mover = ""
+
+ if parent == "root":
+ cmds.parent(name + "_mover_grp", "root_mover")
+ mover = "root_mover"
+
+ else:
+ # find the parent mover name to parent to
+ networkNodes = utils.returnRigModules()
+ mover = utils.findMoverNodeFromJointName(networkNodes, parent)
+ if mover != None:
+ cmds.parent(name + "_mover_grp", mover)
+
+ # create the connection geo between the two
+ childMover = utils.findOffsetMoverFromName(name)
+ riggingUtils.createBoneConnection(mover, childMover, name)
+ self.applyModuleChanges(self)
+
+ self.aimMode_Setup(True)
+
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def resetSettings(self):
+ 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":
+ if attr.find("Joints") == -1:
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ cmds.setAttr(networkNode + "." + attr, 0, lock=True)
+ else:
+ if attr.find("thumb") != -1:
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ cmds.setAttr(networkNode + "." + attr, 2, lock=True)
+ else:
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ cmds.setAttr(networkNode + "." + attr, 3, lock=True)
+
+ if attrType == "bool":
+ if attr.find("thumbMeta") != -1 or attr.find("includeClavicle") != -1:
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ cmds.setAttr(networkNode + "." + attr, True, lock=True)
+
+ else:
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ cmds.setAttr(networkNode + "." + attr, False, 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)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pinModule(self, state):
+
+ networkNode = self.returnNetworkNode
+ includeClav = cmds.getAttr(networkNode + ".includeClavicle")
+
+ if state:
+ if includeClav:
+ topLevelMover = self.name + "_clavicle_mover_grp"
+ else:
+ topLevelMover = self.name + "_upperarm_mover_grp"
+
+ loc = cmds.spaceLocator()[0]
+ cmds.setAttr(loc + ".v", False, lock=True)
+ constraint = cmds.parentConstraint(topLevelMover, loc)[0]
+ cmds.delete(constraint)
+ const = cmds.parentConstraint(loc, topLevelMover)[0]
+
+ if not cmds.objExists(networkNode + ".pinConstraint"):
+ cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message")
+
+ cmds.connectAttr(const + ".message", networkNode + ".pinConstraint")
+
+ if not state:
+ connections = cmds.listConnections(networkNode + ".pinConstraint")
+ if len(connections) > 0:
+ constraint = connections[0]
+ cmds.delete(constraint)
+
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skinProxyGeo(self):
+
+ # get the network node
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ # get this module's proxy geo meshes
+ cmds.select(name + "_mover_grp", hi=True)
+ proxyGeoMeshes = []
+ selection = cmds.ls(sl=True)
+ for each in selection:
+ if each.find("proxy_geo") != -1:
+ parent = cmds.listRelatives(each, parent=True)[0]
+ if cmds.nodeType(each) == "transform":
+ proxyGeoMeshes.append(each)
+
+ # skin the proxy geo meshes
+ for mesh in proxyGeoMeshes:
+ dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0]
+ cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False)
+ cmds.setAttr(dupeMesh + ".overrideDisplayType", 0)
+
+ # create skinned geo group
+ if not cmds.objExists("skinned_proxy_geo"):
+ cmds.group(empty=True, name="skinned_proxy_geo")
+
+ cmds.parent(dupeMesh, "skinned_proxy_geo")
+
+ boneName = mesh.partition(name + "_")[2]
+ boneName = boneName.partition("_proxy_geo")[0]
+ joint = prefix + boneName + suffix
+
+ if not cmds.objExists(joint):
+ cmds.delete(dupeMesh)
+
+ else:
+ cmds.select([dupeMesh, joint])
+ cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0,
+ normalizeWeights=True)
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRigCustom(self, textEdit, uiInst):
+
+ # get the network node and find out which rigs to build
+ networkNode = self.returnNetworkNode
+ buildFK = True
+ buildIK_V1 = True
+
+ # have it build all rigs by default, unless there is an attr stating otherwise (backwards- compatability)
+ numRigs = 0
+ if cmds.objExists(networkNode + ".buildFK"):
+ buildFK = cmds.getAttr(networkNode + ".buildFK")
+ if buildFK:
+ numRigs += 1
+ if cmds.objExists(networkNode + ".buildIK_V1"):
+ buildIK_V1 = cmds.getAttr(networkNode + ".buildIK_V1")
+ if buildIK_V1:
+ numRigs += 1
+
+ builtRigs = []
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create groups and settings
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create the arm group
+ armJoints = self.getMainArmJoints()
+ self.armGroup = cmds.group(empty=True, name=self.name + "_group")
+ constraint = cmds.parentConstraint(armJoints[1][0], self.armGroup)[0]
+ cmds.delete(constraint)
+
+ # create the arm settings group
+ self.armSettings = cmds.group(empty=True, name=self.name + "_settings")
+ cmds.parent(self.armSettings, self.armGroup)
+ for attr in (cmds.listAttr(self.armSettings, keyable=True)):
+ cmds.setAttr(self.armSettings + "." + attr, lock=True, keyable=False)
+
+ # add mode attribute to settings
+ if numRigs > 1:
+ cmds.addAttr(self.armSettings, ln="mode", min=0, max=numRigs - 1, dv=0, keyable=True)
+
+ # create the ctrl group (what will get the constraint to the parent)
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.armCtrlGrp = cmds.group(empty=True, name=self.name + "_arm_ctrl_grp")
+
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ constraint = cmds.parentConstraint(armJoints[0], self.armCtrlGrp)[0]
+ else:
+ constraint = cmds.parentConstraint("driver_" + parentBone, self.armCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(self.armCtrlGrp, self.armGroup)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # build the rigs
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # FK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # if build FK was true, build the FK rig now
+ if buildFK:
+ self.buildFkArm(textEdit, uiInst, builtRigs, networkNode)
+ builtRigs.append(["FK", [self.armCtrlGrp]])
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # IK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ if buildIK_V1:
+ ikArmJoints = self.buildIkArm(textEdit, uiInst, builtRigs, networkNode)
+ builtRigs.append(["IK", [self.ikCtrlGrp]])
+
+ # ===================================================================
+ # #create upper arm twist rig
+ # ===================================================================
+ twistJoints = self.getTwistJoints(True, False)
+
+ if cmds.getAttr(networkNode + ".side") == "Left":
+ twistCtrls = riggingUtils.createCounterTwistRig(twistJoints, self.name, networkNode, armJoints[1][0],
+ armJoints[1][1], self.armGroup, [-90, 0, 0])
+ if cmds.getAttr(networkNode + ".side") == "Right":
+ twistCtrls = riggingUtils.createCounterTwistRig(twistJoints, self.name, networkNode, armJoints[1][0],
+ armJoints[1][1], self.armGroup, [90, 0, 0])
+
+ if not cmds.objExists(networkNode + ".upArmTwistControls"):
+ cmds.addAttr(networkNode, ln="upArmTwistControls", dt="string")
+ jsonString = json.dumps(twistCtrls)
+ cmds.setAttr(networkNode + ".upArmTwistControls", jsonString, type="string")
+
+ # create lowerarm twist rig
+ twistJoints = self.getTwistJoints(False, True)
+ twistCtrls = riggingUtils.createTwistRig(twistJoints, self.name, networkNode, armJoints[1][1], armJoints[1][2],
+ self.armGroup, [-90, 0, 0])
+
+ if not cmds.objExists(networkNode + ".loArmTwistControls"):
+ cmds.addAttr(networkNode, ln="loArmTwistControls", dt="string")
+ jsonString = json.dumps(twistCtrls)
+ cmds.setAttr(networkNode + ".loArmTwistControls", jsonString, type="string")
+
+ # =======================================================================
+ # # #build finger rigs (if needed)
+ # =======================================================================
+ # gather data on which fingers are available for rigging
+ fingers = self.getFingerJoints()
+
+ # create finger group
+ self.fingerGrp = cmds.group(empty=True, name=self.name + "_finger_group")
+ constraint = cmds.parentConstraint(armJoints[1][2], self.fingerGrp)[0]
+ cmds.delete(constraint)
+ cmds.parent(self.fingerGrp, self.armGroup)
+
+ fingerNodes = self.buildFingers(fingers, textEdit, uiInst, builtRigs, networkNode)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # CLAVICLE # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ clavData = self.buildClavicleRig(textEdit, uiInst, builtRigs, networkNode)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Hook up ArmCtrlGrp # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ armCtrlPointConst = \
+ cmds.pointConstraint(["fk_" + armJoints[0] + "_anim", self.name + "_clav_follow"], self.armCtrlGrp)[0]
+ armCtrlOrientConst = \
+ cmds.orientConstraint(["fk_" + armJoints[0] + "_anim", self.name + "_clav_follow"], self.armCtrlGrp)[0]
+
+ attrData = []
+ for connection in [armCtrlPointConst, armCtrlOrientConst]:
+ driveAttrs = []
+ targets = cmds.getAttr(connection + ".target", mi=True)
+ if len(targets) > 1:
+ for each in targets:
+ driveAttrs.append(
+ cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p=True))
+
+ attrData.append(driveAttrs)
+
+ # setup set driven keys on our moder attr and those target attributes
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ for i in range(numRigs):
+ cmds.setAttr(self.armSettings + ".clavMode", i)
+
+ # go through attr data and zero out anything but the first element in the list
+ for data in attrData:
+ for each in data:
+ cmds.setAttr(each[0], 0)
+
+ cmds.setAttr(data[i][0], 1)
+
+ # set driven keys
+ for data in attrData:
+ for each in data:
+ cmds.setDrivenKeyframe(each[0], cd=self.armSettings + ".clavMode", itt="linear", ott="linear")
+
+ # =======================================================================
+ # # auto clav set driven keys for ik arm
+ # =======================================================================
+ cmds.parent(ikArmJoints[0], self.armCtrlGrp)
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ if len(builtRigs) > 1:
+ # set elbow pose constraint keys based on arm mode
+
+ elbowConstAttrs = []
+
+ targets = cmds.getAttr(clavData[0] + ".target", mi=True)
+ if len(targets) > 1:
+ for each in targets:
+ elbowConstAttrs.append(
+ cmds.listConnections(clavData[0] + ".target[" + str(each) + "].targetWeight", p=True))
+
+ for i in range(len(builtRigs)):
+ cmds.setAttr(self.armSettings + ".mode", i)
+ # go through attr data and zero out anything but the first element in the list
+ for data in elbowConstAttrs:
+ for each in data:
+ cmds.setAttr(each, 0)
+
+ cmds.setAttr(elbowConstAttrs[i][0], 1)
+
+ # set driven keys
+ for data in elbowConstAttrs:
+ for each in data:
+ cmds.setDrivenKeyframe(each, cd=self.armSettings + ".mode", itt="linear", ott="linear")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Hook up FK/IK Switching # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # mode
+ if numRigs > 1:
+ attrData = []
+ rampData = []
+
+ """ CONSTRAINTS """
+ # get the constraint connections on the driver joints for the arms
+ connections = []
+ for joint in armJoints[1]:
+ connections.extend(list(set(cmds.listConnections("driver_" + joint, type="constraint"))))
+ ramps = (list(set(cmds.listConnections("driver_" + joint, type="ramp"))))
+ for ramp in ramps:
+ connections.append(ramp + ".uCoord")
+
+ for connection in connections:
+ driveAttrs = []
+
+ if cmds.nodeType(connection) in ["pointConstraint", "orientConstraint"]:
+
+ # get those constraint target attributes for each constraint connection
+ targets = cmds.getAttr(connection + ".target", mi=True)
+ if len(targets) > 1:
+ for each in targets:
+ driveAttrs.append(
+ cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight",
+ p=True))
+
+ # add this data to our master list of constraint attribute data
+ attrData.append(driveAttrs)
+ else:
+ if cmds.nodeType(connection) == "ramp":
+ rampData.append(connection)
+
+ rampData = list(set(rampData))
+
+ # setup set driven keys on our moder attr and those target attributes
+ for i in range(numRigs):
+
+ cmds.setAttr(self.armSettings + ".mode", i)
+
+ # go through attr data and zero out anything but the first element in the list
+ for data in attrData:
+ for each in data:
+ cmds.setAttr(each[0], 0)
+
+ cmds.setAttr(data[i][0], 1)
+
+ # set driven keys
+ for data in attrData:
+ for each in data:
+ cmds.setDrivenKeyframe(each[0], cd=self.armSettings + ".mode", itt="linear", ott="linear")
+
+ """ RAMPS """
+ # direct connect mode to uCoord value (only works if there are 2 rigs...) <- not sure if that is the case
+ # still
+ for data in rampData:
+ # create a multiply node that takes first input of 1/numRigs and 2nd of mode direct connection
+ multNode = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_" + data.partition(".uCoord")[0] + "_mult")
+ cmds.setAttr(multNode + ".input1X", float(float(1) / float(numRigs - 1)))
+ cmds.connectAttr(self.armSettings + ".mode", multNode + ".input2X")
+ cmds.connectAttr(multNode + ".outputX", data)
+
+ # hook up control visibility
+ for i in range(len(builtRigs)):
+ cmds.setAttr(self.armSettings + ".mode", i)
+ for rig in builtRigs:
+ visNodes = rig[1]
+ for node in visNodes:
+ if node != None:
+ cmds.setAttr(node + ".v", 0)
+
+ if builtRigs.index(rig) == i:
+ visNodes = rig[1]
+ for node in visNodes:
+ if node != None:
+ cmds.setAttr(node + ".v", 1)
+
+ cmds.setDrivenKeyframe(visNodes, at="visibility", cd=self.armSettings + ".mode", itt="linear",
+ ott="linear")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Parent Under Offset Ctrl # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # parent under offset_anim if it exists(it always should)
+ if cmds.objExists("offset_anim"):
+ cmds.parent(self.armGroup, "offset_anim")
+
+ # return data
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ try:
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ uiInst.rigData.append([self.name + "_auto_clav_grp", "driver_" + parentBone, numRigs])
+ uiInst.rigData.append([self.clavCtrlGrp, "driver_" + parentBone, numRigs])
+
+ else:
+ uiInst.rigData.append([self.armCtrlGrp, "driver_" + parentBone, numRigs])
+ except:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildClavicleRig(self, textEdit, uiInst, builtRigs, networkNode):
+
+ # add clavicle mode to rig settings
+ cmds.addAttr(self.armSettings, ln="clavMode", min=0, max=1, dv=0, keyable=True)
+
+ # Rig Joint
+ joints = self.getMainArmJoints()
+ clavJoint = joints[0]
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+
+ rigJnt = cmds.createNode("joint", name=self.name + "_clav_rigJnt")
+ const = cmds.parentConstraint(clavJoint, rigJnt)[0]
+ cmds.delete(const)
+
+ cmds.setAttr(rigJnt + ".v", 0, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # FK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create rig control
+ data = riggingUtils.createControlFromMover(clavJoint, networkNode, True, False)
+
+ fkControl = cmds.rename(data[0], "fk_" + clavJoint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + clavJoint + "_anim_grp")
+ riggingUtils.colorControl(fkControl)
+
+ for attr in [".translateX", ".translateY", ".translateZ", ".scaleX", ".scaleY", ".scaleZ", ".visibility"]:
+ cmds.setAttr(fkControl + attr, lock=True, keyable=False)
+
+ # create clav rig grp
+ self.clavCtrlGrp = cmds.group(empty=True, name=self.name + "_clav_ctrl_grp")
+ constraint = cmds.parentConstraint(parentBone, self.clavCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(self.clavCtrlGrp, self.armGroup)
+
+ # parent fk clav to clav grp
+ cmds.parent(animGrp, self.clavCtrlGrp)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # IK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create rig control
+ ikControl = riggingUtils.createControl("arrow", 1, "ik_" + clavJoint + "_anim", True)
+ ikCtrlGrp = cmds.group(empty=True, name="ik_" + clavJoint + "_anim_grp")
+
+ cmds.setAttr(ikControl + ".rotateX", -90)
+ cmds.makeIdentity(ikControl, t=1, r=1, s=1, apply=True)
+
+ const = cmds.pointConstraint(joints[1][0], ikCtrlGrp)[0]
+ cmds.delete(const)
+
+ const = cmds.pointConstraint(joints[1][0], ikControl)[0]
+ cmds.delete(const)
+ const = cmds.orientConstraint(joints[1][0], ikControl, skip=["x"])[0]
+ cmds.delete(const)
+
+ cmds.parent(ikControl, ikCtrlGrp)
+ cmds.makeIdentity(ikControl, t=1, r=1, s=1, apply=True)
+
+ upArmPiv = cmds.xform(joints[1][0], q=True, ws=True, rp=True)
+ cmds.xform(ikControl, ws=True, piv=upArmPiv)
+ cmds.xform(ikCtrlGrp, ws=True, piv=upArmPiv)
+
+ riggingUtils.colorControl(ikControl)
+
+ for attr in [".rotateX", ".rotateY", ".rotateZ", ".scaleX", ".scaleY", ".scaleZ", ".visibility"]:
+ cmds.setAttr(ikControl + attr, lock=True, keyable=False)
+
+ # create the ik joint chain
+ startJnt = cmds.createNode("joint", name=self.name + "_clav_ik_start")
+ endJnt = cmds.createNode("joint", name=self.name + "_clav_ik_end")
+ pointJnt = cmds.createNode("joint", name=self.name + "_clav_follow")
+
+ const = cmds.parentConstraint(clavJoint, startJnt)[0]
+ cmds.delete(const)
+
+ const = cmds.parentConstraint(joints[1][0], endJnt)[0]
+ cmds.delete(const)
+
+ const = cmds.parentConstraint(clavJoint, pointJnt)[0]
+ cmds.delete(const)
+
+ cmds.parent(endJnt, startJnt)
+
+ # hide joints
+ for jnt in [startJnt, endJnt, pointJnt]:
+ cmds.setAttr(jnt + ".v", 0, lock=True)
+
+ # create the ikHandle
+ ikNodes = cmds.ikHandle(sj=startJnt, ee=endJnt, sol="ikSCsolver", name=self.name + "_clav_ikHandle")[0]
+ cmds.parent(ikNodes, ikControl)
+ cmds.setAttr(ikNodes + ".v", 0, lock=True)
+ cmds.setAttr(ikNodes + ".stickiness", 1)
+ cmds.setAttr(ikNodes + ".snapEnable", 1)
+
+ # =======================================================================
+ # #lastly, connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+
+ rigJntPointConst = cmds.pointConstraint([fkControl, startJnt], rigJnt, mo=True)[0]
+ rigJointOrientConst = cmds.orientConstraint([fkControl, startJnt], rigJnt)[0]
+
+ attrData = []
+ for connection in [rigJntPointConst, rigJointOrientConst]:
+ driveAttrs = []
+ targets = cmds.getAttr(connection + ".target", mi=True)
+ if len(targets) > 1:
+ for each in targets:
+ driveAttrs.append(
+ cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p=True))
+
+ attrData.append(driveAttrs)
+
+ cmds.setAttr(rigJointOrientConst + ".interpType", 2)
+
+ # setup set driven keys on our moder attr and those target attributes
+ for i in range(2):
+ cmds.setAttr(self.armSettings + ".clavMode", i)
+
+ # go through attr data and zero out anything but the first element in the list
+ for data in attrData:
+ for each in data:
+ cmds.setAttr(each[0], 0)
+
+ cmds.setAttr(data[i][0], 1)
+
+ # set driven keys
+ for data in attrData:
+ for each in data:
+ cmds.setDrivenKeyframe(each[0], cd=self.armSettings + ".clavMode", itt="linear", ott="linear")
+
+ # =======================================================================
+ # #connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+
+ cmds.pointConstraint(rigJnt, "driver_" + clavJoint, mo=True)
+ cmds.orientConstraint(rigJnt, "driver_" + clavJoint)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into
+ # input 2,and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=clavJoint + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(rigJnt + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + clavJoint, "scale", False, 2, 1, "output")
+ else:
+ riggingUtils.createConstraint(rigJnt, "driver_" + clavJoint, "scale", False, 2, 1)
+
+ # =======================================================================
+ # #add IK matcher under FK clav control
+ # =======================================================================
+ ikMatchGrp = cmds.group(empty=True, name=self.name + "_ik_clav_matcher")
+ cmds.parent(ikMatchGrp, fkControl)
+ const = cmds.pointConstraint(ikControl, ikMatchGrp)[0]
+ cmds.delete(const)
+
+ # =======================================================================
+ # #hook up auto clavicle
+ # =======================================================================
+
+ # create the main grp to hold all auto clav contents
+ autoClavGrp = cmds.group(empty=True, name=self.name + "_auto_clav_grp")
+ constraint = cmds.parentConstraint("driver_" + parentBone, autoClavGrp)[0]
+ cmds.delete(constraint)
+
+ # create invis arm chain
+ invisArmJnts = []
+ for joint in joints[1]:
+ jnt = cmds.createNode("joint", name="auto_clav_" + joint)
+ const = cmds.parentConstraint(joint, jnt)[0]
+ cmds.delete(const)
+ invisArmJnts.append(jnt)
+
+ invisArmJnts.reverse()
+ for i in range(len(invisArmJnts)):
+ try:
+ cmds.parent(invisArmJnts[i], invisArmJnts[i + 1])
+ except IndexError:
+ pass
+
+ cmds.setAttr(invisArmJnts[i] + ".v", 0, lock=True)
+
+ invisArmJnts.reverse()
+ cmds.makeIdentity(invisArmJnts[0], t=0, r=1, s=0, apply=True)
+ cmds.parent(invisArmJnts[0], autoClavGrp)
+
+ # create the invis upper arm fk control/grp
+ invisAnimGrp = cmds.group(empty=True, name="auto_clav_fk_" + joints[1][0] + "_anim_grp")
+ const = cmds.parentConstraint(joints[1][0], invisAnimGrp)[0]
+ cmds.delete(const)
+
+ invisArmAnim = cmds.spaceLocator(name="auto_clav_fk_" + joints[1][0] + "_anim")[0]
+ const = cmds.parentConstraint(joints[1][0], invisArmAnim)[0]
+ cmds.delete(const)
+ cmds.setAttr(invisArmAnim + ".v", 0, lock=True)
+
+ cmds.parent(invisArmAnim, invisAnimGrp)
+ cmds.parent(invisAnimGrp, autoClavGrp)
+
+ # create orient loc/grp
+ orientLocGrp = cmds.group(empty=True, name=self.name + "_auto_clav_orient_loc_grp")
+ const = cmds.parentConstraint(joints[1][0], orientLocGrp)[0]
+ cmds.delete(const)
+
+ orientLoc = cmds.spaceLocator(name=self.name + "_auto_clav_orient_loc")[0]
+ const = cmds.parentConstraint(joints[1][0], orientLoc)[0]
+ cmds.delete(const)
+
+ cmds.parent(orientLoc, orientLocGrp)
+ cmds.parent(orientLocGrp, invisArmAnim)
+
+ # orient constrain invis upper arm to orient loc
+ cmds.orientConstraint(orientLoc, invisArmJnts[0])
+
+ # connect real fk upperarm anim.rotate to invisArmAnim.rotate
+ side = cmds.getAttr(networkNode + ".side")[0]
+ if side == "L":
+ cmds.connectAttr("fk_" + joints[1][0] + "_anim.rotate", invisArmAnim + ".rotate")
+ else:
+ reverseMult = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_" + side + "_multNodeReverse")
+ cmds.setAttr(reverseMult + ".input2X", -1)
+ cmds.setAttr(reverseMult + ".input2Y", -1)
+ cmds.setAttr(reverseMult + ".input2Z", -1)
+ cmds.connectAttr("fk_" + joints[1][0] + "_anim.rotate", reverseMult + ".input1")
+ cmds.connectAttr(reverseMult + ".output", invisArmAnim + ".rotate")
+
+ # create a locator that tracks our elbow position
+ currentElbowPose = cmds.spaceLocator(name=self.name + "_auto_clav_current_elbow_loc")[0]
+ const = cmds.parentConstraint(joints[1][1], currentElbowPose)[0]
+ cmds.delete(const)
+ cmds.setAttr(currentElbowPose + ".v", 0, lock=True)
+
+ # create a group for that locator
+ currentPoseGrp = cmds.group(empty=True, name=self.name + "_auto_clav_current_elbow_grp")
+ const = cmds.parentConstraint(joints[1][1], currentPoseGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(currentElbowPose, currentPoseGrp)
+ cmds.parent(currentPoseGrp, autoClavGrp)
+
+ # point constraint locator grp to invis lower arm
+ cmds.pointConstraint(invisArmJnts[1], currentPoseGrp)
+
+ # create switcher group
+ switcherGrp = cmds.group(empty=True, name=self.name + "_auto_clav_switcher_grp")
+ const = cmds.pointConstraint(invisArmJnts[0], switcherGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(switcherGrp, autoClavGrp)
+
+ # point constrain to autoClavGrp
+ cmds.pointConstraint(autoClavGrp, switcherGrp)
+
+ # create ik master grp
+ ikMasterGrp = cmds.group(empty=True, name=self.name + "_auto_clav_ik_master_grp")
+ const = cmds.pointConstraint(invisArmJnts[0], ikMasterGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(ikMasterGrp, switcherGrp)
+ cmds.makeIdentity(ikMasterGrp, t=1, r=1, s=1, apply=True)
+
+ # create ik grp
+ ikGrp = cmds.group(empty=True, name=self.name + "_auto_clav_ik_grp")
+ const = cmds.pointConstraint(invisArmJnts[0], ikGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(ikGrp, ikMasterGrp)
+ cmds.makeIdentity(ikGrp, t=1, r=1, s=1, apply=True)
+
+ # connect ik clav anim.translate to this grp.translate
+ cmds.connectAttr(ikControl + ".translate", ikGrp + ".translate")
+
+ # create parent space group for driven group
+ ikDrivenSpace = cmds.group(empty=True, name=self.name + "_auto_clav_ik_driven_space_grp")
+ const = cmds.parentConstraint(invisArmJnts[0], ikDrivenSpace)[0]
+ cmds.delete(const)
+
+ cmds.parent(ikDrivenSpace, ikGrp)
+
+ # create two more groups. ikDrivenGrp and autoClavTranslateGrp. drivenGrp is what will get the pose reader SDKs,
+ # autoClavTranslateGrp is what will carry the ikHandle
+ ikDrivenGrp = cmds.group(empty=True, name=self.name + "_auto_clav_ik_driven_grp")
+ const = cmds.parentConstraint(invisArmJnts[0], ikDrivenGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(ikDrivenGrp, ikDrivenSpace)
+ cmds.makeIdentity(ikDrivenGrp, t=1, r=1, s=1, apply=True)
+
+ # create parent space group for autoClavTranslateGrp
+ autoClavTransGrpSpace = cmds.group(empty=True, name=self.name + "_auto_clav_ik_trans_space_grp")
+ const = cmds.parentConstraint(invisArmJnts[0], autoClavTransGrpSpace)[0]
+ cmds.delete(const)
+
+ cmds.parent(autoClavTransGrpSpace, ikGrp)
+
+ autoClavTranslateGrp = cmds.group(empty=True, name=self.name + "_auto_clav_trans_grp")
+ const = cmds.parentConstraint(invisArmJnts[0], autoClavTranslateGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(autoClavTranslateGrp, autoClavTransGrpSpace)
+ cmds.makeIdentity(autoClavTranslateGrp, t=1, r=1, s=1, apply=True)
+
+ # parent the ik clav ikHandle under the autoClavTranslateGrp
+ cmds.parent(ikNodes, autoClavTranslateGrp)
+
+ # add setting to arm settings for autoShoulders
+ cmds.addAttr(self.armSettings, ln="autoShoulders", min=0, max=1, dv=0, keyable=True)
+
+ # connect ikDrivenGrp.translate to multDivide node input1, connect autoShoulders attr to input 2,
+ # connect output to autoClavTranslateGrp.translate
+ clavTransMult = cmds.shadingNode("multiplyDivide", name=self.name + "_clav_trans_mult", asUtility=True)
+ cmds.connectAttr(ikDrivenGrp + ".translate", clavTransMult + ".input1")
+ cmds.connectAttr(self.armSettings + ".autoShoulders", clavTransMult + ".input2X")
+ cmds.connectAttr(self.armSettings + ".autoShoulders", clavTransMult + ".input2Y")
+ cmds.connectAttr(self.armSettings + ".autoShoulders", clavTransMult + ".input2Z")
+ cmds.connectAttr(clavTransMult + ".output", autoClavTranslateGrp + ".translate")
+
+ # make auto clav work for IK arm
+ ikArmAutoClavGrp = cmds.group(empty=True, name=self.name + "_ikArm_auto_clav_grp")
+ const = cmds.parentConstraint(self.ikHandCtrl, ikArmAutoClavGrp)[0]
+ cmds.delete(const)
+
+ ikArmAutoClavLoc = cmds.spaceLocator(name=self.name + "_ikArm_auto_clav_loc")[0]
+ const = cmds.pointConstraint(joints[1][1], ikArmAutoClavLoc)[0]
+ cmds.delete(const)
+ cmds.setAttr(ikArmAutoClavLoc + ".v", 0, lock=True)
+
+ cmds.parent(ikArmAutoClavGrp, self.ikHandCtrl)
+ cmds.parent(ikArmAutoClavLoc, ikArmAutoClavGrp)
+
+ cmds.makeIdentity(ikArmAutoClavLoc, t=1, r=1, s=1, apply=True)
+ elbowLocConst = cmds.pointConstraint([invisArmJnts[1], ikArmAutoClavLoc], currentPoseGrp)[0]
+
+ # aim ikArmAutoClavGrp to the IK PV
+ cmds.aimConstraint(self.name + "_ik_elbow_anim", ikArmAutoClavGrp, aimVector=[-1, 0, 0], upVector=[0, 0, 1],
+ wut="scene", wu=[0, 0, 1])
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Clean Up # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ cmds.parent(startJnt, autoClavGrp)
+ cmds.parent(ikCtrlGrp, autoClavGrp)
+ cmds.parent(pointJnt, autoClavGrp)
+ cmds.makeIdentity(pointJnt, t=0, r=1, s=0, apply=True)
+ cmds.pointConstraint(endJnt, pointJnt, mo=True)
+
+ # create a clavicle grp
+ self.clavicleGrp = cmds.group(empty=True, name=self.name + "_clavicle_grp")
+ const = cmds.parentConstraint(self.armCtrlGrp, self.clavicleGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(self.clavicleGrp, self.armGroup)
+
+ # parent rigJnt to clavicle group
+ cmds.parent(rigJnt, self.clavicleGrp)
+
+ # parent autoClavGrp and self.clavCtrlGrp to clavicle grp
+ cmds.parent(autoClavGrp, self.clavicleGrp)
+ cmds.parent(self.clavCtrlGrp, self.clavicleGrp)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # POSE READER # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ """
+ Create vectors from the base locator, to the current locator, and from the base to a pose locator
+ Subtract the end position with the base.
+ Get the angle between the two vectors. compare the angle between the vectors to the max cone angle given.
+ """
+
+ cmds.loadPlugin('matrixNodes.dll')
+ # global
+
+ baseLoc = cmds.spaceLocator(name=self.name + "_poseReader_Base")[0]
+ const = cmds.parentConstraint(self.name + "_base", baseLoc)[0]
+ cmds.delete(const)
+ cmds.parent(baseLoc, self.armGroup)
+ cmds.setAttr(baseLoc + ".v", 0, lock=True)
+
+ baseDM = cmds.shadingNode("decomposeMatrix", asUtility=True, name=self.name + "_poseReader_base_matrix")
+ cmds.connectAttr(baseLoc + ".worldMatrix[0]", baseDM + ".inputMatrix")
+
+ currentDM = cmds.shadingNode("decomposeMatrix", asUtility=True, name=self.name + "_poseReader_current_matrix")
+ cmds.connectAttr(self.name + "_auto_clav_current_elbow_loc.worldMatrix[0]", currentDM + ".inputMatrix")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # Arm Up
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ upArmLoc = cmds.spaceLocator(name=self.name + "_poseReader_armUp_pose")[0]
+ const = cmds.parentConstraint(self.name + "_arm_up_pose", upArmLoc)[0]
+ cmds.delete(const)
+ cmds.parent(upArmLoc, self.armGroup)
+ cmds.setAttr(upArmLoc + ".v", 0, lock=True)
+
+ armUpTargetDM = cmds.shadingNode("decomposeMatrix", asUtility=True, name=self.name + "_poseReader_armUp_target")
+ cmds.connectAttr(upArmLoc + ".worldMatrix[0]", armUpTargetDM + ".inputMatrix")
+
+ # create plusMinusAverage node, set to subtract. armUpTargetDM.outputTranslate -> plusMinusAvg.input3D[0].
+ # baseDM.outputTranslate -> plusMinusAvg.input3D[1]
+ armUpTargetPMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armUp_targetFromBase")
+ cmds.setAttr(armUpTargetPMA + ".operation", 2)
+ cmds.connectAttr(armUpTargetDM + ".outputTranslate", armUpTargetPMA + ".input3D[0]")
+ cmds.connectAttr(baseDM + ".outputTranslate", armUpTargetPMA + ".input3D[1]")
+
+ # create plusMinusAverage node, set to subtract. currentDM.outputTranslate -> plusMinusAvg.input3D[0].
+ # baseDM.outputTranslate -> plusMinusAvg.input3D[1]
+ armUpCurrentPMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armUp_currentFromBase")
+ cmds.setAttr(armUpCurrentPMA + ".operation", 2)
+ cmds.connectAttr(currentDM + ".outputTranslate", armUpCurrentPMA + ".input3D[0]")
+ cmds.connectAttr(baseDM + ".outputTranslate", armUpCurrentPMA + ".input3D[1]")
+
+ # get angle between vectors
+ armUpAngleBetween = cmds.shadingNode("angleBetween", asUtility=True, name=self.name + "_armUp_AngleBetween")
+ cmds.connectAttr(armUpTargetPMA + ".output3D", armUpAngleBetween + ".vector1")
+ cmds.connectAttr(armUpCurrentPMA + ".output3D", armUpAngleBetween + ".vector2")
+
+ # add attr to the base locator for armUpConeAngle
+ cmds.addAttr(baseLoc, ln="armUpConeAngle", keyable=True)
+ cmds.setAttr(baseLoc + ".armUpConeAngle", 180)
+
+ # halve the cone angle
+ armUpMultDL = cmds.shadingNode("multDoubleLinear", asUtility=True, name=self.name + "_armUp_coneAngleMult")
+ cmds.connectAttr(baseLoc + ".armUpConeAngle", armUpMultDL + ".input1")
+ cmds.setAttr(armUpMultDL + ".input2", 0.5)
+
+ # divide the angle between our vectors by the cone angle
+ armUpConeRatio = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_armUp_coneAngleRatio")
+ cmds.setAttr(armUpConeRatio + ".operation", 2)
+
+ cmds.connectAttr(armUpAngleBetween + ".angle", armUpConeRatio + ".input1X")
+ cmds.connectAttr(armUpMultDL + ".output", armUpConeRatio + ".input2X")
+
+ # create condition. If result > 1, use 1. If result < 1, use result
+ armUpCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_armUp_condition")
+ cmds.setAttr(armUpCondition + ".operation", 2)
+
+ cmds.connectAttr(armUpConeRatio + ".outputX", armUpCondition + ".firstTerm")
+ cmds.setAttr(armUpCondition + ".secondTerm", 1)
+ cmds.setAttr(armUpCondition + ".colorIfTrueR", 1)
+ cmds.connectAttr(armUpConeRatio + ".outputX", armUpCondition + ".colorIfFalseR")
+
+ # plug condition result into a new plusMinusAvg (subtract) input3D[1]. set input3D[0] to 1
+ armUpReversePMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armUp_reverse")
+ cmds.setAttr(armUpReversePMA + ".operation", 2)
+
+ cmds.connectAttr(armUpCondition + ".outColorR", armUpReversePMA + ".input1D[1]")
+ cmds.setAttr(armUpReversePMA + ".input1D[0]", 1)
+
+ # add attr to base loc for armUp result
+ cmds.addAttr(baseLoc, ln="armUpResult", dv=0, min=0, max=1, keyable=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # Arm Forward
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ armForwardLoc = cmds.spaceLocator(name=self.name + "_poseReader_armForward_pose")[0]
+ const = cmds.parentConstraint(self.name + "_arm_forward_pose", armForwardLoc)[0]
+ cmds.delete(const)
+ cmds.parent(armForwardLoc, self.armGroup)
+ cmds.setAttr(armForwardLoc + ".v", 0, lock=True)
+
+ armForwardTargetDM = cmds.shadingNode("decomposeMatrix", asUtility=True,
+ name=self.name + "_poseReader_armForward_target")
+ cmds.connectAttr(armForwardLoc + ".worldMatrix[0]", armForwardTargetDM + ".inputMatrix")
+
+ # create plusMinusAverage node, set to subtract. armUpTargetDM.outputTranslate -> plusMinusAvg.input3D[0].
+ # baseDM.outputTranslate -> plusMinusAvg.input3D[1]
+ armForwardTargetPMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armForward_targetFromBase")
+ cmds.setAttr(armForwardTargetPMA + ".operation", 2)
+ cmds.connectAttr(armForwardTargetDM + ".outputTranslate", armForwardTargetPMA + ".input3D[0]")
+ cmds.connectAttr(baseDM + ".outputTranslate", armForwardTargetPMA + ".input3D[1]")
+
+ # create plusMinusAverage node, set to subtract. currentDM.outputTranslate -> plusMinusAvg.input3D[0].
+ # baseDM.outputTranslate -> plusMinusAvg.input3D[1]
+ armForwardCurrentPMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armForward_currentFromBase")
+ cmds.setAttr(armForwardCurrentPMA + ".operation", 2)
+ cmds.connectAttr(currentDM + ".outputTranslate", armForwardCurrentPMA + ".input3D[0]")
+ cmds.connectAttr(baseDM + ".outputTranslate", armForwardCurrentPMA + ".input3D[1]")
+
+ # get angle between vectors
+ armForwardAngleBetween = cmds.shadingNode("angleBetween", asUtility=True,
+ name=self.name + "_armForward_AngleBetween")
+ cmds.connectAttr(armForwardTargetPMA + ".output3D", armForwardAngleBetween + ".vector1")
+ cmds.connectAttr(armForwardCurrentPMA + ".output3D", armForwardAngleBetween + ".vector2")
+
+ # add attr to the base locator for armUpConeAngle
+ cmds.addAttr(baseLoc, ln="armForwardConeAngle", keyable=True)
+ cmds.setAttr(baseLoc + ".armForwardConeAngle", 180)
+
+ # halve the cone angle
+ armForwardMultDL = cmds.shadingNode("multDoubleLinear", asUtility=True,
+ name=self.name + "_armForward_coneAngleMult")
+ cmds.connectAttr(baseLoc + ".armUpConeAngle", armForwardMultDL + ".input1")
+ cmds.setAttr(armForwardMultDL + ".input2", 0.5)
+
+ # divide the angle between our vectors by the cone angle
+ armForwardConeRatio = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_armForward_coneAngleRatio")
+ cmds.setAttr(armForwardConeRatio + ".operation", 2)
+
+ cmds.connectAttr(armForwardAngleBetween + ".angle", armForwardConeRatio + ".input1X")
+ cmds.connectAttr(armForwardMultDL + ".output", armForwardConeRatio + ".input2X")
+
+ # create condition. If result > 1, use 1. If result < 1, use result
+ armForwardCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_armForward_condition")
+ cmds.setAttr(armForwardCondition + ".operation", 2)
+
+ cmds.connectAttr(armForwardConeRatio + ".outputX", armForwardCondition + ".firstTerm")
+ cmds.setAttr(armForwardCondition + ".secondTerm", 1)
+ cmds.setAttr(armForwardCondition + ".colorIfTrueR", 1)
+ cmds.connectAttr(armForwardConeRatio + ".outputX", armForwardCondition + ".colorIfFalseR")
+
+ # plug condition result into a new plusMinusAvg (subtract) input3D[1]. set input3D[0] to 1
+ armForwardReversePMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armForward_reverse")
+ cmds.setAttr(armForwardReversePMA + ".operation", 2)
+
+ cmds.connectAttr(armForwardCondition + ".outColorR", armForwardReversePMA + ".input1D[1]")
+ cmds.setAttr(armForwardReversePMA + ".input1D[0]", 1)
+
+ # add attr to base loc for armUp result
+ cmds.addAttr(baseLoc, ln="armForwardResult", dv=0, min=0, max=1, keyable=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # Arm Backward
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ armBackwardLoc = cmds.spaceLocator(name=self.name + "_poseReader_armBackward_pose")[0]
+ const = cmds.parentConstraint(self.name + "_arm_back_pose", armBackwardLoc)[0]
+ cmds.delete(const)
+ cmds.parent(armBackwardLoc, self.armGroup)
+ cmds.setAttr(armBackwardLoc + ".v", 0, lock=True)
+
+ armBackwardTargetDM = cmds.shadingNode("decomposeMatrix", asUtility=True,
+ name=self.name + "_poseReader_armBackward_target")
+ cmds.connectAttr(armBackwardLoc + ".worldMatrix[0]", armBackwardTargetDM + ".inputMatrix")
+
+ # create plusMinusAverage node, set to subtract. armUpTargetDM.outputTranslate -> plusMinusAvg.input3D[0].
+ # baseDM.outputTranslate -> plusMinusAvg.input3D[1]
+ armBackwardTargetPMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armBackward_targetFromBase")
+ cmds.setAttr(armBackwardTargetPMA + ".operation", 2)
+ cmds.connectAttr(armBackwardTargetDM + ".outputTranslate", armBackwardTargetPMA + ".input3D[0]")
+ cmds.connectAttr(baseDM + ".outputTranslate", armBackwardTargetPMA + ".input3D[1]")
+
+ # create plusMinusAverage node, set to subtract. currentDM.outputTranslate -> plusMinusAvg.input3D[0].
+ # baseDM.outputTranslate -> plusMinusAvg.input3D[1]
+ armBackwardCurrentPMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armBackward_currentFromBase")
+ cmds.setAttr(armBackwardCurrentPMA + ".operation", 2)
+ cmds.connectAttr(currentDM + ".outputTranslate", armBackwardCurrentPMA + ".input3D[0]")
+ cmds.connectAttr(baseDM + ".outputTranslate", armBackwardCurrentPMA + ".input3D[1]")
+
+ # get angle between vectors
+ armBackwardAngleBetween = cmds.shadingNode("angleBetween", asUtility=True,
+ name=self.name + "_armBackward_AngleBetween")
+ cmds.connectAttr(armBackwardTargetPMA + ".output3D", armBackwardAngleBetween + ".vector1")
+ cmds.connectAttr(armBackwardCurrentPMA + ".output3D", armBackwardAngleBetween + ".vector2")
+
+ # add attr to the base locator for armUpConeAngle
+ cmds.addAttr(baseLoc, ln="armBackwardConeAngle", keyable=True)
+ cmds.setAttr(baseLoc + ".armBackwardConeAngle", 180)
+
+ # halve the cone angle
+ armBackwardMultDL = cmds.shadingNode("multDoubleLinear", asUtility=True,
+ name=self.name + "_armBackward_coneAngleMult")
+ cmds.connectAttr(baseLoc + ".armUpConeAngle", armBackwardMultDL + ".input1")
+ cmds.setAttr(armBackwardMultDL + ".input2", 0.5)
+
+ # divide the angle between our vectors by the cone angle
+ armBackwardConeRatio = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_armBackward_coneAngleRatio")
+ cmds.setAttr(armBackwardConeRatio + ".operation", 2)
+
+ cmds.connectAttr(armBackwardAngleBetween + ".angle", armBackwardConeRatio + ".input1X")
+ cmds.connectAttr(armBackwardMultDL + ".output", armBackwardConeRatio + ".input2X")
+
+ # create condition. If result > 1, use 1. If result < 1, use result
+ armBackwardCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_armBackward_condition")
+ cmds.setAttr(armBackwardCondition + ".operation", 2)
+
+ cmds.connectAttr(armBackwardConeRatio + ".outputX", armBackwardCondition + ".firstTerm")
+ cmds.setAttr(armBackwardCondition + ".secondTerm", 1)
+ cmds.setAttr(armBackwardCondition + ".colorIfTrueR", 1)
+ cmds.connectAttr(armBackwardConeRatio + ".outputX", armBackwardCondition + ".colorIfFalseR")
+
+ # plug condition result into a new plusMinusAvg (subtract) input3D[1]. set input3D[0] to 1
+ armBackwardReversePMA = cmds.shadingNode("plusMinusAverage", asUtility=True,
+ name=self.name + "_poseReader_armBackward_reverse")
+ cmds.setAttr(armBackwardReversePMA + ".operation", 2)
+
+ cmds.connectAttr(armBackwardCondition + ".outColorR", armBackwardReversePMA + ".input1D[1]")
+ cmds.setAttr(armBackwardReversePMA + ".input1D[0]", 1)
+
+ # add attr to base loc for armUp result
+ cmds.addAttr(baseLoc, ln="armBackwardResult", dv=0, min=0, max=1, keyable=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # SET DRIVEN KEYS (pose reader) # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ side = cmds.getAttr(networkNode + ".side")[0]
+
+ # arm up
+ cmds.setAttr(baseLoc + ".armUpResult", 0)
+ cmds.setAttr(ikDrivenGrp + ".translateZ", 0)
+ cmds.setDrivenKeyframe(ikDrivenGrp + ".translateZ", cd=baseLoc + ".armUpResult")
+
+ cmds.setAttr(baseLoc + ".armUpResult", 1)
+ if side == "L":
+ cmds.setAttr(ikDrivenGrp + ".translateZ", cmds.getAttr(upArmLoc + ".translateZ"))
+ else:
+ cmds.setAttr(ikDrivenGrp + ".translateZ", cmds.getAttr(upArmLoc + ".translateZ") * -1)
+ cmds.setDrivenKeyframe(ikDrivenGrp + ".translateZ", cd=baseLoc + ".armUpResult")
+
+ cmds.connectAttr(armUpReversePMA + ".output1D", baseLoc + ".armUpResult")
+
+ # arm forward
+ cmds.setAttr(baseLoc + ".armForwardResult", 0.5)
+ cmds.setAttr(ikDrivenGrp + ".translateY", 0)
+ cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armForwardResult")
+
+ cmds.setAttr(baseLoc + ".armForwardResult", 1)
+ if side == "L":
+ cmds.setAttr(ikDrivenGrp + ".translateY", cmds.getAttr(armForwardLoc + ".translateY") / 2)
+ else:
+ cmds.setAttr(ikDrivenGrp + ".translateY", (cmds.getAttr(armForwardLoc + ".translateY") / 2) * -1)
+ cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armForwardResult")
+
+ cmds.connectAttr(armForwardReversePMA + ".output1D", baseLoc + ".armForwardResult")
+
+ # arm backward
+ cmds.setAttr(baseLoc + ".armBackwardResult", 0.5)
+ cmds.setAttr(ikDrivenGrp + ".translateY", 0)
+ cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armBackwardResult")
+
+ cmds.setAttr(baseLoc + ".armBackwardResult", 1)
+ if side == "L":
+ cmds.setAttr(ikDrivenGrp + ".translateY", cmds.getAttr(armBackwardLoc + ".translateY") / 2)
+ else:
+ cmds.setAttr(ikDrivenGrp + ".translateY", (cmds.getAttr(armBackwardLoc + ".translateY") / 2) * -1)
+ cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armBackwardResult")
+
+ cmds.connectAttr(armBackwardReversePMA + ".output1D", baseLoc + ".armBackwardResult")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Hook Up Modes # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ cmds.setAttr(self.armSettings + ".clavMode", 0)
+ cmds.setAttr(animGrp + ".v", 1)
+ cmds.setAttr(ikCtrlGrp + ".v", 0)
+ cmds.setDrivenKeyframe([animGrp + ".v", ikCtrlGrp + ".v"], cd=self.armSettings + ".clavMode")
+
+ cmds.setAttr(self.armSettings + ".clavMode", 1)
+ cmds.setAttr(animGrp + ".v", 0)
+ cmds.setAttr(ikCtrlGrp + ".v", 1)
+ cmds.setDrivenKeyframe([animGrp + ".v", ikCtrlGrp + ".v"], cd=self.armSettings + ".clavMode")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Add Data to Node # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # add created control info to module
+ if not cmds.objExists(networkNode + ".clavControls"):
+ cmds.addAttr(networkNode, ln="clavControls", dt="string")
+ clavCtrls = [fkControl, ikControl]
+ jsonString = json.dumps(clavCtrls)
+ cmds.setAttr(networkNode + ".clavControls", jsonString, type="string")
+
+ return [elbowLocConst]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildFkArm(self, textEdit, uiInst, builtRigs, networkNode):
+
+ # update progress
+ if textEdit != None:
+ textEdit.append(" Starting FK Arm Rig Build..")
+
+ # build the rig
+ slot = len(builtRigs)
+
+ # find the joints in the arm module that need rigging
+ joints = self.getMainArmJoints()
+ fkControls = []
+ self.topNode = None
+
+ for joint in joints[1]:
+ if joint.find("upperarm") != -1:
+ data = riggingUtils.createControlFromMover(joint, networkNode, True, True)
+
+ fkControl = cmds.rename(data[0], "fk_" + joint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp")
+ spaceSwitcher = cmds.rename(data[2], "fk_" + joint + "_anim_space_switcher")
+ spaceSwitchFollow = cmds.rename(data[3], "fk_" + joint + "_anim_space_switcher_follow")
+ self.topNode = spaceSwitchFollow
+
+ fkControls.append([spaceSwitchFollow, fkControl, joint])
+ # color the control
+ riggingUtils.colorControl(fkControl)
+
+ else:
+ data = riggingUtils.createControlFromMover(joint, networkNode, True, False)
+
+ fkControl = cmds.rename(data[0], "fk_" + joint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp")
+
+ fkControls.append([animGrp, fkControl, joint])
+
+ # color the control
+ riggingUtils.colorControl(fkControl)
+
+ # create hierarchy
+ fkControls.reverse()
+
+ for i in range(len(fkControls)):
+ try:
+ cmds.parent(fkControls[i][0], fkControls[i + 1][1])
+ except IndexError:
+ pass
+
+ # =======================================================================
+ # #lastly, connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+ for each in fkControls:
+ control = each[1]
+ joint = each[2]
+
+ cmds.pointConstraint(control, "driver_" + joint, mo=True)
+ cmds.orientConstraint(control, "driver_" + joint)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into
+ # input 2,and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(control + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output")
+ else:
+ riggingUtils.createConstraint(control, "driver_" + joint, "scale", False, 2, slot)
+
+ # #=======================================================================
+ # clean up
+ # #=======================================================================
+ # parent top group into arm group
+ cmds.parent(self.topNode, self.armCtrlGrp)
+
+ # lock attrs
+ for each in fkControls:
+ control = each[1]
+ for attr in [".scaleX", ".scaleY", ".scaleZ", ".visibility"]:
+ cmds.setAttr(control + attr, lock=True, keyable=False)
+
+ fkRigData = []
+ for each in fkControls:
+ fkRigData.append(each[1])
+
+ # add created control info to module
+ if not cmds.objExists(networkNode + ".fkControls"):
+ cmds.addAttr(networkNode, ln="fkControls", dt="string")
+ jsonString = json.dumps(fkRigData)
+ cmds.setAttr(networkNode + ".fkControls", jsonString, type="string")
+
+ # update progress
+ if textEdit != None:
+ textEdit.setTextColor(QtGui.QColor(0, 255, 18))
+ textEdit.append(" SUCCESS: FK Build Complete!")
+ textEdit.setTextColor(QtGui.QColor(255, 255, 255))
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildIkArm(self, textEdit, uiInst, builtRigs, networkNode):
+
+ # update progress
+ if textEdit != None:
+ textEdit.append(" Starting IK Arm Rig Build..")
+
+ # build the rig
+ slot = len(builtRigs)
+
+ # find the joints in the arm module that need rigging
+ joints = self.getMainArmJoints()
+ ikControls = []
+
+ # =======================================================================
+ # # create the ik arm joint chain
+ # =======================================================================
+
+ ikArmJoints = []
+ for joint in joints[1]:
+ jnt = cmds.createNode("joint", name="ik_" + joint + "_jnt")
+ const = cmds.parentConstraint(joint, jnt)[0]
+ cmds.delete(const)
+ ikArmJoints.append(jnt)
+
+ # create the wrist end joint
+ jnt = cmds.createNode("joint", name="ik_" + ikArmJoints[2] + "_end_jnt")
+ const = cmds.parentConstraint(ikArmJoints[2], jnt)[0]
+ cmds.delete(const)
+ ikArmJoints.append(jnt)
+
+ # create hierarchy
+ ikArmJoints.reverse()
+ for i in range(len(ikArmJoints)):
+ try:
+ cmds.parent(ikArmJoints[i], ikArmJoints[i + 1])
+ except IndexError:
+ pass
+
+ ikArmJoints.reverse()
+
+ cmds.setAttr(ikArmJoints[0] + ".v", 0, lock=True)
+
+ # move hand end joint out a bit. If tx is negative, add -2, if positive, add 2
+ cmds.makeIdentity(ikArmJoints[0], t=0, r=1, s=0, apply=True)
+
+ if cmds.getAttr(ikArmJoints[2] + ".tx") > 0:
+ cmds.setAttr(ikArmJoints[3] + ".tx", 10)
+ else:
+ cmds.setAttr(ikArmJoints[3] + ".tx", -10)
+
+ # =======================================================================
+ # # connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+ for joint in joints[1]:
+ sourceBone = "ik_" + joint + "_jnt"
+
+ cmds.pointConstraint(sourceBone, "driver_" + joint, mo=True)
+ cmds.orientConstraint(sourceBone, "driver_" + joint)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into
+ # input 2,and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(sourceBone + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output")
+ else:
+ riggingUtils.createConstraint(sourceBone, "driver_" + joint, "scale", False, 2, slot)
+
+ # =======================================================================
+ # # create fk matching joints
+ # =======================================================================
+ fkMatchUpArm = cmds.duplicate(ikArmJoints[0], po=True, name="ik_" + joints[1][0] + "_fk_matcher")[0]
+ fkMatchLowArm = cmds.duplicate(ikArmJoints[1], po=True, name="ik_" + joints[1][1] + "_fk_matcher")[0]
+ fkMatchWrist = cmds.duplicate(ikArmJoints[2], po=True, name="ik_" + joints[1][2] + "_fk_matcher")[0]
+
+ cmds.parent(fkMatchWrist, fkMatchLowArm)
+ cmds.parent(fkMatchLowArm, fkMatchUpArm)
+
+ # constrain fk match joints
+ cmds.parentConstraint(ikArmJoints[0], fkMatchUpArm, mo=True)
+ cmds.parentConstraint(ikArmJoints[1], fkMatchLowArm, mo=True)
+ cmds.parentConstraint(ikArmJoints[2], fkMatchWrist, mo=True)
+
+ # =======================================================================
+ # # rotate order and preferred angle
+ # =======================================================================
+ # set rotate order on ikUpArm
+ cmds.setAttr(ikArmJoints[0] + ".rotateOrder", 3)
+
+ # set preferred angle on arm
+ cmds.setAttr(ikArmJoints[1] + ".preferredAngleZ", -90)
+
+ # =======================================================================
+ # # create the ik control
+ # =======================================================================
+ handControlInfo = riggingUtils.createControlFromMover(joints[1][2], networkNode, True, True)
+
+ cmds.parent(handControlInfo[0], world=True)
+ constraint = cmds.orientConstraint(self.name + "_ik_hand_ctrl_orient", handControlInfo[3])[0]
+ cmds.delete(constraint)
+ cmds.makeIdentity(handControlInfo[2], t=1, r=1, s=1, apply=True)
+ cmds.parent(handControlInfo[0], handControlInfo[1])
+ cmds.makeIdentity(handControlInfo[0], t=1, r=1, s=1, apply=True)
+
+ # rename the control info
+ self.ikHandCtrl = cmds.rename(handControlInfo[0], "ik_" + joints[1][2] + "_anim")
+ cmds.rename(handControlInfo[1], self.ikHandCtrl + "_grp")
+ cmds.rename(handControlInfo[2], self.ikHandCtrl + "_space_switcher")
+ spaceSwitcherFollow = cmds.rename(handControlInfo[3], self.ikHandCtrl + "_space_switcher_follow")
+
+ fkMatchGrp = cmds.group(empty=True, name=self.ikHandCtrl + "_fkMatch_grp")
+ constraint = cmds.parentConstraint(fkMatchWrist, fkMatchGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(fkMatchGrp, self.ikHandCtrl)
+
+ fkMatch = cmds.group(empty=True, name=self.ikHandCtrl + "_fkMatch")
+ constraint = cmds.parentConstraint(fkMatchWrist, fkMatch)[0]
+ cmds.delete(constraint)
+ cmds.parent(fkMatch, fkMatchGrp)
+
+ # create RP IK on arm and SC ik from wrist to wrist end
+ rpIkHandle = \
+ cmds.ikHandle(name=self.name + "_rp_arm_ikHandle", solver="ikRPsolver", sj=ikArmJoints[0], ee=ikArmJoints[2])[0]
+ scIkHandle = \
+ cmds.ikHandle(name=self.name + "_sc_hand_ikHandle", solver="ikSCsolver", sj=ikArmJoints[2], ee=ikArmJoints[3])[
+ 0]
+
+ cmds.parent(scIkHandle, rpIkHandle)
+ cmds.setAttr(rpIkHandle + ".v", 0)
+ cmds.setAttr(scIkHandle + ".v", 0)
+
+ cmds.setAttr(rpIkHandle + ".stickiness", 1)
+ cmds.setAttr(rpIkHandle + ".snapEnable", 1)
+
+ cmds.setAttr(scIkHandle + ".stickiness", 1)
+ cmds.setAttr(scIkHandle + ".snapEnable", 1)
+
+ # parent IK to ik control
+ cmds.parent(rpIkHandle, self.ikHandCtrl)
+
+ # =======================================================================
+ # # create the ik pole vector
+ # =======================================================================
+ ikPvCtrl = riggingUtils.createControl("sphere", 5, self.name + "_ik_elbow_anim", True)
+ constraint = cmds.pointConstraint(ikArmJoints[1], ikPvCtrl)[0]
+ cmds.delete(constraint)
+
+ # create anim grp
+ ikPvCtrlGrp = cmds.group(empty=True, name=self.name + "_ik_elbow_anim_grp")
+ constraint = cmds.pointConstraint(ikArmJoints[1], ikPvCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(ikPvCtrl, ikPvCtrlGrp)
+ cmds.makeIdentity(ikPvCtrl, t=1, r=1, s=1, apply=True)
+
+ # create space switcher
+ ikPvSpaceSwitch = cmds.duplicate(ikPvCtrlGrp, po=True, name=self.name + "_ik_elbow_anim_space_switcher")[0]
+
+ # create space switcher follow
+ ikPvSpaceSwitchFollow = \
+ cmds.duplicate(ikPvCtrlGrp, po=True, name=self.name + "_ik_elbow_anim_space_switcher_follow")[0]
+
+ cmds.parent(ikPvSpaceSwitch, ikPvSpaceSwitchFollow)
+ cmds.parent(ikPvCtrlGrp, ikPvSpaceSwitch)
+
+ # move out pv ctrl
+ scaleFactor = riggingUtils.getScaleFactor()
+ cmds.setAttr(ikPvCtrl + ".ty", 30 * scaleFactor)
+
+ cmds.makeIdentity(ikPvCtrl, t=1, r=1, s=1, apply=True)
+
+ # setup pole vector constraint
+ cmds.poleVectorConstraint(ikPvCtrl, rpIkHandle)
+
+ # create the match group
+ pvMatchGrp = cmds.group(empty=True, name=ikPvCtrl + "_fkMatchGrp")
+ constraint = cmds.parentConstraint(ikPvCtrl, pvMatchGrp)[0]
+ cmds.delete(constraint)
+
+ fk_controls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ cmds.parent(pvMatchGrp, fk_controls[1])
+
+ pvMatch = cmds.group(empty=True, name=ikPvCtrl + "_fkMatch")
+ constraint = cmds.parentConstraint(ikPvCtrl, pvMatch)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(pvMatch, pvMatchGrp)
+
+ # =======================================================================
+ # # setup squash and stretch
+ # =======================================================================
+ # add attrs to the hand ctrl
+ cmds.addAttr(self.ikHandCtrl, longName=("stretch"), at='double', min=0, max=1, dv=0, keyable=True)
+ cmds.addAttr(self.ikHandCtrl, longName=("squash"), at='double', min=0, max=1, dv=0, keyable=True)
+
+ # need to get the total length of the arm chain
+ totalDist = abs(cmds.getAttr(ikArmJoints[1] + ".tx") + cmds.getAttr(ikArmJoints[2] + ".tx"))
+
+ # create a distanceBetween node
+ distBetween = cmds.shadingNode("distanceBetween", asUtility=True, name=self.name + "_ik_arm_distBetween")
+
+ # get world positions of thigh and ik
+ baseGrp = cmds.group(empty=True, name=self.name + "_ik_arm_base_grp")
+ endGrp = cmds.group(empty=True, name=self.name + "_ik_arm_end_grp")
+ cmds.pointConstraint(ikArmJoints[0], baseGrp)
+ cmds.pointConstraint(self.ikHandCtrl, endGrp)
+
+ # hook in group translates into distanceBetween node inputs
+ cmds.connectAttr(baseGrp + ".translate", distBetween + ".point1")
+ cmds.connectAttr(endGrp + ".translate", distBetween + ".point2")
+
+ # create a condition node that will compare original length to current length
+ # if second term is greater than, or equal to the first term, the chain needs to stretch
+ ikArmCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_ik_arm_stretch_condition")
+ cmds.setAttr(ikArmCondition + ".operation", 3)
+ cmds.connectAttr(distBetween + ".distance", ikArmCondition + ".secondTerm")
+ cmds.setAttr(ikArmCondition + ".firstTerm", totalDist)
+
+ # hook up the condition node's return colors
+ cmds.setAttr(ikArmCondition + ".colorIfTrueR", totalDist)
+ cmds.connectAttr(distBetween + ".distance", ikArmCondition + ".colorIfFalseR")
+
+ # add attr to foot control for stretch bias
+ cmds.addAttr(self.ikHandCtrl, ln="stretchBias", minValue=-1.0, maxValue=1.0, defaultValue=0.0, keyable=True)
+
+ # add divide node so that instead of driving 0-1, we're actually only driving 0 - 0.2
+ divNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_stretchBias_Div")
+ cmds.connectAttr(self.ikHandCtrl + ".stretchBias", divNode + ".input1X")
+ cmds.setAttr(divNode + ".operation", 2)
+ cmds.setAttr(divNode + ".input2X", 5)
+
+ # create the add node and connect the stretchBias into it, adding 1
+ addNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=self.name + "_stretchBias_Add")
+ cmds.connectAttr(divNode + ".outputX", addNode + ".input1D[0]")
+ cmds.setAttr(addNode + ".input1D[1]", 1.0)
+
+ # connect output of addNode to new mult node input1x
+ stretchBiasMultNode = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_stretchBias_multNode")
+ cmds.connectAttr(addNode + ".output1D", stretchBiasMultNode + ".input1X")
+
+ # create the mult/divide node(set to divide) that will take the original creation length as a static value in
+ # input2x,and the connected length into 1x. This will get the scale factor
+ armDistMultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_arm_dist_multNode")
+ cmds.setAttr(armDistMultNode + ".operation", 2) # divide
+ cmds.connectAttr(ikArmCondition + ".outColorR", armDistMultNode + ".input1X")
+
+ # set input2x to totalDist
+ cmds.setAttr(stretchBiasMultNode + ".input2X", totalDist)
+ cmds.connectAttr(stretchBiasMultNode + ".outputX", armDistMultNode + ".input2X")
+
+ # This differs from the original code. Instead of using a condition, I will use a blendColors node so that
+ # stretch % has an effect
+
+ # create a blendColors node for stretch
+ blendResult = cmds.shadingNode("blendColors", asUtility=True, name=self.name + "_arm_stretch_scaleFactor")
+ cmds.setAttr(blendResult + ".color2R", 1)
+ cmds.connectAttr(armDistMultNode + ".outputX", blendResult + ".color1R")
+ cmds.connectAttr(self.ikHandCtrl + ".stretch", blendResult + ".blender")
+
+ # create a blendColors node for squash
+ blendResultSquash = cmds.shadingNode("blendColors", asUtility=True, name=self.name + "_arm_squash_scaleFactor")
+ cmds.setAttr(blendResultSquash + ".color2R", 1)
+ cmds.connectAttr(armDistMultNode + ".outputX", blendResultSquash + ".color1R")
+ cmds.connectAttr(self.ikHandCtrl + ".squash", blendResultSquash + ".blender")
+
+ # get the sqrt of the scale factor by creating a multiply node and setting it to power operation
+ powerNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_sqrt_scaleFactor")
+ cmds.setAttr(powerNode + ".operation", 3)
+ cmds.connectAttr(blendResultSquash + ".outputR", powerNode + ".input1X")
+ cmds.setAttr(powerNode + ".input2X", .5)
+
+ # now divide 1 by that result
+ squashDivNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_squash_Value")
+ cmds.setAttr(squashDivNode + ".operation", 2)
+ cmds.setAttr(squashDivNode + ".input1X", 1)
+ cmds.connectAttr(powerNode + ".outputX", squashDivNode + ".input2X")
+
+ # connect to arm joint scale attributes
+ cmds.connectAttr(blendResult + ".outputR", ikArmJoints[0] + ".sx")
+ cmds.connectAttr(blendResult + ".outputR", ikArmJoints[1] + ".sx")
+
+ cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[1] + ".sy")
+ cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[1] + ".sz")
+
+ cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[0] + ".sy")
+ cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[0] + ".sz")
+
+ # =======================================================================
+ # # color controls and lock attrs
+ # =======================================================================
+ for control in [self.ikHandCtrl, ikPvCtrl]:
+ riggingUtils.colorControl(control)
+
+ for attr in [".scaleX", ".scaleY", ".globalScale", ".visibility"]:
+ cmds.setAttr(self.ikHandCtrl + attr, lock=True, keyable=False)
+
+ for attr in [".scaleX", ".scaleY", ".scaleZ", ".rotateX", ".rotateY", ".rotateZ", ".visibility"]:
+ cmds.setAttr(ikPvCtrl + attr, lock=True, keyable=False)
+
+ # =======================================================================
+ # # clean up IK nodes
+ # =======================================================================
+ self.ikCtrlGrp = cmds.group(empty=True, name=self.name + "_arm_ik_ctrls_grp")
+ cmds.parent(self.ikCtrlGrp, self.armGroup)
+
+ cmds.parent(ikPvSpaceSwitchFollow, self.ikCtrlGrp)
+ cmds.parent(spaceSwitcherFollow, self.ikCtrlGrp)
+ cmds.parent(fkMatchUpArm, self.ikCtrlGrp)
+
+ cmds.parent(baseGrp, self.ikCtrlGrp)
+ cmds.parent(endGrp, self.ikCtrlGrp)
+
+ # add created control info to module
+ ikRigData = [self.ikHandCtrl, ikPvCtrl]
+ if not cmds.objExists(networkNode + ".ikControls"):
+ cmds.addAttr(networkNode, ln="ikControls", dt="string")
+ jsonString = json.dumps(ikRigData)
+ cmds.setAttr(networkNode + ".ikControls", jsonString, type="string")
+
+ # update progress
+ if textEdit != None:
+ textEdit.setTextColor(QtGui.QColor(0, 255, 18))
+ textEdit.append(" SUCCESS: IK Build Complete!")
+ textEdit.setTextColor(QtGui.QColor(255, 255, 255))
+
+ return ikArmJoints
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildFingers(self, fingers, textEdit, uiInst, builtRigs, networkNode):
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # create groups
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ armJoints = self.getMainArmJoints()
+ fkFingerCtrlsGrp = cmds.group(empty=True, name=self.name + "_fk_finger_ctrls")
+ const = cmds.parentConstraint(armJoints[1][2], fkFingerCtrlsGrp)[0]
+ cmds.delete(const)
+
+ handDrivenMasterGrp = cmds.duplicate(fkFingerCtrlsGrp, po=True, name=self.name + "_hand_driven_master_grp")
+ handDrivenGrp = cmds.duplicate(fkFingerCtrlsGrp, po=True, name=self.name + "_hand_driven_grp")
+
+ cmds.parent(handDrivenMasterGrp, self.fingerGrp)
+ cmds.parent(handDrivenGrp, handDrivenMasterGrp)
+ cmds.parent(fkFingerCtrlsGrp, handDrivenGrp)
+
+ # setup constraints/sdks on handDrivenGrp
+ const = cmds.parentConstraint("driver_" + armJoints[1][2], handDrivenGrp)
+
+ fkRigInfo = []
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # create metacarpal controls
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ metaCarpals = []
+ phalanges = []
+ for each in fingers:
+ if each[0].find("metacarpal") != -1:
+ if each[0].find("thumb") == -1:
+ metaCarpals.append(each[0])
+
+ fingerData = []
+ for finger in each:
+ if finger.find("metacarpal") == -1:
+ if each[0].find("thumb") == -1:
+ fingerData.append(finger)
+
+ for finger in each:
+ if finger.find("thumb") != -1:
+ fingerData.append(finger)
+
+ phalanges.append(fingerData)
+
+ for metacarpal in metaCarpals:
+ data = riggingUtils.createControlFromMover(metacarpal, networkNode, True, False)
+ ctrl = cmds.rename(data[0], metacarpal + "_anim")
+ grp = cmds.rename(data[1], metacarpal + "_anim_grp")
+ cmds.parent(grp, handDrivenGrp)
+
+ # color the control
+ riggingUtils.colorControl(ctrl)
+ fkRigInfo.append(ctrl)
+
+ for attr in [".scaleX", ".scaleY", ".scaleZ", ".visibility"]:
+ cmds.setAttr(ctrl + attr, lock=True, keyable=False)
+
+ # first create a group for the IK handles to go into
+
+ ikHandlesGrp = cmds.group(empty=True, name=self.name + "_fkOrient_ikHandles_grp")
+ cmds.parent(ikHandlesGrp, handDrivenGrp)
+
+ # setup constraints
+ const = cmds.parentConstraint([handDrivenGrp[0], self.fingerGrp], ikHandlesGrp)[0]
+
+ # add attr (globalStick)
+ cmds.addAttr(self.armSettings, ln="globalSticky", dv=0, min=0, max=1, keyable=True)
+
+ # set driven keys
+ cmds.setAttr(self.armSettings + ".globalSticky", 0)
+ cmds.setAttr(const + "." + handDrivenGrp[0] + "W0", 1)
+ cmds.setAttr(const + "." + self.fingerGrp + "W1", 0)
+ cmds.setDrivenKeyframe([const + "." + handDrivenGrp[0] + "W0", const + "." + self.fingerGrp + "W1"],
+ cd=self.armSettings + ".globalSticky", itt='linear', ott='linear')
+
+ cmds.setAttr(self.armSettings + ".globalSticky", 1)
+ cmds.setAttr(const + "." + handDrivenGrp[0] + "W0", 0)
+ cmds.setAttr(const + "." + self.fingerGrp + "W1", 1)
+ cmds.setDrivenKeyframe([const + "." + handDrivenGrp[0] + "W0", const + "." + self.fingerGrp + "W1"],
+ cd=self.armSettings + ".globalSticky", itt='linear', ott='linear')
+
+ cmds.setAttr(self.armSettings + ".globalSticky", 0)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # create the FK orient joints
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ fkOrients = []
+
+ for each in phalanges:
+ if len(each) > 0:
+
+ # find tip locator name
+ nameData = self.returnPrefixSuffix
+ splitString = each[0]
+ if nameData[0] != None:
+ splitString = each[0].partition(nameData[0])[2]
+
+ if nameData[1] != None:
+ splitString = splitString.partition(nameData[1])[0]
+
+ splitString = splitString.partition("_")[0]
+ tipLoc = self.name + "_" + splitString + "_tip"
+
+ # create base and end joints
+ baseJnt = cmds.createNode('joint', name="fk_orient_" + each[0] + "_jnt")
+ const = cmds.parentConstraint(each[0], baseJnt)[0]
+ cmds.delete(const)
+
+ endJnt = cmds.createNode('joint', name="fk_orient_" + each[0] + "_end")
+ const = cmds.parentConstraint(tipLoc, endJnt)[0]
+ cmds.delete(const)
+
+ cmds.parent(endJnt, baseJnt)
+ cmds.makeIdentity(baseJnt, t=0, r=1, s=0, apply=True)
+ cmds.setAttr(baseJnt + ".v", 0, lock=True)
+
+ # create SC ik handles for each chain
+ ikNodes = cmds.ikHandle(sol="ikSCsolver", name=baseJnt + "_ikHandle", sj=baseJnt, ee=endJnt)[0]
+ cmds.parent(ikNodes, ikHandlesGrp)
+ cmds.setAttr(ikNodes + ".v", 0)
+
+ # parent orient joint to metacarpal control if it exists
+ jntBaseName = self.getFingerBaseName(each[0]).partition("_")[0]
+ metaCtrl = ""
+ for each in metaCarpals:
+ if each.find(jntBaseName) != -1:
+ metaCtrl = each + "_anim"
+
+ if cmds.objExists(metaCtrl):
+ cmds.parent(baseJnt, metaCtrl)
+ fkOrients.append(baseJnt)
+ else:
+ fkOrients.append(baseJnt)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # create FK controls for the phalanges
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ fkInfo = []
+ for each in phalanges:
+ fingerData = []
+
+ for finger in each:
+ # create the FK control/anim grp/driven grp
+ data = riggingUtils.createControlFromMover(finger, networkNode, True, False)
+ ctrl = cmds.rename(data[0], finger + "_anim")
+ grp = cmds.rename(data[1], finger + "_anim_grp")
+ drivenGrp = cmds.group(empty=True, name=finger + "_driven_grp")
+ const = cmds.parentConstraint(grp, drivenGrp)[0]
+ cmds.delete(const)
+
+ fkInfo.append([ctrl, finger])
+ fkRigInfo.append(ctrl)
+
+ # setup hierarchy
+ cmds.parent(drivenGrp, grp)
+ cmds.parent(ctrl, drivenGrp)
+
+ cmds.makeIdentity(drivenGrp, t=1, r=1, s=1, apply=True)
+ fingerData.append(ctrl)
+
+ # color control
+ riggingUtils.colorControl(ctrl)
+
+ # lock attrs on ctrl
+ cmds.setAttr(ctrl + ".v", lock=True, keyable=False)
+ cmds.aliasAttr(ctrl + ".sz", rm=True)
+
+ fingerData.reverse()
+
+ for i in range(len(fingerData)):
+ try:
+ cmds.parent(fingerData[i] + "_grp", fingerData[i + 1])
+ except IndexError:
+ pass
+
+ fingerData.reverse()
+
+ # parent FK control to metacarpal control if it exists
+ jntBaseName = self.getFingerBaseName(each[0]).partition("_")[0]
+ metaCtrl = ""
+ for each in metaCarpals:
+ if each.find(jntBaseName) != -1:
+ metaCtrl = each + "_anim"
+
+ jntName = fingerData[0].partition("_anim")[0]
+ baseJnt = "fk_orient_" + jntName + "_jnt"
+
+ # parent the control to the meta control or to the fk finger controls group
+ if cmds.objExists(metaCtrl):
+ if metaCtrl.find("thumb") == -1:
+ cmds.parent(fingerData[0] + "_grp", metaCtrl)
+ else:
+ cmds.parent(fingerData[0] + "_grp", fkFingerCtrlsGrp)
+ cmds.parent(baseJnt, fkFingerCtrlsGrp)
+
+ else:
+ cmds.parent(fingerData[0] + "_grp", fkFingerCtrlsGrp)
+ cmds.parent(baseJnt, fkFingerCtrlsGrp)
+
+ # add sticky attribute
+ if fingerData[0].find("thumb") == -1:
+ cmds.addAttr(fingerData[0], ln="sticky", defaultValue=0, minValue=0, maxValue=1, keyable=True)
+
+ # setup the constraint between the fk finger orient joint and the ctrlGrp
+
+ if metaCtrl == '':
+ masterObj = fkFingerCtrlsGrp
+ else:
+ masterObj = metaCtrl
+
+ constraint = cmds.parentConstraint([masterObj, baseJnt], fingerData[0] + "_grp", mo=True)[0]
+
+ # set driven keyframes on constraint
+ if cmds.objExists(fingerData[0] + ".sticky"):
+ cmds.setAttr(fingerData[0] + ".sticky", 1)
+ cmds.setAttr(constraint + "." + masterObj + "W0", 0)
+ cmds.setAttr(constraint + "." + baseJnt + "W1", 1)
+ cmds.setDrivenKeyframe([constraint + "." + masterObj + "W0", constraint + "." + baseJnt + "W1"],
+ cd=fingerData[0] + ".sticky", itt="linear", ott="linear")
+
+ cmds.setAttr(fingerData[0] + ".sticky", 0)
+ cmds.setAttr(constraint + "." + masterObj + "W0", 1)
+ cmds.setAttr(constraint + "." + baseJnt + "W1", 0)
+ cmds.setDrivenKeyframe([constraint + "." + masterObj + "W0", constraint + "." + baseJnt + "W1"],
+ cd=fingerData[0] + ".sticky", itt="linear", ott="linear")
+
+ # write FK data to network node
+ if len(fkRigInfo) > 0:
+ if not cmds.objExists(networkNode + ".fkFingerControls"):
+ cmds.addAttr(networkNode, ln="fkFingerControls", dt='string')
+
+ jsonString = json.dumps(fkRigInfo)
+ cmds.setAttr(networkNode + ".fkFingerControls", jsonString, type="string")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # setup hand roll
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create our 4 locators(pivots) and position
+ pinkyPiv = cmds.spaceLocator(name=self.name + "_hand_pinky_pivot")[0]
+ thumbPiv = cmds.spaceLocator(name=self.name + "_hand_thumb_pivot")[0]
+ midPiv = cmds.spaceLocator(name=self.name + "_hand_mid_pivot")[0]
+ tipPiv = cmds.spaceLocator(name=self.name + "_hand_tip_pivot")[0]
+
+ for piv in [pinkyPiv, thumbPiv, midPiv, tipPiv]:
+ cmds.setAttr(piv + ".v", 0)
+
+ # posititon locators
+
+ const = cmds.parentConstraint(self.name + "_pinky_pivot", pinkyPiv)[0]
+ cmds.delete(const)
+ const = cmds.parentConstraint(self.name + "_thumb_pivot", thumbPiv)[0]
+ cmds.delete(const)
+ const = cmds.parentConstraint(self.name + "_palm_pivot", midPiv)[0]
+ cmds.delete(const)
+ const = cmds.parentConstraint(self.name + "_middle_tip", tipPiv)[0]
+ cmds.delete(const)
+
+ # create the control groups for the pivots so our values are zeroed
+ for each in [pinkyPiv, thumbPiv, midPiv, tipPiv]:
+ group = cmds.group(empty=True, name=each + "_grp")
+ constraint = cmds.parentConstraint(each, group)[0]
+ cmds.delete(constraint)
+ cmds.parent(each, group)
+
+ # setup hierarchy
+ cmds.parent(thumbPiv + "_grp", pinkyPiv)
+ cmds.parent(tipPiv + "_grp", thumbPiv)
+ cmds.parent(midPiv + "_grp", tipPiv)
+
+ # parent the arm IK handles under the midPiv locator
+ cmds.parent(self.name + "_rp_arm_ikHandle", midPiv)
+ cmds.parent(pinkyPiv + "_grp", self.ikHandCtrl)
+
+ # add attrs to the IK hand control (side, roll, tip pivot)
+ cmds.addAttr(self.ikHandCtrl, longName="side", defaultValue=0, keyable=True)
+ cmds.addAttr(self.ikHandCtrl, longName="mid_bend", defaultValue=0, keyable=True)
+ cmds.addAttr(self.ikHandCtrl, longName="mid_swivel", defaultValue=0, keyable=True)
+ cmds.addAttr(self.ikHandCtrl, longName="tip_pivot", defaultValue=0, keyable=True)
+ cmds.addAttr(self.ikHandCtrl, longName="tip_swivel", defaultValue=0, keyable=True)
+
+ # hook up attrs to pivot locators
+ cmds.connectAttr(self.ikHandCtrl + ".mid_bend", midPiv + ".rz")
+ cmds.connectAttr(self.ikHandCtrl + ".tip_pivot", tipPiv + ".rz")
+
+ cmds.connectAttr(self.ikHandCtrl + ".mid_swivel", midPiv + ".ry")
+ cmds.connectAttr(self.ikHandCtrl + ".tip_swivel", tipPiv + ".ry")
+
+ # set driven keys for side to side attr
+
+ cmds.setAttr(self.ikHandCtrl + ".side", 0)
+ cmds.setAttr(pinkyPiv + ".rx", 0)
+ cmds.setAttr(thumbPiv + ".rx", 0)
+ cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd=self.ikHandCtrl + ".side", itt='linear',
+ ott='linear')
+
+ cmds.setAttr(self.ikHandCtrl + ".side", 180)
+ cmds.setAttr(pinkyPiv + ".rx", -180)
+ cmds.setAttr(thumbPiv + ".rx", 0)
+ cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd=self.ikHandCtrl + ".side", itt='linear',
+ ott='linear')
+
+ cmds.setAttr(self.ikHandCtrl + ".side", -180)
+ cmds.setAttr(pinkyPiv + ".rx", 0)
+ cmds.setAttr(thumbPiv + ".rx", 180)
+ cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd=self.ikHandCtrl + ".side", itt='linear',
+ ott='linear')
+
+ cmds.setAttr(self.ikHandCtrl + ".side", 0)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # setup ik fingers (if applicable)
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ scaleFactor = riggingUtils.getScaleFactor()
+ ikInfo = []
+ ikCtrlData = []
+
+ for each in phalanges:
+ if len(each) == 3:
+ ikJnts = []
+ pvGrps = []
+
+ # create the IK finger joints
+ for bone in each:
+ jnt = cmds.createNode('joint', name="ik_" + bone + "_jnt")
+ const = cmds.parentConstraint(bone, jnt)[0]
+ cmds.delete(const)
+ ikJnts.append(jnt)
+
+ # parent ik joints
+ ikJnts.reverse()
+ for i in range(len(ikJnts)):
+ try:
+ cmds.parent(ikJnts[i], ikJnts[i + 1])
+ except IndexError:
+ pass
+
+ # create the ik tip jnt
+ jnt = cmds.createNode('joint', name=ikJnts[0] + "_tip")
+
+ # find tip locator name
+ nameData = self.returnPrefixSuffix
+ splitString = each[0]
+ if nameData[0] != None:
+ splitString = each[0].partition(nameData[0])[2]
+
+ if nameData[1] != None:
+ splitString = splitString.partition(nameData[1])[0]
+
+ jntType = splitString.partition("_")[0]
+ tipLoc = self.name + "_" + jntType + "_tip"
+
+ const = cmds.parentConstraint(tipLoc, jnt)[0]
+ cmds.delete(const)
+
+ cmds.parent(jnt, ikJnts[0])
+ ikJnts.reverse()
+ ikJnts.append(jnt)
+
+ cmds.makeIdentity(ikJnts[0], t=0, r=1, s=0, apply=True)
+
+ # parent the ik to the handDrivenGrp
+ cmds.parent(ikJnts[0], handDrivenGrp)
+ cmds.setAttr(ikJnts[0] + ".v", 0, lock=True)
+
+ # create the IK
+ ikNodes = \
+ cmds.ikHandle(sol="ikRPsolver", name=self.name + jntType + "_ikHandle", sj=ikJnts[0], ee=ikJnts[2])[0]
+ ikTipNodes = \
+ cmds.ikHandle(sol="ikSCsolver", name=self.name + jntType + "_tip_ikHandle", sj=ikJnts[2], ee=ikJnts[3])[
+ 0]
+ cmds.setAttr(ikNodes + ".v", 0)
+ cmds.parent(ikTipNodes, ikNodes)
+
+ # create the IK PV
+ poleVector = cmds.spaceLocator(name=self.name + "_" + jntType + "_pv_anim")[0]
+ constraint = cmds.parentConstraint(ikJnts[1], poleVector)[0]
+ cmds.delete(constraint)
+ riggingUtils.colorControl(poleVector)
+
+ # create a pole vector group
+ pvGrp = cmds.group(empty=True, name=poleVector + "_grp")
+ constraint = cmds.parentConstraint(poleVector, pvGrp)[0]
+ cmds.delete(constraint)
+ pvGrps.append(pvGrp)
+
+ # parent to the joint, and move out away from finger
+ cmds.parent(poleVector, ikJnts[1])
+
+ if cmds.getAttr(networkNode + ".side") == "Left":
+ cmds.setAttr(poleVector + ".ty", -40 * scaleFactor)
+
+ if cmds.getAttr(networkNode + ".side") == "Right":
+ cmds.setAttr(poleVector + ".ty", 40 * scaleFactor)
+
+ cmds.makeIdentity(poleVector, t=1, r=1, s=1, apply=True)
+ cmds.parent(poleVector, pvGrp, absolute=True)
+ cmds.makeIdentity(poleVector, t=1, r=1, s=1, apply=True)
+
+ # create the IK finger controls
+ data = riggingUtils.createControlFromMover(each[2], networkNode, True, True)
+ ikFingerCtrl = cmds.rename(data[0], each[2] + "_ik_anim")
+ ikFingerGrp = cmds.rename(data[1], each[2] + "_ik_anim_grp")
+ spaceSwitcher = cmds.rename(data[2], each[2] + "_ik_anim_space_switcher")
+ spaceFollow = cmds.rename(data[3], each[2] + "_ik_anim_space_switcher_follow")
+ riggingUtils.colorControl(ikFingerCtrl)
+ ikCtrlData.append(ikFingerCtrl)
+ ikCtrlData.append(poleVector)
+
+ # parent ik to ctrl
+ cmds.parent(ikNodes, ikFingerCtrl)
+
+ # create the PV constraint
+ cmds.poleVectorConstraint(poleVector, ikNodes)
+
+ # add attr to show pole vector control
+ cmds.addAttr(ikFingerCtrl, longName="poleVectorVis", defaultValue=0, minValue=0, maxValue=1,
+ keyable=True)
+ cmds.connectAttr(ikFingerCtrl + ".poleVectorVis", poleVector + ".v")
+
+ for group in pvGrps:
+ cmds.parent(group, handDrivenGrp)
+
+ # create the global IK control
+ if not cmds.objExists(armJoints[1][2] + "_global_ik_anim"):
+ globalIkAnim = riggingUtils.createControl("square", 30, armJoints[1][2] + "_global_ik_anim", True)
+ riggingUtils.colorControl(globalIkAnim)
+
+ const = cmds.pointConstraint(midPiv, globalIkAnim)[0]
+ cmds.delete(const)
+
+ globalIkGrp = cmds.group(empty=True, name=globalIkAnim + "_grp")
+ const = cmds.pointConstraint(midPiv, globalIkGrp)[0]
+ cmds.delete(const)
+ const = cmds.orientConstraint(self.ikHandCtrl, globalIkGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(globalIkAnim, globalIkGrp)
+ cmds.makeIdentity(globalIkAnim, t=1, r=1, s=1, apply=True)
+
+ # translate down in z
+ cmds.setAttr(globalIkAnim + ".tz", -5)
+ cmds.makeIdentity(globalIkAnim, t=1, r=1, s=1, apply=True)
+
+ # reposition the grp to the control
+ cmds.parent(globalIkAnim, world=True)
+ constraint = cmds.pointConstraint(globalIkAnim, globalIkGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(globalIkAnim, globalIkGrp)
+ cmds.makeIdentity(globalIkAnim, t=1, r=1, s=1, apply=True)
+
+ # create a space switcher grp
+ globalIKSpaceFollow = \
+ cmds.duplicate(globalIkGrp, po=True, name=globalIkAnim + "_space_switcher_follow")[0]
+ globalIKSpaceSwitch = cmds.duplicate(globalIkGrp, po=True, name=globalIkAnim + "_space_switcher")[0]
+
+ globalMasterGrp = cmds.group(empty=True, name=self.name + "_global_finger_ik_grp")
+ const = cmds.parentConstraint(armJoints[1][2], globalMasterGrp)[0]
+ cmds.delete(const)
+
+ cmds.parent(globalIKSpaceSwitch, globalIKSpaceFollow)
+ cmds.parent(globalIkGrp, globalIKSpaceSwitch)
+ cmds.parent(globalIKSpaceFollow, globalMasterGrp)
+ cmds.parent(globalMasterGrp, self.fingerGrp)
+ cmds.parentConstraint("driver_" + armJoints[1][2], globalMasterGrp, mo=True)
+
+ # add global ctrl visibility attr
+ cmds.addAttr(self.armSettings, ln="globalIkVis", dv=0, min=0, max=1, keyable=True)
+ shape = cmds.listRelatives(globalIkAnim, shapes=True)[0]
+ cmds.connectAttr(self.armSettings + ".globalIkVis", shape + ".v")
+
+ ikCtrlData.append(globalIkAnim)
+
+ # parent ik control grps to this global control
+ cmds.parent(spaceFollow, globalIkAnim)
+
+ # collect data per finger
+ ikInfo.append([globalIKSpaceFollow, globalIkAnim, ikJnts, jntType, spaceFollow, pvGrp])
+
+ # write IK data to network node
+ if len(ikCtrlData) > 0:
+ if not cmds.objExists(networkNode + ".ikFingerControls"):
+ cmds.addAttr(networkNode, ln="ikFingerControls", dt='string')
+
+ jsonString = json.dumps(ikCtrlData)
+ cmds.setAttr(networkNode + ".ikFingerControls", jsonString, type="string")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # setup finger modes/driven keys
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ for each in ikInfo:
+ fkCtrl = each[2][0].partition("ik_")[2].rpartition("_jnt")[0] + "_anim_grp"
+ cmds.addAttr(self.armSettings, ln=each[3] + "_finger_mode", dv=0, min=0, max=1, keyable=True)
+
+ cmds.setAttr(self.armSettings + "." + each[3] + "_finger_mode", 0)
+ cmds.setAttr(each[4] + ".v", 0)
+ cmds.setAttr(each[5] + ".v", 0)
+ cmds.setAttr(fkCtrl + ".v", 1)
+ cmds.setDrivenKeyframe([each[4] + ".v", each[5] + ".v", fkCtrl + ".v"],
+ cd=self.armSettings + "." + each[3] + "_finger_mode", itt='linear', ott='linear')
+
+ cmds.setAttr(self.armSettings + "." + each[3] + "_finger_mode", 1)
+ cmds.setAttr(each[4] + ".v", 1)
+ cmds.setAttr(each[5] + ".v", 1)
+ cmds.setAttr(fkCtrl + ".v", 0)
+ cmds.setDrivenKeyframe([each[4] + ".v", each[5] + ".v", fkCtrl + ".v"],
+ cd=self.armSettings + "." + each[3] + "_finger_mode", itt='linear', ott='linear')
+
+ cmds.setAttr(self.armSettings + "." + each[3] + "_finger_mode", 0)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # parent IK finger joints under metacarpals (if they exist)
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ for each in ikInfo:
+ metaCtrl = ""
+ jntBaseName = self.getFingerBaseName(each[2][0]).partition("_")[0]
+ for carpal in metaCarpals:
+ if carpal.find(jntBaseName) != -1:
+ metaCtrl = carpal + "_anim"
+
+ if cmds.objExists(metaCtrl):
+ cmds.parent(each[2][0], metaCtrl)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # Hook up driver joints
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ for each in fkInfo:
+ fkCtrl = each[0]
+ jnt = each[1]
+ ikJnt = "ik_" + jnt + "_jnt"
+ driverJnt = "driver_" + jnt
+
+ # find joint base name
+ nameData = self.returnPrefixSuffix
+ splitString = jnt
+ if nameData[0] != None:
+ splitString = jnt.partition(nameData[0])[2]
+
+ if nameData[1] != None:
+ splitString = splitString.partition(nameData[1])[0]
+
+ jntBaseName = splitString.partition("_")[0]
+
+ if cmds.objExists(ikJnt):
+ pConst = cmds.parentConstraint([fkCtrl, ikJnt], driverJnt, mo=True)[0]
+
+ # set driven keys
+ cmds.setAttr(self.armSettings + "." + jntBaseName + "_finger_mode", 0)
+ cmds.setAttr(pConst + "." + fkCtrl + "W0", 1)
+ cmds.setAttr(pConst + "." + ikJnt + "W1", 0)
+ cmds.setDrivenKeyframe([pConst + "." + fkCtrl + "W0", pConst + "." + ikJnt + "W1"],
+ cd=self.armSettings + "." + jntBaseName + "_finger_mode", itt='linear',
+ ott='linear')
+
+ cmds.setAttr(self.armSettings + "." + jntBaseName + "_finger_mode", 1)
+ cmds.setAttr(pConst + "." + fkCtrl + "W0", 0)
+ cmds.setAttr(pConst + "." + ikJnt + "W1", 1)
+ cmds.setDrivenKeyframe([pConst + "." + fkCtrl + "W0", pConst + "." + ikJnt + "W1"],
+ cd=self.armSettings + "." + jntBaseName + "_finger_mode", itt='linear',
+ ott='linear')
+
+ cmds.setAttr(self.armSettings + "." + jntBaseName + "_finger_mode", 0)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale
+ # into input 2, and plugs that into driver joint
+ slot = 0
+ for each in [fkCtrl, ikJnt]:
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=jnt + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(each + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + jnt, "scale", False, 2, slot,
+ "output")
+ else:
+ riggingUtils.createConstraint(each, "driver_" + jnt, "scale", False, 2, slot)
+
+ slot = slot + 1
+
+ else:
+ pConst = cmds.parentConstraint(fkCtrl, driverJnt)[0]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getMainArmJoints(self):
+
+ clavicleJoint = None
+ upperarmJoint = None
+ lowerarmJoint = None
+ handJoint = None
+
+ returnData = []
+
+ joints = self.returnCreatedJoints
+
+ # clavicle
+ for joint in joints:
+ if joint.find("clavicle") != -1:
+ clavicleJoint = joint
+
+ # upperarm
+ joints = self.returnCreatedJoints
+ for joint in joints:
+ if joint.find("upperarm") != -1:
+ if joint.find("twist") == -1:
+ upperarmJoint = joint
+
+ # lowerarm
+ for joint in joints:
+ if joint.find("lowerarm") != -1:
+ if joint.find("twist") == -1:
+ lowerarmJoint = joint
+
+ # hand
+ for joint in joints:
+ if joint.find("hand") != -1:
+ handJoint = joint
+
+ returnData = [clavicleJoint, [upperarmJoint, lowerarmJoint, handJoint]]
+ return returnData
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getTwistJoints(self, upperarm, lowerarm):
+
+ upperTwistBones = []
+ lowerTwistBones = []
+
+ joints = self.returnCreatedJoints
+
+ # upper arm
+ for joint in joints:
+ if joint.find("upperarm") != -1:
+ if joint.find("twist") != -1:
+ upperTwistBones.append(joint)
+
+ # calf
+ for joint in joints:
+ if joint.find("lowerarm") != -1:
+ if joint.find("twist") != -1:
+ lowerTwistBones.append(joint)
+
+ if upperarm:
+ return upperTwistBones
+ if lowerarm:
+ return lowerTwistBones
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getFingerJoints(self):
+
+ joints = self.returnCreatedJoints
+ indexJoints = []
+ middleJoints = []
+ ringJoints = []
+ pinkyJoints = []
+ thumbJoints = []
+
+ for joint in joints:
+
+ if joint.find("thumb") != -1:
+ thumbJoints.append(joint)
+
+ if joint.find("index") != -1:
+ indexJoints.append(joint)
+
+ if joint.find("middle") != -1:
+ if joint.find("index") == -1:
+ if joint.find("ring") == -1:
+ if joint.find("pinky") == -1:
+ middleJoints.append(joint)
+
+ if joint.find("ring") != -1:
+ ringJoints.append(joint)
+
+ if joint.find("pinky") != -1:
+ pinkyJoints.append(joint)
+
+ returnData = []
+ for each in [indexJoints, middleJoints, ringJoints, pinkyJoints, thumbJoints]:
+ if each != []:
+ returnData.append(each)
+ return returnData
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getFingerBaseName(self, finger):
+
+ nameData = self.returnPrefixSuffix
+ if nameData[0] != None:
+ if nameData[1] != None:
+ jointName = finger.partition(nameData[0] + "_")[2].partition("_" + nameData[1])[0]
+ else:
+ jointName = finger.partition(nameData[0] + "_")[2]
+ else:
+ if nameData[1] != None:
+ jointName = finger.partition("_" + nameData[1])[0]
+ else:
+ jointName = finger.partition("_")[0]
+
+ return jointName
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def switchClavMode(self, mode, checkBox, range=False):
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+ controls = json.loads(cmds.getAttr(networkNode + ".clavControls"))
+
+ # are we matching?
+ if not range:
+ match = checkBox.isChecked()
+ else:
+ match = True
+
+ # if being called from match over frame range
+ if range:
+ if mode == matchData[1][0]:
+ mode = "FK"
+ if mode == matchData[1][1]:
+ mode = "IK"
+
+ if mode == "FK":
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode")
+
+ if match:
+ dupe = cmds.duplicate(namespace + ":" + controls[0], rr=True, po=True)[0]
+ const = cmds.orientConstraint(namespace + ":" + self.name + "_clav_ik_start", dupe)[0]
+ cmds.delete(const)
+
+ rotateXvalue = cmds.getAttr(dupe + ".rotateX")
+ rotateYvalue = cmds.getAttr(dupe + ".rotateY")
+ rotateZvalue = cmds.getAttr(dupe + ".rotateZ")
+
+ cmds.setAttr(namespace + ":" + controls[0] + ".rotateX", rotateXvalue)
+ cmds.setAttr(namespace + ":" + controls[0] + ".rotateY", rotateYvalue)
+ cmds.setAttr(namespace + ":" + controls[0] + ".rotateZ", rotateZvalue)
+
+ cmds.setKeyframe(namespace + ":" + controls[0])
+
+ cmds.delete(dupe)
+ cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode")
+
+ if mode == "IK":
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode")
+
+ if match:
+ dupe = cmds.duplicate(namespace + ":" + controls[1], rr=True)[0]
+ const = cmds.pointConstraint(namespace + ":" + self.name + "_ik_clav_matcher", dupe)[0]
+ cmds.delete(const)
+
+ transXvalue = cmds.getAttr(dupe + ".translateX")
+ transYvalue = cmds.getAttr(dupe + ".translateY")
+ transZvalue = cmds.getAttr(dupe + ".translateZ")
+
+ cmds.setAttr(namespace + ":" + controls[1] + ".translateX", transXvalue)
+ cmds.setAttr(namespace + ":" + controls[1] + ".translateY", transYvalue)
+ cmds.setAttr(namespace + ":" + controls[1] + ".translateZ", transZvalue)
+
+ cmds.setKeyframe(namespace + ":" + controls[1])
+
+ cmds.delete(dupe)
+
+ cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def switchMode(self, mode, checkBox, range=False):
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ # are we matching?
+ if not range:
+ match = checkBox.isChecked()
+ else:
+ match = True
+
+ # if being called from match over frame range
+ if range:
+ if mode == matchData[1][0]:
+ mode = "FK"
+ if mode == matchData[1][1]:
+ mode = "IK"
+
+ # switch to FK mode
+ if mode == "FK":
+ # get current mode
+ currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode")
+ if currentMode == 0.0:
+ cmds.warning("Already in FK mode.")
+ return
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if match:
+ # get fk controls
+ controls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+
+ # create a duplicate chain
+ topCtrl = controls[2]
+ topGrp = cmds.listRelatives(namespace + ":" + topCtrl, parent=True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world=True)
+
+ # match the fk controls to the corresponding joint
+ controls.reverse()
+ for control in controls:
+ joint = control.partition("fk_")[2].partition("_anim")[0]
+ joint = namespace + ":" + joint
+
+ constraint = cmds.parentConstraint(joint, control)[0]
+
+ translate = cmds.getAttr(control + ".translate")[0]
+ rotate = cmds.getAttr(control + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2],
+ type='double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ # delete dupes
+ cmds.delete(newControls[0])
+
+ # switch modes
+ if not range:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ # switch to IK mode
+ if mode == "IK":
+
+ # get current mode
+ currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode")
+ if currentMode == 1.0:
+ return
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if match:
+
+ # get IK controls
+ controls = json.loads(cmds.getAttr(networkNode + ".ikControls"))
+
+ # HAND
+ # create a duplicate hand anim
+ control = controls[0]
+ topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world=True)
+
+ # duplicate the control once more and parent under the fkMatch node
+ matchCtrl = cmds.duplicate(control, po=True)[0]
+ cmds.parent(matchCtrl, control + "_fkMatch")
+
+ # match the hand anim to the hand joint
+ joint = control.partition("ik_")[2].partition("_anim")[0]
+ joint = namespace + ":" + joint
+ constraint = cmds.parentConstraint(joint, control + "_fkMatch")[0]
+ cmds.delete(constraint)
+
+ # unparent the match control from the fkMatch, and put it under the topGrp
+ cmds.parent(matchCtrl, topGrp)
+
+ # this will now give use good values
+ translate = cmds.getAttr(matchCtrl + ".translate")[0]
+ rotate = cmds.getAttr(matchCtrl + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2],
+ type='double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ # delete dupes
+ cmds.delete(newControls[0])
+ cmds.delete(matchCtrl)
+
+ # ELBOW
+ # create a duplicate elbow pv anim
+ control = controls[1]
+ topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world=True)
+
+ # match to the pvMatch node
+ constraint = cmds.pointConstraint(namespace + ":" + control + "_fkMatch", control)[0]
+ cmds.delete(constraint)
+
+ # this will now give use good values
+ translate = cmds.getAttr(control + ".translate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2],
+ type='double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ # delete dupes
+ cmds.delete(newControls[0])
+
+ # switch modes
+ if not range:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if range:
+ self.switchClavMode(mode, checkBox, True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def switchFingerMode(self, mode, finger, range=False):
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ # switch to FK mode
+ if mode == "FK":
+ if finger == "All":
+ cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode")
+
+ else:
+ if finger.partition(namespace)[2].find(":index") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode")
+
+ if finger.partition(namespace)[2].find(":middle") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode")
+
+ if finger.partition(namespace)[2].find(":ring") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode")
+
+ if finger.partition(namespace)[2].find(":pinky") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode")
+
+ if finger.partition(namespace)[2].find(":thumb") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode")
+
+ if mode == "IK":
+
+ if finger == "All":
+ cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode")
+ cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode")
+
+ else:
+ if finger.partition(namespace)[2].find(":index") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode")
+
+ if finger.partition(namespace)[2].find(":middle") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode")
+
+ if finger.partition(namespace)[2].find(":ring") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode")
+
+ if finger.partition(namespace)[2].find(":pinky") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode")
+
+ if finger.partition(namespace)[2].find(":thumb") == 0:
+ # switch modes
+ cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX(self, importMethod, character):
+
+ returnControls = []
+
+ networkNode = self.returnRigNetworkNode
+ moduleName = cmds.getAttr(networkNode + ".moduleName")
+
+ # find created joints
+ joints = cmds.getAttr(networkNode + ".Created_Bones")
+
+ splitJoints = joints.split("::")
+ createdJoints = []
+ armJoints = []
+ clavJoint = None
+
+ fingers = []
+ if cmds.objExists(networkNode + ".fkFingerControls"):
+ fingers = json.loads(cmds.getAttr(networkNode + ".fkFingerControls"))
+
+ for bone in splitJoints:
+ if bone != "":
+ createdJoints.append(bone)
+
+ for joint in createdJoints:
+ if joint.find("upperarm") != -1:
+ if joint.find("twist") == -1:
+ upArmJnt = joint
+ armJoints.append(upArmJnt)
+
+ if joint.find("lowerarm") != -1:
+ if joint.find("twist") == -1:
+ loArmJnt = joint
+ armJoints.append(loArmJnt)
+
+ if joint.find("hand") != -1:
+ handJoint = joint
+ armJoints.append(handJoint)
+
+ if joint.find("clavicle") != -1:
+ clavJoint = joint
+
+ solveClav = False
+
+ if cmds.getAttr(networkNode + ".includeClavicle"):
+ solveClav = True
+ clavControls = json.loads(cmds.getAttr(networkNode + ".clavControls"))
+
+ # Handle Import Method/Constraints
+ if importMethod == "FK":
+ cmds.setAttr(character + ":" + moduleName + "_settings.mode", 0)
+ cmds.setAttr(character + ":" + moduleName + "_settings.clavMode", 0)
+
+ if solveClav:
+ cmds.orientConstraint(clavJoint, character + ":" + clavControls[0])
+ returnControls.append(character + ":" + clavControls[0])
+
+ for joint in armJoints:
+ cmds.orientConstraint(joint, character + ":fk_" + joint + "_anim")
+ returnControls.append(character + ":fk_" + joint + "_anim")
+
+ if len(fingers) > 0:
+ for finger in fingers:
+ cmds.orientConstraint(finger.partition("_anim")[0], character + ":" + finger)
+ returnControls.append(character + ":" + finger)
+
+ if importMethod == "IK":
+
+ if solveClav:
+ cmds.pointConstraint(armJoints[0], character + ":" + clavControls[1])
+ returnControls.append(character + ":" + clavControls[1])
+
+ cmds.parentConstraint(armJoints[2], character + ":ik_" + armJoints[2] + "_anim", mo=True)
+ returnControls.append(character + ":ik_" + armJoints[2] + "_anim")
+
+ cmds.pointConstraint(armJoints[1], character + ":" + self.name + "_ik_elbow_anim", mo=True)
+ returnControls.append(character + ":" + self.name + "_ik_elbow_anim")
+
+ if len(fingers) > 0:
+ for finger in fingers:
+ cmds.orientConstraint(finger.partition("_anim")[0], character + ":" + finger)
+ returnControls.append(character + ":" + finger)
+
+ if importMethod == "Both":
+ if solveClav:
+ cmds.orientConstraint(clavJoint, character + ":" + clavControls[0])
+ returnControls.append(character + ":" + clavControls[0])
+
+ cmds.pointConstraint(armJoints[0], character + ":" + clavControls[1])
+ returnControls.append(character + ":" + clavControls[1])
+
+ cmds.parentConstraint(armJoints[2], character + ":ik_" + armJoints[2] + "_anim", mo=True)
+ returnControls.append(character + ":ik_" + armJoints[2] + "_anim")
+
+ cmds.pointConstraint(armJoints[1], character + ":" + self.name + "_ik_elbow_anim", mo=True)
+ returnControls.append(character + ":" + self.name + "_ik_elbow_anim")
+
+ for joint in armJoints:
+ cmds.orientConstraint(joint, character + ":fk_" + joint + "_anim")
+ returnControls.append(character + ":fk_" + joint + "_anim")
+
+ if len(fingers) > 0:
+ for finger in fingers:
+ cmds.orientConstraint(finger.partition("_anim")[0], character + ":" + finger)
+ returnControls.append(character + ":" + finger)
+
+ if importMethod == "None":
+ pass
+
+ return returnControls
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def selectRigControls(self, mode):
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ # list any attributes on the network node that contain "controls"
+ controls = cmds.listAttr(networkNode, st="*Controls")
+ fkControls = ["fkControls", "upArmTwistControls", "loArmTwistControls", "fkFingerControls", "clavControls"]
+ ikControls = ["ikControls", "ikFingerControls", "clavControls"]
+
+ # get that data on that attr
+ for control in controls:
+
+ # select all controls
+ if mode == "all":
+ data = json.loads(cmds.getAttr(networkNode + "." + control))
+ if data != None:
+ for each in data:
+ cmds.select(namespace + ":" + each, add=True)
+
+ # select fk controls
+ if mode == "fk":
+ if control in fkControls:
+ data = json.loads(cmds.getAttr(networkNode + "." + control))
+ if data != None:
+ for each in data:
+ if each.find("fk") != -1:
+ cmds.select(namespace + ":" + each, add=True)
+
+ # select ik controls
+ if mode == "ik":
+ if control in ikControls:
+ data = json.loads(cmds.getAttr(networkNode + "." + control))
+ if data != None:
+ for each in data:
+ if each.find("fk") == -1:
+ cmds.select(namespace + ":" + each, add=True)
diff --git a/Core/Scripts/RigModules/ART_Chain.py b/Core/Scripts/RigModules/ART_Chain.py
new file mode 100644
index 0000000..7420c43
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Chain.py
@@ -0,0 +1,294 @@
+"""
+Author: Jeremy Ernst
+
+===============
+File Attributes
+===============
+ * **icon:** This is the image file (125x75 .png) that gets used in the RigCreatorUI
+
+ * **hoverIcon:** When you hover over the module in the module list, it will swap to this icon
+ (background changes to orange). There are .psd template files for these.
+
+ * **search:** These are search terms that are accepted when searching the list of modules in the
+ RigCreatorUI
+
+ * **class name:** The name of the class.
+
+ * **jointMover:** The relative path to the joint mover file. Relative to the ARTv2 root directory.
+
+ * **baseName:** The default name the module will get created with. Users can then add a prefix and/or
+ suffix to the base name.
+
+ * **rigs:** This is a simple list of what rigs this module can build. This feature isn't implemented yet,
+ but the plan is to query this list and present these options to the user for them to select what rigs
+ they want to build for the module. Right now, it will build all rigs.
+
+ * **fbxImport:** This is a list that will show the options for the module in the import mocap interface.
+ Normally, this list will have at least None and FK.
+
+ * **matchData:** This is a list of options that will be presented for the module in a comboBox in the
+ match over frame range interface. First argument is a bool as to whether the module can or can't
+ match. The second arg is a list of strings to display for the match options. For example:
+ matchData = [True, ["Match FK to IK", "Match IK to FK"]]
+
+ * **controlTypes:** This is a list of lists, where each item in the main list is a list comprised of the
+ name of the attribute that gets added to the network node that contains the control information.
+ The second arg in each list entry is a control type, like FK or IK. This is used in the select
+ rig controls interface for filtering out which controls on each module you want to select. On
+ this module, the values are: controlTypes = [["fkControls", "FK"]], which means that the
+ attribute that holds the control info is called fkControls, and those controls are of type FK.
+
+ .. image:: /images/selectRigControls.png
+
+===============
+Class
+===============
+"""
+# file imports
+import json
+import os
+from functools import partial
+
+import maya.cmds as cmds
+
+import System.interfaceUtils as interfaceUtils
+import System.riggingUtils as riggingUtils
+import System.utils as utils
+from System.ART_RigModule import ART_RigModule
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+# file attributes
+icon = "Modules/chain.png"
+hoverIcon = "Modules/hover_chain.png"
+search = "chain"
+className = "ART_Chain"
+jointMover = "Core/JointMover/ART_Chain.ma"
+baseName = "chain"
+rigs = ["FK", "IK", "Dynamic"]
+fbxImport = ["None", "FK", "IK", "Both"]
+matchData = [True, ["Match FK to IK", "Match IK to FK"]]
+controlTypes = [["fkControls", "FK"], ["ikControls", "IK"], ["dynControls", "FK"]]
+
+
+class ART_Chain(ART_RigModule):
+ """This class creates the chain module, which can have a minimum of 2 joints and a maximum of 99."""
+
+ def __init__(self, rigUiInst, moduleUserName):
+ """Initiate the class, taking in the instance to the interface and the user specified name.
+
+ :param rigUiInst: This is the rig creator interface instance being passed in.
+ :param moduleUserName: This is the name specified by the user on module creation.
+
+ Instantiate the following class variables as well:
+ * **self.rigUiInst:** take the passed in interface instance and make it a class var
+ * **self.moduleUserName:** take the passed in moduleUserName and make it a class var
+ * **self.outlinerWidget:** an empty list that will hold all of the widgets added to the outliner
+
+ Also, read the QSettings to find out where needed paths are.
+ """
+
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+
+ settings = QtCore.QSettings("Epic Games", "ARTv2")
+ self.toolsPath = settings.value("toolsPath")
+
+ ART_RigModule.__init__(self, "ART_Chain_Module", "ART_Chain", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ """
+ Add custom attributes this module needs to the network node.
+
+ Always calls on base class function first, then extends with any attributes unique to the class.
+ """
+
+ # call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ # add custom attributes for this specific module
+ cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", "joint_01::joint_02::joint_03::", type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".canAim", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".aimMode", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="numJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".numJoints", 3, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="hasDynamics", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".hasDynamics", False, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+ """
+ This is the UI for the module that has all of the configuration settings.
+
+ :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.
+
+
+ Build the groupBox that contains all of the settings for this module. Parent the groupBox
+ into the main skeletonSettingsUI layout.
+ Lastly, call on updateSettingsUI to populate the UI based off of the network node values.
+
+ .. image:: /images/skeletonSettings.png
+
+ """
+ # width, height, checkable
+
+ networkNode = self.returnNetworkNode
+ font = QtGui.QFont()
+ font.setPointSize(8)
+
+ headerFont = QtGui.QFont()
+ headerFont.setPointSize(8)
+ headerFont.setBold(True)
+
+ # groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 288, True)
+
+ # STANDARD BUTTONS
+
+ # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot
+ self.mainLayout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.frame = QtWidgets.QFrame(self.groupBox)
+ self.mainLayout.addWidget(self.frame)
+ self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.frame.setMinimumSize(QtCore.QSize(320, 270))
+ self.frame.setMaximumSize(QtCore.QSize(320, 270))
+
+ # create layout that is a child of the frame
+ self.layout = QtWidgets.QVBoxLayout(self.frame)
+
+ # mirror module
+ self.mirrorModLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.mirrorModLayout)
+ self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ")
+ self.mirrorModuleLabel.setFont(font)
+ self.mirrorModLayout.addWidget(self.mirrorModuleLabel)
+
+ mirror = cmds.getAttr(networkNode + ".mirrorModule")
+ if mirror == "":
+ mirror = "None"
+ self.mirrorMod = QtWidgets.QLabel(mirror)
+ self.mirrorMod.setFont(font)
+ self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter)
+ self.mirrorModLayout.addWidget(self.mirrorMod)
+
+ # current parent
+ self.currentParentMod = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.currentParentMod)
+ self.currentParentLabel = QtWidgets.QLabel("Current Parent: ")
+ self.currentParentLabel.setFont(font)
+ self.currentParentMod.addWidget(self.currentParentLabel)
+
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.currentParent = QtWidgets.QLabel(parent)
+ self.currentParent.setFont(font)
+ self.currentParent.setAlignment(QtCore.Qt.AlignHCenter)
+ self.currentParentMod.addWidget(self.currentParent)
+
+ # button layout for name/parent
+ self.buttonLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.buttonLayout)
+ self.changeNameBtn = QtWidgets.QPushButton("Change Name")
+ self.changeParentBtn = QtWidgets.QPushButton("Change Parent")
+ self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module")
+ self.buttonLayout.addWidget(self.changeNameBtn)
+ self.buttonLayout.addWidget(self.changeParentBtn)
+ self.buttonLayout.addWidget(self.mirrorModuleBtn)
+ self.changeNameBtn.setObjectName("blueButton")
+ self.changeParentBtn.setObjectName("blueButton")
+ self.mirrorModuleBtn.setObjectName("blueButton")
+
+ # button signal/slots
+ self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst))
+ self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst))
+ self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst))
+
+ # bake offsets button
+ self.bakeToolsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.bakeToolsLayout)
+
+ # Bake OFfsets
+ self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets")
+ self.bakeOffsetsBtn.setFont(headerFont)
+ self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync")
+ self.bakeOffsetsBtn.setObjectName("blueButton")
+
+ # Rig Settings
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.layout.addItem(spacerItem)
+
+ self.hasDynamics = QtWidgets.QCheckBox("Has Dynamics")
+ self.layout.addWidget(self.hasDynamics)
+ self.hasDynamics.setChecked(False)
+ # self.hasDynamics.clicked.connect(partial(self.applyModuleChanges, self))
+
+ spacerItem = QtWidgets.QSpacerItem(20, 30, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.layout.addItem(spacerItem)
+
+ # Number of joints in chain
+ self.numJointsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.numJointsLayout)
+
+ self.numJointsLabel = QtWidgets.QLabel("Number of Joints in Chain: ")
+ self.numJointsLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.numJointsLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.numJointsLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.numJointsLayout.addWidget((self.numJointsLabel))
+
+ self.numJoints = QtWidgets.QSpinBox()
+ self.numJoints.setMaximum(99)
+ self.numJoints.setMinimum(2)
+ self.numJoints.setMinimumSize(QtCore.QSize(100, 20))
+ self.numJoints.setMaximumSize(QtCore.QSize(100, 20))
+ self.numJoints.setValue(3)
+ self.numJoints.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.numJointsLayout.addWidget(self.numJoints)
+
+ # rebuild button
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.layout.addItem(spacerItem)
+
+ self.applyButton = QtWidgets.QPushButton("Apply Changes")
+ self.layout.addWidget(self.applyButton)
+ self.applyButton.setFont(headerFont)
+ self.applyButton.setMinimumSize(QtCore.QSize(300, 40))
+ self.applyButton.setMaximumSize(QtCore.QSize(300, 40))
+ self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.applyButton.setEnabled(False)
+ self.applyButton.clicked.connect(partial(self.applyModuleChanges, self))
+
+ # signal slot for groupbox checkbox
+ QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible)
+ self.groupBox.setChecked(False)
+
+ # add custom skeletonUI settings name, parent, rig types to install, mirror module, etc.
+ # add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+ # Populate the settings UI based on the network node attributes
+ # self.updateSettingsUI()
diff --git a/Core/Scripts/RigModules/ART_Head.py b/Core/Scripts/RigModules/ART_Head.py
new file mode 100644
index 0000000..296701a
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Head.py
@@ -0,0 +1,1068 @@
+"""
+Author: Jeremy Ernst
+
+===============
+File Attributes
+===============
+ * **icon:** This is the image file (125x75 .png) that gets used in the RigCreatorUI
+
+ * **hoverIcon:** When you hover over the module in the module list, it will swap to this icon
+ (background changes to orange). There are .psd template files for these.
+
+ * **search:** These are search terms that are accepted when searching the list of modules in the
+ RigCreatorUI
+
+ * **class name:** The name of the class.
+
+ * **jointMover:** The relative path to the joint mover file. Relative to the ARTv2 root directory.
+
+ * **baseName:** The default name the module will get created with. Users can then add a prefix and/or
+ suffix to the base name.
+
+ * **rigs:** This is a simple list of what rigs this module can build. This feature isn't implemented yet,
+ but the plan is to query this list and present these options to the user for them to select what rigs
+ they want to build for the module. Right now, it will build all rigs.
+
+ * **fbxImport:** This is a list that will show the options for the module in the import mocap interface.
+ Normally, this list will have at least None and FK.
+
+ * **matchData:** This is a list of options that will be presented for the module in a comboBox in the
+ match over frame range interface. First argument is a bool as to whether the module can or can't
+ match. The second arg is a list of strings to display for the match options. For example:
+ matchData = [True, ["Match FK to IK", "Match IK to FK"]]
+
+ * **controlTypes:** This is a list of lists, where each item in the main list is a list comprised of the
+ name of the attribute that gets added to the network node that contains the control information.
+ The second arg in each list entry is a control type, like FK or IK. This is used in the select
+ rig controls interface for filtering out which controls on each module you want to select. On
+ this module, the values are: controlTypes = [["fkControls", "FK"]], which means that the
+ attribute that holds the control info is called fkControls, and those controls are of type FK.
+
+ .. image:: /images/selectRigControls.png
+
+===============
+Class
+===============
+"""
+# file imports
+import json
+import os
+from functools import partial
+
+import maya.cmds as cmds
+
+import System.interfaceUtils as interfaceUtils
+import System.riggingUtils as riggingUtils
+import System.utils as utils
+from System.ART_RigModule import ART_RigModule
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+# file attributes
+icon = "Modules/head.png"
+hoverIcon = "Modules/hover_head.png"
+search = "biped:head:neck"
+className = "ART_Head"
+jointMover = "Core/JointMover/ART_Head_1Neck.ma"
+baseName = "Head"
+rigs = ["FK"]
+fbxImport = ["None", "FK"]
+matchData = [False, None] # This is for matching over frame range options. (Matching between rigs of the module)
+controlTypes = [["fkControls", "FK"]]
+
+
+class ART_Head(ART_RigModule):
+ """This class creates the head module"""
+
+ def __init__(self, rigUiInst, moduleUserName):
+ """Initiate the class, taking in the instance to the interface and the user specified name.
+
+ :param rigUiInst: This is the rig creator interface instance being passed in.
+ :param moduleUserName: This is the name specified by the user on module creation.
+
+ Instantiate the following class variables as well:
+ * **self.rigUiInst:** take the passed in interface instance and make it a class var
+ * **self.moduleUserName:** take the passed in moduleUserName and make it a class var
+ * **self.outlinerWidget:** an empty list that will hold all of the widgets added to the outliner
+
+ Also, read the QSettings to find out where needed paths are.
+ """
+
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+
+ settings = QtCore.QSettings("Epic Games", "ARTv2")
+ self.toolsPath = settings.value("toolsPath")
+
+ ART_RigModule.__init__(self, "ART_Head_Module", "ART_Head", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ """
+ Add custom attributes this module needs to the network node.
+
+ Always calls on base class function first, then extends with any attributes unique to the class.
+ """
+
+ # call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ # add custom attributes for this specific module
+ cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", "neck_01::head::", type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".canAim", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".aimMode", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="neckJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".neckJoints", 1, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+ """
+ This is the UI for the module that has all of the configuration settings.
+
+ :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.
+
+
+ Build the groupBox that contains all of the settings for this module. Parent the groupBox
+ into the main skeletonSettingsUI layout.
+ Lastly, call on updateSettingsUI to populate the UI based off of the network node values.
+
+ .. image:: /images/skeletonSettings.png
+
+ """
+ # width, height, checkable
+
+ networkNode = self.returnNetworkNode
+ font = QtGui.QFont()
+ font.setPointSize(8)
+
+ headerFont = QtGui.QFont()
+ headerFont.setPointSize(8)
+ headerFont.setBold(True)
+
+ # groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 228, True)
+
+ # STANDARD BUTTONS
+
+ # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot
+ self.mainLayout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.frame = QtWidgets.QFrame(self.groupBox)
+ self.mainLayout.addWidget(self.frame)
+ self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.frame.setMinimumSize(QtCore.QSize(320, 210))
+ self.frame.setMaximumSize(QtCore.QSize(320, 210))
+
+ # create layout that is a child of the frame
+ self.layout = QtWidgets.QVBoxLayout(self.frame)
+
+ # current parent
+ self.currentParentMod = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.currentParentMod)
+ self.currentParentLabel = QtWidgets.QLabel("Current Parent: ")
+ self.currentParentLabel.setFont(font)
+ self.currentParentMod.addWidget(self.currentParentLabel)
+
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.currentParent = QtWidgets.QLabel(parent)
+ self.currentParent.setFont(font)
+ self.currentParent.setAlignment(QtCore.Qt.AlignHCenter)
+ self.currentParentMod.addWidget(self.currentParent)
+
+ # button layout for name/parent
+ self.buttonLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.buttonLayout)
+ self.changeNameBtn = QtWidgets.QPushButton("Change Name")
+ self.changeParentBtn = QtWidgets.QPushButton("Change Parent")
+ self.buttonLayout.addWidget(self.changeNameBtn)
+ self.buttonLayout.addWidget(self.changeParentBtn)
+ self.changeNameBtn.setObjectName("blueButton")
+ self.changeParentBtn.setObjectName("blueButton")
+
+ # bake offsets button
+ self.bakeToolsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.bakeToolsLayout)
+
+ # Bake OFfsets
+ self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets")
+ self.bakeOffsetsBtn.setFont(headerFont)
+ self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync")
+
+ self.bakeOffsetsBtn.setObjectName("blueButton")
+
+ # button signal/slots
+ self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst))
+ self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst))
+
+ # Number of Neck Bones
+ self.neckLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.neckLayout)
+
+ self.numNeckBonesLabel = QtWidgets.QLabel("Number of Neck Bones: ")
+ self.numNeckBonesLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.numNeckBonesLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.numNeckBonesLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.neckLayout.addWidget((self.numNeckBonesLabel))
+
+ self.numNeck = QtWidgets.QSpinBox()
+ self.numNeck.setMaximum(3)
+ self.numNeck.setMinimum(1)
+ self.numNeck.setMinimumSize(QtCore.QSize(100, 20))
+ self.numNeck.setMaximumSize(QtCore.QSize(100, 20))
+ self.numNeck.setValue(1)
+ self.numNeck.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.neckLayout.addWidget(self.numNeck)
+
+ # rebuild button
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.layout.addItem(spacerItem)
+
+ self.applyButton = QtWidgets.QPushButton("Apply Changes")
+ self.layout.addWidget(self.applyButton)
+ self.applyButton.setFont(headerFont)
+ self.applyButton.setMinimumSize(QtCore.QSize(300, 40))
+ self.applyButton.setMaximumSize(QtCore.QSize(300, 40))
+ self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.applyButton.setEnabled(False)
+ self.applyButton.clicked.connect(partial(self.applyModuleChanges, self))
+
+ # spinBox & checkbox signal/slots
+ self.numNeck.valueChanged.connect(self.toggleButtonState)
+
+ # signal slot for groupbox checkbox
+ QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible)
+ self.groupBox.setChecked(False)
+
+ # add custom skeletonUI settings name, parent, rig types to install, mirror module, etc.
+ # add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+ # Populate the settings UI based on the network node attributes
+ self.updateSettingsUI()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateSettingsUI(self):
+
+ """
+ Update the skeleton settings UI based on the network node values for this module.
+ """
+
+ networkNode = self.returnNetworkNode
+ numNeck = cmds.getAttr(networkNode + ".neckJoints")
+
+ # update UI elements
+ self.numNeck.setValue(numNeck)
+
+ # apply changes
+ self.applyButton.setEnabled(False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateNeck(self, attachedModules, oldNum):
+
+ """
+ Take the number of neck bones value and rebuild the joint mover.
+
+ The head module has 3 joint mover files, 1 for each possible neck number. When the number of neck bones is
+ changed, the current module has its information stored (placement, etc), the module is then deleted,
+ the new joint mover path is constructed and brought in, and lastly it resolves any dependency issues.
+ (Like if there was a leaf joint as a child of a neck bone that no longer exists)
+
+ :param attachedModules: self.checkForDependencies()
+ :param oldNum: the existing amount of neck bones prior to the update
+ """
+
+ # gather information (current name, current parent, etc)
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ newNum = int(cmds.getAttr(networkNode + ".neckJoints"))
+
+ # call on base class delete
+ movers = self.returnJointMovers
+ for moverGrp in movers:
+ for mover in moverGrp:
+ cmds.lockNode(mover, lock=False)
+
+ # store mover positions (movers = [all global, all offset, all geo])
+ basePositions = {}
+
+ for each in movers:
+ for mover in each:
+ attrs = cmds.listAttr(mover, keyable=True)
+ attrValues = []
+ for attr in attrs:
+ value = cmds.getAttr(mover + "." + attr)
+ attrValues.append([attr, value])
+ basePositions[mover] = attrValues
+
+ # delete joint mover
+ cmds.delete(self.name + "_mover_grp")
+
+ # build new jmPath name
+ jmPath = jointMover.partition(".ma")[0].rpartition("_")[0] + "_" + str(newNum) + "Neck.ma" # ART_Head_1Neck
+ self.jointMover_Build(jmPath)
+
+ # apply base positions
+ for key in basePositions:
+
+ mover = key
+ attrList = basePositions.get(key)
+
+ for attr in attrList:
+ if cmds.objExists(mover):
+ cmds.setAttr(mover + "." + attr[0], attr[1])
+
+ # parent the joint mover to the offset mover of the parent
+ mover = ""
+
+ if parent == "root":
+ mover = "root_mover"
+
+ else:
+ # find the parent mover name to parent to
+ networkNodes = utils.returnRigModules()
+ mover = utils.findMoverNodeFromJointName(networkNodes, parent)
+
+ # delete the old constraint and create the new one
+ if cmds.objExists(self.name + "_mover_grp_parentConstraint*"):
+ cmds.delete(self.name + "_mover_grp_parentConstraint*")
+
+ if mover is not None:
+ cmds.parentConstraint(mover, self.name + "_mover_grp", mo=True)
+
+ if cmds.objExists(self.name + "_mover_grp_scaleConstraint*"):
+ cmds.delete(self.name + "_mover_grp_scaleConstraint*")
+
+ if mover is not None:
+ cmds.scaleConstraint(mover, self.name + "_mover_grp", mo=True)
+
+ # create the connection geo between the two
+ childMover = utils.findOffsetMoverFromName(name)
+ riggingUtils.createBoneConnection(mover, childMover, name)
+ self.applyModuleChanges(self)
+ cmds.select(clear=True)
+
+ # if there were any module dependencies, fix those now.
+ if len(attachedModules) > 0:
+ elementList = []
+
+ for each in attachedModules:
+ elementList.append([each[2], " -> parent changed from: ", each[1], " to: ", "root\n"])
+ currentParent = cmds.listRelatives(each[2] + "_mover_grp", parent=True)[0]
+ if currentParent != "root_mover":
+ cmds.parentConstraint("root_mover", each[2] + "_mover_grp", mo=True)
+ cmds.scaleConstraint("root_mover", each[2] + "_mover_grp", mo=True)
+ cmds.setAttr(each[0] + ".parentModuleBone", lock=False)
+ cmds.setAttr(each[0] + ".parentModuleBone", "root", type="string", lock=True)
+
+ # then, update settings UI for those dependency modules to display new parent info
+ modules = self.getAllModules
+
+ if each[0] in modules:
+ modName = cmds.getAttr(each[0] + ".moduleName")
+
+ for modInst in self.rigUiInst.moduleInstances:
+ if modInst.networkNode == each[0]:
+ # 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
+ modInst.skeletonSettings_UI(modName)
+
+ # create the connection geo between the two
+ mover = "root_mover"
+ childMover = utils.findOffsetMoverFromName(each[2])
+ riggingUtils.createBoneConnection(mover, childMover, each[2])
+ each[3].applyModuleChanges(each[3])
+ cmds.select(clear=True)
+
+ # warn user about changes
+ 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()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def applyModuleChanges(self, moduleInst):
+
+ """
+ Update the scene after the settings are changed in the skeleton settings UI.
+
+ This means also updating the created_bones attr, updating the joint mover if needed,
+ running self.updateNeck, updating the outliner, and updating the bone count.
+
+ :param moduleInst: self (usually, but there are cases like templates where an inst on disc is passed in.)
+ """
+
+ networkNode = self.returnNetworkNode
+
+ # get prefix/suffix
+ name = self.groupBox.title()
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ if len(prefix) > 0:
+ if prefix.find("_") == -1:
+ prefix = prefix + "_"
+ if len(suffix) > 0:
+ if suffix.find("_") == -1:
+ suffix = "_" + suffix
+
+ # create list of the new created bones
+ joints = []
+
+ # get current neck value
+ currentNum = int(cmds.getAttr(networkNode + ".neckJoints"))
+
+ # get new neck value
+ uiNeckVal = self.numNeck.value()
+
+ if uiNeckVal != currentNum:
+ # update neck value, and call on update neck
+ cmds.setAttr(networkNode + ".neckJoints", lock=False)
+ cmds.setAttr(networkNode + ".neckJoints", uiNeckVal, lock=True)
+
+ # look for any attached modules
+ attachedModules = self.checkForDependencies()
+ self.updateNeck(attachedModules, currentNum)
+
+ for i in range(uiNeckVal):
+ joints.append(prefix + "neck_0" + str(i + 1) + suffix)
+
+ joints.append(prefix + "head" + suffix)
+
+ # build attrString
+ attrString = ""
+ for bone in joints:
+ attrString += bone + "::"
+
+ networkNode = self.returnNetworkNode
+ cmds.setAttr(networkNode + ".Created_Bones", lock=False)
+ cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True)
+
+ # reset button
+ self.applyButton.setEnabled(False)
+
+ # update outliner
+ self.updateOutliner()
+ self.updateBoneCount()
+
+ # clear selection
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleButtonState(self):
+
+ """Toggle the state of the Apply Changes button."""
+
+ state = self.applyButton.isEnabled()
+ if state is False:
+ self.applyButton.setEnabled(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addJointMoverToOutliner(self):
+
+ """
+ Add the joint movers for this module to the outliner.
+
+ Depending on the module settings, different joint movers may or may not be added. Also, each "joint" usually
+ has three movers: global, offset, and geo. However, not all joints do, so this method is also used to specify
+ which joint movers for each joint are added to the outliner.
+
+ .. image:: /images/outliner.png
+
+ """
+ index = self.rigUiInst.treeWidget.topLevelItemCount()
+
+ # Add the module to the tree widget in the outliner tab of the rig creator UI
+ self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget)
+ self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name)
+ foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255))
+ self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground)
+
+ # add the neck 01
+ self.outlinerWidgets[self.name + "_neck_01"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_neck_01"].setText(0, self.name + "_neck_01")
+ self.createGlobalMoverButton(self.name + "_neck_01", self.outlinerWidgets[self.name + "_neck_01"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_neck_01", self.outlinerWidgets[self.name + "_neck_01"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_neck_01", self.outlinerWidgets[self.name + "_neck_01"], self.rigUiInst)
+
+ # add neck 02
+ self.outlinerWidgets[self.name + "_neck_02"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_neck_01"])
+ self.outlinerWidgets[self.name + "_neck_02"].setText(0, self.name + "_neck_02")
+ self.createGlobalMoverButton(self.name + "_neck_02", self.outlinerWidgets[self.name + "_neck_02"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_neck_02", self.outlinerWidgets[self.name + "_neck_02"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_neck_02", self.outlinerWidgets[self.name + "_neck_02"], self.rigUiInst)
+
+ # add neck 03
+ self.outlinerWidgets[self.name + "_neck_03"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_neck_02"])
+ self.outlinerWidgets[self.name + "_neck_03"].setText(0, self.name + "_neck_03")
+ self.createGlobalMoverButton(self.name + "_neck_03", self.outlinerWidgets[self.name + "_neck_03"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_neck_03", self.outlinerWidgets[self.name + "_neck_03"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_neck_03", self.outlinerWidgets[self.name + "_neck_03"], self.rigUiInst)
+
+ # add head
+ self.outlinerWidgets[self.name + "_head"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_head"].setText(0, self.name + "_head")
+ self.createGlobalMoverButton(self.name + "_head", self.outlinerWidgets[self.name + "_head"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_head", self.outlinerWidgets[self.name + "_head"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_head", self.outlinerWidgets[self.name + "_head"], self.rigUiInst)
+
+ # create selection script job for module
+ self.createScriptJob()
+
+ # update based on spinBox values
+ self.updateOutliner()
+ self.updateBoneCount()
+ self.rigUiInst.treeWidget.expandAll()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateOutliner(self):
+ """
+ Whenever changes are made to the module settings, update the outliner to show the new or removed movers
+ """
+
+ # NECK
+ numNeck = self.numNeck.value()
+ if numNeck == 1:
+ self.outlinerWidgets[self.originalName + "_neck_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_neck_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_neck_03"].setHidden(True)
+
+ if numNeck == 2:
+ self.outlinerWidgets[self.originalName + "_neck_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_neck_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_neck_03"].setHidden(True)
+
+ if numNeck == 3:
+ self.outlinerWidgets[self.originalName + "_neck_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_neck_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_neck_03"].setHidden(False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pinModule(self, state):
+ """
+ Pin the module in place so the parent does not move the module. Each module has to define how it needs to be
+ pinned.
+ """
+ networkNode = self.returnNetworkNode
+ topLevelMover = self.name + "_neck_01_mover_grp"
+
+ if state:
+
+ loc = cmds.spaceLocator()[0]
+ cmds.setAttr(loc + ".v", False, lock=True)
+ constraint = cmds.parentConstraint(topLevelMover, loc)[0]
+ cmds.delete(constraint)
+ const = cmds.parentConstraint(loc, topLevelMover)[0]
+
+ if not cmds.objExists(networkNode + ".pinConstraint"):
+ cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message")
+
+ cmds.connectAttr(const + ".message", networkNode + ".pinConstraint")
+
+ if not state:
+
+ connections = cmds.listConnections(networkNode + ".pinConstraint")
+ if len(connections) > 0:
+ constraint = connections[0]
+ cmds.delete(constraint)
+
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skinProxyGeo(self):
+ """
+ Skin the proxy geo brought in by the module. Each module has to define how it wants to skin its proxy geo.
+ """
+
+ # get the network node
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ if len(prefix) > 0:
+ if prefix.find("_") == -1:
+ prefix = prefix + "_"
+ if len(suffix) > 0:
+ if suffix.find("_") == -1:
+ suffix = "_" + suffix
+
+ # get this module's proxy geo meshes
+ cmds.select(name + "_mover_grp", hi=True)
+ proxyGeoMeshes = []
+ selection = cmds.ls(sl=True)
+ for each in selection:
+ if each.find("proxy_geo") != -1:
+ parent = cmds.listRelatives(each, parent=True)[0]
+ if cmds.nodeType(each) == "transform":
+ proxyGeoMeshes.append(each)
+
+ # skin the proxy geo meshes
+ for mesh in proxyGeoMeshes:
+ dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0]
+ cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False)
+ cmds.setAttr(dupeMesh + ".overrideDisplayType", 0)
+
+ # create skinned geo group
+ if not cmds.objExists("skinned_proxy_geo"):
+ cmds.group(empty=True, name="skinned_proxy_geo")
+
+ cmds.parent(dupeMesh, "skinned_proxy_geo")
+
+ boneName = mesh.partition(name + "_")[2]
+ boneName = boneName.partition("_proxy_geo")[0]
+ joint = prefix + boneName + suffix
+
+ if not cmds.objExists(joint):
+ cmds.delete(dupeMesh)
+
+ else:
+ cmds.select([dupeMesh, joint])
+ cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0,
+ normalizeWeights=True)
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRigCustom(self, textEdit, uiInst):
+ """
+ Build the rigs for this module.
+
+ This method defines what rigs are built and how they are built when the asset is published. It posts any build
+ info to the passed in textEdit.
+
+ :param textEdit: passed in text edit that the rig build can post updates to
+ :param uiInst: passed in instance of the buildProgressUI
+ """
+
+ if textEdit is not None:
+ textEdit.append(" Building " + self.name + " Rig..")
+
+ # get the created joints
+ networkNode = self.returnNetworkNode
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ joints = self.returnCreatedJoints
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create groups and settings
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create the rig group
+ self.rigGrp = cmds.group(empty=True, name=self.name + "_group")
+ constraint = cmds.parentConstraint(parentBone, self.rigGrp)[0]
+ cmds.delete(constraint)
+
+ # create the rig settings group
+ self.rigSettings = cmds.group(empty=True, name=self.name + "_settings")
+ cmds.parent(self.rigSettings, self.rigGrp)
+ for attr in (cmds.listAttr(self.rigSettings, keyable=True)):
+ cmds.setAttr(self.rigSettings + "." + attr, lock=True, keyable=False)
+
+ # create the ctrl group (what will get the constraint to the parent)
+ self.rigCtrlGrp = cmds.group(empty=True, name=self.name + "_ctrl_grp")
+ constraint = cmds.parentConstraint(parentBone, self.rigCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(self.rigCtrlGrp, self.rigGrp)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # Build the FK Neck Rig
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ fkControls = []
+ self.topNode = None
+
+ # get number of neck bones
+ numNeck = cmds.getAttr(networkNode + ".neckJoints")
+ neckJoints = []
+ for i in range(len(joints) - 1):
+ neckJoints.append(joints[i])
+
+ # create FK controls for neck joints, adding space switching to base neck joint
+ for joint in neckJoints:
+ if joint == joints[0]:
+ data = riggingUtils.createControlFromMover(joint, networkNode, True, True)
+
+ fkControl = cmds.rename(data[0], "fk_" + joint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp")
+ spaceSwitcher = cmds.rename(data[2], "fk_" + joint + "_anim_space_switcher")
+ spaceSwitchFollow = cmds.rename(data[3], "fk_" + joint + "_anim_space_switcher_follow")
+ self.topNode = spaceSwitchFollow
+
+ fkControls.append([spaceSwitchFollow, fkControl, joint])
+ # color the control
+ riggingUtils.colorControl(fkControl, 18)
+
+ else:
+ data = riggingUtils.createControlFromMover(joint, networkNode, True, False)
+
+ fkControl = cmds.rename(data[0], "fk_" + joint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp")
+
+ fkControls.append([animGrp, fkControl, joint])
+
+ # color the control
+ riggingUtils.colorControl(fkControl, 18)
+
+ # create hierarchy
+ fkControls.reverse()
+
+ for i in range(len(fkControls)):
+ try:
+ cmds.parent(fkControls[i][0], fkControls[i + 1][1])
+ except IndexError:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # Build the FK Head Rig
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ headJoint = joints[-1]
+ data = riggingUtils.createControlFromMover(headJoint, networkNode, True, True)
+
+ headControl = cmds.rename(data[0], "fk_" + headJoint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + headJoint + "_anim_grp")
+ spaceSwitcher = cmds.rename(data[2], "fk_" + headJoint + "_anim_space_switcher")
+ spaceSwitchFollow = cmds.rename(data[3], "fk_" + headJoint + "_anim_space_switcher_follow")
+
+ # color the control
+ riggingUtils.colorControl(headControl, 17)
+
+ # parent head to neck
+ lastNeck = fkControls[0][1]
+ cmds.parent(spaceSwitchFollow, lastNeck)
+
+ fkControls.append([animGrp, headControl, headJoint])
+
+ # parent head rig to rigGrp
+ cmds.parent(self.topNode, self.rigCtrlGrp)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # lock attrs
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ for each in fkControls:
+ control = each[1]
+ if control != headControl:
+ for attr in [".scaleX", ".scaleY", ".globalScale", ".visibility"]:
+ cmds.setAttr(control + attr, lock=True, keyable=False)
+ else:
+ for attr in [".visibility"]:
+ cmds.setAttr(control + attr, lock=True, keyable=False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # hook up to driver skeleton
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ for each in fkControls:
+ control = each[1]
+ joint = each[2]
+
+ cmds.pointConstraint(control, "driver_" + joint, mo=True)
+ cmds.orientConstraint(control, "driver_" + joint)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale
+ # into input 2, and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(control + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, 0, "output")
+ else:
+ riggingUtils.createConstraint(control, "driver_" + joint, "scale", False, 2, 0)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # add info to module
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ fkRigData = []
+ for each in fkControls:
+ fkRigData.append(each[1])
+
+ # add created control info to module
+ if not cmds.objExists(networkNode + ".fkControls"):
+ cmds.addAttr(networkNode, ln="fkControls", dt="string")
+ jsonString = json.dumps(fkRigData)
+ cmds.setAttr(networkNode + ".fkControls", jsonString, type="string")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Parent Under Offset Ctrl # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # parent under offset_anim if it exists(it always should)
+ if cmds.objExists("offset_anim"):
+ cmds.parent(self.rigGrp, "offset_anim")
+
+ # return data
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ try:
+ uiInst.rigData.append([self.rigCtrlGrp, "driver_" + parentBone, 1])
+ except:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # update progress
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ if textEdit is not None:
+ textEdit.setTextColor(QtGui.QColor(0, 255, 18))
+ textEdit.append(" SUCCESS: FK Build Complete!")
+ textEdit.setTextColor(QtGui.QColor(255, 255, 255))
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pickerUI(self, center, animUI, networkNode, namespace):
+ """
+ Build the animation picker for the module.
+
+
+ :param center: the center of the QGraphicsScene
+ :param animUI: the instance of the AnimationUI
+ :param networkNode: the module's network node
+ :param namespace: the namespace of the character
+
+ """
+
+ self.namespace = namespace
+ neckJoints = cmds.getAttr(networkNode + ".neckJoints")
+
+ # create qBrushes
+ yellowBrush = QtCore.Qt.yellow
+ blueBrush = QtGui.QColor(100, 220, 255)
+ greenBrush = QtGui.QColor(0, 255, 30)
+ clearBrush = QtGui.QBrush(QtCore.Qt.black)
+ clearBrush.setStyle(QtCore.Qt.NoBrush)
+
+ # create the picker border item
+ if networkNode.find(":") != -1:
+ moduleNode = networkNode.partition(":")[2]
+ else:
+ moduleNode = networkNode
+
+ borderItem = interfaceUtils.pickerBorderItem(center.x() - 50, center.y() - 50, 100, 100, clearBrush, moduleNode)
+
+ # get controls
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ fkControls.reverse()
+ buttonData = []
+
+ # create buttons
+ headButton = interfaceUtils.pickerButtonCustom(100, 100,
+ [[10, 60], [30, 60], [40, 40], [40, 10], [35, 5], [30, 0],
+ [10, 0], [5, 5], [0, 10], [0, 40], [10, 60]], [30, 5],
+ namespace + fkControls[0], yellowBrush, borderItem)
+ buttonData.append([headButton, namespace + fkControls[0], yellowBrush])
+
+ if neckJoints == 1:
+ neck1Button = interfaceUtils.pickerButtonCustom(100, 100,
+ [[5, 55], [8, 63], [32, 63], [35, 55], [40, 85], [0, 85],
+ [5, 55]], [30, 5], namespace + fkControls[1], blueBrush,
+ borderItem)
+ buttonData.append([neck1Button, namespace + fkControls[1], blueBrush])
+
+ if neckJoints == 2:
+ neck1Button = interfaceUtils.pickerButtonCustom(100, 100,
+ [[5, 55], [8, 63], [32, 63], [35, 55], [37, 68], [3, 68],
+ [5, 55]], [30, 5], namespace + fkControls[1], blueBrush,
+ borderItem)
+ buttonData.append([neck1Button, namespace + fkControls[1], blueBrush])
+
+ neck2Button = interfaceUtils.pickerButtonCustom(100, 100, [[3, 70], [37, 70], [40, 80], [0, 80]], [30, 5],
+ namespace + fkControls[2], blueBrush, borderItem)
+ buttonData.append([neck2Button, namespace + fkControls[2], blueBrush])
+
+ if neckJoints == 3:
+ neck1Button = interfaceUtils.pickerButtonCustom(100, 100,
+ [[5, 55], [8, 63], [32, 63], [35, 55], [37, 68], [3, 68],
+ [5, 55]], [30, 5], namespace + fkControls[1], blueBrush,
+ borderItem)
+ buttonData.append([neck1Button, namespace + fkControls[1], blueBrush])
+
+ neck2Button = interfaceUtils.pickerButtonCustom(100, 100, [[3, 70], [37, 70], [38, 76], [2, 76]], [30, 5],
+ namespace + fkControls[2], blueBrush, borderItem)
+ buttonData.append([neck2Button, namespace + fkControls[2], blueBrush])
+
+ neck3Button = interfaceUtils.pickerButtonCustom(100, 100, [[2, 78], [38, 78], [40, 84], [0, 84]], [30, 5],
+ namespace + fkControls[3], blueBrush, borderItem)
+ buttonData.append([neck3Button, namespace + fkControls[3], blueBrush])
+
+ # =======================================================================
+ # go through button data, adding menu items
+ # =======================================================================
+ for each in buttonData:
+ button = each[0]
+
+ zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png"))))
+ zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png"))))
+ selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png"))))
+
+ button.menu.addAction(selectIcon, "Select All Controls", partial(self.selectRigControls))
+ button.menu.addSeparator()
+
+ button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True))
+ button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False))
+
+ # =======================================================================
+ # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5)
+ # =======================================================================
+ scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)],
+ kws=True)
+ borderItem.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ return [borderItem, False, scriptJob]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX(self, importMethod, character):
+ """
+ Import FBX motion onto this module's rig controls.
+
+ :param importMethod: The import method to be used (options defined in the file attributes)
+ :param character: the namespace of the character
+
+ Each module has to define what import methods it offers (at the very top of the module file) and then define
+ how motion is imported using those methods.
+ """
+
+ returnControls = []
+
+ # get basic info of node
+ networkNode = self.returnRigNetworkNode
+ moduleName = cmds.getAttr(networkNode + ".moduleName")
+ baseModuleName = cmds.getAttr(networkNode + ".baseName")
+
+ # find prefix/suffix of module name
+ prefixSuffix = moduleName.split(baseModuleName)
+ prefix = None
+ suffix = None
+
+ if prefixSuffix[0] != '':
+ prefix = prefixSuffix[0]
+ if prefixSuffix[1] != '':
+ suffix = prefixSuffix[1]
+
+ # get joints
+ joints = cmds.getAttr(networkNode + ".Created_Bones")
+ splitJoints = joints.split("::")
+ createdJoints = []
+
+ for bone in splitJoints:
+ if bone != "":
+ createdJoints.append(bone)
+
+ # IMPORT FK
+ if importMethod == "FK":
+
+ for joint in createdJoints:
+ if cmds.objExists(character + ":" + "fk_" + joint + "_anim"):
+ cmds.parentConstraint(joint, character + ":" + "fk_" + joint + "_anim")
+ returnControls.append(character + ":" + "fk_" + joint + "_anim")
+
+ # IMPORT NONE
+ if importMethod == "None":
+ pass
+
+ return returnControls
diff --git a/Core/Scripts/RigModules/ART_Leaf.py b/Core/Scripts/RigModules/ART_Leaf.py
new file mode 100644
index 0000000..0350d11
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Leaf.py
@@ -0,0 +1,1414 @@
+import json
+import os
+from functools import partial
+
+import maya.cmds as cmds
+
+import System.interfaceUtils as interfaceUtils
+import System.utils as utils
+from System.ART_RigModule import ART_RigModule
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+# file attributes
+icon = "Modules/leafJoint.png"
+hoverIcon = "Modules/hover_leafJoint.png"
+search = "jnt:joint:leaf"
+className = "ART_Leaf"
+jointMover = "Core/JointMover/ART_Leaf.ma"
+baseName = "jnt"
+fbxImport = ["None", "FK"]
+matchData = [False, None] # This is for matching over frame range options. (Matching between rigs of the module)
+controlTypes = [["leafControls", "FK"]]
+
+
+class ART_Leaf(ART_RigModule):
+ def __init__(self, rigUiInst, moduleUserName):
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+
+ settings = QtCore.QSettings("Epic Games", "ARTv2")
+ self.toolsPath = settings.value("toolsPath")
+
+ ART_RigModule.__init__(self, "ART_Leaf_Module", "ART_Leaf", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ # call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ # add custom attributes for this specific module
+ cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", "jnt", type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".canAim", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".aimMode", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="controlType", at="enum",
+ en="Circle:Square:Triangle:Cube:Sphere:Cylinder:Arrow", keyable=False)
+ cmds.setAttr(self.networkNode + ".controlType", 0, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="proxyShape", at="enum", en="Cube:Cylinder:Capsule:Sphere:Cone",
+ keyable=False)
+ cmds.setAttr(self.networkNode + ".proxyShape", 0, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="hasDynamics", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".hasDynamics", False, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="transX", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".transX", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="transY", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".transY", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="transZ", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".transZ", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="rotX", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".rotX", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="rotY", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".rotY", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="rotZ", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".rotZ", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="scaleX", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".scaleX", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="scaleY", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".scaleY", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="scaleZ", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".scaleZ", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="customAttrs", dt="string", keyable=False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+
+ networkNode = self.returnNetworkNode
+
+ # groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 438, True)
+
+ font = QtGui.QFont()
+ font.setPointSize(8)
+
+ headerFont = QtGui.QFont()
+ headerFont.setPointSize(8)
+ headerFont.setBold(True)
+
+ # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot
+ self.mainLayout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.frame = QtWidgets.QFrame(self.groupBox)
+ self.mainLayout.addWidget(self.frame)
+ self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.frame.setMinimumSize(QtCore.QSize(320, 420))
+ self.frame.setMaximumSize(QtCore.QSize(320, 420))
+
+ # create layout that is a child of the frame
+ self.layout = QtWidgets.QVBoxLayout(self.frame)
+
+ # mirror module
+ self.mirrorModLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.mirrorModLayout)
+ self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ")
+ self.mirrorModuleLabel.setFont(font)
+ self.mirrorModLayout.addWidget(self.mirrorModuleLabel)
+
+ mirror = cmds.getAttr(networkNode + ".mirrorModule")
+ if mirror == "":
+ mirror = "None"
+ self.mirrorMod = QtWidgets.QLabel(mirror)
+ self.mirrorMod.setFont(font)
+ self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter)
+ self.mirrorModLayout.addWidget(self.mirrorMod)
+
+ # current parent
+ self.currentParentMod = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.currentParentMod)
+ self.currentParentLabel = QtWidgets.QLabel("Current Parent: ")
+ self.currentParentLabel.setFont(font)
+ self.currentParentMod.addWidget(self.currentParentLabel)
+
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.currentParent = QtWidgets.QLabel(parent)
+ self.currentParent.setFont(font)
+ self.currentParent.setAlignment(QtCore.Qt.AlignHCenter)
+ self.currentParentMod.addWidget(self.currentParent)
+
+ # button layout for name/parent
+ self.buttonLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.buttonLayout)
+ self.changeNameBtn = QtWidgets.QPushButton("Change Name")
+ self.changeParentBtn = QtWidgets.QPushButton("Change Parent")
+ self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module")
+ self.buttonLayout.addWidget(self.changeNameBtn)
+ self.buttonLayout.addWidget(self.changeParentBtn)
+ self.buttonLayout.addWidget(self.mirrorModuleBtn)
+ self.changeNameBtn.setObjectName("blueButton")
+ self.changeParentBtn.setObjectName("blueButton")
+ self.mirrorModuleBtn.setObjectName("blueButton")
+
+ # button signal/slots
+ self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst))
+ self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst))
+ self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst))
+
+ # bake offsets button
+ self.bakeToolsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.bakeToolsLayout)
+
+ # Bake OFfsets
+ self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets")
+ self.bakeOffsetsBtn.setFont(headerFont)
+ self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync")
+ self.bakeOffsetsBtn.setObjectName("blueButton")
+
+ # settings for control shape
+ self.controlShapeLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.controlShapeLayout)
+
+ self.controlShapeLabel = QtWidgets.QLabel("Control Type: ")
+ self.controlShapeLabel.setFont(font)
+ self.controlShapeLayout.addWidget(self.controlShapeLabel)
+
+ self.controlShapeType = QtWidgets.QComboBox()
+ self.controlShapeLayout.addWidget(self.controlShapeType)
+ self.controlShapeType.addItem("Circle")
+ self.controlShapeType.addItem("Square")
+ self.controlShapeType.addItem("Triangle")
+ self.controlShapeType.addItem("Cube")
+ self.controlShapeType.addItem("Sphere")
+ self.controlShapeType.addItem("Cylinder")
+ self.controlShapeType.addItem("Arrow")
+
+ # settings for proxy geo shape
+ self.proxyShapeLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.proxyShapeLayout)
+
+ self.proxyShapeLabel = QtWidgets.QLabel("Proxy Shape: ")
+ self.proxyShapeLabel.setFont(font)
+ self.proxyShapeLayout.addWidget(self.proxyShapeLabel)
+
+ self.proxyShapeType = QtWidgets.QComboBox()
+ self.proxyShapeLayout.addWidget(self.proxyShapeType)
+ self.proxyShapeType.addItem("Cube")
+ self.proxyShapeType.addItem("Cylinder")
+ self.proxyShapeType.addItem("Capsule")
+ self.proxyShapeType.addItem("Sphere")
+ self.proxyShapeType.addItem("Cone")
+
+ # Rig Settings
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.layout.addItem(spacerItem)
+
+ self.hasDynamics = QtWidgets.QCheckBox("Has Dynamics")
+ self.layout.addWidget(self.hasDynamics)
+ self.hasDynamics.setChecked(False)
+ self.hasDynamics.clicked.connect(partial(self.applyModuleChanges, self))
+
+ spacerItem = QtWidgets.QSpacerItem(20, 15, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.layout.addItem(spacerItem)
+
+ label = QtWidgets.QLabel("Keyable Attributes:")
+ label.setFont(headerFont)
+ self.layout.addWidget(label)
+
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.MinimumExpanding)
+ self.layout.addItem(spacerItem)
+
+ # TRANSLATES
+ self.translateSettingsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.translateSettingsLayout)
+
+ self.txAttr = QtWidgets.QCheckBox("TranslateX")
+ self.txAttr.setChecked(True)
+ self.translateSettingsLayout.addWidget(self.txAttr)
+ self.txAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ self.tyAttr = QtWidgets.QCheckBox("TranslateY")
+ self.tyAttr.setChecked(True)
+ self.translateSettingsLayout.addWidget(self.tyAttr)
+ self.tyAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ self.tzAttr = QtWidgets.QCheckBox("TranslateZ")
+ self.tzAttr.setChecked(True)
+ self.translateSettingsLayout.addWidget(self.tzAttr)
+ self.tzAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ # ROTATES
+ self.rotateSettingsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.rotateSettingsLayout)
+
+ self.rxAttr = QtWidgets.QCheckBox("RotateX")
+ self.rxAttr.setChecked(True)
+ self.rotateSettingsLayout.addWidget(self.rxAttr)
+ self.rxAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ self.ryAttr = QtWidgets.QCheckBox("RotateY")
+ self.ryAttr.setChecked(True)
+ self.rotateSettingsLayout.addWidget(self.ryAttr)
+ self.ryAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ self.rzAttr = QtWidgets.QCheckBox("RotateZ")
+ self.rzAttr.setChecked(True)
+ self.rotateSettingsLayout.addWidget(self.rzAttr)
+ self.rzAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ # SCALES
+ self.scaleSettingsLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(self.scaleSettingsLayout)
+
+ self.sxAttr = QtWidgets.QCheckBox("ScaleX")
+ self.sxAttr.setChecked(True)
+ self.scaleSettingsLayout.addWidget(self.sxAttr)
+ self.sxAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ self.syAttr = QtWidgets.QCheckBox("ScaleY")
+ self.syAttr.setChecked(True)
+ self.scaleSettingsLayout.addWidget(self.syAttr)
+ self.syAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ self.szAttr = QtWidgets.QCheckBox("ScaleZ")
+ self.szAttr.setChecked(True)
+ self.scaleSettingsLayout.addWidget(self.szAttr)
+ self.szAttr.clicked.connect(partial(self.applyModuleChanges, self))
+
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding)
+ self.layout.addItem(spacerItem)
+
+ # signal slot for groupbox checkbox
+ QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible)
+ self.groupBox.setChecked(False)
+
+ # add custom attributes
+ buttonLayout = QtWidgets.QHBoxLayout()
+ self.layout.addLayout(buttonLayout)
+
+ self.addAttrBtn = QtWidgets.QPushButton("Add Custom Attribute")
+ buttonLayout.addWidget(self.addAttrBtn)
+ self.addAttrBtn.clicked.connect(self.customAttr_UI)
+
+ self.removeAttrBtn = QtWidgets.QPushButton("Remove Selected Attr")
+ buttonLayout.addWidget(self.removeAttrBtn)
+ self.removeAttrBtn.clicked.connect(self.removeCustomAttr)
+
+ self.customAttrsList = QtWidgets.QListWidget()
+ self.layout.addWidget(self.customAttrsList)
+
+ # add custom skeletonUI settings name, parent, rig types to install, mirror module, thigh twist, calf twists,
+ # ball joint, toes,
+ # add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+ # Populate the settings UI based on the network node attributes
+ self.updateSettingsUI()
+
+ # hook up combo box signals
+ self.controlShapeType.currentIndexChanged.connect(partial(self.changeControlShape))
+ self.proxyShapeType.currentIndexChanged.connect(partial(self.changeProxyGeo))
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def removeCustomAttr(self):
+
+ selected = self.customAttrsList.currentRow()
+ selectedText = json.loads(self.customAttrsList.item(selected).text())
+ self.customAttrsList.takeItem(selected)
+
+ # remove custom attr info from network node attr
+ networkNode = self.returnNetworkNode
+ newList = []
+
+ if cmds.objExists(networkNode + ".customAttrs"):
+
+ data = json.loads(cmds.getAttr(networkNode + ".customAttrs"))
+
+ if selectedText in data:
+ for each in data:
+ if each != selectedText:
+ newList.append(each)
+
+ jsonString = json.dumps(newList)
+ cmds.setAttr(networkNode + ".customAttrs", lock=False)
+ cmds.setAttr(networkNode + ".customAttrs", jsonString, type="string", lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def customAttr_UI(self):
+
+ # load stylesheet
+ styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss")
+ f = open(styleSheetFile, "r")
+ self.style = f.read()
+ f.close()
+
+ if cmds.window("pyART_customAttr_UI_Win", exists=True):
+ cmds.deleteUI("pyART_customAttr_UI_Win", wnd=True)
+
+ # create window
+ self.custAttr_mainWin = QtWidgets.QMainWindow(self.rigUiInst)
+ self.custAttr_mainWin.setMinimumSize(300, 180)
+ self.custAttr_mainWin.setMaximumSize(300, 180)
+ self.custAttr_mainWin.setWindowTitle("Add Attribute")
+ self.custAttr_mainWin.setStyleSheet(self.style)
+ self.custAttr_mainWin.setObjectName("pyART_customAttr_UI_Win")
+
+ # frame and layout
+ self.custAttr_frame = QtWidgets.QFrame()
+ self.custAttr_mainWin.setCentralWidget(self.custAttr_frame)
+
+ mainLayout = QtWidgets.QVBoxLayout(self.custAttr_frame)
+
+ # attribute name
+ nameLayout = QtWidgets.QHBoxLayout()
+ mainLayout.addLayout(nameLayout)
+
+ label = QtWidgets.QLabel("Attribute Name:")
+ label.setStyleSheet("background: transparent;")
+ nameLayout.addWidget(label)
+
+ self.custAttr_attrName = QtWidgets.QLineEdit()
+ nameLayout.addWidget(self.custAttr_attrName)
+
+ # attribute type
+ typeLayout = QtWidgets.QHBoxLayout()
+ mainLayout.addLayout(typeLayout)
+
+ label = QtWidgets.QLabel("Attribute Type:")
+ label.setStyleSheet("background: transparent;")
+ typeLayout.addWidget(label)
+
+ self.custAttr_attrType = QtWidgets.QComboBox()
+ typeLayout.addWidget(self.custAttr_attrType)
+
+ self.custAttr_attrType.addItem("Float")
+ self.custAttr_attrType.addItem("Bool")
+ self.custAttr_attrType.currentIndexChanged.connect(self.customAttr_UI_attrType)
+
+ # min/max/default
+ valueLayout = QtWidgets.QHBoxLayout()
+ mainLayout.addLayout(valueLayout)
+
+ self.custAttr_minField = QtWidgets.QLineEdit()
+ self.custAttr_minField.setPlaceholderText("Min")
+ valueLayout.addWidget(self.custAttr_minField)
+
+ self.custAttr_maxField = QtWidgets.QLineEdit()
+ self.custAttr_maxField.setPlaceholderText("Max")
+ valueLayout.addWidget(self.custAttr_maxField)
+
+ self.custAttr_defaultField = QtWidgets.QLineEdit()
+ self.custAttr_defaultField.setPlaceholderText("Default")
+ valueLayout.addWidget(self.custAttr_defaultField)
+
+ # Ok/Cancel buttons
+ buttonLayout = QtWidgets.QHBoxLayout()
+ mainLayout.addLayout(buttonLayout)
+
+ self.custAttr_AcceptBTN = QtWidgets.QPushButton("Accept")
+ buttonLayout.addWidget(self.custAttr_AcceptBTN)
+ self.custAttr_AcceptBTN.setObjectName("blueButton")
+ self.custAttr_AcceptBTN.clicked.connect(self.customAttr_UI_Accept)
+
+ self.custAttr_CancelBTN = QtWidgets.QPushButton("Cancel")
+ buttonLayout.addWidget(self.custAttr_CancelBTN)
+ self.custAttr_CancelBTN.setObjectName("blueButton")
+
+ # show window
+ self.custAttr_mainWin.show()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def customAttr_UI_attrType(self):
+
+ if self.custAttr_attrType.currentText() == "Float":
+ self.custAttr_minField.setVisible(True)
+ self.custAttr_maxField.setVisible(True)
+
+ if self.custAttr_attrType.currentText() == "Bool":
+ self.custAttr_minField.setVisible(False)
+ self.custAttr_maxField.setVisible(False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def customAttr_UI_Accept(self):
+
+ # data list
+ data = []
+ networkNode = self.returnNetworkNode
+
+ # get name
+ name = self.custAttr_attrName.text()
+ try:
+ existingData = json.loads(cmds.getAttr(networkNode + ".customAttrs"))
+
+ # double check that name is valid and doesn't already exist
+ for each in existingData:
+ if isinstance(each, list):
+ attrName = each[0]
+ if attrName == name:
+ cmds.warning("Attribute with given name already exists on this module.")
+ return
+ else:
+ attrName = existingData[0]
+ if attrName == name:
+ cmds.warning("Attribute with given name already exists on this module.")
+ return
+ except:
+ pass
+
+ data.append(name)
+
+ # get type
+ type = self.custAttr_attrType.currentText()
+ data.append(type)
+
+ if type == "Float":
+
+ # get min/max
+ minValue = self.custAttr_minField.text()
+ maxValue = self.custAttr_maxField.text()
+
+ if minValue != "" and maxValue != "":
+ # validate
+ try:
+ minValue = float(minValue)
+ maxValue = float(maxValue)
+
+ if minValue > maxValue:
+ cmds.warning("Min Value cannot be larger than the maximum value")
+ return
+
+ except:
+ cmds.warning("Min or Max contain non-integers")
+ return
+
+ data.append(minValue)
+ data.append(maxValue)
+
+ # get default
+ defaultValue = self.custAttr_defaultField.text()
+
+ try:
+ defaultValue = float(defaultValue)
+
+ if type == "Float":
+ if minValue != "" and maxValue != "":
+ if defaultValue > maxValue or defaultValue < minValue:
+ cmds.warning("Default value not in range")
+ return
+
+ if type == "Bool":
+ if defaultValue > 1 or defaultValue < 0:
+ cmds.warning("Default value must be a 0 or 1")
+ return
+ except:
+ cmds.warning("Default value is a non-integer.")
+ return
+
+ data.append(defaultValue)
+
+ # close UI
+ cmds.deleteUI("pyART_customAttr_UI_Win", wnd=True)
+
+ jsonString = json.dumps(data)
+
+ # add to list
+ self.customAttrsList.addItem(jsonString)
+
+ # add to network node, get existing value
+ newList = []
+ try:
+ existingData = json.loads(cmds.getAttr(networkNode + ".customAttrs"))
+ if len(existingData) > 0:
+ if isinstance(existingData[0], list):
+ for each in existingData:
+ newList.append(each)
+ except:
+ pass
+
+ newList.append(data)
+ jsonString = json.dumps(newList)
+ cmds.setAttr(networkNode + ".customAttrs", lock=False)
+ cmds.setAttr(networkNode + ".customAttrs", jsonString, type="string", lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addJointMoverToOutliner(self):
+
+ index = self.rigUiInst.treeWidget.topLevelItemCount()
+
+ # Add the module to the tree widget in the outliner tab of the rig creator UI
+ self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget)
+ self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name)
+ foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255))
+ self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground)
+
+ # add the buttons
+ self.createGlobalMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst)
+ self.createMeshMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst)
+
+ # create selection script job for module
+ self.updateBoneCount()
+ self.createScriptJob()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def mirrorTransformations_Custom(self):
+
+ networkNode = self.returnNetworkNode
+ mirrorModule = cmds.getAttr(networkNode + ".mirrorModule")
+ moduleName = cmds.getAttr(networkNode + ".moduleName")
+
+ for mover in [self.name + "_mover", self.name + "_mover_offset", self.name + "_mover_geo"]:
+ mirrorMover = mover.replace(moduleName, mirrorModule)
+ for attr in [".ty", ".tz", ".ry", ".rz"]:
+ value = cmds.getAttr(mirrorMover + attr)
+ cmds.setAttr(mirrorMover + attr, value * -1)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def applyModuleChanges(self, moduleInst, *args):
+
+ networkNode = self.returnNetworkNode
+
+ # translations
+ cmds.setAttr(networkNode + ".transX", lock=False)
+ cmds.setAttr(networkNode + ".transX", self.txAttr.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".transY", lock=False)
+ cmds.setAttr(networkNode + ".transY", self.tyAttr.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".transZ", lock=False)
+ cmds.setAttr(networkNode + ".transZ", self.tzAttr.isChecked(), lock=True)
+
+ # rotations
+ cmds.setAttr(networkNode + ".rotX", lock=False)
+ cmds.setAttr(networkNode + ".rotX", self.rxAttr.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".rotY", lock=False)
+ cmds.setAttr(networkNode + ".rotY", self.ryAttr.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".rotZ", lock=False)
+ cmds.setAttr(networkNode + ".rotZ", self.rzAttr.isChecked(), lock=True)
+
+ # scales
+ cmds.setAttr(networkNode + ".scaleX", lock=False)
+ cmds.setAttr(networkNode + ".scaleX", self.sxAttr.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".scaleY", lock=False)
+ cmds.setAttr(networkNode + ".scaleY", self.syAttr.isChecked(), lock=True)
+
+ cmds.setAttr(networkNode + ".scaleZ", lock=False)
+ cmds.setAttr(networkNode + ".scaleZ", self.szAttr.isChecked(), lock=True)
+
+ # dynamics
+ cmds.setAttr(networkNode + ".hasDynamics", lock=False)
+ cmds.setAttr(networkNode + ".hasDynamics", self.hasDynamics.isChecked(), lock=True)
+
+ # shapes
+ cmds.setAttr(networkNode + ".controlType", lock=False)
+ cmds.setAttr(networkNode + ".controlType", self.controlShapeType.currentIndex(), lock=True)
+
+ cmds.setAttr(networkNode + ".proxyShape", lock=False)
+ cmds.setAttr(networkNode + ".proxyShape", self.proxyShapeType.currentIndex(), lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateSettingsUI(self):
+
+ cmds.refresh(force=True)
+ networkNode = self.returnNetworkNode
+
+ # shapes
+ controlShape = cmds.getAttr(networkNode + ".controlType")
+ self.controlShapeType.setCurrentIndex(controlShape)
+
+ proxyShape = cmds.getAttr(networkNode + ".proxyShape")
+ self.proxyShapeType.setCurrentIndex(proxyShape)
+
+ # transformations
+ self.txAttr.setChecked(cmds.getAttr(networkNode + ".transX"))
+ self.tyAttr.setChecked(cmds.getAttr(networkNode + ".transY"))
+ self.tzAttr.setChecked(cmds.getAttr(networkNode + ".transZ"))
+
+ self.rxAttr.setChecked(cmds.getAttr(networkNode + ".rotX"))
+ self.ryAttr.setChecked(cmds.getAttr(networkNode + ".rotY"))
+ self.rzAttr.setChecked(cmds.getAttr(networkNode + ".rotZ"))
+
+ self.sxAttr.setChecked(cmds.getAttr(networkNode + ".scaleX"))
+ self.syAttr.setChecked(cmds.getAttr(networkNode + ".scaleY"))
+ self.szAttr.setChecked(cmds.getAttr(networkNode + ".scaleZ"))
+
+ # has dynamics
+ self.hasDynamics.setChecked(cmds.getAttr(networkNode + ".hasDynamics"))
+
+ # custom attrs
+ self.customAttrsList.clear()
+ try:
+ data = json.loads(cmds.getAttr(networkNode + ".customAttrs"))
+
+ if isinstance(data[0], list):
+ for each in data:
+ jsonString = json.dumps(each)
+ self.customAttrsList.addItem(jsonString)
+ else:
+ jsonString = json.dumps(data)
+ self.customAttrsList.addItem(jsonString)
+ except:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def changeProxyGeo(self, *args):
+
+ currentSelection = cmds.ls(sl=True)
+
+ # get new proxy geo value from comboBox
+ newShape = self.proxyShapeType.currentText()
+
+ # construct the path
+ path = os.path.join(self.toolsPath, "Core/JointMover/controls/")
+ fullPath = os.path.join(path, "proxy_" + newShape + ".ma")
+ fullPath = utils.returnFriendlyPath(fullPath)
+
+ # import the file
+ cmds.file(fullPath, i=True, iv=True, type="mayaAscii", rnn=True)
+
+ # 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)
+
+ # parent under mover_geo
+ cmds.parent("proxy_geo", self.name + "_mover_geo", r=True)
+
+ # delete old proxy geo
+ cmds.delete(self.name + "_proxy_geo")
+ proxy = cmds.rename("proxy_geo", self.name + "_proxy_geo")
+
+ cmds.setAttr(proxy + ".overrideEnabled", True, lock=True)
+ cmds.setAttr(proxy + ".overrideDisplayType", 2)
+
+ # apply module changes
+ self.applyModuleChanges(self)
+
+ # re-select selection
+ cmds.select(currentSelection)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def changeControlShape(self, *args):
+
+ currentSelection = cmds.ls(sl=True)
+
+ # get new proxy geo value from comboBox
+ newShape = self.controlShapeType.currentText()
+
+ # construct the path
+ path = os.path.join(self.toolsPath, "Core/JointMover/controls/")
+ fullPath = os.path.join(path, "shape_" + newShape + ".ma")
+ fullPath = utils.returnFriendlyPath(fullPath)
+
+ # import the file
+ cmds.file(fullPath, i=True, iv=True, type="mayaAscii", rnn=True)
+
+ # replace the shape node of each mover with the new ones from the file
+ for mover in ["_mover", "_mover_offset", "_mover_geo"]:
+ newMoverShape = cmds.listRelatives("shape_curve" + mover, children=True)[0]
+
+ cmds.parent(newMoverShape, self.name + mover, r=True, shape=True)
+ cmds.delete(self.name + mover + "Shape")
+ cmds.rename(newMoverShape, self.name + mover + "Shape")
+
+ cmds.delete("shape_curve" + mover)
+
+ # refresh UI to capture new mover shapes and set thier visibility
+ self.rigUiInst.setMoverVisibility()
+
+ # apply module changes
+ self.applyModuleChanges(self)
+
+ # re-select selection
+ cmds.select(currentSelection)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pinModule(self, state):
+
+ networkNode = self.returnNetworkNode
+ topLevelMover = self.name + "_mover"
+
+ if state:
+
+ loc = cmds.spaceLocator()[0]
+ cmds.setAttr(loc + ".v", False, lock=True)
+ constraint = cmds.parentConstraint(topLevelMover, loc)[0]
+ cmds.delete(constraint)
+ const = cmds.parentConstraint(loc, topLevelMover)[0]
+ attrs = cmds.listAttr(topLevelMover, keyable=True)
+
+ for attr in attrs:
+ try:
+ cmds.setAttr(topLevelMover + "." + attr, keyable=False, lock=True)
+ except:
+ pass
+ if not cmds.objExists(networkNode + ".pinConstraint"):
+ cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message")
+
+ cmds.connectAttr(const + ".message", networkNode + ".pinConstraint")
+
+ if not state:
+ attrs = cmds.listAttr(topLevelMover, keyable=True)
+ for attr in attrs:
+ try:
+ cmds.setAttr(topLevelMover + "." + attr, lock=True)
+ except:
+ pass
+
+ connections = cmds.listConnections(networkNode + ".pinConstraint")
+ if len(connections) > 0:
+ constraint = connections[0]
+ cmds.delete(constraint)
+
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skinProxyGeo(self):
+
+ # get the network node
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ # get this module's proxy geo meshes
+ cmds.select(name + "_mover_grp", hi=True)
+ proxyGeoMeshes = []
+ selection = cmds.ls(sl=True)
+ for each in selection:
+ if each.find("proxy_geo") != -1:
+ parent = cmds.listRelatives(each, parent=True)[0]
+ if cmds.nodeType(each) == "transform":
+ proxyGeoMeshes.append(each)
+
+ # skin the proxy geo meshes
+ for mesh in proxyGeoMeshes:
+ dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0]
+ cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False)
+ cmds.setAttr(dupeMesh + ".overrideDisplayType", 0)
+
+ # create skinned geo group
+ if not cmds.objExists("skinned_proxy_geo"):
+ cmds.group(empty=True, name="skinned_proxy_geo")
+
+ cmds.parent(dupeMesh, "skinned_proxy_geo")
+
+ boneName = mesh.partition(name + "_")[2]
+ boneName = boneName.partition("_proxy_geo")[0]
+ joint = name
+
+ if not cmds.objExists(joint):
+ cmds.delete(dupeMesh)
+
+ else:
+ cmds.select([dupeMesh, joint])
+ cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0,
+ normalizeWeights=True)
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRigCustom(self, textEdit, uiInst):
+
+ if textEdit is not None:
+ textEdit.append(" Building " + self.name + " Rig..")
+
+ # get the created joint
+ networkNode = self.returnNetworkNode
+ joint = cmds.getAttr(networkNode + ".Created_Bones")
+ joint = joint.replace("::", "")
+ globalMover = joint + "_mover"
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+
+ # determine the rigs to be built
+ numRigs = 1
+ if cmds.getAttr(networkNode + ".hasDynamics"):
+ numRigs += 1
+
+ builtRigs = []
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create groups and settings
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create the rig group
+ self.rigGrp = cmds.group(empty=True, name=self.name + "_group")
+ constraint = cmds.parentConstraint(globalMover, self.rigGrp)[0]
+ cmds.delete(constraint)
+
+ # create the rig settings group
+ self.rigSettings = cmds.group(empty=True, name=self.name + "_settings")
+ cmds.parent(self.rigSettings, self.rigGrp)
+ for attr in (cmds.listAttr(self.rigSettings, keyable=True)):
+ cmds.setAttr(self.rigSettings + "." + attr, lock=True, keyable=False)
+
+ # add mode attribute to settings
+ cmds.addAttr(self.rigSettings, ln="mode", min=0, max=numRigs - 1, dv=0, keyable=True)
+
+ # create the ctrl group (what will get the constraint to the parent)
+ self.rigCtrlGrp = cmds.group(empty=True, name=self.name + "_ctrl_grp")
+ constraint = cmds.parentConstraint(parentBone, self.rigCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(self.rigCtrlGrp, self.rigGrp)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # build the rigs
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # FK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # find the mover, duplicate it to create the rig control
+ dupe = cmds.duplicate(globalMover, rr=True)[0]
+ utils.deleteChildren(dupe)
+ parent = cmds.listRelatives(dupe, parent=True)
+ if parent is not None:
+ cmds.parent(dupe, world=True)
+
+ # turn on visiblity of the control
+ cmds.setAttr(dupe + ".v", 1)
+
+ # ensure pivot is correct
+ piv = cmds.xform(joint, q=True, ws=True, rp=True)
+ cmds.xform(dupe, ws=True, rp=piv)
+
+ # rename the control
+ fkControl = cmds.rename(dupe, joint + "_anim")
+
+ # create an anim group for the control
+ controlGrp = cmds.group(empty=True, name=joint + "_anim_grp")
+ constraint = cmds.parentConstraint(joint, controlGrp)[0]
+ cmds.delete(constraint)
+
+ # create the space switcher group
+ spaceSwitchFollow = cmds.duplicate(controlGrp, po=True, name=fkControl + "_space_switcher_follow")[0]
+ spaceSwitch = cmds.duplicate(controlGrp, po=True, name=fkControl + "_space_switcher")[0]
+
+ utils.deleteChildren(spaceSwitchFollow)
+ utils.deleteChildren(spaceSwitch)
+
+ cmds.parent(spaceSwitch, spaceSwitchFollow)
+ cmds.parent(controlGrp, spaceSwitch)
+
+ # parent the control under the controlGrp
+ cmds.parent(fkControl, controlGrp)
+ cmds.parent(spaceSwitchFollow, self.rigCtrlGrp)
+
+ # freeze transformations on the control
+ cmds.makeIdentity(fkControl, t=1, r=1, s=1, apply=True)
+
+ # color the control
+ cmds.setAttr(fkControl + ".overrideEnabled", 1)
+ cmds.setAttr(fkControl + ".overrideColor", 18)
+
+ # constrain joint
+ cmds.parentConstraint(fkControl, "driver_" + joint)
+ cmds.scaleConstraint(fkControl, "driver_" + joint)
+
+ # parent under offset_anim if it exists(it always should)
+ if cmds.objExists("offset_anim"):
+ cmds.parent(self.rigGrp, "offset_anim")
+
+ # check settings and lock attributes that need locking
+ if not cmds.getAttr(networkNode + ".transX"):
+ cmds.setAttr(fkControl + ".tx", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".transY"):
+ cmds.setAttr(fkControl + ".ty", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".transZ"):
+ cmds.setAttr(fkControl + ".tz", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".rotX"):
+ cmds.setAttr(fkControl + ".rx", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".rotY"):
+ cmds.setAttr(fkControl + ".ry", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".rotZ"):
+ cmds.setAttr(fkControl + ".rz", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".scaleX"):
+ cmds.setAttr(fkControl + ".sx", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".scaleY"):
+ cmds.setAttr(fkControl + ".sy", lock=True, keyable=False)
+
+ if not cmds.getAttr(networkNode + ".scaleZ"):
+ cmds.setAttr(fkControl + ".sz", lock=True, keyable=False)
+
+ # lock visibility regardless
+ cmds.setAttr(fkControl + ".v", lock=True, keyable=False)
+
+ # check for custom attributes and add them if they exist
+ try:
+ data = json.loads(cmds.getAttr(networkNode + ".customAttrs"))
+ print data
+ for each in data:
+ attrName = each[0]
+ attrType = each[1]
+
+ if attrType == "Bool":
+ value = each[2]
+
+ if not cmds.objExists(fkControl + "." + attrName):
+ cmds.addAttr(fkControl, ln=attrName, at="bool", keyable=True, dv=value)
+
+ if attrType == "Float":
+ minVal = each[2]
+ maxVal = each[3]
+ hasMin = True
+ hasMax = True
+
+ if minVal == '':
+ hasMin = False
+ minVal = 0
+
+ if maxVal == '':
+ hasMax = False
+ maxVal = 0
+
+ if not cmds.objExists(fkControl + "." + attrName):
+
+ if hasMin is False and hasMax is False:
+ cmds.addAttr(fkControl, ln=attrName, at="float", keyable=True, dv=float(each[4]))
+ if hasMin is False and hasMax is True:
+ cmds.addAttr(fkControl, ln=attrName, at="float", keyable=True, max=float(maxVal),
+ dv=float(each[4]))
+ if hasMin is True and hasMax is False:
+ cmds.addAttr(fkControl, ln=attrName, at="float", keyable=True, min=float(minVal),
+ dv=float(each[4]))
+
+ except Exception, e:
+ print e
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Dynamics # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ if cmds.getAttr(networkNode + ".hasDynamics"):
+ cubeGrp = cmds.group(empty=True, name=self.name + "_dyn_grp")
+ const = cmds.parentConstraint(joint, cubeGrp)[0]
+ cmds.delete(const)
+ cmds.parent(cubeGrp, self.rigGrp)
+
+ # make grp pivot same as parent bone
+ piv = cmds.xform(parentBone, q=True, ws=True, rp=True)
+ cmds.xform(cubeGrp, ws=True, piv=piv)
+ cmds.parentConstraint("driver_" + parentBone, cubeGrp, mo=True)
+
+ # creation: cube rigid body in same spot as leaf joint
+ self.rigidCube = cmds.polyCube(name=self.name + "_dyn_obj")[0]
+ const = cmds.parentConstraint(joint, self.rigidCube)[0]
+ cmds.delete(const)
+
+ cmds.setAttr(self.rigidCube + ".v", 0, lock=True)
+ cmds.parent(self.rigidCube, cubeGrp)
+ cmds.makeIdentity(self.rigidCube, t=1, r=1, s=1, apply=True)
+
+ # usually this is done automatically, but for some reason, this damn cube would not add the attr
+ # properly in the loop. so..hax
+ cmds.addAttr(self.rigidCube, ln="sourceModule", dt="string")
+
+ # create the rigid body
+ cmds.select(self.rigidCube)
+ rigidBody = cmds.rigidBody(act=True, m=1, damping=0.1, staticFriction=0.2, dynamicFriction=0.2,
+ bounciness=0.6, layer=0, tesselationFactor=200)
+
+ # create the spring constraint
+ cmds.select(self.rigidCube)
+ spring = cmds.constrain(spring=True, stiffness=100, damping=1.0, i=0)
+ cmds.refresh(force=True)
+ cmds.setAttr(spring + ".v", 0, lock=True)
+
+ # position spring
+ pos = cmds.xform(joint, q=True, ws=True, t=True)
+
+ cmds.setAttr(spring + ".translateX", pos[0])
+ cmds.setAttr(spring + ".translateY", pos[1])
+ cmds.setAttr(spring + ".translateZ", pos[2])
+ cmds.refresh(force=True)
+
+ cmds.parent(spring, "driver_" + parentBone)
+
+ # create a group that is point constrained to the cube, but orient constrained to the parent bone
+ tracker = cmds.group(empty=True, name=self.name + "_dyn_tracker")
+ const = cmds.parentConstraint(joint, tracker)[0]
+ cmds.delete(const)
+
+ cmds.parent(tracker, self.rigGrp)
+ cmds.pointConstraint(self.rigidCube, tracker)
+ orientConst = cmds.orientConstraint("driver_" + parentBone, tracker, mo=True)[0]
+
+ # constrain joint
+ cmds.parentConstraint(tracker, "driver_" + joint)
+ cmds.scaleConstraint(tracker, "driver_" + joint)
+
+ # add relevant settings to the settings node
+ cmds.addAttr(self.rigSettings, ln="mass", keyable=True, dv=1)
+ cmds.addAttr(self.rigSettings, ln="bounciness", keyable=True, dv=0.6, min=0, max=2)
+ cmds.addAttr(self.rigSettings, ln="damping", keyable=True, dv=0.97, min=-10, max=10)
+ cmds.addAttr(self.rigSettings, ln="springDamping", keyable=True, dv=1.0, min=-10, max=10)
+ cmds.addAttr(self.rigSettings, ln="springStiffness", keyable=True, dv=500, min=0)
+ cmds.addAttr(self.rigSettings, ln="orientToParent", keyable=True, dv=1, min=0, max=1)
+
+ # then hook them up
+ cmds.connectAttr(self.rigSettings + ".mass", rigidBody + ".mass")
+ cmds.connectAttr(self.rigSettings + ".bounciness", rigidBody + ".bounciness")
+ cmds.connectAttr(self.rigSettings + ".damping", rigidBody + ".damping")
+ cmds.connectAttr(self.rigSettings + ".springStiffness", spring + ".springStiffness")
+ cmds.connectAttr(self.rigSettings + ".springDamping", spring + ".springDamping")
+ cmds.connectAttr(self.rigSettings + ".orientToParent", orientConst + ".driver_" + parentBone + "W0")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # SETTINGS # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # mode
+ if numRigs > 1:
+ attrData = []
+
+ """ CONSTRAINTS """
+ # get the constraint connections on the driver joints for the leaf
+ connections = []
+ connections.extend(list(set(cmds.listConnections("driver_" + joint, type="constraint"))))
+
+ for connection in connections:
+ driveAttrs = []
+
+ if cmds.nodeType(connection) in ["parentConstraint", "scaleConstraint"]:
+
+ # get those constraint target attributes for each constraint connection
+ targets = cmds.getAttr(connection + ".target", mi=True)
+ if len(targets) > 1:
+ for each in targets:
+ driveAttrs.append(
+ cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p=True))
+
+ # add this data to our master list of constraint attribute data
+ attrData.append(driveAttrs)
+
+ # setup set driven keys on our moder attr and those target attributes
+ for i in range(numRigs):
+ cmds.setAttr(self.rigSettings + ".mode", i)
+
+ # go through attr data and zero out anything but the first element in the list
+ for data in attrData:
+ for each in data:
+ cmds.setAttr(each[0], 0)
+
+ cmds.setAttr(data[i][0], 1)
+
+ # set driven keys
+ for data in attrData:
+ for each in data:
+ cmds.setDrivenKeyframe(each[0], cd=self.rigSettings + ".mode", itt="linear", ott="linear")
+
+ # hook up control visibility
+ cmds.setAttr(self.rigSettings + ".mode", 0)
+ cmds.setAttr(controlGrp + ".v", 1)
+ cmds.setDrivenKeyframe(controlGrp, at="visibility", cd=self.rigSettings + ".mode", itt="linear",
+ ott="linear")
+
+ cmds.setAttr(self.rigSettings + ".mode", 1)
+ cmds.setAttr(controlGrp + ".v", 0)
+ cmds.setDrivenKeyframe(controlGrp, at="visibility", cd=self.rigSettings + ".mode", itt="linear",
+ ott="linear")
+
+ cmds.setAttr(self.rigSettings + ".mode", 0)
+
+ controls = [fkControl]
+ if not cmds.objExists(networkNode + ".leafControls"):
+ cmds.addAttr(networkNode, ln="leafControls", dt="string")
+ jsonString = json.dumps(controls)
+ cmds.setAttr(networkNode + ".leafControls", jsonString, type="string")
+
+ # return data
+ try:
+ uiInst.rigData.append([self.rigCtrlGrp, "driver_" + parentBone, numRigs])
+
+ except:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pickerUI(self, center, animUI, networkNode, namespace):
+
+ # create qBrushes
+ blueBrush = QtGui.QColor(100, 220, 255)
+ clearBrush = QtGui.QBrush(QtCore.Qt.black)
+ clearBrush.setStyle(QtCore.Qt.NoBrush)
+
+ # create border item
+ if networkNode.find(":") != -1:
+ moduleNode = networkNode.partition(":")[2]
+ else:
+ moduleNode = networkNode
+ borderItem = interfaceUtils.pickerBorderItem(center.x() - 40, center.y() - 70, 50, 50, clearBrush, moduleNode)
+
+ # get controls
+ networkNode = self.returnNetworkNode
+ controls = json.loads(cmds.getAttr(networkNode + ".leafControls"))
+
+ # anim button
+ button = interfaceUtils.pickerButton(30, 30, [10, 2], namespace + controls[0], blueBrush, borderItem)
+ button.setToolTip(self.name)
+
+ # add right click menu to select settings
+ fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png"))))
+ button.menu.addAction(fkIcon, "Settings", partial(self.selectSettings, namespace))
+ button.menu.addAction("Change Button Color", partial(self.changeButtonColor, animUI, button, borderItem,
+ namespace + controls[0]))
+
+ # =======================================================================
+ # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5)
+ # =======================================================================
+ scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI,
+ [[button, namespace + controls[0], blueBrush]])],
+ kws=True)
+
+ borderItem.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ return [borderItem, False, scriptJob]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def changeButtonColor(self, animUI, button, border, control, color=None):
+ """
+ Leaf joints give the user the option to change the button's color. This function will remove the existing
+ scriptJob, set the new button color, and create a new scriptJob with that information.
+
+ :param animUI: The animation UI instance
+ :param button: The button whose color we wish to set.
+ :param border: The border item of the button that holds the scriptJob number to kill
+ :param control: The control this button selects.
+ """
+ print color, control
+ # launch a color dialog to get a new color
+ if color is None:
+ newColor = QtGui.QColorDialog.getColor()
+ else:
+ newColor = color
+
+ # delete the existing scriptJob
+ scriptJob = border.data(5)
+ cmds.scriptJob(kill=scriptJob)
+ animUI.selectionScriptJobs.remove(scriptJob)
+
+ # set the button color
+ button.brush.setColor(newColor)
+
+ # create the new scriptJob
+ scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI,
+ [[button, control, newColor]])],
+ kws=True)
+ border.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def selectSettings(self, namespace):
+
+ cmds.select(namespace + self.name + "_settings")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pasteSettings(self):
+
+ # this shit right here is so hacky. For some reason, paste and reset have to run multiple times to get
+ # everything
+ # and I haven't taken the time to figure out why
+ 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]
+ attrType = str(cmds.getAttr(networkNode + "." + attr, type=True))
+
+ if attrType != "string":
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ cmds.setAttr(networkNode + "." + attr, value, lock=True)
+
+ if attr == "customAttrs":
+ cmds.setAttr(networkNode + "." + attr, lock=False)
+ try:
+ cmds.setAttr(networkNode + "." + attr, value, type="string", lock=True)
+ except:
+ pass
+
+ # relaunch the UI
+ self.updateSettingsUI()
+ self.applyModuleChanges(self)
+ else:
+ cmds.warning("No data in clipboard")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX(self, importMethod, character):
+
+ returnControls = []
+
+ networkNode = self.returnRigNetworkNode
+ control = json.loads(cmds.getAttr(networkNode + ".leafControls"))
+ joints = cmds.getAttr(networkNode + ".Created_Bones")
+ joint = joints.partition("::")[0]
+
+ if importMethod == "FK":
+ cmds.parentConstraint(joint, character + ":" + control[0])
+ returnControls.append(character + ":" + control[0])
+
+ if importMethod == "None":
+ pass
+
+ return returnControls
diff --git a/Core/Scripts/RigModules/ART_Leg_Standard.py b/Core/Scripts/RigModules/ART_Leg_Standard.py
new file mode 100644
index 0000000..75db728
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Leg_Standard.py
@@ -0,0 +1,3758 @@
+import maya.cmds as cmds
+import os, time, json, weakref
+from functools import partial
+
+
+from System.ART_RigModule import ART_RigModule
+from System import mathUtils
+from System import utils
+from System import riggingUtils
+import System.interfaceUtils as interfaceUtils
+
+
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+
+#file attributes
+icon = "Modules/legStandard.png"
+hoverIcon = "Modules/hover_legStandard.png"
+search = "biped:leg"
+className = "ART_Leg_Standard"
+jointMover = "Core/JointMover/ART_Leg_Standard.ma"
+baseName = "leg"
+rigs = ["FK::IK"]
+fbxImport = ["None", "FK", "IK", "Both"]
+matchData = [True, ["Match FK to IK", "Match IK to FK"]]
+controlTypes = [["fkControls", "FK"], ["ikV1Controls", "IK"], ["thighTwistControls", "FK"], ["calfTwistControls", "FK"], ["toeControls", "FK"]]
+
+#begin class
+class ART_Leg_Standard(ART_RigModule):
+
+ _instances = set()
+
+ def __init__(self, rigUiInst, moduleUserName):
+
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+
+
+ self.__class__._instances.add(weakref.ref(self))
+
+
+ ART_RigModule.__init__(self, "ART_Leg_Standard_Module", "ART_Leg_Standard", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ #call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ #add custom attributes for this specific module
+ cmds.addAttr(self.networkNode, sn = "Created_Bones", dt = "string", keyable = False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", "thigh::calf::foot::ball::", type = "string", lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "baseName", dt = "string", keyable = False)
+ cmds.setAttr(self.networkNode + ".baseName", baseName , type = "string", lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "canAim", at = "bool", keyable = False)
+ cmds.setAttr(self.networkNode + ".canAim", True, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "aimMode", at = "bool", keyable = False)
+ cmds.setAttr(self.networkNode + ".aimMode", False, lock = True)
+
+ #joint mover settings
+ cmds.addAttr(self.networkNode, sn = "thighTwists", keyable = False)
+ cmds.setAttr(self.networkNode + ".thighTwists", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "calfTwists", keyable = False)
+ cmds.setAttr(self.networkNode + ".calfTwists", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "bigToeJoints", keyable = False)
+ cmds.setAttr(self.networkNode + ".bigToeJoints", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "bigToeMeta", keyable = False, at = "bool")
+ cmds.setAttr(self.networkNode + ".bigToeMeta", False, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "indexToeJoints", keyable = False)
+ cmds.setAttr(self.networkNode + ".indexToeJoints", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "indexToeMeta", keyable = False, at = "bool")
+ cmds.setAttr(self.networkNode + ".indexToeMeta", False, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "middleToeJoints", keyable = False)
+ cmds.setAttr(self.networkNode + ".middleToeJoints", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "middleToeMeta", keyable = False, at = "bool")
+ cmds.setAttr(self.networkNode + ".middleToeMeta", False, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "ringToeJoints", keyable = False)
+ cmds.setAttr(self.networkNode + ".ringToeJoints", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "ringToeMeta", keyable = False, at = "bool")
+ cmds.setAttr(self.networkNode + ".ringToeMeta", False, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "pinkyToeJoints", keyable = False)
+ cmds.setAttr(self.networkNode + ".pinkyToeJoints", 0, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "pinkyToeMeta", keyable = False, at = "bool")
+ cmds.setAttr(self.networkNode + ".pinkyToeMeta", False, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "includeBall", at = "bool", keyable = False)
+ cmds.setAttr(self.networkNode + ".includeBall", True, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "side", dt = "string", keyable = False)
+ cmds.setAttr(self.networkNode + ".side", "Left", type = "string", lock = True)
+
+ #rig creation settings
+ cmds.addAttr(self.networkNode, sn = "buildFK", at = "bool", keyable = False)
+ cmds.setAttr(self.networkNode + ".buildFK", True, lock = True)
+
+ cmds.addAttr(self.networkNode, sn = "buildIK_V1", at = "bool", keyable = False)
+ cmds.setAttr(self.networkNode + ".buildIK_V1", True, lock = True)
+
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+ networkNode = self.returnNetworkNode
+
+ #groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 480, True)
+
+ font = QtGui.QFont()
+ font.setPointSize(8)
+
+ headerFont = QtGui.QFont()
+ headerFont.setPointSize(8)
+ headerFont.setBold(True)
+
+
+ #create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot
+ self.layout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.frame = QtWidgets.QFrame(self.groupBox)
+ self.layout.addWidget(self.frame)
+
+ self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.frame.setMinimumSize(QtCore.QSize(320, 445))
+ self.frame.setMaximumSize(QtCore.QSize(320, 445))
+
+
+ #add layout for custom settings
+ self.customSettingsLayout = QtWidgets.QVBoxLayout(self.frame)
+
+ #mirror module
+ self.mirrorModLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.mirrorModLayout)
+ self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ")
+ self.mirrorModuleLabel.setFont(font)
+ self.mirrorModLayout.addWidget(self.mirrorModuleLabel)
+
+ mirror = cmds.getAttr(networkNode +".mirrorModule")
+ if mirror == "":
+ mirror = "None"
+ self.mirrorMod = QtWidgets.QLabel(mirror)
+ self.mirrorMod.setFont(font)
+ self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter)
+ self.mirrorModLayout.addWidget(self.mirrorMod)
+
+ spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ #current parent
+ self.currentParentMod = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.currentParentMod)
+ self.currentParentLabel = QtWidgets.QLabel("Current Parent: ")
+ self.currentParentLabel.setFont(font)
+ self.currentParentMod.addWidget(self.currentParentLabel)
+
+ parent = cmds.getAttr(networkNode +".parentModuleBone")
+ self.currentParent = QtWidgets.QLabel(parent)
+ self.currentParent.setFont(font)
+ self.currentParent.setAlignment(QtCore.Qt.AlignHCenter)
+ self.currentParentMod.addWidget(self.currentParent)
+
+
+ #button layout for name/parent
+ self.buttonLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.buttonLayout)
+ self.changeNameBtn = QtWidgets.QPushButton("Change Name")
+ self.changeParentBtn = QtWidgets.QPushButton("Change Parent")
+ self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module")
+ self.buttonLayout.addWidget(self.changeNameBtn)
+ self.buttonLayout.addWidget(self.changeParentBtn)
+ self.buttonLayout.addWidget(self.mirrorModuleBtn)
+ self.changeNameBtn.setObjectName("blueButton")
+ self.changeParentBtn.setObjectName("blueButton")
+ self.mirrorModuleBtn.setObjectName("blueButton")
+
+ spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ #add side settings
+ self.sideLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.sideLayout)
+ self.sideLabel = QtWidgets.QLabel("Side: ")
+ self.sideLabel.setFont(font)
+ self.leftSideBtn = QtWidgets.QRadioButton("Left Side")
+ self.rightSideBtn = QtWidgets.QRadioButton("Right Side")
+ self.sideLayout.addWidget(self.sideLabel)
+ self.sideLayout.addWidget(self.leftSideBtn)
+ self.sideLayout.addWidget(self.rightSideBtn)
+
+ #get current side
+ if cmds.getAttr(networkNode + ".side") == "Left":
+ self.leftSideBtn.setChecked(True)
+ if cmds.getAttr(networkNode + ".side") == "Right":
+ self.rightSideBtn.setChecked(True)
+
+ self.leftSideBtn.clicked.connect(self.changeSide)
+ self.rightSideBtn.clicked.connect(self.changeSide)
+
+ spacerItem = QtWidgets.QSpacerItem(20, 80, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.customSettingsLayout.addItem(spacerItem)
+
+
+ #coplanar mode and bake offsets layout
+ self.legToolsLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.legToolsLayout)
+
+ #Coplanar mode
+ self.coplanarBtn = QtWidgets.QPushButton("Coplanar Mode")
+ self.coplanarBtn.setFont(headerFont)
+ self.legToolsLayout.addWidget(self.coplanarBtn)
+ self.coplanarBtn.setCheckable(True)
+ self.coplanarBtn.clicked.connect(self.coplanarMode)
+ self.coplanarBtn.setToolTip("[EXPERIMENTAL] Forces leg joints to always be planar for best IK setup")
+
+ #Bake OFfsets
+ self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets")
+ self.bakeOffsetsBtn.setFont(headerFont)
+ self.legToolsLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync")
+
+ self.coplanarBtn.setObjectName("blueButton")
+ self.bakeOffsetsBtn.setObjectName("blueButton")
+
+ #Twist Bones Section
+ self.twistSettingsLabel = QtWidgets.QLabel("Twist Bone Settings: ")
+ self.twistSettingsLabel.setFont(headerFont)
+ self.twistSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);")
+ self.customSettingsLayout.addWidget(self.twistSettingsLabel)
+
+ self.separatorA = QtWidgets.QFrame()
+ self.separatorA.setFrameShape(QtWidgets.QFrame.HLine)
+ self.separatorA.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.customSettingsLayout.addWidget(self.separatorA)
+
+ #twist bones HBoxLayout
+ self.twistBonesLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.twistBonesLayout)
+
+ self.twistForm = QtWidgets.QFormLayout()
+ self.thighTwistLabel = QtWidgets.QLabel("Thigh Twists: ")
+ self.thighTwistLabel.setFont(font)
+ self.twistForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.thighTwistLabel)
+ self.thighTwistNum = QtWidgets.QSpinBox()
+ self.thighTwistNum.setMaximum(3)
+ self.twistForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.thighTwistNum)
+ self.twistBonesLayout.addLayout(self.twistForm)
+
+
+ self.calfForm = QtWidgets.QFormLayout()
+ self.calfTwistLabel = QtWidgets.QLabel("Calf Twists: ")
+ self.calfTwistLabel.setFont(font)
+ self.calfForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.calfTwistLabel)
+ self.calfTwistNum = QtWidgets.QSpinBox()
+ self.calfTwistNum.setMaximum(3)
+ self.calfForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.calfTwistNum)
+ self.twistBonesLayout.addLayout(self.calfForm)
+
+
+ spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ #Feet Settings Section
+ self.feetSettingsLabel = QtWidgets.QLabel("Foot Settings: ")
+ self.feetSettingsLabel.setFont(headerFont)
+ self.feetSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);")
+ self.customSettingsLayout.addWidget(self.feetSettingsLabel)
+
+ self.separatorB = QtWidgets.QFrame()
+ self.separatorB.setFrameShape(QtWidgets.QFrame.HLine)
+ self.separatorB.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.customSettingsLayout.addWidget(self.separatorB)
+
+
+ self.ballJoint = QtWidgets.QCheckBox("Include Ball Joint?")
+ self.ballJoint.setChecked(True)
+ self.customSettingsLayout.addWidget(self.ballJoint)
+
+
+ #Toe Settings: add VBoxLayout
+ self.toeVBoxLayout = QtWidgets.QVBoxLayout()
+ self.customSettingsLayout.addLayout(self.toeVBoxLayout)
+
+ #BIG TOE
+ self.bigToeLayout = QtWidgets.QHBoxLayout()
+
+ self.bigToeLabel = QtWidgets.QLabel("Big Toe Joints: ")
+ self.bigToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.bigToeLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.bigToeLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.bigToeLayout.addWidget((self.bigToeLabel))
+
+
+ self.bigToeNum = QtWidgets.QSpinBox()
+ self.bigToeNum.setMaximum(2)
+ self.bigToeNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.bigToeNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.bigToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.bigToeLayout.addWidget(self.bigToeNum)
+
+ self.bigToeMeta = QtWidgets.QCheckBox("Include Metatarsal")
+ self.bigToeLayout.addWidget(self.bigToeMeta)
+ self.toeVBoxLayout.addLayout(self.bigToeLayout)
+
+
+
+ #INDEX TOE
+ self.indexToeLayout = QtWidgets.QHBoxLayout()
+
+ self.indexToeLabel = QtWidgets.QLabel("Index Toe Joints: ")
+ self.indexToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.indexToeLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.indexToeLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.indexToeLayout.addWidget((self.indexToeLabel))
+
+ self.indexToeNum = QtWidgets.QSpinBox()
+ self.indexToeNum.setMaximum(3)
+ self.indexToeNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.indexToeNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.indexToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.indexToeLayout.addWidget((self.indexToeNum))
+
+ self.indexToeMeta = QtWidgets.QCheckBox("Include Metatarsal")
+ self.indexToeLayout.addWidget(self.indexToeMeta)
+ self.toeVBoxLayout.addLayout(self.indexToeLayout)
+
+ #MIDDLE TOE
+ self.middleToeLayout = QtWidgets.QHBoxLayout()
+
+ self.middleToeLabel = QtWidgets.QLabel("Middle Toe Joints: ")
+ self.middleToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.middleToeLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.middleToeLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.middleToeLayout.addWidget(self.middleToeLabel)
+
+ self.middleToeNum = QtWidgets.QSpinBox()
+ self.middleToeNum.setMaximum(3)
+ self.middleToeNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.middleToeNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.middleToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.middleToeLayout.addWidget(self.middleToeNum)
+
+ self.middleToeMeta = QtWidgets.QCheckBox("Include Metatarsal")
+ self.middleToeLayout.addWidget(self.middleToeMeta)
+ self.toeVBoxLayout.addLayout(self.middleToeLayout)
+
+ #RING TOE
+ self.ringToeLayout = QtWidgets.QHBoxLayout()
+
+ self.ringToeLabel = QtWidgets.QLabel("Ring Toe Joints: ")
+ self.ringToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.ringToeLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.ringToeLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.ringToeLayout.addWidget(self.ringToeLabel)
+
+ self.ringToeNum = QtWidgets.QSpinBox()
+ self.ringToeNum.setMaximum(3)
+ self.ringToeNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.ringToeNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.ringToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.ringToeLayout.addWidget(self.ringToeNum)
+
+ self.ringToeMeta = QtWidgets.QCheckBox("Include Metatarsal")
+ self.ringToeLayout.addWidget(self.ringToeMeta)
+ self.toeVBoxLayout.addLayout(self.ringToeLayout)
+
+
+ #PINKY TOE
+ self.pinkyToeLayout = QtWidgets.QHBoxLayout()
+
+ self.pinkyToeLabel = QtWidgets.QLabel("Pinky Toe Joints: ")
+ self.pinkyToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.pinkyToeLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.pinkyToeLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.pinkyToeLayout.addWidget(self.pinkyToeLabel)
+
+ self.pinkyToeNum = QtWidgets.QSpinBox()
+ self.pinkyToeNum.setMaximum(3)
+ self.pinkyToeNum.setMinimumSize(QtCore.QSize(50, 20))
+ self.pinkyToeNum.setMaximumSize(QtCore.QSize(50, 20))
+ self.pinkyToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.pinkyToeLayout.addWidget(self.pinkyToeNum)
+
+ self.pinkyToeMeta = QtWidgets.QCheckBox("Include Metatarsal")
+ self.pinkyToeLayout.addWidget(self.pinkyToeMeta)
+ self.toeVBoxLayout.addLayout(self.pinkyToeLayout)
+
+
+ #rebuild button
+ spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ self.applyButton = QtWidgets.QPushButton("Apply Changes")
+ self.customSettingsLayout.addWidget(self.applyButton)
+ self.applyButton.setFont(headerFont)
+ self.applyButton.setMinimumSize(QtCore.QSize(300, 40))
+ self.applyButton.setMaximumSize(QtCore.QSize(300, 40))
+ self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.applyButton.setEnabled(False)
+
+
+
+ #SIGNALS/SLOTS
+
+ #signal slot for groupbox checkbox
+ QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible)
+ self.groupBox.setChecked(False)
+
+ #button signal/slots
+ self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst))
+ self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst))
+ self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst))
+ self.applyButton.clicked.connect(partial(self.applyModuleChanges, self))
+
+ #spinBox & checkbox signal/slots
+ self.thighTwistNum.valueChanged.connect(self.toggleButtonState)
+ self.calfTwistNum.valueChanged.connect(self.toggleButtonState)
+ self.bigToeNum.valueChanged.connect(self.toggleButtonState)
+ self.indexToeNum.valueChanged.connect(self.toggleButtonState)
+ self.middleToeNum.valueChanged.connect(self.toggleButtonState)
+ self.ringToeNum.valueChanged.connect(self.toggleButtonState)
+ self.pinkyToeNum.valueChanged.connect(self.toggleButtonState)
+ self.ballJoint.stateChanged.connect(self.toggleButtonState)
+ self.ballJoint.stateChanged.connect(partial(self.includeBallJoint, True))
+
+ self.pinkyToeMeta.stateChanged.connect(self.toggleButtonState)
+ self.ringToeMeta.stateChanged.connect(self.toggleButtonState)
+ self.middleToeMeta.stateChanged.connect(self.toggleButtonState)
+ self.indexToeMeta.stateChanged.connect(self.toggleButtonState)
+ self.bigToeMeta.stateChanged.connect(self.toggleButtonState)
+
+ #add custom skeletonUI settings name, parent, rig types to install, mirror module, thigh twist, calf twists, ball joint, toes,
+ #add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+ #Populate the settings UI based on the network node attributes
+ self.updateSettingsUI()
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pickerUI(self, center, animUI, networkNode, namespace):
+
+ self.namespace = namespace
+
+ #create qBrushes
+ yellowBrush = QtCore.Qt.yellow
+ blueBrush = QtGui.QColor(100,220,255)
+ purpleBrush = QtGui.QColor(111,48,161)
+ greenBrush = QtGui.QColor(0,255,30)
+ clearBrush = QtGui.QBrush(QtCore.Qt.black)
+ clearBrush.setStyle(QtCore.Qt.NoBrush)
+ side = cmds.getAttr(networkNode + ".side")
+
+ #create the picker border item
+ if networkNode.find(":") != -1:
+ moduleNode = networkNode.partition(":")[2]
+ else:
+ moduleNode = networkNode
+
+ borderItem = interfaceUtils.pickerBorderItem(center.x() - 75, center.y() - 130, 150, 260, clearBrush, moduleNode)
+
+ #get controls
+ ikControls = json.loads(cmds.getAttr(networkNode + ".ikV1Controls")) #["ik_foot_anim", "leg_heel_ctrl", "leg_toe_tip_ctrl", "leg_toe_wiggle_ctrl"]
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) #["fk_thigh_anim", "fk_calf_anim", "fk_foot_anim", "fk_ball_anim"]
+ thighTwistControls = json.loads(cmds.getAttr(networkNode + ".thighTwistControls"))
+ calfTwistControls = json.loads(cmds.getAttr(networkNode + ".calfTwistControls"))
+
+ buttonData = []
+ controls = []
+
+ #ik buttons
+ ikFootBtn = interfaceUtils.pickerButton(30, 30, [30,225], namespace + ikControls[0], yellowBrush, borderItem)
+ buttonData.append([ikFootBtn, namespace + ikControls[0], yellowBrush])
+ controls.append(namespace + ikControls[0])
+
+
+
+ ikHeelBtn = interfaceUtils.pickerButton(20, 20, [5,235], namespace + ikControls[1], yellowBrush, borderItem)
+ buttonData.append([ikHeelBtn, namespace + ikControls[1], yellowBrush])
+ controls.append(namespace + ikControls[1])
+
+ ikToeTipBtn = interfaceUtils.pickerButton(20, 20, [135,235], namespace + ikControls[2], yellowBrush, borderItem)
+ buttonData.append([ikToeTipBtn, namespace + ikControls[2], yellowBrush])
+ controls.append(namespace + ikControls[2])
+
+ ikToeWiggleBtn = interfaceUtils.pickerButton(20, 20, [97,200], namespace + ikControls[3], yellowBrush, borderItem)
+ buttonData.append([ikToeWiggleBtn, namespace + ikControls[3], yellowBrush])
+ controls.append(namespace + ikControls[3])
+
+ #fk buttons
+ fkThighBtn = interfaceUtils.pickerButton(30, 100, [30,10], namespace + fkControls[0], blueBrush, borderItem)
+ buttonData.append([fkThighBtn, namespace + fkControls[0], blueBrush])
+ controls.append(namespace + fkControls[0])
+
+ fkCalfBtn = interfaceUtils.pickerButton(30, 90, [30,122], namespace + fkControls[1], blueBrush, borderItem)
+ buttonData.append([fkCalfBtn, namespace + fkControls[1], blueBrush])
+ controls.append(namespace + fkControls[1])
+
+ fkFootBtn = interfaceUtils.pickerButton(30, 30, [62,225], namespace + fkControls[2], blueBrush, borderItem)
+ buttonData.append([fkFootBtn, namespace + fkControls[2], blueBrush])
+ controls.append(namespace + fkControls[2])
+
+ if len(fkControls) == 4:
+ fkBallBtn = interfaceUtils.pickerButton(30, 30, [97,225], namespace + fkControls[3], blueBrush, borderItem)
+ buttonData.append([fkBallBtn, namespace + fkControls[3], blueBrush])
+ controls.append(namespace + fkControls[3])
+
+ #thigh twists
+ if thighTwistControls != None:
+ if len(thighTwistControls) > 0:
+ y = 20
+ for i in range(len(thighTwistControls)):
+ button = interfaceUtils.pickerButton(20, 20, [5, y], namespace + thighTwistControls[i], purpleBrush, borderItem)
+ buttonData.append([button, namespace + thighTwistControls[i], purpleBrush])
+ controls.append(namespace + thighTwistControls[i])
+ y = y + 30
+
+
+ if calfTwistControls != None:
+ if len(calfTwistControls) > 0:
+ y = 192
+ for i in range(len(calfTwistControls)):
+ button = interfaceUtils.pickerButton(20, 20, [5, y], namespace + calfTwistControls[i], purpleBrush, borderItem)
+ buttonData.append([button, namespace + calfTwistControls[i], purpleBrush])
+ controls.append(namespace + calfTwistControls[i])
+ y = y - 30
+
+
+
+
+ #=======================================================================
+ # #TOES !!!! THIS IS A SUB-PICKER !!!!
+ #=======================================================================
+
+ #if there are toes, create a toe picker
+ toeControls = json.loads(cmds.getAttr(networkNode + ".toeControls"))
+ if len(toeControls) > 0:
+
+ name = cmds.getAttr(networkNode + ".moduleName")
+ toeBorder = interfaceUtils.pickerBorderItem(center.x() + 35, center.y() - 75, 100, 100, clearBrush, moduleNode, name + "_toes")
+ toeBorder.setParentItem(borderItem)
+ interfaceUtils.addTextToButton(side[0] + "_Toes", toeBorder, False, True, False)
+
+
+ #create selection set lists
+ bigToes = []
+ indexToes = []
+ middleToes = []
+ ringToes = []
+ pinkyToes = []
+
+ metaTarsals = []
+ distalKnuckles = []
+ middleKnuckles = []
+ proximalKnuckles = []
+
+ #BIG TOE
+ for toe in toeControls:
+ if toe.find("bigtoe_metatarsal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20,75], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ bigToes.append(namespace + toe)
+ metaTarsals.append(namespace + toe)
+
+ if toe.find("bigtoe_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20,40], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ bigToes.append(namespace + toe)
+ proximalKnuckles.append(namespace + toe)
+
+ if toe.find("bigtoe_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [20,25], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ bigToes.append(namespace + toe)
+ distalKnuckles.append(namespace + toe)
+
+
+ #INDEX TOE
+ if toe.find("index_metatarsal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35,75], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ indexToes.append(namespace + toe)
+ metaTarsals.append(namespace + toe)
+
+ if toe.find("index_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35,55], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ indexToes.append(namespace + toe)
+ proximalKnuckles.append(namespace + toe)
+
+ if toe.find("index_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35,40], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ indexToes.append(namespace + toe)
+ middleKnuckles.append(namespace + toe)
+
+ if toe.find("index_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [35,25], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ indexToes.append(namespace + toe)
+ distalKnuckles.append(namespace + toe)
+
+
+ #MIDDLE TOE
+ if toe.find("middle_metatarsal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50,75], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ middleToes.append(namespace + toe)
+ metaTarsals.append(namespace + toe)
+
+ if toe.find("middle_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50,55], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ middleToes.append(namespace + toe)
+ proximalKnuckles.append(namespace + toe)
+
+ if toe.find("middle_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50,40], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ middleToes.append(namespace + toe)
+ middleKnuckles.append(namespace + toe)
+
+ if toe.find("middle_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [50,25], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ middleToes.append(namespace + toe)
+ distalKnuckles.append(namespace + toe)
+
+
+ #RING TOE
+ if toe.find("ring_metatarsal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65,75], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ ringToes.append(namespace + toe)
+ metaTarsals.append(namespace + toe)
+
+ if toe.find("ring_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65,55], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ ringToes.append(namespace + toe)
+ proximalKnuckles.append(namespace + toe)
+
+ if toe.find("ring_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65,40], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ ringToes.append(namespace + toe)
+ middleKnuckles.append(namespace + toe)
+
+ if toe.find("ring_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [65,25], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ ringToes.append(namespace + toe)
+ distalKnuckles.append(namespace + toe)
+
+
+ #PINKY TOE
+ if toe.find("pinky_metatarsal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80,75], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ pinkyToes.append(namespace + toe)
+ metaTarsals.append(namespace + toe)
+
+ if toe.find("pinky_proximal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80,55], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ pinkyToes.append(namespace + toe)
+ proximalKnuckles.append(namespace + toe)
+
+ if toe.find("pinky_middle") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80,40], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ pinkyToes.append(namespace + toe)
+ middleKnuckles.append(namespace + toe)
+
+ if toe.find("pinky_distal") != -1:
+ button = interfaceUtils.pickerButton(10, 10, [80,25], namespace + toe, blueBrush, toeBorder)
+ buttonData.append([button, namespace + toe, blueBrush])
+ controls.append(namespace + toe)
+ pinkyToes.append(namespace + toe)
+ distalKnuckles.append(namespace + toe)
+
+
+ #TOE MASS SELECT BUTTONS
+ interfaceUtils.pickerButtonAll(10, 10, [5,75], metaTarsals, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [5,55], proximalKnuckles, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [5,40], middleKnuckles, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [5,25], distalKnuckles, greenBrush, toeBorder)
+
+ interfaceUtils.pickerButtonAll(10, 10, [20,5], bigToes, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [35,5], indexToes, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [50,5], middleToes, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [65,5], ringToes, greenBrush, toeBorder)
+ interfaceUtils.pickerButtonAll(10, 10, [80,5], pinkyToes, greenBrush, toeBorder)
+
+
+
+
+
+
+ #settings button
+ settingsBtn = interfaceUtils.pickerButton(20, 20, [65,40], namespace + self.name + "_settings", greenBrush, borderItem)
+ buttonData.append([settingsBtn, namespace + ":" + self.name + "_settings", greenBrush])
+ controls.append(namespace + ":" + self.name + "_settings")
+ interfaceUtils.addTextToButton("S", settingsBtn)
+
+
+ #go through button data, adding menu items
+ for each in buttonData:
+ button = each[0]
+
+ fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png"))))
+ ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png"))))
+ zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png"))))
+ zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png"))))
+ selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png"))))
+
+ switchAction = QtWidgets.QAction('Match when Switching', button.menu)
+ switchAction.setCheckable(True)
+ switchAction.setChecked(True)
+
+ button.menu.addAction(selectIcon, "Select All Leg Controls", partial(self.selectRigControls, "all"))
+ button.menu.addAction(selectIcon, "Select FK Leg Controls", partial(self.selectRigControls, "fk"))
+ button.menu.addAction(selectIcon, "Select IK Leg Controls", partial(self.selectRigControls, "ik"))
+ button.menu.addSeparator()
+
+ button.menu.addAction(fkIcon, "FK Mode", partial(self.switchMode, "FK", switchAction))
+ button.menu.addAction(ikIcon, "IK Mode", partial(self.switchMode, "IK", switchAction))
+ button.menu.addAction(switchAction)
+
+ button.menu.addSeparator()
+ button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True))
+ button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False))
+
+
+ #select all button
+ interfaceUtils.pickerButtonAll(20, 20, [65,10], controls, greenBrush, borderItem)
+
+
+ #=======================================================================
+ # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5)
+ #=======================================================================
+ scriptJob = cmds.scriptJob(event = ["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)], kws = True)
+ borderItem.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ #return data and set to mirror if side is right
+ if side == "Right":
+ return [borderItem, True, scriptJob]
+ else:
+ return [borderItem, False, scriptJob]
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRigCustom(self, textEdit, uiInst):
+
+ """
+ The base class gets a buildRig function called from the buildProgressUI. This function has some pre/post functionality that labels new nodes created by the buildRigCustom
+ method. Each derived class will need to have a buildRigCustom implemented. This method should call on any rig building functions for that module.
+
+ -each module should have its own settings group : self.name + "_settings"
+ -each module should have something similar to the builtRigs list, which is a list that holds what rigs have been built (NOT, which are going to BE built, but the ones that already have)
+ -this list looks something like this: [["FK", [nodesToHide]],["IK", [nodesToHide]]]
+ -this is used when it's time to setup the mode switching
+ -each module should also, at the very least, write to an attribute, what controls have been created for that module.
+ -right now, I have it as 2 attrs on the leg. This should probably just be changed to 1 controls attr, or keep what I have and add the controls attr which combines the previous?
+ -This would made looking up controls per module consistent, but may not be necessary?
+ """
+ #TO DO: investigate if controls attrs should be made consistent across all modules
+
+
+ #get the network node and find out which rigs to build
+ networkNode = self.returnNetworkNode
+ buildFK = True
+ buildIK_V1 = True
+
+ #have it build all rigs by default, unless there is an attr stating otherwise (backwards- compatability)
+ numRigs = 0
+ if cmds.objExists(networkNode + ".buildFK"):
+ buildFK = cmds.getAttr(networkNode + ".buildFK")
+ if buildFK:
+ numRigs += 1
+ if cmds.objExists(networkNode + ".buildIK_V1"):
+ buildIK_V1 = cmds.getAttr(networkNode + ".buildIK_V1")
+ if buildIK_V1:
+ numRigs += 1
+
+
+ #find the joints in the leg module that need rigging
+ joints = self.getMainLegJoints()
+
+ builtRigs = []
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ #create groups and settings
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ #create the leg group
+ legJoints = self.getMainLegJoints()
+ self.legGroup = cmds.group(empty = True, name = self.name + "_group")
+ constraint = cmds.parentConstraint(legJoints[0], self.legGroup)[0]
+ cmds.delete(constraint)
+
+ #create the leg settings group
+ self.legSettings = cmds.group(empty = True, name = self.name + "_settings")
+ cmds.parent(self.legSettings, self.legGroup)
+ for attr in(cmds.listAttr(self.legSettings, keyable = True)):
+ cmds.setAttr(self.legSettings + "." + attr, lock = True, keyable = False)
+
+ #add mode attribute to settings
+ if numRigs > 1:
+ cmds.addAttr(self.legSettings, ln = "mode", min = 0, max = numRigs - 1, dv = 0, keyable = True)
+
+ #create the ctrl group (what will get the constraint to the parent)
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.legCtrlGrp = cmds.group(empty = True, name = self.name + "_leg_ctrl_grp")
+ constraint = cmds.parentConstraint(parentBone, self.legCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(self.legCtrlGrp, self.legGroup)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ #build the rigs
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # FK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ #if build FK was true, build the FK rig now
+ if buildFK:
+
+ #update progress
+ if textEdit != None:
+ textEdit.append(" Starting FK Rig Build..")
+
+ #build the rig
+ slot = len(builtRigs)
+ fkRigData = riggingUtils.createFkRig(joints, networkNode, numRigs, slot)
+ self.topNode = fkRigData[0]
+
+ builtRigs.append(["FK", [self.topNode]])
+
+ #parent top node into leg group
+ if self.topNode != None:
+ cmds.parent(self.topNode, self.legCtrlGrp)
+
+ #lock attrs
+ for each in fkRigData[1]:
+ for attr in [".scaleX", ".scaleY",".scaleZ", ".visibility"]:
+ cmds.setAttr(each + attr, lock = True, keyable = False)
+
+ #add created control info to module
+ if not cmds.objExists(networkNode + ".fkControls"):
+ cmds.addAttr(networkNode, ln = "fkControls", dt = "string")
+ jsonString = json.dumps(fkRigData[1])
+ cmds.setAttr(networkNode + ".fkControls", jsonString, type = "string")
+
+ #update progress
+ if textEdit != None:
+ textEdit.setTextColor(QtGui.QColor(0,255,18))
+ textEdit.append(" SUCCESS: FK Build Complete!")
+ textEdit.setTextColor(QtGui.QColor(255,255,255))
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # IK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ #if build IK was true, build the IK rig now
+ if buildIK_V1:
+
+ #update progress
+ if textEdit != None:
+ textEdit.append(" Starting IK (version 1) Rig Build..")
+
+ #build the rig
+ slot = len(builtRigs)
+ ikInfo = self.buildIkRig(numRigs, slot)
+ builtRigs.append(["IK", [self.ikFootCtrl + "_grp", ikInfo[1]]])
+
+
+ #lock attributes on controls
+ for each in ikInfo[0]:
+ for attr in [".visibility", ".scaleX", ".scaleY", ".scaleZ"]:
+ cmds.setAttr(each + attr, lock = True, keyable = False)
+
+ if each != self.ikFootCtrl:
+ for attr in [".translateX", ".translateY", ".translateZ"]:
+ cmds.setAttr(each + attr, lock = True, keyable = False)
+
+ #add created control info to module
+ if not cmds.objExists(networkNode + ".ikV1Controls"):
+ cmds.addAttr(networkNode, ln = "ikV1Controls", dt = "string")
+ jsonString = json.dumps(ikInfo[0])
+ cmds.setAttr(networkNode + ".ikV1Controls", jsonString, type = "string")
+
+ #update progress
+ if textEdit != None:
+ textEdit.setTextColor(QtGui.QColor(0,255,18))
+ textEdit.append(" SUCCESS: IK Build Complete!")
+ textEdit.setTextColor(QtGui.QColor(255,255,255))
+
+
+
+ #===================================================================
+ # #create thigh twist rig
+ #===================================================================
+ twistJoints = self.getLegTwistJoints(True, False)
+ twistCtrls = riggingUtils.createCounterTwistRig(twistJoints, self.name, networkNode, legJoints[0], legJoints[1], self.name + "_group")
+
+ if not cmds.objExists(networkNode + ".thighTwistControls"):
+ cmds.addAttr(networkNode, ln = "thighTwistControls", dt = "string" )
+ jsonString = json.dumps(twistCtrls)
+ cmds.setAttr(networkNode + ".thighTwistControls", jsonString, type = "string")
+
+ #create calf twist rig
+ twistJoints = self.getLegTwistJoints(False, True)
+ twistCtrls = riggingUtils.createTwistRig(twistJoints, self.name, networkNode, legJoints[1], legJoints[2], self.name + "_group")
+
+ if not cmds.objExists(networkNode + ".calfTwistControls"):
+ cmds.addAttr(networkNode, ln = "calfTwistControls", dt = "string" )
+ jsonString = json.dumps(twistCtrls)
+ cmds.setAttr(networkNode + ".calfTwistControls", jsonString, type = "string")
+
+ #=======================================================================
+ # # #build toe rigs (if needed)
+ #=======================================================================
+ prefix = self.name.partition(baseName)[0]
+ suffix = self.name.partition(baseName)[2]
+
+ #lists of toe joints
+ bigToeJoints = ["proximal_phalange", "distal_phalange"]
+ toeJoints = ["proximal_phalange", "middle_phalange", "distal_phalange"]
+
+
+ #loop through our toe attrs, building the toe rig as we go
+ for attr in [[".bigToeJoints", "bigtoe", ".bigToeMeta"], [".indexToeJoints", "index", ".indexToeMeta"], [".middleToeJoints", "middle", ".middleToeMeta"], [".ringToeJoints", "ring", ".ringToeMeta"], [".pinkyToeJoints", "pinky", ".pinkyToeMeta"]]:
+ metaValue = cmds.getAttr(networkNode + attr[2])
+
+ value = cmds.getAttr(networkNode + attr[0])
+ toes = []
+
+ if metaValue:
+ toes.append(prefix + attr[1] + "_metatarsal" + suffix)
+
+ if attr[0] != ".bigToeJoints":
+ for i in range(int(value)):
+ toes.append(prefix + attr[1] + "_" + toeJoints[i] + suffix)
+
+ #build toe rigs
+ self.buildToeRigs(toes)
+
+ else:
+ for i in range(int(value)):
+ toes.append(prefix + attr[1] + "_" + bigToeJoints[i] + suffix)
+ #build toe rigs
+ self.buildToeRigs(toes)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ #hook up settings
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ #mode
+ if numRigs > 1:
+ attrData = []
+ rampData = []
+
+ """ CONSTRAINTS """
+ #get the constraint connections on the driver joints for the legs
+ connections = []
+ for joint in legJoints:
+ connections.extend(list(set(cmds.listConnections("driver_" + joint, type = "constraint"))))
+ ramps = (list(set(cmds.listConnections("driver_" + joint, type = "ramp"))))
+ for ramp in ramps:
+ connections.append(ramp + ".uCoord")
+
+
+ for connection in connections:
+ driveAttrs = []
+
+ if cmds.nodeType(connection) in ["pointConstraint", "orientConstraint"]:
+
+ #get those constraint target attributes for each constraint connection
+ targets = cmds.getAttr(connection + ".target", mi = True)
+ if len(targets) > 1:
+ for each in targets:
+ driveAttrs.append(cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p = True))
+
+ #add this data to our master list of constraint attribute data
+ attrData.append(driveAttrs)
+ else:
+ if cmds.nodeType(connection) == "ramp":
+ rampData.append(connection)
+
+ rampData = list(set(rampData))
+
+
+ #setup set driven keys on our moder attr and those target attributes
+ for i in range(numRigs):
+
+ cmds.setAttr(self.legSettings + ".mode", i)
+
+ #go through attr data and zero out anything but the first element in the list
+ for data in attrData:
+ for each in data:
+ cmds.setAttr(each[0], 0)
+
+ cmds.setAttr(data[i][0], 1)
+
+ #set driven keys
+ for data in attrData:
+ for each in data:
+ cmds.setDrivenKeyframe(each[0], cd = self.legSettings + ".mode", itt = "linear", ott = "linear")
+
+ """ RAMPS """
+ #direct connect mode to uCoord value (only works if there are 2 rigs...) <- not sure if that is the case still
+ for data in rampData:
+ #create a multiply node that takes first input of 1/numRigs and 2nd of mode direct connection
+ multNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_" + data.partition(".uCoord")[0] + "_mult")
+ cmds.setAttr(multNode + ".input1X", float(float(1)/float(numRigs - 1)))
+ cmds.connectAttr(self.legSettings + ".mode", multNode + ".input2X")
+ cmds.connectAttr(multNode + ".outputX", data)
+
+
+ """
+ builtRigs is a list of the rigs that have been built, but each element has the label of what rig was built, and nodes to hide as the second element,
+ like so: ["FK", [topNode]]
+ -the second element is a list of nodes. for FK, there is only 1 item in this list.
+
+ each element in the builtRigs list should coincide with the mode #, so if FK is element 0 in built rigs, mode 0 should be FK.
+ """
+ #hook up control visibility
+ for i in range(len(builtRigs)):
+ cmds.setAttr(self.legSettings + ".mode", i)
+ for rig in builtRigs:
+ visNodes = rig[1]
+ for node in visNodes:
+ if node != None:
+ cmds.setAttr(node + ".v", 0)
+
+ if builtRigs.index(rig) == i:
+ visNodes = rig[1]
+ for node in visNodes:
+ if node != None:
+ cmds.setAttr(node + ".v", 1)
+
+
+ cmds.setDrivenKeyframe(visNodes, at = "visibility", cd = self.legSettings + ".mode", itt = "linear", ott = "linear")
+
+
+
+
+ #parent under offset_anim if it exists(it always should)
+ if cmds.objExists("offset_anim"):
+ cmds.parent(self.legGroup, "offset_anim")
+
+ #return data
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ try:
+ uiInst.rigData.append([self.legCtrlGrp, "driver_" + parentBone, numRigs])
+ except:
+ pass
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildIkRig(self, numRigs, slot):
+
+ networkNode = self.returnNetworkNode
+
+ #get main leg joints to duplicate for IK leg rig
+ legJoints = self.getMainLegJoints()
+
+ self.ikThigh = cmds.duplicate(legJoints[0], po = True, name = "ikV1_" + legJoints[0] + "_joint")[0]
+ self.ikCalf = cmds.duplicate(legJoints[1], po = True, name = "ikV1_" + legJoints[1] + "_joint")[0]
+ self.ikFoot = cmds.duplicate(legJoints[2], po = True, name = "ikV1_" + legJoints[2] + "_joint")[0]
+
+
+ for joint in [self.ikThigh, self.ikCalf, self.ikFoot]:
+ parent = cmds.listRelatives(joint, parent = True)
+ if parent != None:
+ cmds.parent(joint, world = True)
+
+ #create heirarchy
+ cmds.parent(self.ikFoot, self.ikCalf)
+ cmds.parent(self.ikCalf, self.ikThigh)
+
+ #freeze rotates
+ cmds.makeIdentity(self.ikThigh, t = 0, r = 1, s = 0, apply = True)
+
+ #hook up driver joints to these ik joints
+ i = 0
+ for joint in [self.ikThigh, self.ikCalf, self.ikFoot]:
+ cmds.pointConstraint(joint, "driver_" + legJoints[i])
+ cmds.orientConstraint(joint, "driver_" + legJoints[i])
+
+
+ #plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = legJoints[i] + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(joint + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + legJoints[i], "scale", False, numRigs, slot, "output")
+ else:
+ riggingUtils.createConstraint(joint, "driver_" + legJoints[i], "scale", False, numRigs, slot)
+
+
+ cmds.setAttr(joint + ".v", 0, lock = True)
+ i += 1
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create the no-flip setup #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # 1.) Create the No-Flip Bone Chain
+ noFlipBegin = cmds.createNode("joint", name = self.name + "_noFlip_begin_joint")
+ noFlipEnd = cmds.createNode("joint", name = self.name + "_noFlip_end_joint")
+ noFlipGrp = cmds.group(empty = True, name = self.name + "_noFlip_joints_grp")
+
+ cmds.setAttr(noFlipBegin + ".v", 0, lock = True)
+ cmds.setAttr(noFlipEnd + ".v", 0, lock = True)
+ cmds.parent(noFlipEnd, noFlipBegin)
+
+
+ constraint = cmds.parentConstraint(self.ikThigh, noFlipGrp)[0]
+ cmds.delete(constraint)
+ constraint = cmds.parentConstraint(self.ikThigh, noFlipBegin)[0]
+ cmds.delete(constraint)
+ constraint = cmds.parentConstraint(self.ikFoot, noFlipEnd)[0]
+ cmds.delete(constraint)
+
+ #zero out all but tx on noFlipEnd
+ cmds.setAttr(noFlipEnd + ".ty", 0)
+ cmds.setAttr(noFlipEnd + ".tz", 0)
+
+
+ cmds.parent(noFlipBegin, noFlipGrp)
+ cmds.makeIdentity(noFlipBegin, t = 0, r = 1, s = 0, apply = True)
+
+ #set the preferred angle
+ cmds.setAttr(noFlipBegin + ".preferredAngleZ", 90)
+
+
+ # 2.) create target loc/grp
+ targetGrp = cmds.group(empty = True, name = self.name + "_noFlip_target_grp")
+ targetLoc = cmds.spaceLocator(name = self.name + "_noFlip_target_loc")[0]
+ cmds.setAttr(targetLoc + ".v", 0, lock = True)
+
+ cmds.parent(targetLoc, targetGrp)
+
+ constraint = cmds.pointConstraint(noFlipBegin, targetGrp)[0]
+ cmds.delete(constraint)
+ constraint = cmds.pointConstraint(noFlipEnd, targetLoc)[0]
+ cmds.delete(constraint)
+
+ # 3.) create the aim loc/grp
+ aimNodes = cmds.duplicate(targetGrp, name = self.name + "_noFlip_aim_grp", rc = True)
+ aimGrp = aimNodes[0]
+ aimLoc = aimNodes[1]
+ aimLoc = cmds.rename(aimLoc, self.name + "_noFlip_aim_loc")
+
+ #find the world position of the aimGrp
+ worldPos = cmds.xform(aimGrp, q = True, ws = True, t = True)
+
+ #find the bone length of the noFlip chain
+ length = cmds.getAttr(noFlipEnd + ".tx")
+
+ #now create the world position of where the aim locator needs to be
+ if worldPos[0] >= 0:
+ aimLocPos = [worldPos[0] + abs(length), worldPos[1], worldPos[2]]
+ if worldPos[0] < 0:
+ aimLocPos = [(abs(worldPos[0]) + abs(length)) * -1, worldPos[1], worldPos[2]]
+
+ #rotate the aim grp in 90 in every axis until the world position of the aim locator matches the passed in aimLocPos
+ self.rotateAimGrp(int(aimLocPos[0]), aimGrp, aimLoc)
+
+ # 4.) Connect TX and TZ of aimLoc to targetLoc
+ cmds.connectAttr(targetLoc + ".tx", aimLoc + ".tx")
+ cmds.connectAttr(targetLoc + ".tz", aimLoc + ".tz")
+
+ # 5.) set limits on aimLoc translateZ
+ currentValue = cmds.getAttr(aimLoc + ".tz")
+ cmds.transformLimits(aimLoc, etz = [1, 1], tz = [currentValue, -10])
+
+ # 6.) Create RP IK for noFlip bone chain
+ ikNodes = cmds.ikHandle(name = self.name + "_noFlip_ikHandle", solver = "ikRPsolver", sj = noFlipBegin, ee = noFlipEnd)
+ cmds.setAttr(ikNodes[0] + ".v", 0, lock = True)
+
+ # 7.) pointConstraint IKHandle to targetLoc
+ cmds.pointConstraint(targetLoc, ikNodes[0])
+
+ # 8.) snap target loc to ankle
+ constraint = cmds.pointConstraint(self.ikFoot, targetLoc)[0]
+ cmds.delete(constraint)
+
+ # 9.) pole vector constraint between ikHandle and aimLoc
+ cmds.poleVectorConstraint(aimLoc, ikNodes[0])
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create the foot control #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ footControlInfo = riggingUtils.createControlFromMover(legJoints[2], networkNode, False, True)
+
+ cmds.parent(footControlInfo[0], world = True)
+ constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", footControlInfo[3])[0]
+ cmds.delete(constraint)
+ cmds.makeIdentity(footControlInfo[2], t = 1, r= 1, s = 1, apply = True)
+ cmds.parent(footControlInfo[0], footControlInfo[1])
+ cmds.makeIdentity(footControlInfo[0], t = 1, r= 1, s = 1, apply = True)
+
+ #rename the control info
+ self.ikFootCtrl = cmds.rename(footControlInfo[0], "ik_" + legJoints[2] + "_anim")
+ cmds.rename(footControlInfo[1], self.ikFootCtrl + "_grp")
+ cmds.rename(footControlInfo[2], self.ikFootCtrl + "_space_switcher")
+ spaceSwitcherFollow = cmds.rename(footControlInfo[3], self.ikFootCtrl + "_space_switcher_follow")
+
+ #Create leg RP IK
+ legIkNodes = cmds.ikHandle(name = self.name + "_noFlip_ikHandle", solver = "ikRPsolver", sj = self.ikThigh, ee = self.ikFoot)
+ cmds.setAttr(legIkNodes[0] + ".v", 0, lock = True)
+
+ #parent ik under the foot control
+ cmds.parent(legIkNodes[0], self.ikFootCtrl)
+
+ #create a FK matcher node
+ fkMatchGrp = cmds.group(empty = True, name = "ik_" + legJoints[2] + "_anim_fkMatchGrp")
+ constr = cmds.parentConstraint(self.ikFoot, fkMatchGrp)[0]
+ cmds.delete(constr)
+ cmds.parent(fkMatchGrp, self.ikFootCtrl)
+
+ fkMatch = cmds.group(empty = True, name = "ik_" + legJoints[2] + "_anim_fkMatch")
+ constr = cmds.parentConstraint(self.ikFoot, fkMatch)[0]
+ cmds.delete(constr)
+ cmds.parent(fkMatch, fkMatchGrp)
+
+ #point constraint target loc to foot ctrl
+ cmds.pointConstraint(self.ikFootCtrl, targetLoc)
+
+ #color the foot control
+ riggingUtils.colorControl(self.ikFootCtrl)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create the leg chain PV #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ noFlipVectorLoc = cmds.spaceLocator(name = self.name + "_noFlip_pv_loc")[0]
+ noFlipVectorGrp = cmds.group(empty = True, name = self.name + "_noFlip_pv_grp")
+ cmds.setAttr(noFlipVectorLoc + ".v", 0, lock = True)
+
+ constraint = cmds.pointConstraint([noFlipBegin, noFlipEnd], noFlipVectorLoc)[0]
+ cmds.delete(constraint)
+ constraint = cmds.pointConstraint(targetLoc, noFlipVectorGrp)[0]
+ cmds.delete(constraint)
+
+ #get the length of the leg
+ legLength = abs(cmds.getAttr(noFlipEnd + ".tx"))
+
+ #use that length to push out the noFlipVectorLoc in front
+ cmds.parent(noFlipVectorLoc, self.ikCalf)
+ cmds.setAttr(noFlipVectorLoc + ".translate", 0,0,0, type = "double3")
+ cmds.setAttr(noFlipVectorLoc + ".rotate", 0,0,0, type = "double3")
+
+ #get the forward vector for the knee and set the length of the leg on the noFlipVectorLoc translateY
+ forwardVector = cmds.xform(self.ikThigh, q = True, ws = True, ro = True)[1]
+ if forwardVector < 0:
+ cmds.setAttr(noFlipVectorLoc + ".ty", (legLength * -1))
+ else:
+ cmds.setAttr(noFlipVectorLoc + ".ty", legLength)
+
+ #parent noFlipVectorLoc and constrain the grp to the no flip end joint
+ cmds.parent(noFlipVectorLoc, noFlipVectorGrp)
+ cmds.makeIdentity(noFlipVectorLoc, t = 1, r = 1, s = 1, apply = True)
+ cmds.parentConstraint(noFlipEnd, noFlipVectorGrp, mo = True)
+
+ #pole vector constrain the ikHandle for the leg to the vectorLoc
+ cmds.poleVectorConstraint(noFlipVectorLoc, legIkNodes[0])
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create the knee vector display #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ kneeControl = riggingUtils.createControl("arrow", 1.25, self.name + "_ik_knee_anim")
+ constraint = cmds.pointConstraint(self.ikCalf, kneeControl)[0]
+ cmds.delete(constraint)
+
+ kneeGrp = cmds.group(empty = True, name = self.name + "_ik_knee_anim_grp")
+ constraint = cmds.pointConstraint(self.ikCalf, kneeGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(kneeControl, kneeGrp)
+ cmds.makeIdentity(kneeControl, t = 1, r = 1, s = 1, apply = True)
+
+ cmds.pointConstraint(self.ikCalf, kneeGrp, mo = True)
+ cmds.setAttr(kneeControl + ".overrideEnabled", 1)
+ cmds.setAttr(kneeControl + ".overrideDisplayType", 2)
+
+ cmds.aimConstraint(noFlipVectorLoc, kneeGrp, aim = [0, -1, 0], u = [0, 0, 1], wut = "vector", wu = [0, 0, 1])
+ cmds.orientConstraint(self.ikCalf, kneeControl, mo = True)
+
+ #color the control
+ riggingUtils.colorControl(kneeControl)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create the foot rig #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ ballExists = False
+
+ #create ball and toe joints
+ if len(legJoints) == 4:
+ if cmds.objExists(legJoints[3]):
+ ballExists = True
+
+
+ cmds.select(clear = True)
+
+ #select vertices influenced by foot and ball joint
+ selection = []
+ skinClusters = cmds.ls(type = "skinCluster")
+ for skin in skinClusters:
+ infs = cmds.skinCluster(skin, q = True, wi = True)
+ if legJoints[2] in infs:
+ cmds.skinCluster(skin, edit = True, siv = legJoints[2])
+ selection.extend(cmds.ls(sl = True, flatten = True))
+
+ if len(legJoints) == 4:
+ if legJoints[3] in infs:
+ cmds.skinCluster(skin, edit = True, siv = legJoints[3])
+ selection.extend(cmds.ls(sl = True, flatten = True))
+
+ #get the bounds of the foot to find the foot length
+ cmds.select(selection)
+ try:
+ bounds = cmds.exactWorldBoundingBox(cmds.ls(sl = True), ce = True, ii = True)
+ length = abs(bounds[1] - bounds[4])
+ except:
+ pass
+
+ cmds.select(clear = True)
+
+ # # #
+ #create ball and toe joint
+ # # #
+
+ #ball joint creation
+ if ballExists:
+ self.ikBallJoint = cmds.createNode("joint", name = "ikV1_" + legJoints[3] + "_joint")
+ constraint = cmds.parentConstraint(legJoints[3], self.ikBallJoint)[0]
+ cmds.delete(constraint)
+ cmds.move(0, moveZ = True, ws = True)
+
+
+ #if there is no ball joint, we need to create one and place it approx. where it should go
+ else:
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ nameData = self.name.split(baseName)
+
+ self.ikBallJoint = cmds.createNode("joint", name = "ikV1_" + nameData[0] + "ball" + nameData[1] + "_joint")
+ constraint = cmds.pointConstraint(self.name + "_toe_pivot_mover", self.ikBallJoint)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_inside_pivot_mover_orient", self.ikBallJoint)[0]
+ cmds.delete(constraint)
+
+ cmds.setAttr(self.ikBallJoint + ".v", 0, lock = True)
+
+ #toe joint creation
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ nameData = self.name.split(baseName)
+
+ self.ikToeJoint = cmds.createNode("joint", name = "ikV1_" + nameData[0] + "toe" + nameData[1] + "_joint")
+ constraint = cmds.pointConstraint(self.name + "_toe_pivot_mover", self.ikToeJoint)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_ball_mover", self.ikToeJoint)[0]
+ cmds.delete(constraint)
+
+ cmds.setAttr(self.ikToeJoint + ".v", 0, lock = True)
+
+ #parent ball and toe joints into ik joint hierarchy
+ cmds.parent(self.ikToeJoint, self.ikBallJoint)
+ cmds.parent(self.ikBallJoint, self.ikFoot)
+ cmds.makeIdentity(self.ikBallJoint, t = 0, r = 1, s = 0, apply = True)
+
+ #constrain driver ball joint to ik ball joint
+ if ballExists:
+
+ cmds.pointConstraint(self.ikBallJoint, "driver_" + legJoints[3])
+ cmds.orientConstraint(self.ikBallJoint, "driver_" + legJoints[3])
+ #plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = legJoints[i] + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(joint + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + legJoints[i], "scale", False, numRigs, slot, "output")
+ else:
+ riggingUtils.createConstraint(joint, "driver_" + legJoints[i], "scale", False, numRigs, slot)
+
+
+ #create the SC IK for the ball -> toe
+ ballIKNodes = cmds.ikHandle(name = self.name + "_ikHandle_ball", solver = "ikSCsolver", sj = self.ikFoot, ee = self.ikBallJoint)
+ toeIKNodes = cmds.ikHandle(name = self.name + "_ikHandle_toe", solver = "ikSCsolver", sj = self.ikBallJoint, ee = self.ikToeJoint)
+ cmds.setAttr(ballIKNodes[0] + ".v", 0, lock = True)
+ cmds.setAttr(toeIKNodes[0] + ".v", 0, lock = True)
+
+ #create the locators we need for the foot rig
+ toeTipPivot = cmds.spaceLocator(name = self.name + "_ik_foot_toe_tip_pivot")[0]
+ insidePivot = cmds.spaceLocator(name = self.name + "_ik_foot_inside_pivot")[0]
+ outsidePivot = cmds.spaceLocator(name = self.name + "_ik_foot_outside_pivot")[0]
+ heelPivot = cmds.spaceLocator(name = self.name + "_ik_foot_heel_pivot")[0]
+ toePivot = cmds.spaceLocator(name = self.name + "_ik_foot_toe_pivot")[0]
+ ballPivot = cmds.spaceLocator(name = self.name + "_ik_foot_ball_pivot")[0]
+ masterBallPivot = cmds.spaceLocator(name = self.name + "_master_foot_ball_pivot")[0]
+
+
+ #create the controls
+ heelControl = riggingUtils.createControl("arrowOnBall", 1, self.name + "_heel_ctrl")
+ toeWiggleControl = riggingUtils.createControl("arrowOnBall", 1.5, self.name + "_toe_wiggle_ctrl")
+ toeControl = riggingUtils.createControl("arrowOnBall", 1, self.name + "_toe_tip_ctrl")
+
+ #orient controls in worldspace correctly
+ cmds.setAttr(heelControl + ".rx", -90)
+ cmds.setAttr(toeControl + ".rx", 90)
+ cmds.makeIdentity(heelControl, t = 0, r = 1, s = 0, apply = True)
+ cmds.makeIdentity(toeControl, t = 0, r = 1, s = 0, apply = True)
+
+ #position controls
+ constraint = cmds.parentConstraint(self.name + "_heel_pivot_orient", heelControl)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.pointConstraint(self.name + "_toe_pivot_mover", toeControl)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_toe_pivot_orient", toeControl)[0]
+ cmds.delete(constraint)
+
+
+ constraint = cmds.pointConstraint(self.ikBallJoint, toeWiggleControl)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.orientConstraint(self.name + "_toe_pivot_orient", toeWiggleControl)[0]
+ cmds.delete(constraint)
+
+ #create control groups and orient controls properly
+
+ #heelControl
+ heelCtrlGrp = cmds.group(empty = True, name = self.name + "_heel_ctrl_grp")
+ constraint = cmds.parentConstraint(heelControl, heelCtrlGrp)[0]
+ cmds.delete(constraint)
+ cmds.parent(heelControl, heelCtrlGrp)
+ cmds.makeIdentity(heelControl, t = 1, r = 1, s = 1, apply = True)
+
+ #toeControl
+ toeCtrlGrp = cmds.group(empty = True, name = self.name + "_toe_tip_ctrl_grp")
+ constraint = cmds.pointConstraint(toeControl, toeCtrlGrp)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.ikToeJoint, toeCtrlGrp)[0]
+ cmds.delete(constraint)
+ cmds.makeIdentity(toeControl, t = 0, r = 1, s = 0, apply = True)
+ cmds.setAttr(toeControl + ".rx", -90)
+ cmds.parent(toeControl, toeCtrlGrp)
+ cmds.makeIdentity(toeControl, t = 1, r = 1, s = 1, apply = True)
+
+ #toeWiggleControl
+ toeWiggleCtrlGrp = cmds.group(empty = True, name = self.name + "_toe_wiggle_ctrl_grp")
+ constraint = cmds.pointConstraint(self.ikBallJoint, toeWiggleCtrlGrp)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.ikBallJoint, toeWiggleCtrlGrp)[0]
+ cmds.delete(constraint)
+ cmds.parent(toeWiggleControl, toeWiggleCtrlGrp)
+ cmds.setAttr(toeWiggleControl + ".rx", -90)
+ cmds.makeIdentity(toeWiggleControl, t = 1, r = 1, s = 1, apply = True)
+
+ if not ballExists:
+ cmds.setAttr(toeWiggleControl + ".v", 0, lock = True)
+
+ #place the pivot locators
+ constraint = cmds.pointConstraint(heelControl, heelPivot)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", heelPivot)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.pointConstraint(toeWiggleControl, ballPivot)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", ballPivot)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.pointConstraint(toeWiggleControl, masterBallPivot)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", masterBallPivot)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.pointConstraint(toeControl, toeTipPivot)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", toeTipPivot)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.pointConstraint(toeControl, toePivot)[0]
+ cmds.delete(constraint)
+ constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", toePivot)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.parentConstraint(self.name + "_inside_pivot_mover_orient", insidePivot)[0]
+ cmds.delete(constraint)
+
+ constraint = cmds.parentConstraint(self.name + "_outside_pivot_mover_orient", outsidePivot)[0]
+ cmds.delete(constraint)
+
+
+ #create groups for each pivot and parent the pivot to the corresponding group
+ for piv in [heelPivot, ballPivot, toeTipPivot, toePivot, insidePivot, outsidePivot, masterBallPivot]:
+ pivGrp = cmds.group(empty = True, name = piv + "_grp")
+ constraint = cmds.parentConstraint(piv, pivGrp)[0]
+ cmds.delete(constraint)
+ cmds.parent(piv, pivGrp)
+ shape = cmds.listRelatives(piv, shapes = True)[0]
+ cmds.setAttr(shape + ".v", 0)
+
+
+ #setup pivot hierarchy
+ cmds.parent(toeWiggleCtrlGrp, toePivot)
+ cmds.parent(ballPivot + "_grp", toePivot)
+ cmds.parent(toePivot + "_grp", heelPivot)
+ cmds.parent(heelPivot + "_grp", outsidePivot)
+ cmds.parent(outsidePivot + "_grp", insidePivot)
+ cmds.parent(insidePivot + "_grp", toeTipPivot)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create the set driven keys #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ #get the side attribute
+ side = cmds.getAttr(networkNode + ".side")
+
+ # # # FOOT ROLL # # #
+ cmds.setAttr(heelControl + ".rz", 0)
+ cmds.setAttr(heelPivot + ".rx", 0)
+ cmds.setAttr(toePivot + ".rx", 0)
+ cmds.setAttr(ballPivot + ".rx", 0)
+ cmds.setDrivenKeyframe([heelPivot + ".rx", toePivot + ".rx", ballPivot + ".rx"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
+
+ cmds.setAttr(heelControl + ".rz", -90)
+ cmds.setAttr(heelPivot + ".rx", 0)
+ cmds.setAttr(toePivot + ".rx", 0)
+ cmds.setAttr(ballPivot + ".rx", 90)
+ cmds.setDrivenKeyframe([heelPivot + ".rx", toePivot + ".rx", ballPivot + ".rx"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
+
+ cmds.setAttr(heelControl + ".rz", 90)
+ cmds.setAttr(heelPivot + ".rx", -90)
+ cmds.setAttr(toePivot + ".rx", 0)
+ cmds.setAttr(ballPivot + ".rx", 0)
+ cmds.setDrivenKeyframe([heelPivot + ".rx", toePivot + ".rx", ballPivot + ".rx"], cd = heelControl + ".rz", itt = "linear", ott = "linear")
+
+ cmds.setAttr(heelControl + ".rz", 0)
+ cmds.setAttr(heelPivot + ".rx", 0)
+ cmds.setAttr(toePivot + ".rx", 0)
+ cmds.setAttr(ballPivot + ".rx", 0)
+
+ # # # HEEL CONTROL RX & RY # # #
+ cmds.connectAttr(heelControl + ".rx", ballPivot + ".rz")
+ cmds.connectAttr(heelControl + ".ry", ballPivot + ".ry")
+
+ # # # TOE CONTROL RY & RZ # # #
+ if side == "Left":
+ cmds.connectAttr(toeControl + ".ry", toeTipPivot + ".rz")
+
+ else:
+ toeRzMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_toeTipPivot_RZ_mult")
+ cmds.setAttr(toeRzMult + ".input2X", -1)
+ cmds.connectAttr(toeControl + ".ry", toeRzMult + ".input1X")
+ cmds.connectAttr(toeRzMult + ".outputX", toeTipPivot + ".rz")
+
+ toeRxMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_toeTipPivot_RX_mult")
+ cmds.setAttr(toeRxMult + ".input2X", -1)
+ cmds.connectAttr(toeControl + ".rz", toeRxMult + ".input1X")
+ cmds.connectAttr(toeRxMult + ".outputX", toeTipPivot + ".rx")
+
+ # # # FOOT SIDE TO SIDE # # #
+ cmds.setAttr(toeControl + ".rx", 0)
+ cmds.setAttr(insidePivot + ".rx", 0)
+ cmds.setAttr(outsidePivot + ".rx", 0)
+ cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
+
+ cmds.setAttr(toeControl + ".rx", -90)
+ cmds.setAttr(insidePivot + ".rx", 0)
+ cmds.setAttr(outsidePivot + ".rx", -90)
+ cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
+
+ cmds.setAttr(toeControl + ".rx", 90)
+ cmds.setAttr(insidePivot + ".rx", 90)
+ cmds.setAttr(outsidePivot + ".rx", 0)
+ cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear")
+
+ cmds.setAttr(toeControl + ".rx", 0)
+ cmds.setAttr(insidePivot + ".rx", 0)
+ cmds.setAttr(outsidePivot + ".rx", 0)
+
+ #parent the IK nodes into the foot rig setup
+ cmds.parent(legIkNodes[0], ballPivot)
+ cmds.parent(ballIKNodes[0], ballPivot)
+ cmds.parent(toeIKNodes[0], toeWiggleControl)
+
+ cmds.parent([toeTipPivot + "_grp", heelControl + "_grp", toeControl + "_grp"], masterBallPivot)
+ cmds.parent(masterBallPivot + "_grp", self.ikFootCtrl)
+
+ #add the heel pivot and ball pivot attrs to the foot control
+ cmds.addAttr(heelControl, longName= ( "heelPivot" ), defaultValue=0, keyable = True)
+ cmds.addAttr(heelControl, longName= ( "ballPivot" ), defaultValue=0, keyable = True)
+
+ #setup heel and ball pivot
+ if side == "Left":
+ cmds.connectAttr(heelControl + ".heelPivot", heelPivot + ".rz")
+ cmds.connectAttr(heelControl + ".ballPivot", masterBallPivot + ".rz")
+
+ else:
+ heelPivotMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_heelPivotMult")
+ cmds.setAttr(heelPivotMult + ".input2X", -1)
+ cmds.connectAttr(heelControl + ".heelPivot", heelPivotMult + ".input1X")
+ cmds.connectAttr(heelPivotMult + ".outputX", heelPivot + ".rz")
+
+ ballPivotMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_ballPivotMult")
+ cmds.setAttr(ballPivotMult + ".input2X", -1)
+ cmds.connectAttr(heelControl + ".ballPivot", ballPivotMult + ".input1X")
+ cmds.connectAttr(ballPivotMult + ".outputX", masterBallPivot + ".rz")
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # connect ik twist attr to custom attr on foot ctrl #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ cmds.addAttr(self.ikFootCtrl, longName=("knee_twist"), at = 'double', keyable = True)
+
+ if side == "Right":
+ cmds.connectAttr(self.ikFootCtrl + ".knee_twist", legIkNodes[0] + ".twist")
+ else:
+ twistMultNode = cmds.shadingNode("multiplyDivide", name = self.name + "ik_knee_twistMultNode", asUtility = True)
+ cmds.connectAttr(self.ikFootCtrl + ".knee_twist", twistMultNode + ".input1X")
+ cmds.setAttr(twistMultNode + ".input2X", -1)
+ cmds.connectAttr(twistMultNode + ".outputX", legIkNodes[0] + ".twist")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # setup ik squash and stretch #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+
+ """
+ Note about stretch bias, since this part is really confusing:
+
+ the math goes like this:
+ if the current leg length > original leg length, then the leg needs to stretch (if attr is on)
+ 1.) take the stretch bias attr from the foot control and divide by 5.
+ -Why 5? It's just an arbitrary number. The point of stretch bias is to essentially add onto the original length,
+ so that when we divide current by original, we get a slightly smaller number than we normally would. If stretch bias is 0, this returns 0. If 1, then .2
+ 2.) Take that result and add 1.
+ -Why? So that we aren't dividing the current length by 0 (original length * that result). At most, we would divide it by current length/(original * 1.2)
+ -At least would be current length /(original * 1)
+ 3.) Take the add node result (1 + stretch bias output) and multiply it by original length
+ 4.) Take the current length and put that into input1 of a new mult node
+ 5.) Take the result of step 3 and put it into input 2. Set operation to divide
+ 6.) This gets us current/(original * stretch bias output)
+ 7.) Lastly, create a blendColors node passing in color 1r as 1.0, and 2r as the scale factor
+ 8.) Pass in the stretch attr into blender. if stretch is .5, given 1 and 1.3, result is 1.15. That is the scale to be applied to joints.
+ """
+
+
+
+ #add attrs to the foot ctrl
+ cmds.addAttr(self.ikFootCtrl, longName=("stretch"), at = 'double',min = 0, max = 1, dv = 0, keyable = True)
+ cmds.addAttr(self.ikFootCtrl, longName=("squash"), at = 'double',min = 0, max = 1, dv = 0, keyable = True)
+ cmds.addAttr(self.ikFootCtrl, longName=("toeCtrlVis"), at = 'bool', dv = 0, keyable = True)
+
+ #need to get the total length of the leg chain
+ totalDist = abs(cmds.getAttr(self.ikCalf + ".tx" ) + cmds.getAttr(self.ikFoot + ".tx"))
+
+ #create a distanceBetween node
+ distBetween = cmds.shadingNode("distanceBetween", asUtility = True, name = self.name + "_ik_leg_distBetween")
+
+ #get world positions of thigh and ik
+ baseGrp = cmds.group(empty = True, name = self.name + "_ik_leg_base_grp")
+ endGrp = cmds.group(empty = True, name = self.name + "_ik_leg_end_grp")
+ cmds.pointConstraint(self.ikThigh, baseGrp)
+ cmds.pointConstraint(self.ikFootCtrl, endGrp)
+
+ #hook in group translates into distanceBetween node inputs
+ cmds.connectAttr(baseGrp + ".translate", distBetween + ".point1")
+ cmds.connectAttr(endGrp + ".translate", distBetween + ".point2")
+
+
+ #create a condition node that will compare original length to current length
+ #if second term is greater than, or equal to the first term, the chain needs to stretch
+ ikLegCondition = cmds.shadingNode("condition", asUtility = True, name = self.name + "_ik_leg_stretch_condition")
+ cmds.setAttr(ikLegCondition + ".operation", 3)
+ cmds.connectAttr(distBetween + ".distance", ikLegCondition + ".secondTerm")
+ cmds.setAttr(ikLegCondition + ".firstTerm", totalDist)
+
+
+ #hook up the condition node's return colors
+ cmds.setAttr(ikLegCondition + ".colorIfTrueR", totalDist)
+ cmds.connectAttr(distBetween + ".distance", ikLegCondition + ".colorIfFalseR")
+
+ #add attr to foot control for stretch bias
+ cmds.addAttr(self.ikFootCtrl, ln = "stretchBias", minValue = -1.0, maxValue = 1.0, defaultValue = 0.0, keyable = True)
+
+ #add divide node so that instead of driving 0-1, we're actually only driving 0 - 0.2
+ divNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_stretchBias_Div")
+ cmds.connectAttr(self.ikFootCtrl + ".stretchBias", divNode + ".input1X")
+ cmds.setAttr(divNode + ".operation", 2)
+ cmds.setAttr(divNode + ".input2X", 5)
+
+ #create the add node and connect the stretchBias into it, adding 1
+ addNode = cmds.shadingNode("plusMinusAverage", asUtility = True, name = self.name + "_stretchBias_Add")
+ cmds.connectAttr(divNode + ".outputX", addNode + ".input1D[0]")
+ cmds.setAttr(addNode + ".input1D[1]", 1.0)
+
+ #connect output of addNode to new mult node input1x
+ stretchBiasMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_stretchBias_multNode")
+ cmds.connectAttr(addNode + ".output1D", stretchBiasMultNode + ".input1X")
+
+ #create the mult/divide node(set to divide) that will take the original creation length as a static value in input2x, and the connected length into 1x. This will get the scale factor
+ legDistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_leg_dist_multNode")
+ cmds.setAttr(legDistMultNode + ".operation", 2) #divide
+ cmds.connectAttr(ikLegCondition + ".outColorR", legDistMultNode + ".input1X")
+
+ #set input2x to totalDist
+ cmds.setAttr(stretchBiasMultNode + ".input2X", totalDist)
+ cmds.connectAttr(stretchBiasMultNode + ".outputX", legDistMultNode + ".input2X")
+
+
+ """ This differs from the original code. Instead of using a condition, I will use a blendColors node so that stretch % has an effect """
+
+ #create a blendColors node for stretch
+ blendResult = cmds.shadingNode("blendColors", asUtility = True, name = self.name + "_leg_stretch_scaleFactor")
+ cmds.setAttr(blendResult + ".color2R", 1)
+ cmds.connectAttr(legDistMultNode + ".outputX", blendResult + ".color1R")
+ cmds.connectAttr(self.ikFootCtrl + ".stretch", blendResult + ".blender")
+
+ #create a blendColors node for squash
+ blendResultSquash = cmds.shadingNode("blendColors", asUtility = True, name = self.name + "_leg_squash_scaleFactor")
+ cmds.setAttr(blendResultSquash + ".color2R", 1)
+ cmds.connectAttr(legDistMultNode + ".outputX", blendResultSquash + ".color1R")
+ cmds.connectAttr(self.ikFootCtrl + ".squash", blendResultSquash + ".blender")
+
+ #get the sqrt of the scale factor by creating a multiply node and setting it to power operation
+ powerNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_sqrt_scaleFactor")
+ cmds.setAttr(powerNode + ".operation", 3)
+ cmds.connectAttr(blendResultSquash + ".outputR", powerNode + ".input1X")
+ cmds.setAttr(powerNode + ".input2X", .5)
+
+ #now divide 1 by that result
+ squashDivNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_squash_Value")
+ cmds.setAttr(squashDivNode + ".operation", 2)
+ cmds.setAttr(squashDivNode + ".input1X", 1)
+ cmds.connectAttr(powerNode + ".outputX", squashDivNode + ".input2X")
+
+
+ #connect to leg joint scale attributes
+ cmds.connectAttr(blendResult + ".outputR", self.ikThigh + ".sx")
+ cmds.connectAttr(blendResult + ".outputR", self.ikCalf + ".sx")
+
+ cmds.connectAttr(squashDivNode + ".outputX", self.ikCalf + ".sy")
+ cmds.connectAttr(squashDivNode + ".outputX", self.ikCalf + ".sz")
+
+ cmds.connectAttr(squashDivNode + ".outputX", self.ikThigh + ".sy")
+ cmds.connectAttr(squashDivNode + ".outputX", self.ikThigh + ".sz")
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # clean up #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ cmds.parent([targetGrp, aimGrp, noFlipVectorGrp], noFlipGrp)
+ cmds.parent([self.ikThigh, noFlipGrp], self.legCtrlGrp)
+
+ ikGrp = cmds.group(name = self.name + "_ik_group", empty = True)
+ cmds.parent([spaceSwitcherFollow, ikNodes[0], kneeGrp], ikGrp)
+
+ cmds.parent([spaceSwitcherFollow, ikGrp, baseGrp, endGrp], self.legGroup)
+
+ return [[self.ikFootCtrl, heelControl, toeControl, toeWiggleControl], kneeGrp]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildToeRigs(self, joints):
+
+ networkNode = self.returnNetworkNode
+
+ #number of rigs. Might need to be pulled from a setting in the future
+ buildFK = True
+ buildIK = False #later feature? Skip for now.
+ numRigs = 0
+
+ if buildFK:
+ numRigs += 1
+ if buildIK:
+ numRigs += 1
+
+ if numRigs > 1:
+ cmds.addAttr(self.legSettings, ln = "toeRigMode", min = 0, max = numRigs - 1, dv = 0, keyable = True)
+
+ if numRigs >= 1:
+ #setup visibility to leg settings toe mode (will need to add attribute first)
+ if not cmds.objExists(self.legSettings + ".toeCtrlVis"):
+ cmds.addAttr(self.legSettings, ln = "toeCtrlVis", min = 0, max = 1, dv = 0, keyable = True)
+
+ #build the fk rig if needed
+ if buildFK:
+
+ if not cmds.objExists(self.name + "_toe_rig_grp"):
+ toeRigGrp = cmds.group(empty = True, name = self.name + "_toe_rig_grp")
+ cmds.parent(toeRigGrp, self.legGroup)
+
+ #create the control from the mover
+ fkToeNodes = riggingUtils.createFkRig(joints, networkNode, numRigs, 0)
+
+ if not cmds.objExists(networkNode + ".toeControls"):
+ cmds.addAttr(networkNode, ln = "toeControls", dt = "string")
+ jsonString = json.dumps(fkToeNodes[1])
+ cmds.setAttr(networkNode + ".toeControls", jsonString, type = "string")
+
+ else:
+ currentData = json.loads(cmds.getAttr(networkNode + ".toeControls"))
+ currentData.extend(fkToeNodes[1])
+ jsonString = json.dumps(currentData)
+ cmds.setAttr(networkNode + ".toeControls", jsonString, type = "string")
+
+ for toe in fkToeNodes[1]:
+
+
+ #default color
+ color = 18
+
+ #first, let's color controls
+ currentColor = cmds.getAttr(toe + ".overrideColor")
+ if currentColor == 13:
+ color = 4
+
+ cmds.setAttr(toe + ".overrideColor", color)
+
+ #next, duplicate the toe group for each toe, parent under the toe grp, freeze transforms, and parent the toe control under it
+ drivenGrp = cmds.duplicate(toe + "_grp", po = True, name = toe + "_driven_grp")
+ cmds.parent(drivenGrp, toe + "_grp")
+ cmds.makeIdentity(drivenGrp, t = 1, r = 1, s = 1, apply = True)
+ cmds.parent(toe, drivenGrp)
+
+ #need to find the top most group node's parent, and unparent the top most group node from it
+ #parent under the toe rig grp and parentConstraint to original parent's driver joint
+ parent = cmds.listRelatives(toe + "_grp", parent = True)
+
+ if parent == None:
+ cmds.parent(toe + "_grp", self.name + "_toe_rig_grp")
+
+ #get the joint the parent is driving
+ joint = toe.partition("fk_")[2].partition("_anim")[0]
+ parent = cmds.listRelatives(joint, parent = True)[0]
+ driverJnt = "driver_" + parent
+ cmds.parentConstraint(driverJnt, toe + "_grp", mo = True)
+
+
+ #setup set connections on toes for toe ctrl vis
+ cmds.connectAttr(self.legSettings + ".toeCtrlVis", toe + "_grp.v")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def rotateAimGrp(self, aimLocPos, aimGrp, aimLoc):
+
+ for attr in [".rotateX", ".rotateY", ".rotateZ"]:
+ cmds.setAttr(aimGrp + attr, 90)
+ currentVal = int(cmds.xform(aimLoc, q = True, ws = True, t = True)[0])
+ if currentVal == aimLocPos:
+ return
+ else:
+ cmds.setAttr(aimGrp + attr, -90)
+ currentVal = int(cmds.xform(aimLoc, q = True, ws = True, t = True)[0])
+ if currentVal == aimLocPos:
+ return
+ else:
+ cmds.setAttr(aimGrp + attr, 0)
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getMainLegJoints(self):
+
+ thighJoint = None
+ calfJoint = None
+ footJoint = None
+ ballJoint = None
+
+ returnData = []
+
+ #thigh
+ joints = self.returnCreatedJoints
+ for joint in joints:
+ if joint.find("thigh") != -1:
+ if joint.find("twist") == -1:
+ thighJoint = joint
+ returnData.append(thighJoint)
+
+ #calf
+ for joint in joints:
+ if joint.find("calf") != -1:
+ if joint.find("twist") == -1:
+ calfJoint = joint
+ returnData.append(calfJoint)
+
+ #foot
+ for joint in joints:
+ if joint.find("foot") != -1:
+ footJoint = joint
+ returnData.append(footJoint)
+
+ #ball
+ for joint in joints:
+ if joint.find("ball") != -1:
+ ballJoint = joint
+ returnData.append(ballJoint)
+
+ return returnData
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getLegTwistJoints(self, thighTwists, calfTwists):
+
+ thighTwistBones = []
+ calfTwistBones = []
+
+ joints = self.returnCreatedJoints
+
+
+ #thigh
+ for joint in joints:
+ if joint.find("thigh") != -1:
+ if joint.find("twist") != -1:
+ thighTwistBones.append(joint)
+
+ #calf
+ for joint in joints:
+ if joint.find("calf") != -1:
+ if joint.find("twist") != -1:
+ calfTwistBones.append(joint)
+
+
+ if thighTwists:
+ return thighTwistBones
+ if calfTwists:
+ return calfTwistBones
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def setAttrViaInterface(self, attr, checkbox):
+
+ networkNode = self.returnNetworkNode
+
+ state = checkbox.isChecked()
+
+ cmds.setAttr(networkNode + "." + attr, lock = False)
+ cmds.setAttr(networkNode + "." + attr, state, lock = True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def mirrorTransformations_Custom(self):
+
+ networkNode = self.returnNetworkNode
+ mirrorModule = cmds.getAttr(networkNode + ".mirrorModule")
+ moduleName = cmds.getAttr(networkNode + ".moduleName")
+
+ for mover in [self.name + "_toe_pivot_mover", self.name + "_heel_pivot_mover"]:
+ for attr in [".rotateY", ".rotateZ"]:
+ value = cmds.getAttr(mover + attr)
+ mirrorMover = mover.replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + attr, value * -1)
+
+ for attr in [".translateY", ".translateZ"]:
+ value = cmds.getAttr(mover + attr)
+ mirrorMover = mover.replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + attr, value)
+
+ for mover in [self.name + "_outside_pivot_mover", self.name + "_inside_pivot_mover"]:
+ for attr in [".rotateX", ".rotateZ"]:
+ value = cmds.getAttr(mover + attr)
+ mirrorMover = mover.replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + attr, value * -1)
+
+ #outside translates
+ value = cmds.getAttr(self.name + "_outside_pivot_mover.tz")
+ mirrorMover = (self.name + "_outside_pivot_mover").replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + ".tz", value)
+
+ value = cmds.getAttr(self.name + "_outside_pivot_mover.ty")
+ mirrorMover = (self.name + "_outside_pivot_mover").replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + ".ty", value)
+
+ #inside translates
+ value = cmds.getAttr(self.name + "_inside_pivot_mover.tz")
+ mirrorMover = (self.name + "_inside_pivot_mover").replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + ".tz", value)
+
+ value = cmds.getAttr(self.name + "_inside_pivot_mover.tx")
+ mirrorMover = (self.name + "_inside_pivot_mover").replace(moduleName, mirrorModule)
+ cmds.setAttr(mirrorMover + ".tx", value)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def includeBallJoint(self, apply, *args):
+ state = self.ballJoint.isChecked()
+
+ self.bigToeNum.setEnabled(state)
+ self.indexToeNum.setEnabled(state)
+ self.middleToeNum.setEnabled(state)
+ self.ringToeNum.setEnabled(state)
+ self.pinkyToeNum.setEnabled(state)
+
+ if state == False:
+ #set values back to 0
+ self.bigToeNum.setValue(0)
+ self.indexToeNum.setValue(0)
+ self.middleToeNum.setValue(0)
+ self.ringToeNum.setValue(0)
+ self.pinkyToeNum.setValue(0)
+
+ #show ball to toe bone geo
+ cmds.setAttr(self.name + "_noToes_bone_geo.v", lock = False)
+ cmds.setAttr(self.name + "_noToes_bone_geo.v", 1, lock = True)
+
+ #hide ball mover controls
+ cmds.setAttr(self.name + "_ball_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_ball_mover_grp.v", 0, lock = True)
+
+
+ if state == True:
+ #show ball mover controls
+ cmds.setAttr(self.name + "_ball_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_ball_mover_grp.v", 1, lock = True)
+
+ #apply changes
+ if apply:
+ self.applyModuleChanges(self)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleButtonState(self):
+
+ state = self.applyButton.isEnabled()
+ if state == False:
+ self.applyButton.setEnabled(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def editMetaTarsals(self, uiWidget, searchKey, *args):
+
+ #uiWidget is the spinBox
+ #isBigToe will be the special case, since there are only the three joints instead of the 4
+ #searchKey is the basname (bigToe, middle, ring, etc)
+
+ #unlock bone representations
+ cmds.select(self.name + "_bone_representations", hi = True)
+ selection = cmds.ls(sl = True, type = "transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock = False)
+
+
+ #toggle visibility
+ if uiWidget.isChecked():
+ try:
+ cmds.parent(self.name + "_" + searchKey + "_proximal_phalange_mover_grp", self.name + "_" + searchKey + "_metatarsal_mover")
+ except Exception, e:
+ print e
+
+ cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_bone_geo.v", 1)
+
+
+ if not uiWidget.isChecked():
+ try:
+ cmds.parent(self.name + "_" + searchKey + "_proximal_phalange_mover_grp", self.name + "_ball_mover")
+ except Exception, e:
+ print e
+
+ cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", 0, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_bone_geo.v", 0)
+
+ #relock bone representations
+ cmds.select(self.name + "_bone_representations", hi = True)
+ selection = cmds.ls(sl = True, type = "transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock = True)
+
+ #toggle mover vis
+ self.rigUiInst.setMoverVisibility()
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def editJointMoverViaSpinBox(self, uiWidget, searchKey, isBigToe, *args):
+
+ #uiWidget is the spinBox
+ #isBigToe will be the special case, since there are only the three joints instead of the 4
+ #searchKey is the basname (bigToe, middle, ring, etc)
+
+ #unlock bone representations
+ cmds.select(self.name + "_bone_representations", hi = True)
+ selection = cmds.ls(sl = True, type = "transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock = False)
+
+ #check number in spinBox
+ num = uiWidget.value()
+
+ #set visibility on movers and geo depending on the value of num
+ for i in range(num + 1):
+ #purely for fanciness
+ time.sleep(.05)
+ cmds.refresh(force = True)
+
+ if isBigToe == False:
+
+ moverList = ["_proximal_phalange", "_middle_phalange", "_distal_phalange"]
+ for mover in moverList:
+ if moverList.index(mover) <= i -1:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1)
+
+ if i == 0:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0)
+
+ if isBigToe == True:
+
+ moverList = ["_proximal_phalange", "_distal_phalange"]
+ for mover in moverList:
+ if moverList.index(mover) <= i -1:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1)
+
+ if i == 0:
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False)
+ self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0)
+ cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0)
+
+
+ #relock bone representations
+ cmds.select(self.name + "_bone_representations", hi = True)
+ selection = cmds.ls(sl = True, type = "transform")
+
+ for each in selection:
+ cmds.setAttr(each + ".v", lock = True)
+
+ #toggle mover vis
+ self.rigUiInst.setMoverVisibility()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def editJointMoverTwistBones(self, uiWidget, searchKey, *args):
+
+ #check number in spinBox
+ num = uiWidget.value()
+
+ for i in range(num + 1):
+
+ if i == 0:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 0, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock = True)
+
+ if i == 1:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock = True)
+
+ if i == 2:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock = True)
+
+ if i == 3:
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock = True)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False)
+ cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 1, lock = True)
+
+
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addJointMoverToOutliner(self):
+
+ index = self.rigUiInst.treeWidget.topLevelItemCount()
+
+ #Add the module to the tree widget in the outliner tab of the rig creator UI
+ self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget)
+ self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name)
+ foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255))
+ self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground)
+
+ #add the thigh
+ self.outlinerWidgets[self.name + "_thigh"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_thigh"].setText(0, self.name + "_thigh")
+ self.createGlobalMoverButton(self.name + "_thigh", self.outlinerWidgets[self.name + "_thigh"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thigh", self.outlinerWidgets[self.name + "_thigh"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_thigh", self.outlinerWidgets[self.name + "_thigh"], self.rigUiInst)
+
+ #add the thigh twists
+ self.outlinerWidgets[self.name + "_thigh_twist_01"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"])
+ self.outlinerWidgets[self.name + "_thigh_twist_01"].setText(0, self.name + "_thigh_twist_01")
+ #self.createGlobalMoverButton(self.name + "_thigh_twist_01", self.outlinerWidgets[self.name + "_thigh_twist_01"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thigh_twist_01", self.outlinerWidgets[self.name + "_thigh_twist_01"], self.rigUiInst)
+ #self.createMeshMoverButton(self.name + "_thigh_twist_01", self.outlinerWidgets[self.name + "_thigh_twist_01"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_thigh_twist_01"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_thigh_twist_02"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"])
+ self.outlinerWidgets[self.name + "_thigh_twist_02"].setText(0, self.name + "_thigh_twist_02")
+ #self.createGlobalMoverButton(self.name + "_thigh_twist_02", self.outlinerWidgets[self.name + "_thigh_twist_02"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thigh_twist_02", self.outlinerWidgets[self.name + "_thigh_twist_02"], self.rigUiInst)
+ #self.createMeshMoverButton(self.name + "_thigh_twist_02", self.outlinerWidgets[self.name + "_thigh_twist_02"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_thigh_twist_02"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_thigh_twist_03"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"])
+ self.outlinerWidgets[self.name + "_thigh_twist_03"].setText(0, self.name + "_thigh_twist_03")
+ #self.createGlobalMoverButton(self.name + "_thigh_twist_03", self.outlinerWidgets[self.name + "_thigh_twist_03"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_thigh_twist_03", self.outlinerWidgets[self.name + "_thigh_twist_03"], self.rigUiInst)
+ #self.createMeshMoverButton(self.name + "_thigh_twist_03", self.outlinerWidgets[self.name + "_thigh_twist_03"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_thigh_twist_03"].setHidden(True)
+
+ #add the calf
+ self.outlinerWidgets[self.name + "_calf"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"] )
+ self.outlinerWidgets[self.name + "_calf"].setText(0, self.name + "_calf")
+ self.createGlobalMoverButton(self.name + "_calf", self.outlinerWidgets[self.name + "_calf"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_calf", self.outlinerWidgets[self.name + "_calf"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_calf", self.outlinerWidgets[self.name + "_calf"], self.rigUiInst)
+
+ #add the calf twists
+ self.outlinerWidgets[self.name + "_calf_twist_01"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] )
+ self.outlinerWidgets[self.name + "_calf_twist_01"].setText(0, self.name + "_calf_twist_01")
+ #self.createGlobalMoverButton(self.name + "_calf_twist_01", self.outlinerWidgets[self.name + "_calf_twist_01"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_calf_twist_01", self.outlinerWidgets[self.name + "_calf_twist_01"], self.rigUiInst)
+ #self.createMeshMoverButton(self.name + "_calf_twist_01", self.outlinerWidgets[self.name + "_calf_twist_01"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_calf_twist_01"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_calf_twist_02"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] )
+ self.outlinerWidgets[self.name + "_calf_twist_02"].setText(0, self.name + "_calf_twist_02")
+ #self.createGlobalMoverButton(self.name + "_calf_twist_02", self.outlinerWidgets[self.name + "_calf_twist_02"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_calf_twist_02", self.outlinerWidgets[self.name + "_calf_twist_02"], self.rigUiInst)
+ #self.createMeshMoverButton(self.name + "_calf_twist_02", self.outlinerWidgets[self.name + "_calf_twist_02"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_calf_twist_02"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_calf_twist_03"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] )
+ self.outlinerWidgets[self.name + "_calf_twist_03"].setText(0, self.name + "_calf_twist_03")
+ #self.createGlobalMoverButton(self.name + "_calf_twist_03", self.outlinerWidgets[self.name + "_calf_twist_03"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_calf_twist_03", self.outlinerWidgets[self.name + "_calf_twist_03"], self.rigUiInst)
+ #self.createMeshMoverButton(self.name + "_calf_twist_03", self.outlinerWidgets[self.name + "_calf_twist_03"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_calf_twist_03"].setHidden(True)
+
+ #add the foot
+ self.outlinerWidgets[self.name + "_foot"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] )
+ self.outlinerWidgets[self.name + "_foot"].setText(0, self.name + "_foot")
+ self.createGlobalMoverButton(self.name + "_foot", self.outlinerWidgets[self.name + "_foot"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_foot", self.outlinerWidgets[self.name + "_foot"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_foot", self.outlinerWidgets[self.name + "_foot"], self.rigUiInst)
+
+ #add the ball
+ self.outlinerWidgets[self.name + "_ball"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_foot"] )
+ self.outlinerWidgets[self.name + "_ball"].setText(0, self.name + "_ball")
+ self.createGlobalMoverButton(self.name + "_ball", self.outlinerWidgets[self.name + "_ball"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ball", self.outlinerWidgets[self.name + "_ball"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ball", self.outlinerWidgets[self.name + "_ball"], self.rigUiInst)
+
+ #add the big toes
+ self.outlinerWidgets[self.name + "_bigtoe_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_bigtoe_metatarsal"].setText(0, self.name + "_bigtoe_metatarsal")
+ self.createGlobalMoverButton(self.name + "_bigtoe_metatarsal", self.outlinerWidgets[self.name + "_bigtoe_metatarsal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_bigtoe_metatarsal", self.outlinerWidgets[self.name + "_bigtoe_metatarsal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_bigtoe_metatarsal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"].setText(0, self.name + "_bigtoe_proximal_phalange")
+ self.createGlobalMoverButton(self.name + "_bigtoe_proximal_phalange", self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_bigtoe_proximal_phalange", self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_bigtoe_proximal_phalange", self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"] )
+ self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"].setText(0, self.name + "_bigtoe_distal_phalange")
+ self.createGlobalMoverButton(self.name + "_bigtoe_distal_phalange", self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_bigtoe_distal_phalange", self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_bigtoe_distal_phalange", self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"].setHidden(True)
+
+ #add the index toes
+ self.outlinerWidgets[self.name + "_index_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_index_metatarsal"].setText(0, self.name + "_index_metatarsal")
+ self.createGlobalMoverButton(self.name + "_index_metatarsal", self.outlinerWidgets[self.name + "_index_metatarsal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_metatarsal", self.outlinerWidgets[self.name + "_index_metatarsal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_index_metatarsal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_index_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_index_proximal_phalange"].setText(0, self.name + "_index_proximal_phalange")
+ self.createGlobalMoverButton(self.name + "_index_proximal_phalange", self.outlinerWidgets[self.name + "_index_proximal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_proximal_phalange", self.outlinerWidgets[self.name + "_index_proximal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_index_proximal_phalange", self.outlinerWidgets[self.name + "_index_proximal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_index_proximal_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_index_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_index_proximal_phalange"] )
+ self.outlinerWidgets[self.name + "_index_middle_phalange"].setText(0, self.name + "_index_middle_phalange")
+ self.createGlobalMoverButton(self.name + "_index_middle_phalange", self.outlinerWidgets[self.name + "_index_middle_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_middle_phalange", self.outlinerWidgets[self.name + "_index_middle_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_index_middle_phalange", self.outlinerWidgets[self.name + "_index_middle_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_index_middle_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_index_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_index_middle_phalange"] )
+ self.outlinerWidgets[self.name + "_index_distal_phalange"].setText(0, self.name + "_index_distal_phalange")
+ self.createGlobalMoverButton(self.name + "_index_distal_phalange", self.outlinerWidgets[self.name + "_index_distal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_index_distal_phalange", self.outlinerWidgets[self.name + "_index_distal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_index_distal_phalange", self.outlinerWidgets[self.name + "_index_distal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_index_distal_phalange"].setHidden(True)
+
+
+ #add the middle toes
+ self.outlinerWidgets[self.name + "_middle_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_middle_metatarsal"].setText(0, self.name + "_middle_metatarsal")
+ self.createGlobalMoverButton(self.name + "_middle_metatarsal", self.outlinerWidgets[self.name + "_middle_metatarsal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_metatarsal", self.outlinerWidgets[self.name + "_middle_metatarsal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_middle_metatarsal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_middle_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_middle_proximal_phalange"].setText(0, self.name + "_middle_proximal_phalange")
+ self.createGlobalMoverButton(self.name + "_middle_proximal_phalange", self.outlinerWidgets[self.name + "_middle_proximal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_proximal_phalange", self.outlinerWidgets[self.name + "_middle_proximal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_middle_proximal_phalange", self.outlinerWidgets[self.name + "_middle_proximal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_middle_proximal_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_middle_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_middle_proximal_phalange"] )
+ self.outlinerWidgets[self.name + "_middle_middle_phalange"].setText(0, self.name + "_middle_middle_phalange")
+ self.createGlobalMoverButton(self.name + "_middle_middle_phalange", self.outlinerWidgets[self.name + "_middle_middle_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_middle_phalange", self.outlinerWidgets[self.name + "_middle_middle_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_middle_middle_phalange", self.outlinerWidgets[self.name + "_middle_middle_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_middle_middle_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_middle_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_middle_middle_phalange"] )
+ self.outlinerWidgets[self.name + "_middle_distal_phalange"].setText(0, self.name + "_middle_distal_phalange")
+ self.createGlobalMoverButton(self.name + "_middle_distal_phalange", self.outlinerWidgets[self.name + "_middle_distal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_middle_distal_phalange", self.outlinerWidgets[self.name + "_middle_distal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_middle_distal_phalange", self.outlinerWidgets[self.name + "_middle_distal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_middle_distal_phalange"].setHidden(True)
+
+
+ #add the ring toes
+ self.outlinerWidgets[self.name + "_ring_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_ring_metatarsal"].setText(0, self.name + "_ring_metatarsal")
+ self.createGlobalMoverButton(self.name + "_ring_metatarsal", self.outlinerWidgets[self.name + "_ring_metatarsal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_metatarsal", self.outlinerWidgets[self.name + "_ring_metatarsal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_ring_metatarsal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_ring_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_ring_proximal_phalange"].setText(0, self.name + "_ring_proximal_phalange")
+ self.createGlobalMoverButton(self.name + "_ring_proximal_phalange", self.outlinerWidgets[self.name + "_ring_proximal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_proximal_phalange", self.outlinerWidgets[self.name + "_ring_proximal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ring_proximal_phalange", self.outlinerWidgets[self.name + "_ring_proximal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_ring_proximal_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_ring_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ring_proximal_phalange"] )
+ self.outlinerWidgets[self.name + "_ring_middle_phalange"].setText(0, self.name + "_ring_middle_phalange")
+ self.createGlobalMoverButton(self.name + "_ring_middle_phalange", self.outlinerWidgets[self.name + "_ring_middle_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_middle_phalange", self.outlinerWidgets[self.name + "_ring_middle_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ring_middle_phalange", self.outlinerWidgets[self.name + "_ring_middle_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_ring_middle_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_ring_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ring_middle_phalange"] )
+ self.outlinerWidgets[self.name + "_ring_distal_phalange"].setText(0, self.name + "_ring_distal_phalange")
+ self.createGlobalMoverButton(self.name + "_ring_distal_phalange", self.outlinerWidgets[self.name + "_ring_distal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_ring_distal_phalange", self.outlinerWidgets[self.name + "_ring_distal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_ring_distal_phalange", self.outlinerWidgets[self.name + "_ring_distal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_ring_distal_phalange"].setHidden(True)
+
+
+ #add the pinky toes
+ self.outlinerWidgets[self.name + "_pinky_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_pinky_metatarsal"].setText(0, self.name + "_pinky_metatarsal")
+ self.createGlobalMoverButton(self.name + "_pinky_metatarsal", self.outlinerWidgets[self.name + "_pinky_metatarsal"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_metatarsal", self.outlinerWidgets[self.name + "_pinky_metatarsal"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_pinky_metatarsal"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_pinky_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] )
+ self.outlinerWidgets[self.name + "_pinky_proximal_phalange"].setText(0, self.name + "_pinky_proximal_phalange")
+ self.createGlobalMoverButton(self.name + "_pinky_proximal_phalange", self.outlinerWidgets[self.name + "_pinky_proximal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_proximal_phalange", self.outlinerWidgets[self.name + "_pinky_proximal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pinky_proximal_phalange", self.outlinerWidgets[self.name + "_pinky_proximal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_pinky_proximal_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_pinky_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_pinky_proximal_phalange"] )
+ self.outlinerWidgets[self.name + "_pinky_middle_phalange"].setText(0, self.name + "_pinky_middle_phalange")
+ self.createGlobalMoverButton(self.name + "_pinky_middle_phalange", self.outlinerWidgets[self.name + "_pinky_middle_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_middle_phalange", self.outlinerWidgets[self.name + "_pinky_middle_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pinky_middle_phalange", self.outlinerWidgets[self.name + "_pinky_middle_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_pinky_middle_phalange"].setHidden(True)
+
+ self.outlinerWidgets[self.name + "_pinky_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_pinky_middle_phalange"] )
+ self.outlinerWidgets[self.name + "_pinky_distal_phalange"].setText(0, self.name + "_pinky_distal_phalange")
+ self.createGlobalMoverButton(self.name + "_pinky_distal_phalange", self.outlinerWidgets[self.name + "_pinky_distal_phalange"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pinky_distal_phalange", self.outlinerWidgets[self.name + "_pinky_distal_phalange"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pinky_distal_phalange", self.outlinerWidgets[self.name + "_pinky_distal_phalange"], self.rigUiInst)
+ self.outlinerWidgets[self.name + "_pinky_distal_phalange"].setHidden(True)
+
+
+ #create selection script job for module
+ self.createScriptJob()
+
+ #update based on spinBox values
+ self.updateOutliner()
+ self.updateBoneCount()
+ self.rigUiInst.treeWidget.expandAll()
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateSettingsUI(self):
+
+ #this function will update the settings UI when the UI is launched based on the network node settings in the scene
+ networkNode = self.returnNetworkNode
+
+ thighTwists = cmds.getAttr(networkNode + ".thighTwists")
+ calfTwists = cmds.getAttr(networkNode + ".calfTwists")
+ bigToes = cmds.getAttr(networkNode + ".bigToeJoints")
+ indexToes = cmds.getAttr(networkNode + ".indexToeJoints")
+ middleToes = cmds.getAttr(networkNode + ".middleToeJoints")
+ ringToes = cmds.getAttr(networkNode + ".ringToeJoints")
+ pinkyToes = cmds.getAttr(networkNode + ".pinkyToeJoints")
+ includeBall = cmds.getAttr(networkNode + ".includeBall")
+ bigToeMeta = cmds.getAttr(networkNode + ".bigToeMeta")
+ indexToeMeta = cmds.getAttr(networkNode + ".indexToeMeta")
+ middleToeMeta = cmds.getAttr(networkNode + ".middleToeMeta")
+ ringToeMeta = cmds.getAttr(networkNode + ".ringToeMeta")
+ pinkyToeMeta = cmds.getAttr(networkNode + ".pinkyToeMeta")
+
+ #update UI elements
+ self.thighTwistNum.setValue(thighTwists)
+ self.calfTwistNum.setValue(calfTwists)
+ self.ballJoint.setChecked(includeBall)
+
+ self.bigToeNum.setValue(bigToes)
+ self.indexToeNum.setValue(indexToes)
+ self.middleToeNum.setValue(middleToes)
+ self.ringToeNum.setValue(ringToes)
+ self.pinkyToeNum.setValue(pinkyToes)
+
+ self.bigToeMeta.setChecked(bigToeMeta)
+ self.indexToeMeta.setChecked(indexToeMeta)
+ self.middleToeMeta.setChecked(middleToeMeta)
+ self.ringToeMeta.setChecked(ringToeMeta)
+ self.pinkyToeMeta.setChecked(pinkyToeMeta)
+
+ #apply changes
+ self.applyButton.setEnabled(False)
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateOutliner(self):
+
+ #whenever changes are made to the module settings, update the outliner to show the new or removed movers
+
+ #THIGH TWISTS
+ thighTwists = self.thighTwistNum.value()
+ if thighTwists == 0:
+ self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(True)
+ if thighTwists == 1:
+ self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(True)
+ if thighTwists == 2:
+ self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(True)
+ if thighTwists == 3:
+ self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(False)
+
+ #CALF TWISTS
+ calfTwists = self.calfTwistNum.value()
+ if calfTwists == 0:
+ self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(True)
+ if calfTwists == 1:
+ self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(True)
+ if calfTwists == 2:
+ self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(True)
+ if calfTwists == 3:
+ self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(False)
+
+ #BALL JOINT
+ ballJoint = self.ballJoint.isChecked()
+ if ballJoint:
+ self.outlinerWidgets[self.originalName + "_ball"].setHidden(False)
+ else:
+ self.outlinerWidgets[self.originalName + "_ball"].setHidden(True)
+
+
+ #BIG TOES
+ bigToes = self.bigToeNum.value()
+ bigToeMeta = self.bigToeMeta.isChecked()
+
+ if bigToes == 0:
+ self.outlinerWidgets[self.originalName + "_bigtoe_proximal_phalange"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_bigtoe_distal_phalange"].setHidden(True)
+ if bigToes == 1:
+ self.outlinerWidgets[self.originalName + "_bigtoe_proximal_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_bigtoe_distal_phalange"].setHidden(True)
+ if bigToes == 2:
+ self.outlinerWidgets[self.originalName + "_bigtoe_proximal_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_bigtoe_distal_phalange"].setHidden(False)
+
+ if bigToeMeta:
+ self.outlinerWidgets[self.originalName + "_bigtoe_metatarsal"].setHidden(False)
+ if not bigToeMeta:
+ self.outlinerWidgets[self.originalName + "_bigtoe_metatarsal"].setHidden(True)
+
+ toes = [[self.indexToeNum, "index", self.indexToeMeta],[self.middleToeNum, "middle", self.middleToeMeta],[self.ringToeNum, "ring", self.ringToeMeta],[self.pinkyToeNum, "pinky", self.pinkyToeMeta]]
+
+ #OTHER TOES
+ for toe in toes:
+ value = toe[0].value()
+ meta = toe[2].isChecked()
+
+ if value == 0:
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(True)
+ if value == 1:
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(True)
+ if value == 2:
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(True)
+ if value == 3:
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(False)
+
+ if meta:
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_metatarsal"].setHidden(False)
+ if not meta:
+ self.outlinerWidgets[self.originalName + "_" + toe[1] + "_metatarsal"].setHidden(True)
+
+
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def resetSettings(self):
+
+ networkNode = self.returnNetworkNode
+ attrs = cmds.listAttr(networkNode, ud = True, hd = 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":
+ if attr.find("Meta") != -1:
+ cmds.setAttr(networkNode + "." + attr, lock = False)
+ cmds.setAttr(networkNode + "." + attr, False, lock = True)
+ if attr.find("Meta") == -1:
+ cmds.setAttr(networkNode + "." + attr, lock = False)
+ cmds.setAttr(networkNode + "." + attr, True, lock = True)
+
+
+ #relaunch the UI
+ self.updateSettingsUI()
+ self.applyModuleChanges(self)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def applyModuleChanges(self, moduleInst):
+
+ #create an array of the created bones that fit a format [thighName, thighTwistA, thighTwistB, thighTwistC, calfName, etc]
+ createdBones = self.returnCreatedJoints
+ #list all base names of spinBox/checkBox joints
+ removeBones = ["ball", "thigh_twist_0", "calf_twist_0", "pinky", "index", "bigtoe", "ring", "middle"]
+
+ removeList = []
+ for bone in createdBones:
+ for removeBone in removeBones:
+ if bone.find(removeBone) != -1:
+ removeList.append(bone)
+
+
+ keepBones = []
+ for bone in createdBones:
+ if bone not in removeList:
+ keepBones.append(bone)
+
+ #get prefix/suffix
+ name = self.groupBox.title()
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ if len(prefix) > 0:
+ if prefix.find("_") == -1:
+ prefix = prefix + "_"
+ if len(suffix) > 0:
+ if suffix.find("_") == -1:
+ suffix = "_" + suffix
+
+ legJoints = [keepBones[0]]
+
+ #get thigh twists, calf twists, and toes
+ thighTwists = self.thighTwistNum.value()
+ for i in range(thighTwists):
+ legJoints.append(prefix + "thigh_twist_0" + str(i + 1) + suffix)
+ legJoints.append(keepBones[1])
+
+ calfTwists = self.calfTwistNum.value()
+ for i in range(calfTwists):
+ legJoints.append(prefix + "calf_twist_0" + str(i + 1) + suffix)
+ legJoints.append(keepBones[2])
+
+ ballJoint = self.ballJoint.isChecked()
+ if ballJoint:
+ legJoints.append(prefix + "ball" + suffix)
+
+ #toes
+ bigToes = self.bigToeNum.value()
+ bigToeJoints = ["proximal_phalange", "distal_phalange"]
+ toeJoints = ["proximal_phalange", "middle_phalange", "distal_phalange"]
+ for i in range(bigToes):
+ legJoints.append(prefix + "bigtoe_" + bigToeJoints[i] + suffix)
+
+ indexToes = self.indexToeNum.value()
+ for i in range(indexToes):
+ legJoints.append(prefix + "index_" + toeJoints[i] + suffix)
+
+ middleToes = self.middleToeNum.value()
+ for i in range(middleToes):
+ legJoints.append(prefix + "middle_" + toeJoints[i] + suffix)
+
+ ringToes = self.ringToeNum.value()
+ for i in range(ringToes):
+ legJoints.append(prefix + "ring_" + toeJoints[i] + suffix)
+
+ pinkyToes = self.pinkyToeNum.value()
+ for i in range(pinkyToes):
+ legJoints.append(prefix + "pinky_" + toeJoints[i] + suffix)
+
+ #metatarsals
+ if self.bigToeMeta.isChecked():
+ legJoints.append(prefix + "bigtoe_metatarsal" + suffix)
+ if self.indexToeMeta.isChecked():
+ legJoints.append(prefix + "index_metatarsal" + suffix)
+ if self.middleToeMeta.isChecked():
+ legJoints.append(prefix + "middle_metatarsal" + suffix)
+ if self.ringToeMeta.isChecked():
+ legJoints.append(prefix + "ring_metatarsal" + suffix)
+ if self.pinkyToeMeta.isChecked():
+ legJoints.append(prefix + "pinky_metatarsal" + suffix)
+
+
+ #build attrString
+ attrString = ""
+ for bone in legJoints:
+ attrString += bone + "::"
+
+ networkNode = self.returnNetworkNode
+ cmds.setAttr(networkNode + ".Created_Bones", lock = False)
+ cmds.setAttr(networkNode + ".Created_Bones", attrString, type = "string", lock = True)
+
+ #reset button
+ self.applyButton.setEnabled(False)
+
+ #hide/show noToes geo based on numToes
+ numToes = 0
+ for each in [self.bigToeNum, self.indexToeNum, self.middleToeNum, self.ringToeNum, self.pinkyToeNum]:
+ value = each.value()
+ if value > 0:
+ numToes += 1
+ cmds.setAttr(self.name + "_noToes_bone_geo.v", lock = False)
+ if numToes > 0:
+ cmds.setAttr(self.name + "_noToes_bone_geo.v", 0, lock = True)
+ else:
+ cmds.setAttr(self.name + "_noToes_bone_geo.v", 1, lock = True)
+
+ #update joint mover
+ self.editJointMoverViaSpinBox(self.bigToeNum, "bigtoe", True)
+ self.editJointMoverViaSpinBox(self.indexToeNum, "index", False)
+ self.editJointMoverViaSpinBox(self.middleToeNum, "middle", False)
+ self.editJointMoverViaSpinBox(self.ringToeNum, "ring", False)
+ self.editJointMoverViaSpinBox(self.pinkyToeNum, "pinky", False)
+
+ self.editJointMoverTwistBones(self.thighTwistNum, "thigh")
+ self.editJointMoverTwistBones(self.calfTwistNum, "calf")
+
+ self.includeBallJoint(False)
+
+ self.editMetaTarsals(self.bigToeMeta, "bigtoe")
+ self.editMetaTarsals(self.indexToeMeta, "index")
+ self.editMetaTarsals(self.middleToeMeta, "middle")
+ self.editMetaTarsals(self.ringToeMeta, "ring")
+ self.editMetaTarsals(self.pinkyToeMeta, "pinky")
+
+
+ #set network node attributes
+ cmds.setAttr(networkNode + ".thighTwists", lock = False)
+ cmds.setAttr(networkNode + ".thighTwists", thighTwists, lock = True)
+
+ cmds.setAttr(networkNode + ".calfTwists", lock = False)
+ cmds.setAttr(networkNode + ".calfTwists", calfTwists, lock = True)
+
+ cmds.setAttr(networkNode + ".bigToeJoints", lock = False)
+ cmds.setAttr(networkNode + ".bigToeJoints", bigToes, lock = True)
+
+ cmds.setAttr(networkNode + ".indexToeJoints", lock = False)
+ cmds.setAttr(networkNode + ".indexToeJoints", indexToes, lock = True)
+
+ cmds.setAttr(networkNode + ".middleToeJoints", lock = False)
+ cmds.setAttr(networkNode + ".middleToeJoints", middleToes, lock = True)
+
+ cmds.setAttr(networkNode + ".ringToeJoints", lock = False)
+ cmds.setAttr(networkNode + ".ringToeJoints", ringToes, lock = True)
+
+ cmds.setAttr(networkNode + ".pinkyToeJoints", lock = False)
+ cmds.setAttr(networkNode + ".pinkyToeJoints", pinkyToes, lock = True)
+
+ cmds.setAttr(networkNode + ".includeBall", lock = False)
+ cmds.setAttr(networkNode + ".includeBall", ballJoint, lock = True)
+
+ cmds.setAttr(networkNode + ".bigToeMeta", lock = False)
+ cmds.setAttr(networkNode + ".bigToeMeta", self.bigToeMeta.isChecked(), lock = True)
+
+ cmds.setAttr(networkNode + ".indexToeMeta", lock = False)
+ cmds.setAttr(networkNode + ".indexToeMeta", self.indexToeMeta.isChecked(), lock = True)
+
+ cmds.setAttr(networkNode + ".ringToeMeta", lock = False)
+ cmds.setAttr(networkNode + ".ringToeMeta", self.ringToeMeta.isChecked(), lock = True)
+
+ cmds.setAttr(networkNode + ".middleToeMeta", lock = False)
+ cmds.setAttr(networkNode + ".middleToeMeta", self.middleToeMeta.isChecked(), lock = True)
+
+ cmds.setAttr(networkNode + ".pinkyToeMeta", lock = False)
+ cmds.setAttr(networkNode + ".pinkyToeMeta", self.pinkyToeMeta.isChecked(), lock = True)
+
+ #update outliner
+ self.updateOutliner()
+ self.updateBoneCount()
+
+ #clear selection
+ cmds.select(clear = True)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pinModule(self, state):
+
+ networkNode = self.returnNetworkNode
+
+ if state:
+ topLevelMover = self.name + "_thigh_mover_grp"
+ loc = cmds.spaceLocator()[0]
+ cmds.setAttr(loc + ".v", False, lock = True)
+ constraint = cmds.parentConstraint(topLevelMover, loc)[0]
+ cmds.delete(constraint)
+ const = cmds.parentConstraint(loc, topLevelMover)[0]
+
+
+ if not cmds.objExists(networkNode + ".pinConstraint"):
+ cmds.addAttr(networkNode, ln = "pinConstraint", keyable = True, at = "message")
+
+ cmds.connectAttr(const + ".message", networkNode + ".pinConstraint")
+
+ if not state:
+ connections = cmds.listConnections(networkNode + ".pinConstraint")
+ if len(connections) > 0:
+ constraint = connections[0]
+ cmds.delete(constraint)
+
+ cmds.select(clear = True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skinProxyGeo(self):
+
+ #get the network node
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ #get this module's proxy geo meshes
+ cmds.select(name + "_mover_grp", hi = True)
+ proxyGeoMeshes = []
+ selection = cmds.ls(sl = True)
+ for each in selection:
+ if each.find("proxy_geo") != -1:
+ parent = cmds.listRelatives(each, parent = True)[0]
+ if parent != name + "_noToes_bone_geo":
+ if cmds.nodeType(each) == "transform":
+ proxyGeoMeshes.append(each)
+
+
+ #skin the proxy geo meshes
+ for mesh in proxyGeoMeshes:
+ dupeMesh = cmds.duplicate(mesh, name = "skin_" + mesh)[0]
+ cmds.setAttr(dupeMesh + ".overrideEnabled", lock = False)
+ cmds.setAttr(dupeMesh + ".overrideDisplayType", 0)
+
+ #create skinned geo group
+ if not cmds.objExists("skinned_proxy_geo"):
+ cmds.group(empty = True, name = "skinned_proxy_geo")
+
+ cmds.parent(dupeMesh, "skinned_proxy_geo")
+
+ boneName = mesh.partition(name + "_")[2]
+ boneName = boneName.partition("_proxy_geo")[0]
+ joint = prefix + boneName + suffix
+
+ if not cmds.objExists(joint):
+ cmds.delete(dupeMesh)
+
+ else:
+ cmds.select([dupeMesh, joint])
+ cmds.skinCluster(tsb = True, maximumInfluences = 1, obeyMaxInfluences = True, bindMethod = 0, skinMethod = 0, normalizeWeights = True)
+ cmds.select(clear = True)
+
+
+
+ #SPECIAL CASE FOR TOES/NO TOES
+ numToes = 0
+ for attr in ["bigToeJoints", "indexToeJoints", "middleToeJoints", "ringToeJoints", "pinkyToeJoints"]:
+ value = cmds.getAttr(networkNode + "." + attr)
+ if value > 0:
+ numToes += 1
+
+ if numToes == 0:
+ if cmds.getAttr(networkNode + ".includeBall") == False:
+ joint = prefix + "foot" + suffix
+ else:
+ joint = prefix + "ball" + suffix
+
+ #dupe the toe_proxy geo
+ dupeMesh = cmds.duplicate(name + "_toe_proxy_geo")[0]
+ cmds.select(dupeMesh, hi = True)
+ cmds.delete(constraints = True)
+ cmds.parent(dupeMesh, "skinned_proxy_geo")
+
+ #skin the geo
+ if not cmds.objExists(joint):
+ cmds.delete(dupeMesh)
+
+ else:
+ cmds.select([dupeMesh, joint])
+ cmds.skinCluster(tsb = True, maximumInfluences = 1, obeyMaxInfluences = True, bindMethod = 0, skinMethod = 0, normalizeWeights = True)
+ cmds.select(clear = True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def changeSide(self):
+
+ #gather information (current name, current parent, etc)
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ currentSide = cmds.getAttr(networkNode + ".side")
+
+ if cmds.getAttr(networkNode + ".aimMode") == True:
+ self.aimMode_Setup(False)
+
+ #call on base class delete
+ cmds.select(self.name + "_mover_grp", hi = True)
+ nodes = cmds.ls(sl = True)
+ for node in nodes:
+ cmds.lockNode(lock = False)
+ cmds.delete(self.name + "_mover_grp")
+
+
+ #figure out side
+ if currentSide == "Left":
+ cmds.setAttr(networkNode + ".side", lock = False)
+ cmds.setAttr(networkNode + ".side", "Right", type = "string", lock = True)
+ side = "Right"
+ if currentSide == "Right":
+ cmds.setAttr(networkNode + ".side", lock = False)
+ cmds.setAttr(networkNode + ".side", "Left", type = "string", lock = True)
+ side = "Left"
+
+
+ #build new jmPath name
+ jmPath = jointMover.partition(".ma")[0] + "_" + side + ".ma"
+ self.jointMover_Build(jmPath)
+
+ #parent the joint mover to the offset mover of the parent
+ mover = ""
+
+ if parent == "root":
+ cmds.parent(name + "_mover_grp", "root_mover")
+ mover = "root_mover"
+
+ else:
+ #find the parent mover name to parent to
+ networkNodes = utils.returnRigModules()
+ mover = utils.findMoverNodeFromJointName(networkNodes, parent)
+ if mover != None:
+ cmds.parent(name + "_mover_grp", mover)
+
+ #create the connection geo between the two
+ childMover = utils.findOffsetMoverFromName(name)
+ rigging.createBoneConnection(mover, childMover, name)
+ self.applyModuleChanges(self)
+
+ self.aimMode_Setup(True)
+
+
+ cmds.select(clear = True)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def aimMode_Setup(self, state):
+
+ #get attributes needed
+ name = self.groupBox.title()
+ networkNode = self.returnNetworkNode
+ side = cmds.getAttr(networkNode + ".side")
+
+ #setup aim vector details per side
+ legAim = [-1, 0, 0]
+ legUp = [1, 0, 0]
+ ballAim = [0, -1, 0]
+ toeAim = [1, 0, 0]
+ toeUp = [0, 1, 0]
+
+ if side == "Right":
+ legAim = [1, 0, 0]
+ legUp = [-1, 0, 0]
+ ballAim = [0, 1, 0]
+ toeAim = [-1, 0, 0]
+ toeUp = [0, -1, 0]
+
+ #if passed in state is True:
+ if state:
+ #setup aim constraints
+
+ #mesh movers on thigh/calf
+ cmds.aimConstraint(name + "_calf_lra", name + "_thigh_mover_geo", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1], mo = True)
+ cmds.aimConstraint(name + "_foot_lra", name + "_calf_mover_geo", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1], mo = True)
+
+
+ cmds.aimConstraint(name + "_calf_mover_offset", name + "_thigh_mover_offset", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1])
+ cmds.aimConstraint(name + "_foot_mover_offset", name + "_calf_mover_offset", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1])
+
+ #ball
+ if cmds.getAttr(name + "_ball_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ball_mover_offset", name + "_foot_mover_offset", aimVector = ballAim, upVector = legUp, wut = "scene", wu = [0, 0, 1], mo = True)
+
+ #big toe
+ if cmds.getAttr(name + "_bigtoe_proximal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_bigtoe_proximal_phalange_mover_offset", name + "_bigtoe_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_bigtoe_distal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_bigtoe_distal_phalange_mover_offset", name + "_bigtoe_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+
+ #index toe
+ if cmds.getAttr(name + "_index_proximal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_index_proximal_phalange_mover_offset", name + "_index_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_index_middle_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_index_middle_phalange_mover_offset", name + "_index_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_index_distal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_index_distal_phalange_mover_offset", name + "_index_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+
+ #middle toe
+ if cmds.getAttr(name + "_middle_proximal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_middle_proximal_phalange_mover_offset", name + "_middle_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_middle_middle_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_middle_middle_phalange_mover_offset", name + "_middle_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_middle_distal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_middle_distal_phalange_mover_offset", name + "_middle_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+
+ #ring toe
+ if cmds.getAttr(name + "_ring_proximal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ring_proximal_phalange_mover_offset", name + "_ring_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_ring_middle_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ring_middle_phalange_mover_offset", name + "_ring_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_ring_distal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_ring_distal_phalange_mover_offset", name + "_ring_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+
+ #pinky toe
+ if cmds.getAttr(name + "_pinky_proximal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_pinky_proximal_phalange_mover_offset", name + "_pinky_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_pinky_middle_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_pinky_middle_phalange_mover_offset", name + "_pinky_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+ if cmds.getAttr(name + "_pinky_distal_phalange_mover_grp.v") == True:
+ cmds.aimConstraint(name + "_pinky_distal_phalange_mover_offset", name + "_pinky_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1])
+
+ #if passed in state is False:
+ if not state:
+ cmds.select(name + "_mover_grp", hi = True)
+ aimConstraints = cmds.ls(sl = True, exactType = "aimConstraint")
+
+ for constraint in aimConstraints:
+ cmds.lockNode(constraint, lock = False)
+ cmds.delete(constraint)
+
+ self.bakeOffsets()
+ cmds.select(clear = True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def coplanarMode(self):
+
+ #current selection
+ currentSelection = cmds.ls(sl = True)
+
+ #get the state of the button
+ state = self.coplanarBtn.isChecked()
+
+ #write the attribute on the module
+ networkNode = self.returnNetworkNode
+
+ import System.utils as utils
+
+ aimState = cmds.getAttr(networkNode + ".aimMode")
+
+ if state:
+
+
+ #lock out offset movers as they aren't to be used in coplanar mode
+ offsetMovers = self.returnJointMovers[1]
+ for mover in offsetMovers:
+ cmds.lockNode(mover, lock = False)
+ for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]:
+ try:
+ cmds.setAttr(mover + attr, lock = True)
+ except:
+ pass
+
+ #fire script job that watches the coplanarIkHandle attributes, and when they change, snap to IK knee in tz
+ self.coplanarScriptJob1 = cmds.scriptJob(attributeChange = [self.name + "_coplanarIkHandle.translate", partial(riggingUtils.coPlanarModeSnap, self, self.name + "_coplanar_knee", self.name + "_calf_mover_offset", [self.name + "_coplanar_thigh", self.name + "_coplanar_knee"], [self.name + "_thigh_mover_offset", self.name + "_calf_mover_offset"], self.name + "_foot_mover", [])], kws = True)
+
+ #make sure aim mode is on
+ if not aimState:
+ self.aimMode_Setup(True)
+
+
+ #reselect current selection
+ if len(currentSelection) > 0:
+ cmds.select(currentSelection)
+
+ if not state:
+ #unlock all offset movers
+ offsetMovers = self.returnJointMovers[1]
+ for mover in offsetMovers:
+ for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]:
+ try:
+ cmds.setAttr(mover + attr, lock = False)
+
+ except:
+ pass
+
+ cmds.lockNode(mover, lock = True)
+
+ cmds.scriptJob(kill = self.coplanarScriptJob1)
+ self.aimMode_Setup(False)
+
+ if aimState:
+ self.aimMode_Setup(True)
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def setupModelPoseForRig(self):
+
+ createdConstraints = []
+
+ legJoints = self.getMainLegJoints()
+
+ thighMover = self.name + "_thigh_mover_offset"
+ calfMover = self.name + "_calf_mover_offset"
+ footMover = self.name + "_foot_mover_offset"
+
+ footCtrlConst = cmds.parentConstraint(footMover, self.ikFootCtrl, mo = True)[0]
+ createdConstraints.append(footCtrlConst)
+
+ fkThighConst = cmds.parentConstraint(thighMover, "fk_" + legJoints[0] + "_anim")[0]
+ createdConstraints.append(fkThighConst)
+
+ fkCalfConst = cmds.parentConstraint(calfMover, "fk_" + legJoints[1] + "_anim")[0]
+ createdConstraints.append(fkCalfConst)
+
+ fkFootConst = cmds.parentConstraint(footMover, "fk_" + legJoints[2] + "_anim")[0]
+ createdConstraints.append(fkFootConst)
+
+
+ if len(legJoints) == 4:
+ if legJoints[3] != None:
+ ballMover = self.name + "_ball_mover_offset"
+
+ fkBallConst = cmds.parentConstraint(ballMover, "fk_" + legJoints[3] + "_anim")[0]
+ createdConstraints.append(fkBallConst)
+
+ return createdConstraints
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def matchModelPose(self):
+
+ #match the knee twist attribute to the offset mover for the knee
+ legJoints = self.getMainLegJoints()
+
+ #first create locators
+ loc1 = cmds.spaceLocator(name = self.name + "_matchLoc1")[0]
+ loc2 = cmds.spaceLocator(name = self.name + "_matchLoc2")[0]
+
+ constraint = cmds.parentConstraint(self.name + "_calf_mover_offset", loc1)[0]
+ cmds.delete(constraint)
+ cmds.parent(loc1, self.name + "_calf_mover_offset")
+
+ constraint = cmds.parentConstraint(legJoints[1], loc2)[0]
+ cmds.delete(constraint)
+ cmds.parent(loc2, legJoints[1])
+
+ cmds.move(0, -30, 0, loc1, os = True, r = True)
+ cmds.move(0, -30, 0, loc2, os = True, r = True)
+
+ for x in range(1500):
+ angle = mathUtils.getAngleBetween(loc1, loc2)
+ if abs(angle) > .1:
+ self.matchKneeTwist(angle, loc1, loc2)
+ else:
+ break
+
+ cmds.delete(loc1)
+ cmds.delete(loc2)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def matchKneeTwist(self, angle, object1, object2):
+
+ currentVal = cmds.getAttr(self.ikFootCtrl + ".knee_twist")
+ cmds.setAttr(self.ikFootCtrl + ".knee_twist", currentVal + .25)
+
+ newAngle = mathUtils.getAngleBetween(object1, object2)
+ if newAngle > angle:
+ cmds.setAttr(self.ikFootCtrl + ".knee_twist", currentVal - .5)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX(self, importMethod, character):
+
+ returnControls = []
+
+ networkNode = self.returnRigNetworkNode
+ fkControls = cmds.getAttr(networkNode + ".fkControls")
+ ikControls = cmds.getAttr(networkNode + ".ikV1Controls")
+ moduleName = cmds.getAttr(networkNode + ".moduleName")
+
+
+ #find created joints
+ joints = cmds.getAttr(networkNode + ".Created_Bones")
+
+ splitJoints = joints.split("::")
+ createdJoints = []
+ legJoints = []
+
+ for bone in splitJoints:
+ if bone != "":
+ createdJoints.append(bone)
+
+ for joint in createdJoints:
+ if joint.find("thigh") != -1:
+ if joint.find("twist") == -1:
+ thighJoint = joint
+ legJoints.append(thighJoint)
+
+ if joint.find("calf") != -1:
+ if joint.find("twist") == -1:
+ calfJoint = joint
+ legJoints.append(calfJoint)
+
+ if joint.find("foot") != -1:
+ footJoint = joint
+ legJoints.append(footJoint)
+
+ if joint.find("ball") != -1:
+ ballJoint = joint
+ legJoints.append(ballJoint)
+
+
+ #Handle Import Method/Constraints
+ if importMethod == "FK":
+ cmds.setAttr(character + ":" + moduleName + "_settings.mode", 0)
+
+ for joint in legJoints:
+ cmds.parentConstraint(joint, character + ":fk_" + joint + "_anim")
+ returnControls.append(character + ":fk_" + joint + "_anim")
+
+
+ if importMethod == "IK":
+ cmds.parentConstraint(legJoints[2], character + ":ik_" + legJoints[2] + "_anim", mo = True)
+ returnControls.append(character + ":ik_" + legJoints[2] + "_anim")
+
+ if importMethod == "Both":
+ cmds.parentConstraint(legJoints[2], character + ":ik_" + legJoints[2] + "_anim", mo = True)
+ returnControls.append(character + ":ik_" + legJoints[2] + "_anim")
+
+ for joint in legJoints:
+ cmds.parentConstraint(joint, character + ":fk_" + joint + "_anim")
+ returnControls.append(character + ":fk_" + joint + "_anim")
+
+
+ if importMethod == "None":
+ pass
+
+ return returnControls
+
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX_post(self, importMethod, character):
+
+ #get leg joints/controls
+ legJoints = self.getMainLegJoints()
+ self.ikFootCtrl = character + ":ik_" + legJoints[2] + "_anim"
+
+ cmds.refresh(force = True)
+
+ #get start and end frames
+ start = cmds.playbackOptions(q = True, min = True)
+ end = cmds.playbackOptions(q = True, max = True)
+
+ if importMethod == "IK" or importMethod == "Both":
+ for i in range(int(start), int(end) + 1):
+ cmds.currentTime(i)
+ self.ikKneeMatch(character, legJoints[1], legJoints[0], character + ":" + legJoints[1])
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def switchMode(self, mode, checkBox, range = False):
+
+ #get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ #are we matching?
+ if not range:
+ match = checkBox.isChecked()
+ else:
+ match = True
+
+ #if being called from match over frame range
+ if range:
+ if mode == matchData[1][0]:
+ mode = "FK"
+ if mode == matchData[1][1]:
+ mode = "IK"
+
+
+ #switch to FK mode
+ if mode == "FK":
+ #get current mode
+ currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode")
+ if currentMode == 0.0:
+ cmds.warning("Already in FK mode.")
+ return
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if match:
+ #get fk controls
+ controls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+
+ #create a duplicate chain
+ topCtrl = controls[0]
+ topGrp = cmds.listRelatives(namespace + ":" + topCtrl, parent = True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world = True)
+
+
+ #match the fk controls to the corresponding joint
+ for control in controls:
+ joint = control.partition("fk_")[2].partition("_anim")[0]
+ joint = namespace + ":" + joint
+ constraint = cmds.parentConstraint(joint, control)[0]
+ cmds.delete(constraint)
+
+ translate = cmds.getAttr(control + ".translate")[0]
+ rotate = cmds.getAttr(control + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], type = 'double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type = 'double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ #delete dupes
+ cmds.delete(newControls[0])
+
+ #switch modes
+ if not range:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+
+ #switch to IK mode
+ if mode == "IK":
+
+ #get current mode
+ currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode")
+ if currentMode == 1.0:
+ return
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if match:
+
+ #get IK controls
+ controls = json.loads(cmds.getAttr(networkNode + ".ikV1Controls"))
+
+ #create a duplicate foot anim
+ control = controls[0]
+ topGrp = cmds.listRelatives(namespace + ":" + control, parent = True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world = True)
+
+
+ #duplicate the control once more and parent under the fkMatch node
+ matchCtrl = cmds.duplicate(control, po = True)[0]
+ cmds.parent(matchCtrl, control + "_fkMatch")
+
+ #match the foot anim to the foot joint
+ joint = control.partition("ik_")[2].partition("_anim")[0]
+ joint = namespace + ":" + joint
+ constraint = cmds.parentConstraint(joint, control + "_fkMatch")[0]
+ cmds.delete(constraint)
+
+ #unparent the match control from the fkMatch, and put it under the topGrp
+ cmds.parent(matchCtrl, topGrp)
+
+ #this will now give use good values
+ translate = cmds.getAttr(matchCtrl + ".translate")[0]
+ rotate = cmds.getAttr(matchCtrl + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], type = 'double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type = 'double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ #delete dupes
+ cmds.delete(newControls[0])
+ cmds.delete(matchCtrl)
+
+
+ #match the toe wiggle control to the ball (if applicable)
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ if len(fkControls) > 3:
+ toeWiggle = controls[3]
+ ball = fkControls[3]
+
+ rotate = cmds.getAttr(namespace + ":" + ball + ".rotate")[0]
+ cmds.setAttr(namespace + ":" + toeWiggle + ".rotate", rotate[0], rotate[1], rotate[2], type = 'double3')
+
+
+ #match the knee twist
+ legJoints = self.getMainLegJoints()
+ self.ikKneeMatch(namespace, namespace + ":" + legJoints[1], namespace + ":" + legJoints[0], namespace + ":ikV1_" + legJoints[1] + "_joint")
+
+
+ #switch modes
+ if not range:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def ikKneeMatch(self, character, startJoint, middleJoint, endJoint):
+
+ #get leg joints/controls
+ legJoints = self.getMainLegJoints()
+ self.ikFootCtrl = character + ":ik_" + legJoints[2] + "_anim"
+
+ #create locators
+ startPoint = cmds.spaceLocator()[0]
+ cmds.parentConstraint(startJoint, startPoint)[0]
+
+ midPoint = cmds.spaceLocator()[0]
+ cmds.parentConstraint(middleJoint, midPoint)[0]
+
+ endPoint = cmds.spaceLocator()[0]
+ cmds.parentConstraint(endJoint, endPoint)[0]
+
+ #create angle node and hook up attrs to locs
+ angleDimNode = cmds.createNode("angleDimension")
+ cmds.connectAttr(startPoint + ".translate", angleDimNode + ".startPoint")
+ cmds.connectAttr(midPoint + ".translate", angleDimNode + ".middlePoint")
+ cmds.connectAttr(endPoint + ".translate", angleDimNode + ".endPoint")
+
+
+ #find general direction to go in
+ origAngle = cmds.getAttr(angleDimNode + ".angle")
+
+ direction = 1
+ if origAngle != 0:
+ cmds.setAttr(self.ikFootCtrl + ".knee_twist", 1)
+ newAngle = cmds.getAttr(angleDimNode + ".angle")
+
+ if newAngle > origAngle:
+ direction = -1
+
+
+ #reset knee twist
+ cmds.setAttr(self.ikFootCtrl + ".knee_twist", 0)
+
+
+ #HIDE EVERYTHING
+ panels = cmds.getPanel( type = "modelPanel")
+ for panel in panels:
+ editor = cmds.modelPanel(panel, q = True, modelEditor = True)
+ cmds.modelEditor(editor, edit = True, allObjects = 0)
+
+
+ #find best angle
+ for x in range(3000):
+
+ angle = cmds.getAttr(angleDimNode + ".angle")
+
+ if angle > 0.5:
+ currentVal = cmds.getAttr(self.ikFootCtrl + ".knee_twist")
+ cmds.setAttr(self.ikFootCtrl + ".knee_twist", currentVal + direction)
+ cmds.refresh()
+
+ else:
+ cmds.setKeyframe(self.ikFootCtrl + ".knee_twist")
+ cmds.delete([startPoint, midPoint, endPoint])
+ cmds.delete(cmds.listRelatives(angleDimNode, parent = True)[0])
+ break
+
+ #SHOW EVERYTHING
+ panels = cmds.getPanel( type = "modelPanel")
+ for panel in panels:
+ editor = cmds.modelPanel(panel, q = True, modelEditor = True)
+ cmds.modelEditor(editor, edit = True, allObjects = 1)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def selectRigControls(self, mode):
+
+
+ #get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ #list any attributes on the network node that contain "controls"
+ controls = cmds.listAttr(networkNode, st = "*Controls")
+ fkControls = ["fkControls", "thighTwistControls", "calfTwistControls"]
+ ikControls = ["ikV1Controls"]
+
+ #get that data on that attr
+ for control in controls:
+
+ #select all controls
+ if mode == "all":
+ data = json.loads(cmds.getAttr(networkNode + "." + control))
+ if data != None:
+ for each in data:
+ cmds.select(namespace + ":" + each, add = True)
+
+ #select fk controls
+ if mode == "fk":
+ if control in fkControls:
+ data = json.loads(cmds.getAttr(networkNode + "." + control))
+ if data != None:
+ for each in data:
+ if each.find("fk") != -1:
+ cmds.select(namespace + ":" + each, add = True)
+
+ #select ik controls
+ if mode == "ik":
+ if control in ikControls:
+ data = json.loads(cmds.getAttr(networkNode + "." + control))
+ if data != None:
+ for each in data:
+ if each.find("fk") == -1:
+ cmds.select(namespace + ":" + each, add = True)
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ @classmethod
+ def getinstances(cls):
+ for ref in cls._instances:
+ obj = ref()
+
+
diff --git a/Core/Scripts/RigModules/ART_Root.py b/Core/Scripts/RigModules/ART_Root.py
new file mode 100644
index 0000000..74d3ea5
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Root.py
@@ -0,0 +1,246 @@
+#standard imports
+import maya.cmds as cmds
+import json
+from functools import partial
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+#external imports
+from System.ART_RigModule import ART_RigModule
+import System.riggingUtils as riggingUtils
+import System.interfaceUtils as interfaceUtils
+
+#file attributes
+icon = "Core/Icons/Modules/root.png"
+search = "Root"
+className = "ART_Root"
+baseName = "root"
+fbxImport = ["None", "Root Motion: Offset", "Root Motion: Master", "Root Motion: Root"]
+matchData = [False, None]
+controlTypes = [["rootControls", "FK"]]
+
+
+class ART_Root(ART_RigModule):
+
+ def __init__(self, rigUiInst, moduleUserName):
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+
+ ART_RigModule.__init__(self, "ART_Root_Module", "ART_Root", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ #call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ #add custom attributes for this specific module
+ cmds.addAttr(self.networkNode, sn = "Created_Bones", dt = "string", keyable = False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", "root", type = "string", lock = True)
+
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+ #groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 85, False)
+
+ #add a label to the root module saying this module cannot be edited or removed
+ self.layout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.label = QtWidgets.QLabel("All rigs must have a root module. This module cannot be edited or removed.")
+ self.layout.addWidget(self.label)
+ self.label.setGeometry(QtCore.QRect(10, 20, 300, 60))
+ self.label.setMinimumHeight(60)
+ self.label.setWordWrap(True)
+
+
+ #add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pickerUI(self, center, animUI, networkNode, namespace):
+
+ #create qBrushes
+ yellowBrush = QtCore.Qt.yellow
+ blueBrush = QtGui.QColor(100,220,255)
+ purpleBrush = QtGui.QColor(111,48,161)
+ clearBrush = QtGui.QBrush(QtCore.Qt.black)
+ clearBrush.setStyle(QtCore.Qt.NoBrush)
+
+ #create border item
+ if networkNode.find(":") != -1:
+ moduleNode = networkNode.partition(":")[2]
+ else:
+ moduleNode = networkNode
+ borderItem = interfaceUtils.pickerBorderItem(center.x() - 40, center.y() - 70, 50, 98, clearBrush, moduleNode)
+
+ #get controls + namespace
+ networkNode = self.returnNetworkNode
+ controls = json.loads(cmds.getAttr(networkNode + ".rootControls"))
+
+ #master anim button
+ masterBtn = interfaceUtils.pickerButton(30, 30, [10,2], namespace + controls[0], yellowBrush, borderItem)
+ interfaceUtils.addTextToButton("M", masterBtn)
+
+ #offset anim button
+ offsetBtn = interfaceUtils.pickerButton(30, 30, [10,34], namespace + controls[1], blueBrush, borderItem)
+ interfaceUtils.addTextToButton("O", offsetBtn)
+
+ #root anim button
+ rootBtn = interfaceUtils.pickerButton(30, 30, [10,66], namespace + controls[2], purpleBrush, borderItem)
+ interfaceUtils.addTextToButton("R", rootBtn)
+
+ #=======================================================================
+ # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5)
+ #=======================================================================
+ scriptJob = cmds.scriptJob(event = ["SelectionChanged", partial(self.selectionScriptJob_animUI,[[masterBtn,namespace + controls[0], yellowBrush],[offsetBtn, namespace + controls[1], blueBrush],[rootBtn, namespace + controls[2], purpleBrush]])], kws = True)
+ borderItem.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ return [borderItem, False, scriptJob]
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addJointMoverToOutliner(self):
+
+ index = self.rigUiInst.treeWidget.topLevelItemCount()
+
+ #Add the module to the tree widget in the outliner tab of the rig creator UI
+ self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget)
+ self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name)
+ foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255))
+ self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground)
+ #add the buttons
+ self.createGlobalMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst)
+
+ #create selection script job for module
+ self.updateBoneCount()
+ self.createScriptJob()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRigCustom(self, textEdit, uiInst):
+
+ if textEdit != None:
+ textEdit.append(" Building Root Rig..")
+
+ #get the created joint
+ networkNode = self.returnNetworkNode
+ rootJoint = cmds.getAttr(networkNode + ".Created_Bones")
+
+ #create the rig grp
+ rigGrp = cmds.group(empty = True, name = "rig_grp")
+
+
+ #Need to build 3 controls, the master, the offset, and the root control
+ masterControls = riggingUtils.createControlFromMover(rootJoint, networkNode, False, True)
+
+ #rename controls
+ masterControl = cmds.rename(masterControls[0], "master_anim")
+ masterCtrlGrp = cmds.rename(masterControls[1], "master_anim_grp")
+ masterSpaceSwitch = cmds.rename(masterControls[2], "master_anim_space_switcher")
+ masterSpace = cmds.rename(masterControls[3], "master_anim_space_switcher_follow")
+
+ cmds.parent(masterSpace, rigGrp)
+ #scale masterControl
+ cmds.setAttr(masterControl + ".scale", 2, 2, 2, type = "double3")
+ cmds.makeIdentity(masterControl, t = 1, r = 1, s = 1, apply = True)
+
+ #alias attr master control
+ cmds.aliasAttr("globalScale", masterControl + ".scaleZ")
+ cmds.connectAttr(masterControl + ".globalScale", masterControl + ".scaleX")
+ cmds.connectAttr(masterControl + ".globalScale", masterControl + ".scaleY")
+ cmds.setAttr(masterControl + ".scaleX", keyable = False)
+ cmds.setAttr(masterControl + ".scaleY", keyable = False)
+ cmds.setAttr(masterControl + ".visibility", lock = True, keyable = False)
+
+ #create offset anim control
+ offsetAnim = riggingUtils.createControl("circle", 40, "offset_anim", False)
+ cmds.parent(offsetAnim, masterControl)
+ cmds.setAttr(offsetAnim + ".overrideEnabled", 1)
+ cmds.setAttr(offsetAnim + ".overrideColor", 18)
+
+ for attr in [".visibility", ".scaleX", ".scaleY", ".scaleZ"]:
+ cmds.setAttr(offsetAnim + attr, lock = True, keyable = False)
+
+ #create the root control
+ rootAnim = riggingUtils.createControl("sphere", 5, "root_anim", False)
+ cmds.parent(rootAnim, offsetAnim)
+ cmds.makeIdentity(rootAnim, t = 1, r = 1, s = 1, apply = True)
+ cmds.setAttr(rootAnim + ".overrideEnabled", 1)
+ cmds.setAttr(rootAnim + ".overrideColor", 30)
+ cmds.parentConstraint(rootAnim, "driver_root")
+ cmds.scaleConstraint(rootAnim, "driver_root")
+
+ for attr in [".visibility", ".scaleX", ".scaleY", ".scaleZ"]:
+ cmds.setAttr(rootAnim + attr, lock = True, keyable = False)
+
+ if not cmds.objExists(networkNode + ".rootControls"):
+ cmds.addAttr(networkNode, ln = "rootControls", dt = "string")
+
+ controlList = [masterControl, offsetAnim, rootAnim]
+ jsonString = json.dumps(controlList)
+ cmds.setAttr(networkNode + ".rootControls", jsonString, type = "string")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX(self, importMethod, character):
+
+ returnControls = []
+
+ if importMethod == "Root Motion: Offset":
+
+ cmds.parentConstraint("root", character + ":" + "offset_anim")
+ returnControls.append(character + ":" + "offset_anim")
+
+
+ if importMethod == "Root Motion: Master":
+ cmds.parentConstraint("root", character + ":" + "master_anim")
+ returnControls.append(character + ":" + "master_anim")
+
+ if importMethod == "Root Motion: Root":
+ cmds.parentConstraint("root", character + ":" + "root_anim")
+ returnControls.append(character + ":" + "root_anim")
+
+ if importMethod == "None":
+ pass
+
+ return returnControls
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/Scripts/RigModules/ART_Torso.py b/Core/Scripts/RigModules/ART_Torso.py
new file mode 100644
index 0000000..01bcc18
--- /dev/null
+++ b/Core/Scripts/RigModules/ART_Torso.py
@@ -0,0 +1,2394 @@
+import maya.cmds as cmds
+from System.ART_RigModule import ART_RigModule
+import os, time, json, weakref
+from functools import partial
+
+import System.interfaceUtils as interfaceUtils
+import System.riggingUtils as riggingUtils
+import System.utils as utils
+
+from ThirdParty.Qt import QtGui, QtCore, QtWidgets
+
+# file attributes
+icon = "Modules/torso.png"
+hoverIcon = "Modules/hover_torso.png"
+search = "biped:torso:spine"
+className = "ART_Torso"
+jointMover = "Core/JointMover/ART_Torso_3Spine.ma"
+baseName = "torso"
+rigs = ["FK::IK"]
+fbxImport = ["None", "FK", "IK", "Both"]
+matchData = [True, ["Match FK to IK", "Match IK to FK"]]
+controlTypes = [["pelvisControls", "FK"], ["fkControls", "FK"], ["ikControls", "IK"]]
+
+
+# begin class
+class ART_Torso(ART_RigModule):
+ _instances = set()
+
+ def __init__(self, rigUiInst, moduleUserName):
+
+ self.rigUiInst = rigUiInst
+ self.moduleUserName = moduleUserName
+ self.outlinerWidgets = {}
+ self.__class__._instances.add(weakref.ref(self))
+
+ ART_RigModule.__init__(self, "ART_Torso_Module", "ART_Torso", moduleUserName)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addAttributes(self):
+ # call the base class method first to hook up our connections to the master module
+ ART_RigModule.addAttributes(self)
+
+ # add custom attributes for this specific module
+ cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".Created_Bones", "pelvis::spine_01::spine_02::spine_03::", type="string",
+ lock=True)
+
+ cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False)
+ cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True)
+
+ cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".canAim", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".aimMode", False, lock=True)
+
+ # joint mover settings
+
+ cmds.addAttr(self.networkNode, sn="includePelvis", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".includePelvis", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="spineJoints", keyable=False)
+ cmds.setAttr(self.networkNode + ".spineJoints", 3, lock=True)
+
+ # rig creation settings
+ cmds.addAttr(self.networkNode, sn="buildFK", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".buildFK", True, lock=True)
+
+ cmds.addAttr(self.networkNode, sn="buildIK", at="bool", keyable=False)
+ cmds.setAttr(self.networkNode + ".buildIK", True, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skeletonSettings_UI(self, name):
+ networkNode = self.returnNetworkNode
+
+ # groupbox all modules get
+ ART_RigModule.skeletonSettings_UI(self, name, 335, 295, True)
+
+ font = QtGui.QFont()
+ font.setPointSize(8)
+
+ headerFont = QtGui.QFont()
+ headerFont.setPointSize(8)
+ headerFont.setBold(True)
+
+ # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot
+ self.layout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.frame = QtWidgets.QFrame(self.groupBox)
+ self.layout.addWidget(self.frame)
+
+ self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))
+ self.frame.setMinimumSize(QtCore.QSize(320, 260))
+ self.frame.setMaximumSize(QtCore.QSize(320, 260))
+
+ # add layout for custom settings
+ self.customSettingsLayout = QtWidgets.QVBoxLayout(self.frame)
+
+ # current parent
+ self.currentParentMod = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.currentParentMod)
+ self.currentParentLabel = QtWidgets.QLabel("Current Parent: ")
+ self.currentParentLabel.setFont(font)
+ self.currentParentMod.addWidget(self.currentParentLabel)
+
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.currentParent = QtWidgets.QLabel(parent)
+ self.currentParent.setFont(font)
+ self.currentParent.setAlignment(QtCore.Qt.AlignHCenter)
+ self.currentParentMod.addWidget(self.currentParent)
+
+ # button layout for name/parent
+ self.buttonLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.buttonLayout)
+ self.changeNameBtn = QtWidgets.QPushButton("Change Name")
+ self.changeParentBtn = QtWidgets.QPushButton("Change Parent")
+ self.buttonLayout.addWidget(self.changeNameBtn)
+ self.buttonLayout.addWidget(self.changeParentBtn)
+ self.changeNameBtn.setObjectName("blueButton")
+ self.changeParentBtn.setObjectName("blueButton")
+
+ # bake offsets button
+ self.bakeToolsLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.bakeToolsLayout)
+
+ # Bake OFfsets
+ self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets")
+ self.bakeOffsetsBtn.setFont(headerFont)
+ self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn)
+ self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets)
+ self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync")
+
+ self.bakeOffsetsBtn.setObjectName("blueButton")
+
+ # Pelvis Settings
+ spacerItem = QtWidgets.QSpacerItem(200, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ self.pelvisCB = QtWidgets.QCheckBox("Include Pelvis?")
+ self.pelvisCB.setChecked(True)
+ self.customSettingsLayout.addWidget(self.pelvisCB)
+ self.pelvisCB.stateChanged.connect(self.toggleButtonState)
+ spacerItem = QtWidgets.QSpacerItem(200, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ # Spine Bones
+ self.spineLayout = QtWidgets.QHBoxLayout()
+ self.customSettingsLayout.addLayout(self.spineLayout)
+
+ self.numSpineBonesLabel = QtWidgets.QLabel("Number of Spine Bones: ")
+ self.numSpineBonesLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
+ self.numSpineBonesLabel.setMinimumSize(QtCore.QSize(200, 20))
+ self.numSpineBonesLabel.setMaximumSize(QtCore.QSize(200, 20))
+ self.spineLayout.addWidget((self.numSpineBonesLabel))
+
+ self.numSpine = QtWidgets.QSpinBox()
+ self.numSpine.setMaximum(5)
+ self.numSpine.setMinimum(2)
+ self.numSpine.setMinimumSize(QtCore.QSize(100, 20))
+ self.numSpine.setMaximumSize(QtCore.QSize(100, 20))
+ self.numSpine.setValue(3)
+ self.numSpine.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.spineLayout.addWidget(self.numSpine)
+
+ # rebuild button
+ spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ self.customSettingsLayout.addItem(spacerItem)
+
+ self.applyButton = QtWidgets.QPushButton("Apply Changes")
+ self.customSettingsLayout.addWidget(self.applyButton)
+ self.applyButton.setFont(headerFont)
+ self.applyButton.setMinimumSize(QtCore.QSize(300, 40))
+ self.applyButton.setMaximumSize(QtCore.QSize(300, 40))
+ self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ self.applyButton.setEnabled(False)
+
+ # add to the rig cretor UI's module settings layout VBoxLayout
+ self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox)
+
+ # button signal/slots
+ self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst))
+ self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst))
+ self.applyButton.clicked.connect(partial(self.applyModuleChanges, self))
+
+ # signal slot for groupbox checkbox
+ QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible)
+ self.groupBox.setChecked(False)
+
+ # spinBox & checkbox signal/slots
+ self.numSpine.valueChanged.connect(self.toggleButtonState)
+
+ # Populate the settings UI based on the network node attributes
+ self.updateSettingsUI()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pickerUI(self, center, animUI, networkNode, namespace):
+
+ self.namespace = namespace
+
+ # create qBrushes
+ yellowBrush = QtCore.Qt.yellow
+ blueBrush = QtGui.QColor(100, 220, 255)
+ purpleBrush = QtGui.QColor(111, 48, 161)
+ greenBrush = QtGui.QColor(0, 255, 30)
+ clearBrush = QtGui.QBrush(QtCore.Qt.black)
+ clearBrush.setStyle(QtCore.Qt.NoBrush)
+
+ # create the picker border item
+ if networkNode.find(":") != -1:
+ moduleNode = networkNode.partition(":")[2]
+ else:
+ moduleNode = networkNode
+
+ borderItem = interfaceUtils.pickerBorderItem(center.x() - 75, center.y() - 100, 150, 200, clearBrush,
+ moduleNode)
+
+ # get controls
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ fkControls.reverse()
+
+ ikControls = None
+ if cmds.objExists(networkNode + ".ikControls"):
+ ikControls = json.loads(cmds.getAttr(networkNode + ".ikControls"))
+
+ pelvisControls = None
+ if cmds.objExists(networkNode + ".pelvisControls"):
+ pelvisControls = json.loads(cmds.getAttr(networkNode + ".pelvisControls"))
+
+ buttonData = []
+
+ # get number of spine joints
+ spineJoints = int(cmds.getAttr(networkNode + ".spineJoints"))
+
+ if pelvisControls != None:
+ pelvisButton = interfaceUtils.pickerButtonCustom(100, 20, [[0, 0], [100, 0], [90, 20], [10, 20]], [25, 175],
+ namespace + pelvisControls[0], blueBrush, borderItem)
+ bodyButton = interfaceUtils.pickerButton(110, 20, [20, 150], namespace + pelvisControls[1], yellowBrush,
+ borderItem)
+ buttonData.append([pelvisButton, namespace + pelvisControls[0], blueBrush])
+ buttonData.append([bodyButton, namespace + pelvisControls[1], yellowBrush])
+
+ if spineJoints == 2:
+ spine1Button = interfaceUtils.pickerButtonCustom(100, 50, [[10, 0], [100, 0], [110, 50], [0, 50]], [20, 95],
+ namespace + fkControls[0], blueBrush, borderItem)
+ spine2Button = interfaceUtils.pickerButtonCustom(100, 60, [[10, 60], [100, 60], [110, 0], [0, 0]], [20, 30],
+ namespace + fkControls[1], blueBrush, borderItem)
+ buttonData.append([spine1Button, namespace + fkControls[0], blueBrush])
+ buttonData.append([spine2Button, namespace + fkControls[1], blueBrush])
+
+ if spineJoints == 3:
+ chestAnimButton = interfaceUtils.pickerButton(120, 20, [15, 25], namespace + ikControls[0], yellowBrush,
+ borderItem)
+ midAnimButton = interfaceUtils.pickerButton(90, 20, [30, 100], namespace + ikControls[1], yellowBrush,
+ borderItem)
+ buttonData.append([chestAnimButton, namespace + ikControls[0], yellowBrush])
+ buttonData.append([midAnimButton, namespace + ikControls[1], yellowBrush])
+
+ spine1Button = interfaceUtils.pickerButtonCustom(80, 20, [[10, 0], [100, 0], [105, 20], [5, 20]], [20, 125],
+ namespace + fkControls[0], blueBrush, borderItem)
+ spine2Button = interfaceUtils.pickerButtonCustom(80, 20, [[10, 20], [100, 20], [100, 0], [10, 0]], [20, 75],
+ namespace + fkControls[1], blueBrush, borderItem)
+ spine3Button = interfaceUtils.pickerButtonCustom(80, 20, [[10, 20], [100, 20], [105, 0], [5, 0]], [20, 50],
+ namespace + fkControls[2], blueBrush, borderItem)
+ buttonData.append([spine1Button, namespace + fkControls[0], blueBrush])
+ buttonData.append([spine2Button, namespace + fkControls[1], blueBrush])
+ buttonData.append([spine3Button, namespace + fkControls[2], blueBrush])
+
+ if spineJoints == 4:
+ chestAnimButton = interfaceUtils.pickerButton(120, 20, [15, 25], namespace + ikControls[0], yellowBrush,
+ borderItem)
+ midAnimButton = interfaceUtils.pickerButton(90, 15, [30, 90], namespace + ikControls[1], yellowBrush,
+ borderItem)
+ buttonData.append([chestAnimButton, namespace + ikControls[0], yellowBrush])
+ buttonData.append([midAnimButton, namespace + ikControls[1], yellowBrush])
+
+ spine1Button = interfaceUtils.pickerButtonCustom(80, 15, [[10, 0], [100, 0], [105, 15], [5, 15]], [20, 130],
+ namespace + fkControls[0], blueBrush, borderItem)
+ spine2Button = interfaceUtils.pickerButtonCustom(80, 15, [[10, 15], [100, 15], [95, 0], [15, 0]], [20, 110],
+ namespace + fkControls[1], blueBrush, borderItem)
+ spine3Button = interfaceUtils.pickerButtonCustom(80, 15, [[15, 15], [95, 15], [100, 0], [10, 0]], [20, 70],
+ namespace + fkControls[2], blueBrush, borderItem)
+ spine4Button = interfaceUtils.pickerButtonCustom(80, 15, [[10, 15], [100, 15], [110, 0], [0, 0]], [20, 50],
+ namespace + fkControls[3], blueBrush, borderItem)
+ buttonData.append([spine1Button, namespace + fkControls[0], blueBrush])
+ buttonData.append([spine2Button, namespace + fkControls[1], blueBrush])
+ buttonData.append([spine3Button, namespace + fkControls[2], blueBrush])
+ buttonData.append([spine4Button, namespace + fkControls[3], blueBrush])
+
+ if spineJoints == 5:
+ chestAnimButton = interfaceUtils.pickerButton(120, 20, [15, 25], namespace + ikControls[0], yellowBrush,
+ borderItem)
+ midAnimButton = interfaceUtils.pickerButton(90, 20, [30, 95], namespace + ikControls[1], yellowBrush,
+ borderItem)
+ buttonData.append([chestAnimButton, namespace + ikControls[0], yellowBrush])
+ buttonData.append([midAnimButton, namespace + ikControls[1], yellowBrush])
+
+ spine1Button = interfaceUtils.pickerButtonCustom(80, 10, [[0, 10], [110, 10], [105, 0], [5, 0]], [20, 135],
+ namespace + fkControls[0], blueBrush, borderItem)
+ spine2Button = interfaceUtils.pickerButtonCustom(80, 10, [[5, 10], [105, 10], [100, 0], [10, 0]], [20, 120],
+ namespace + fkControls[1], blueBrush, borderItem)
+ spine3Button = interfaceUtils.pickerButtonCustom(80, 10, [[10, 10], [100, 10], [100, 0], [10, 0]], [20, 80],
+ namespace + fkControls[2], blueBrush, borderItem)
+ spine4Button = interfaceUtils.pickerButtonCustom(80, 10, [[10, 10], [100, 10], [105, 0], [5, 0]], [20, 65],
+ namespace + fkControls[3], blueBrush, borderItem)
+ spine5Button = interfaceUtils.pickerButtonCustom(80, 10, [[5, 10], [105, 10], [110, 0], [0, 0]], [20, 50],
+ namespace + fkControls[4], blueBrush, borderItem)
+ buttonData.append([spine1Button, namespace + fkControls[0], blueBrush])
+ buttonData.append([spine2Button, namespace + fkControls[1], blueBrush])
+ buttonData.append([spine3Button, namespace + fkControls[2], blueBrush])
+ buttonData.append([spine4Button, namespace + fkControls[3], blueBrush])
+ buttonData.append([spine5Button, namespace + fkControls[4], blueBrush])
+
+ # =======================================================================
+ # settings button
+ # =======================================================================
+ settingsBtn = interfaceUtils.pickerButton(20, 20, [125, 180], namespace + self.name + "_settings", greenBrush,
+ borderItem)
+ buttonData.append([settingsBtn, namespace + ":" + self.name + "_settings", greenBrush])
+ interfaceUtils.addTextToButton("S", settingsBtn)
+
+ # =======================================================================
+ # go through button data, adding menu items
+ # =======================================================================
+ for each in buttonData:
+ button = each[0]
+
+ fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png"))))
+ ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png"))))
+ zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png"))))
+ zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png"))))
+ selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png"))))
+
+ switchAction = QtWidgets.QAction('Match when Switching', button.menu)
+ switchAction.setCheckable(True)
+ switchAction.setChecked(True)
+
+ button.menu.addAction(selectIcon, "Select All Torso Controls", partial(self.selectRigControls, "all"))
+ button.menu.addAction(selectIcon, "Select FK Torso Controls", partial(self.selectRigControls, "fk"))
+ button.menu.addAction(selectIcon, "Select IK Torso Controls", partial(self.selectRigControls, "ik"))
+
+ button.menu.addSeparator()
+
+ button.menu.addAction(fkIcon, "FK Mode", partial(self.switchMode, "FK", switchAction))
+ button.menu.addAction(ikIcon, "IK Mode", partial(self.switchMode, "IK", switchAction))
+ button.menu.addAction(switchAction)
+
+ button.menu.addSeparator()
+
+ button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True))
+ button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False))
+
+ # =======================================================================
+ # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5)
+ # =======================================================================
+ scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)],
+ kws=True)
+ borderItem.setData(5, scriptJob)
+ animUI.selectionScriptJobs.append(scriptJob)
+
+ return [borderItem, False, scriptJob]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def toggleButtonState(self):
+
+ state = self.applyButton.isEnabled()
+ if state == False:
+ self.applyButton.setEnabled(True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def applyModuleChanges(self, moduleInst):
+
+ networkNode = self.returnNetworkNode
+
+ # get prefix/suffix
+ name = self.groupBox.title()
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ if len(prefix) > 0:
+ if prefix.find("_") == -1:
+ prefix = prefix + "_"
+ if len(suffix) > 0:
+ if suffix.find("_") == -1:
+ suffix = "_" + suffix
+
+ # create list of the new created bones
+ spineJoints = []
+
+ if self.pelvisCB.isChecked():
+ spineJoints.append(prefix + "pelvis" + suffix)
+
+ # get current spine value
+ currentNum = int(cmds.getAttr(networkNode + ".spineJoints"))
+
+ # get new spine value
+ uiSpineNum = self.numSpine.value()
+
+ if uiSpineNum != currentNum:
+ # update spine value, and call on update spine
+ cmds.setAttr(networkNode + ".spineJoints", lock=False)
+ cmds.setAttr(networkNode + ".spineJoints", uiSpineNum, lock=True)
+
+ # look for any attached modules
+ attachedModules = self.checkForDependencies()
+ self.updateSpine(attachedModules, currentNum)
+
+ for i in range(uiSpineNum):
+ spineJoints.append(prefix + "spine_0" + str(i + 1) + suffix)
+
+ # build attrString
+ attrString = ""
+ for bone in spineJoints:
+ attrString += bone + "::"
+
+ networkNode = self.returnNetworkNode
+ cmds.setAttr(networkNode + ".Created_Bones", lock=False)
+ cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True)
+
+ # pelvis
+ self.includePelvis()
+
+ # reset button
+ self.applyButton.setEnabled(False)
+
+ # update outliner
+ self.updateOutliner()
+ self.updateBoneCount()
+
+ # clear selection
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateSpine(self, attachedModules, oldNum):
+
+ # gather information (current name, current parent, etc)
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ parent = cmds.getAttr(networkNode + ".parentModuleBone")
+ newNum = int(cmds.getAttr(networkNode + ".spineJoints"))
+
+ # call on base class delete
+ movers = self.returnJointMovers
+ for moverGrp in movers:
+ for mover in moverGrp:
+ cmds.lockNode(mover, lock=False)
+
+ # store mover positions (movers = [all global, all offset, all geo])
+ basePositions = {}
+
+ for each in movers:
+ for mover in each:
+ attrs = cmds.listAttr(mover, keyable=True)
+ attrValues = []
+ for attr in attrs:
+ value = cmds.getAttr(mover + "." + attr)
+ attrValues.append([attr, value])
+ basePositions[mover] = attrValues
+
+ if cmds.getAttr(networkNode + ".aimMode") == True:
+ self.aimMode_Setup(False)
+
+ # delete joint mover
+ cmds.delete(self.name + "_mover_grp")
+
+ # build new jmPath name
+ jmPath = jointMover.partition(".ma")[0].rpartition("_")[0] + "_" + str(newNum) + "Spine.ma"
+ self.jointMover_Build(jmPath)
+
+ # apply base positions
+ for key in basePositions:
+
+ mover = key
+ attrList = basePositions.get(key)
+
+ for attr in attrList:
+ if cmds.objExists(mover):
+ cmds.setAttr(mover + "." + attr[0], attr[1])
+
+ # parent the joint mover to the offset mover of the parent
+ mover = ""
+ if parent == "root":
+ mover = "root_mover"
+
+ else:
+ # find the parent mover name to parent to
+ networkNodes = utils.returnRigModules()
+ mover = utils.findMoverNodeFromJointName(networkNodes, parent)
+
+ # delete the old constraint and create the new one
+ if cmds.objExists(self.name + "_mover_grp_parentConstraint*"):
+ cmds.delete(self.name + "_mover_grp_parentConstraint*")
+
+ if mover != None:
+ cmds.parentConstraint(mover, self.name + "_mover_grp", mo=True)
+
+ if cmds.objExists(self.name + "_mover_grp_scaleConstraint*"):
+ cmds.delete(self.name + "_mover_grp_scaleConstraint*")
+
+ if mover != None:
+ cmds.scaleConstraint(mover, self.name + "_mover_grp", mo=True)
+
+ # create the connection geo between the two
+ childMover = utils.findOffsetMoverFromName(name)
+ riggingUtils.createBoneConnection(mover, childMover, name)
+ self.applyModuleChanges(self)
+
+ self.aimMode_Setup(True)
+
+ cmds.select(clear=True)
+
+ # if there were any module dependencies, fix those now.
+ if len(attachedModules) > 0:
+ elementList = []
+
+ # first set parent to root mover since it will always be there
+ for each in attachedModules:
+ elementList.append([each[2], " -> parent changed from: ", each[1], " to: ", "root\n"])
+ currentParent = cmds.listRelatives(each[2] + "_mover_grp", parent=True)[0]
+ if currentParent != "root_mover":
+ cmds.parentConstraint("root_mover", each[2] + "_mover_grp", mo=True)
+ cmds.scaleConstraint("root_mover", each[2] + "_mover_grp", mo=True)
+ cmds.setAttr(each[0] + ".parentModuleBone", lock=False)
+ cmds.setAttr(each[0] + ".parentModuleBone", "root", type="string", lock=True)
+
+ # then, update settings UI for those dependency modules to display new parent info
+ modules = self.getAllModules
+
+ if each[0] in modules:
+ modName = cmds.getAttr(each[0] + ".moduleName")
+
+ for modInst in self.rigUiInst.moduleInstances:
+ if modInst.networkNode == each[0]:
+ # 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
+ modInst.skeletonSettings_UI(modName)
+
+ # create the connection geo between the two
+ mover = "root_mover"
+ childMover = utils.findOffsetMoverFromName(each[2])
+ riggingUtils.createBoneConnection(mover, childMover, each[2])
+ each[3].applyModuleChanges(each[3])
+ cmds.select(clear=True)
+
+ # warn user about changes
+ 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()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def addJointMoverToOutliner(self):
+
+ index = self.rigUiInst.treeWidget.topLevelItemCount()
+ self.outlinerWidgets = {}
+
+ # Add the module to the tree widget in the outliner tab of the rig creator UI
+ self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget)
+ self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name)
+ foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255))
+ self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground)
+
+ # add the pelvis
+ self.outlinerWidgets[self.name + "_pelvis"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_pelvis"].setText(0, self.name + "_pelvis")
+ self.createGlobalMoverButton(self.name + "_pelvis", self.outlinerWidgets[self.name + "_pelvis"], self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_pelvis", self.outlinerWidgets[self.name + "_pelvis"], self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_pelvis", self.outlinerWidgets[self.name + "_pelvis"], self.rigUiInst)
+
+ # add spine01
+ self.outlinerWidgets[self.name + "_spine_01"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_treeModule"])
+ self.outlinerWidgets[self.name + "_spine_01"].setText(0, self.name + "_spine_01")
+ self.createGlobalMoverButton(self.name + "_spine_01", self.outlinerWidgets[self.name + "_spine_01"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_spine_01", self.outlinerWidgets[self.name + "_spine_01"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_spine_01", self.outlinerWidgets[self.name + "_spine_01"],
+ self.rigUiInst)
+
+ # add spine02
+ self.outlinerWidgets[self.name + "_spine_02"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_spine_01"])
+ self.outlinerWidgets[self.name + "_spine_02"].setText(0, self.name + "_spine_02")
+ self.createGlobalMoverButton(self.name + "_spine_02", self.outlinerWidgets[self.name + "_spine_02"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_spine_02", self.outlinerWidgets[self.name + "_spine_02"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_spine_02", self.outlinerWidgets[self.name + "_spine_02"],
+ self.rigUiInst)
+
+ # add spine03
+ self.outlinerWidgets[self.name + "_spine_03"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_spine_02"])
+ self.outlinerWidgets[self.name + "_spine_03"].setText(0, self.name + "_spine_03")
+ self.createGlobalMoverButton(self.name + "_spine_03", self.outlinerWidgets[self.name + "_spine_03"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_spine_03", self.outlinerWidgets[self.name + "_spine_03"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_spine_03", self.outlinerWidgets[self.name + "_spine_03"],
+ self.rigUiInst)
+
+ # add spine04
+ self.outlinerWidgets[self.name + "_spine_04"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_spine_03"])
+ self.outlinerWidgets[self.name + "_spine_04"].setText(0, self.name + "_spine_04")
+ self.createGlobalMoverButton(self.name + "_spine_04", self.outlinerWidgets[self.name + "_spine_04"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_spine_04", self.outlinerWidgets[self.name + "_spine_04"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_spine_04", self.outlinerWidgets[self.name + "_spine_04"],
+ self.rigUiInst)
+
+ # add spine05
+ self.outlinerWidgets[self.name + "_spine_05"] = QtWidgets.QTreeWidgetItem(
+ self.outlinerWidgets[self.name + "_spine_04"])
+ self.outlinerWidgets[self.name + "_spine_05"].setText(0, self.name + "_spine_05")
+ self.createGlobalMoverButton(self.name + "_spine_05", self.outlinerWidgets[self.name + "_spine_05"],
+ self.rigUiInst)
+ self.createOffsetMoverButton(self.name + "_spine_05", self.outlinerWidgets[self.name + "_spine_05"],
+ self.rigUiInst)
+ self.createMeshMoverButton(self.name + "_spine_05", self.outlinerWidgets[self.name + "_spine_05"],
+ self.rigUiInst)
+
+ # create selection script job for module
+ self.createScriptJob()
+
+ # update based on spinBox values
+ self.updateOutliner()
+ self.updateBoneCount()
+ self.rigUiInst.treeWidget.expandAll()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateOutliner(self):
+
+ # whenever changes are made to the module settings, update the outliner to show the new or removed movers
+
+ # PELVIS
+
+ if not self.pelvisCB.isChecked():
+ self.outlinerWidgets[self.originalName + "_pelvis"].setHidden(True)
+ else:
+ self.outlinerWidgets[self.originalName + "_pelvis"].setHidden(False)
+
+ # SPINE
+ numSpine = self.numSpine.value()
+ if numSpine == 2:
+ self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(True)
+ if numSpine == 3:
+ self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(True)
+ self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(True)
+ if numSpine == 4:
+ self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(True)
+ if numSpine == 5:
+ self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(False)
+ self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def includePelvis(self, *args):
+ state = self.pelvisCB.isChecked()
+
+ if state == False:
+
+ # hide clavicle mover controls
+ cmds.setAttr(self.name + "_pelvis_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_pelvis_mover_grp.v", 0, lock=True)
+
+ # parent upperarm to mover_grp
+ try:
+ cmds.parent(self.name + "_spine_01_mover_grp", self.name + "_mover_grp")
+ except Exception, e:
+ print e
+
+ if state == True:
+
+ # show clavicle mover controls
+ cmds.setAttr(self.name + "_pelvis_mover_grp.v", lock=False)
+ cmds.setAttr(self.name + "_pelvis_mover_grp.v", 1, lock=True)
+
+ # parent upperarm to mover_grp
+ try:
+ cmds.parent(self.name + "_spine_01_mover_grp", self.name + "_pelvis_mover")
+ except Exception, e:
+ print e
+
+ networkNode = self.returnNetworkNode
+ cmds.setAttr(networkNode + ".includePelvis", lock=False)
+ cmds.setAttr(networkNode + ".includePelvis", state, lock=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def updateSettingsUI(self):
+
+ # this function will update the settings UI when the UI is launched based on the network node settings in the scene
+ networkNode = self.returnNetworkNode
+
+ includePelvis = cmds.getAttr(networkNode + ".includePelvis")
+ numSpine = cmds.getAttr(networkNode + ".spineJoints")
+
+ # update UI elements
+ self.numSpine.setValue(numSpine)
+ self.pelvisCB.setChecked(includePelvis)
+
+ # apply changes
+ self.applyButton.setEnabled(False)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def createContextMenu(self, point):
+
+ networkNode = self.returnNetworkNode
+
+ # icons
+ icon_reset = QtGui.QIcon(os.path.join(self.iconsPath, "System/reset.png"))
+ icon_delete = QtGui.QIcon(os.path.join(self.iconsPath, "System/delete.png"))
+
+ # create the context menu
+ if networkNode != "ART_Root_Module":
+ self.contextMenu = QtWidgets.QMenu()
+ self.contextMenu.addAction(icon_reset, "Reset Settings", self.resetSettings)
+
+ self.contextMenu.addSeparator()
+
+ self.contextMenu.addAction(icon_delete, "Delete Module", self.deleteModule)
+ self.contextMenu.exec_(self.groupBox.mapToGlobal(point))
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def resetSettings(self):
+
+ self.pelvisCB.setChecked(True)
+ self.numSpine.setValue(3)
+
+ # relaunch the UI
+ self.applyModuleChanges(self)
+ self.updateSettingsUI()
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def aimMode_Setup(self, state):
+
+ # get attributes needed
+ name = self.groupBox.title()
+ networkNode = self.returnNetworkNode
+ numSpine = cmds.getAttr(networkNode + ".spineJoints")
+
+ # setup aim vector details per side
+ aimVector = [1, 0, 0]
+ aimUp = [0, 1, 0]
+
+ # if passed in state is True:
+ if state:
+ # setup aim constraints
+
+ # pelvis
+ cmds.aimConstraint(name + "_spine_01_lra", name + "_pelvis_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ if numSpine == 2:
+ cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ if numSpine == 3:
+ cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ cmds.aimConstraint(name + "_spine_03_lra", name + "_spine_02_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ if numSpine == 4:
+ cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ cmds.aimConstraint(name + "_spine_03_lra", name + "_spine_02_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ cmds.aimConstraint(name + "_spine_04_lra", name + "_spine_03_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ if numSpine == 5:
+ cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ cmds.aimConstraint(name + "_spine_03_lra", name + "_spine_02_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ cmds.aimConstraint(name + "_spine_04_lra", name + "_spine_03_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ cmds.aimConstraint(name + "_spine_05_lra", name + "_spine_04_mover_offset", aimVector=aimVector,
+ upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True)
+
+ # if passed in state is False:
+ if not state:
+ cmds.select(name + "_mover_grp", hi=True)
+ aimConstraints = cmds.ls(sl=True, exactType="aimConstraint")
+
+ for constraint in aimConstraints:
+ cmds.lockNode(constraint, lock=False)
+ cmds.delete(constraint)
+
+ self.bakeOffsets()
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def pinModule(self, state):
+
+ networkNode = self.returnNetworkNode
+ includeClav = cmds.getAttr(networkNode + ".includePelvis")
+
+ if state:
+ if includeClav:
+ topLevelMover = self.name + "_pelvis_mover_grp"
+ else:
+ topLevelMover = self.name + "_spine_01_mover_grp"
+
+ loc = cmds.spaceLocator()[0]
+ cmds.setAttr(loc + ".v", False, lock=True)
+ constraint = cmds.parentConstraint(topLevelMover, loc)[0]
+ cmds.delete(constraint)
+ const = cmds.parentConstraint(loc, topLevelMover)[0]
+
+ if not cmds.objExists(networkNode + ".pinConstraint"):
+ cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message")
+
+ cmds.connectAttr(const + ".message", networkNode + ".pinConstraint")
+
+ if not state:
+ connections = cmds.listConnections(networkNode + ".pinConstraint")
+ if len(connections) > 0:
+ constraint = connections[0]
+ cmds.delete(constraint)
+
+ cmds.select(clear=True)
+
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def skinProxyGeo(self):
+
+ # get the network node
+ networkNode = self.returnNetworkNode
+ name = cmds.getAttr(networkNode + ".moduleName")
+ baseName = cmds.getAttr(networkNode + ".baseName")
+ prefix = name.partition(baseName)[0]
+ suffix = name.partition(baseName)[2]
+
+ # get this module's proxy geo meshes
+ cmds.select(name + "_mover_grp", hi=True)
+ proxyGeoMeshes = []
+ selection = cmds.ls(sl=True)
+ for each in selection:
+ if each.find("proxy_geo") != -1:
+ parent = cmds.listRelatives(each, parent=True)[0]
+ if cmds.nodeType(each) == "transform":
+ proxyGeoMeshes.append(each)
+
+ # skin the proxy geo meshes
+ for mesh in proxyGeoMeshes:
+ dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0]
+ cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False)
+ cmds.setAttr(dupeMesh + ".overrideDisplayType", 0)
+
+ # create skinned geo group
+ if not cmds.objExists("skinned_proxy_geo"):
+ cmds.group(empty=True, name="skinned_proxy_geo")
+
+ cmds.parent(dupeMesh, "skinned_proxy_geo")
+
+ boneName = mesh.partition(name + "_")[2]
+ boneName = boneName.partition("_proxy_geo")[0]
+ joint = prefix + boneName + suffix
+
+ if not cmds.objExists(joint):
+ cmds.delete(dupeMesh)
+
+ else:
+ cmds.select([dupeMesh, joint])
+ cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0,
+ normalizeWeights=True)
+ cmds.select(clear=True)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildRigCustom(self, textEdit, uiInst):
+
+ # get the network node and find out which rigs to build
+ networkNode = self.returnNetworkNode
+ buildFK = True
+ buildIK = True
+
+ # have it build all rigs by default, unless there is an attr stating otherwise (backwards- compatability)
+ numRigs = 0
+ if cmds.objExists(networkNode + ".buildFK"):
+ buildFK = cmds.getAttr(networkNode + ".buildFK")
+ if buildFK:
+ numRigs += 1
+ if cmds.objExists(networkNode + ".buildIK"):
+ buildIK_V1 = cmds.getAttr(networkNode + ".buildIK")
+ if buildIK_V1:
+ numRigs += 1
+
+ builtRigs = []
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # create groups and settings
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # create the spine group
+ spineJoints = self.returnCreatedJoints
+ self.spineGroup = cmds.group(empty=True, name=self.name + "_group")
+ constraint = cmds.parentConstraint(spineJoints[0], self.spineGroup)[0]
+ cmds.delete(constraint)
+
+ joints = []
+ for jnt in spineJoints:
+ if jnt.find("pelvis") == -1:
+ joints.append(jnt)
+
+ # create the spine settings group
+ self.spineSettings = cmds.group(empty=True, name=self.name + "_settings")
+ cmds.parent(self.spineSettings, self.spineGroup)
+ for attr in (cmds.listAttr(self.spineSettings, keyable=True)):
+ cmds.setAttr(self.spineSettings + "." + attr, lock=True, keyable=False)
+
+ # create the ctrl group (what will get the constraint to the parent)
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ self.spineCtrlGrp = cmds.group(empty=True, name=self.name + "_spine_ctrl_grp")
+
+ constraint = cmds.parentConstraint("driver_" + parentBone, self.spineCtrlGrp)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(self.spineCtrlGrp, self.spineGroup)
+ cmds.makeIdentity(self.spineCtrlGrp, t=1, r=1, s=1, apply=True)
+
+ includePelvis = cmds.getAttr(networkNode + ".includePelvis")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # build the rigs
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ if includePelvis:
+ self.buildHips(textEdit, uiInst, builtRigs, networkNode)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # FK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # if build FK was true, build the FK rig now
+ if buildFK:
+ fkInfo = self.buildFkSpine(textEdit, uiInst, builtRigs, networkNode)
+ builtRigs.append(["FK", fkInfo]) # [1] = nodes to hide
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # IK # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # if build IK was true, build the IK rig now
+ if buildIK:
+ ikInfo = self.buildIKSpine(textEdit, uiInst, builtRigs, networkNode)
+ if len(joints) > 2:
+ builtRigs.append(["IK", ikInfo]) # [1] = nodes to hide
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Hook up FK/IK Switching # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ # add mode attribute to settings
+ if len(builtRigs) > 1:
+ cmds.addAttr(self.spineSettings, ln="mode", min=0, max=numRigs - 1, dv=0, keyable=True)
+
+ # mode
+ if len(builtRigs) > 1:
+ attrData = []
+ rampData = []
+
+ """ CONSTRAINTS """
+ # get the constraint connections on the driver joints for the arms
+ connections = []
+ for joint in spineJoints:
+ connections.extend(list(set(cmds.listConnections("driver_" + joint, type="constraint"))))
+ ramps = (list(set(cmds.listConnections("driver_" + joint, type="ramp"))))
+ for ramp in ramps:
+ connections.append(ramp + ".uCoord")
+
+ for connection in connections:
+ driveAttrs = []
+
+ if cmds.nodeType(connection) in ["pointConstraint", "orientConstraint"]:
+
+ # get those constraint target attributes for each constraint connection
+ targets = cmds.getAttr(connection + ".target", mi=True)
+ if len(targets) > 1:
+ for each in targets:
+ driveAttrs.append(
+ cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight",
+ p=True))
+
+ # add this data to our master list of constraint attribute data
+ attrData.append(driveAttrs)
+ else:
+ if cmds.nodeType(connection) == "ramp":
+ rampData.append(connection)
+
+ rampData = list(set(rampData))
+
+ # setup set driven keys on our moder attr and those target attributes
+ for i in range(numRigs):
+
+ cmds.setAttr(self.spineSettings + ".mode", i)
+
+ # go through attr data and zero out anything but the first element in the list
+ for data in attrData:
+ for each in data:
+ cmds.setAttr(each[0], 0)
+
+ cmds.setAttr(data[i][0], 1)
+
+ # set driven keys
+ for data in attrData:
+ for each in data:
+ cmds.setDrivenKeyframe(each[0], cd=self.spineSettings + ".mode", itt="linear", ott="linear")
+
+ """ RAMPS """
+ # direct connect mode to uCoord value (only works if there are 2 rigs...) <- not sure if that is the case still
+ for data in rampData:
+ # create a multiply node that takes first input of 1/numRigs and 2nd of mode direct connection
+ multNode = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_" + data.partition(".uCoord")[0] + "_mult")
+ cmds.setAttr(multNode + ".input1X", float(float(1) / float(numRigs - 1)))
+ cmds.connectAttr(self.spineSettings + ".mode", multNode + ".input2X")
+ cmds.connectAttr(multNode + ".outputX", data)
+
+ # hook up control visibility
+ for i in range(len(builtRigs)):
+ cmds.setAttr(self.spineSettings + ".mode", i)
+ for rig in builtRigs:
+ visNodes = rig[1]
+ for node in visNodes:
+ if node != None:
+ cmds.setAttr(node + ".v", 0)
+
+ if builtRigs.index(rig) == i:
+ visNodes = rig[1]
+ for node in visNodes:
+ if node != None:
+ cmds.setAttr(node + ".v", 1)
+
+ cmds.setDrivenKeyframe(visNodes, at="visibility", cd=self.spineSettings + ".mode", itt="linear",
+ ott="linear")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # Parent Under Offset Ctrl # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # parent under offset_anim if it exists(it always should)
+ if cmds.objExists("offset_anim"):
+ cmds.parent(self.spineGroup, "offset_anim")
+
+ # return data
+ parentBone = cmds.getAttr(networkNode + ".parentModuleBone")
+ try:
+ uiInst.rigData.append([self.spineCtrlGrp, "driver_" + parentBone, numRigs])
+ except:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildHips(self, textEdit, uiInst, builtRigs, networkNode):
+
+ # update progress
+ if textEdit != None:
+ textEdit.append(" Building Pelvis Rig..")
+
+ # find the joints in the spine module that need rigging
+ allJnts = self.returnCreatedJoints
+ joints = []
+ for jnt in allJnts:
+ if jnt.find("pelvis") != -1:
+ joints.append(jnt)
+
+ # create the grp and position and orient it correctly
+ controlInfo = riggingUtils.createControlFromMover(joints[0], networkNode, True, True)
+ self.bodyAnim = riggingUtils.createControl("square", 50, self.name + "_body_anim", True)
+
+ constraint = cmds.pointConstraint(controlInfo[0], self.bodyAnim)[0]
+ cmds.delete([constraint, controlInfo[0]])
+
+ cmds.parent(self.bodyAnim, controlInfo[1])
+ cmds.makeIdentity(self.bodyAnim, t=1, r=1, s=1, apply=True)
+
+ self.bodyAnimGrp = cmds.rename(controlInfo[1], self.name + "_body_anim_grp")
+ self.bodyAnimSpace = cmds.rename(controlInfo[2], self.name + "_body_anim_space_switcher")
+ self.bodyAnimFollow = cmds.rename(controlInfo[3], self.name + "_body_anim_space_switcher_follow")
+ riggingUtils.colorControl(self.bodyAnim, 17)
+
+ # Pelvis
+ hipControlInfo = riggingUtils.createControlFromMover(joints[0], networkNode, True, False)
+ self.hipAnim = cmds.rename(hipControlInfo[0], self.name + "_hip_anim")
+ self.hipAnimGrp = cmds.rename(hipControlInfo[1], self.name + "_hip_anim_grp")
+ riggingUtils.colorControl(self.hipAnim, 18)
+
+ cmds.parent(self.hipAnimGrp, self.bodyAnim)
+
+ for each in [self.bodyAnim, self.hipAnim]:
+ for attr in [".scaleX", ".scaleY", ".scaleZ", ".visibility"]:
+ cmds.setAttr(each + attr, lock=True, keyable=False)
+
+ cmds.parent(self.bodyAnimFollow, self.spineCtrlGrp)
+
+ # =======================================================================
+ # #lastly, connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+ cmds.pointConstraint(self.hipAnim, "driver_" + joints[0], mo=True)
+ cmds.orientConstraint(self.hipAnim, "driver_" + joints[0])
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joints[0] + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(self.hipAnim + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + joints[0], "scale", False, 2, 0, "output")
+ else:
+ riggingUtils.createConstraint(self.hipAnim, "driver_" + joints[0], "scale", False, 2, 0)
+
+ # add created control info to module
+ if not cmds.objExists(networkNode + ".pelvisControls"):
+ cmds.addAttr(networkNode, ln="pelvisControls", dt="string")
+ jsonString = json.dumps([self.hipAnim, self.bodyAnim])
+ cmds.setAttr(networkNode + ".pelvisControls", jsonString, type="string")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildFkSpine(self, textEdit, uiInst, builtRigs, networkNode):
+
+ # update progress
+ if textEdit != None:
+ textEdit.append(" Starting FK Spine Rig Build..")
+
+ # build the rig
+ slot = len(builtRigs)
+
+ # find the joints in the spine module that need rigging
+ allJnts = self.returnCreatedJoints
+ joints = []
+
+ for jnt in allJnts:
+ if jnt.find("pelvis") == -1:
+ joints.append(jnt)
+
+ fkControls = []
+ self.topNode = None
+ includePelvis = cmds.getAttr(networkNode + ".includePelvis")
+
+ for joint in joints:
+ if joint == joints[0]:
+ data = riggingUtils.createControlFromMover(joint, networkNode, True, True)
+
+ fkControl = cmds.rename(data[0], "fk_" + joint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp")
+ spaceSwitcher = cmds.rename(data[2], "fk_" + joint + "_anim_space_switcher")
+ spaceSwitchFollow = cmds.rename(data[3], "fk_" + joint + "_anim_space_switcher_follow")
+ self.topNode = spaceSwitchFollow
+
+ fkControls.append([spaceSwitchFollow, fkControl, joint])
+ # color the control
+ riggingUtils.colorControl(fkControl, 18)
+
+
+ else:
+ data = riggingUtils.createControlFromMover(joint, networkNode, True, False)
+
+ fkControl = cmds.rename(data[0], "fk_" + joint + "_anim")
+ animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp")
+
+ fkControls.append([animGrp, fkControl, joint])
+
+ # color the control
+ riggingUtils.colorControl(fkControl, 18)
+
+ # create hierarchy
+ fkControls.reverse()
+
+ for i in range(len(fkControls)):
+ try:
+ cmds.parent(fkControls[i][0], fkControls[i + 1][1])
+ except IndexError:
+ pass
+
+ # =======================================================================
+ # #lastly, connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+ for each in fkControls:
+ control = each[1]
+ joint = each[2]
+
+ cmds.pointConstraint(control, "driver_" + joint, mo=True)
+ cmds.orientConstraint(control, "driver_" + joint)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(control + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output")
+ else:
+ riggingUtils.createConstraint(control, "driver_" + joint, "scale", False, 2, slot)
+
+ # #=======================================================================
+ # clean up
+ # #=======================================================================
+ # parent top group into arm group
+ if includePelvis:
+ cmds.parent(self.topNode, self.bodyAnim)
+ else:
+ cmds.parent(self.topNode, self.spineCtrlGrp)
+
+ # lock attrs
+ for each in fkControls:
+ control = each[1]
+ for attr in [".visibility"]:
+ cmds.setAttr(control + attr, lock=True, keyable=False)
+
+ fkRigData = []
+ for each in fkControls:
+ fkRigData.append(each[1])
+
+ # add created control info to module
+ if not cmds.objExists(networkNode + ".fkControls"):
+ cmds.addAttr(networkNode, ln="fkControls", dt="string")
+ jsonString = json.dumps(fkRigData)
+ cmds.setAttr(networkNode + ".fkControls", jsonString, type="string")
+
+ # update progress
+ if textEdit != None:
+ textEdit.setTextColor(QtGui.QColor(0, 255, 18))
+ textEdit.append(" SUCCESS: FK Build Complete!")
+ textEdit.setTextColor(QtGui.QColor(255, 255, 255))
+
+ return [spaceSwitchFollow]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def buildIKSpine(self, textEdit, uiInst, builtRigs, networkNode):
+
+ slot = len(builtRigs)
+
+ # find the joints in the spine module that need rigging
+ allJnts = self.returnCreatedJoints
+ joints = []
+
+ for jnt in allJnts:
+ if jnt.find("pelvis") == -1:
+ joints.append(jnt)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # Start SplineIK creation
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+ if len(joints) > 2:
+ # duplicate the spine joints we'll need for the spline IK
+
+ parent = None
+ rigJoints = []
+
+ for joint in joints:
+ spineBone = cmds.duplicate(joint, parentOnly=True, name="splineIK_" + joint)[0]
+
+ if parent != None:
+ cmds.parent(spineBone, parent)
+
+ else:
+ cmds.parent(spineBone, world=True)
+
+ parent = spineBone
+ rigJoints.append(str(spineBone))
+
+ # create spine twist joints that will be children of the spline IK joints. This will allow us to control twist distribution directly
+ for joint in rigJoints:
+ twistJoint = cmds.duplicate(joint, name="twist_" + joint, parentOnly=True)[0]
+ cmds.parent(twistJoint, joint)
+
+ # find the driver top and mid joints
+ topDriverJoint = "driver_" + joints[-1]
+ midDriverJoint = "driver_" + joints[len(joints) / 2]
+
+ ###########################################################################################################
+ ###########################################################################################################
+ # create the spline IK
+ ###########################################################################################################
+ ###########################################################################################################
+
+ ikNodes = cmds.ikHandle(sj=str(rigJoints[0]), ee=str(rigJoints[len(rigJoints) - 1]), sol="ikSplineSolver",
+ createCurve=True, simplifyCurve=True, parentCurve=False,
+ name=str(rigJoints[0]) + "_splineIK")
+ ikHandle = ikNodes[0]
+ ikCurve = ikNodes[2]
+ ikCurve = cmds.rename(ikCurve, self.name + "_spine_splineIK_curve")
+ cmds.setAttr(ikCurve + ".inheritsTransform", 0)
+ cmds.setAttr(ikHandle + ".v", 0)
+ cmds.setAttr(ikCurve + ".v", 0)
+
+ # create the three joints to skin the curve to
+ botJoint = cmds.duplicate(rigJoints[0], name=self.name + "_splineIK_bot_jnt", parentOnly=True)[0]
+ topJoint = \
+ cmds.duplicate(rigJoints[len(rigJoints) - 1], name=self.name + "_splineIK_top_jnt", parentOnly=True)[0]
+ midJoint = cmds.duplicate(topJoint, name=self.name + "_splineIK_mid_jnt", parentOnly=True)[0]
+
+ cmds.parent([botJoint, topJoint, midJoint], world=True)
+
+ constraint = cmds.pointConstraint([botJoint, topJoint], midJoint)[0]
+ cmds.delete(constraint)
+
+ # any joint that is not the bottom or top joint needs to be point constrained to be evenly spread
+ drivenConsts = []
+ if len(joints) == 3:
+ drivenConst1 = cmds.pointConstraint([midJoint, rigJoints[1]], "twist_" + rigJoints[1], mo=True)[0]
+ cmds.setAttr(drivenConst1 + "." + rigJoints[1] + "W1", 0)
+ drivenConsts.append(drivenConst1)
+
+ if len(joints) == 4:
+ drivenConst1 = \
+ cmds.pointConstraint([botJoint, midJoint, rigJoints[1]], "twist_" + rigJoints[1], mo=True)[0]
+ drivenConst2 = \
+ cmds.pointConstraint([topJoint, midJoint, rigJoints[2]], "twist_" + rigJoints[2], mo=True)[0]
+
+ cmds.setAttr(drivenConst1 + "." + rigJoints[1] + "W2", 0)
+ cmds.setAttr(drivenConst2 + "." + rigJoints[2] + "W2", 0)
+ drivenConsts.append(drivenConst1)
+ drivenConsts.append(drivenConst2)
+
+ if len(joints) == 5:
+ drivenConst1 = \
+ cmds.pointConstraint([botJoint, midJoint, rigJoints[1]], "twist_" + rigJoints[1], mo=True)[0]
+ drivenConst2 = cmds.pointConstraint([midJoint, rigJoints[2]], "twist_" + rigJoints[2], mo=True)[0]
+ drivenConst3 = \
+ cmds.pointConstraint([midJoint, topJoint, rigJoints[3]], "twist_" + rigJoints[3], mo=True)[0]
+
+ cmds.setAttr(drivenConst1 + "." + rigJoints[1] + "W2", 0)
+ cmds.setAttr(drivenConst2 + "." + rigJoints[2] + "W1", 0)
+ cmds.setAttr(drivenConst3 + "." + rigJoints[3] + "W2", 0)
+
+ drivenConsts.append(drivenConst1)
+ drivenConsts.append(drivenConst2)
+ drivenConsts.append(drivenConst3)
+
+ # skin the joints to the curve
+ cmds.select([botJoint, topJoint, midJoint])
+ skin = cmds.skinCluster([botJoint, topJoint, midJoint], ikCurve, toSelectedBones=True)[0]
+
+ # skin weight the curve
+ curveShape = cmds.listRelatives(ikCurve, shapes=True)[0]
+ numSpans = cmds.getAttr(curveShape + ".spans")
+ degree = cmds.getAttr(curveShape + ".degree")
+ numCVs = numSpans + degree
+
+ # this should always be the case, but just to be safe
+ if numCVs == 4:
+ cmds.skinPercent(skin, ikCurve + ".cv[0]", transformValue=[(botJoint, 1.0)])
+ cmds.skinPercent(skin, ikCurve + ".cv[1]", transformValue=[(botJoint, 0.5), (midJoint, 0.5)])
+ cmds.skinPercent(skin, ikCurve + ".cv[2]", transformValue=[(midJoint, 0.5), (topJoint, 0.5)])
+ cmds.skinPercent(skin, ikCurve + ".cv[3]", transformValue=[(topJoint, 1.0)])
+
+ ###########################################################################################################
+ ###########################################################################################################
+ # create the spline IK controls
+ ###########################################################################################################
+ ###########################################################################################################
+
+ ikControls = []
+
+ ###############################################
+ # TOP CTRL
+ ###############################################
+
+ data = riggingUtils.createControlFromMover(joints[-1], networkNode, True, True)
+
+ topCtrl = cmds.rename(data[0], self.name + "_chest_ik_anim")
+ animGrp = cmds.rename(data[1], self.name + "_chest_ik_anim_grp")
+ driverGrp = cmds.duplicate(animGrp, parentOnly=True, name=self.name + "_chest_ik_anim_driver_grp")[0]
+ spaceSwitcher = cmds.rename(data[2], self.name + "_chest_ik_anim_space_switcher")
+ spaceSwitchFollow = cmds.rename(data[3], self.name + "_chest_ik_anim_space_switcher_follow")
+
+ self.topNode = spaceSwitchFollow
+
+ ikControls.append([spaceSwitchFollow, topCtrl, joints[-1]])
+
+ cmds.parent(driverGrp, animGrp)
+ cmds.parent(topCtrl, driverGrp)
+ cmds.parent(topJoint, topCtrl)
+
+ # color the control
+ riggingUtils.colorControl(topCtrl, 17)
+
+ ###############################################
+ # MID CTRL
+ ###############################################
+
+ data = riggingUtils.createControlFromMover(joints[len(joints) / 2], networkNode, True, False)
+
+ midCtrl = cmds.rename(data[0], self.name + "_mid_ik_anim")
+ midGrp = cmds.rename(data[1], self.name + "_mid_ik_anim_grp")
+ midDriver = cmds.duplicate(midGrp, parentOnly=True, name=self.name + "_mid_ik_anim_driver_grp")[0]
+ midDriverTrans = cmds.duplicate(midGrp, parentOnly=True, name=self.name + "_mid_ik_anim_trans_driver_grp")[
+ 0]
+
+ cmds.parent(midCtrl, midDriver)
+ cmds.parent(midDriver, midDriverTrans)
+ cmds.parent(midDriverTrans, midGrp)
+ cmds.parent(midJoint, midCtrl)
+ ikControls.append([midGrp, midCtrl, joints[len(joints) / 2]])
+
+ # color the control
+ riggingUtils.colorControl(midCtrl, 18)
+
+ ###############################################
+ # BOT CTRL
+ ###############################################
+ includePelvis = cmds.getAttr(networkNode + ".includePelvis")
+
+ if includePelvis:
+ cmds.parent(botJoint, self.hipAnim)
+
+ else:
+ cmds.parent(botJoint, self.spineCtrlGrp)
+
+ ###########################################################################################################
+ ###########################################################################################################
+ # ADDING STRETCH
+ ###########################################################################################################
+ ###########################################################################################################
+
+ # add the attr to the top ctrl
+ cmds.addAttr(topCtrl, longName='stretch', defaultValue=0, minValue=0, maxValue=1, keyable=True)
+ cmds.addAttr(topCtrl, longName='squash', defaultValue=0, minValue=0, maxValue=1, keyable=True)
+
+ # create the curveInfo node#find
+ cmds.select(ikCurve)
+ curveInfoNode = cmds.arclen(cmds.ls(sl=True), ch=True, name=self.name + "_splineIK_curveInfo")
+ originalLength = cmds.getAttr(curveInfoNode + ".arcLength")
+
+ # create the multiply/divide node that will get the scale factor
+ divideNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_splineIK_scaleFactor")
+ divideNode_Inverse = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_splineIK_inverse")
+ cmds.setAttr(divideNode + ".operation", 2)
+ cmds.setAttr(divideNode + ".input2X", originalLength)
+ cmds.setAttr(divideNode_Inverse + ".operation", 2)
+ cmds.setAttr(divideNode_Inverse + ".input1X", originalLength)
+
+ # create the blendcolors node
+ blenderNode = cmds.shadingNode("blendColors", asUtility=True, name=self.name + "_splineIK_blender")
+ cmds.setAttr(blenderNode + ".color2R", 1)
+
+ blenderNode_Inverse = cmds.shadingNode("blendColors", asUtility=True,
+ name=self.name + "_splineIK_blender_inverse")
+ cmds.setAttr(blenderNode_Inverse + ".color2R", 1)
+
+ # connect attrs
+ cmds.connectAttr(curveInfoNode + ".arcLength", divideNode + ".input1X")
+ cmds.connectAttr(curveInfoNode + ".arcLength", divideNode_Inverse + ".input2X")
+ cmds.connectAttr(divideNode + ".outputX", blenderNode + ".color1R")
+ cmds.connectAttr(divideNode_Inverse + ".outputX", blenderNode_Inverse + ".color1R")
+
+ cmds.connectAttr(topCtrl + ".stretch", blenderNode + ".blender")
+ cmds.connectAttr(topCtrl + ".squash", blenderNode_Inverse + ".blender")
+
+ # find ctrl upAxis
+ upAxis = self.getUpAxis(topCtrl)
+ if upAxis == "X":
+ axisB = "Y"
+ axisC = "Z"
+ if upAxis == "Y":
+ axisB = "X"
+ axisC = "Z"
+ if upAxis == "Z":
+ axisB = "X"
+ axisC = "Y"
+
+ # apply squash and stretch to joints
+ for i in range(len(rigJoints)):
+ children = cmds.listRelatives(rigJoints[i], children=True)
+ for child in children:
+ if child.find("twist") != -1:
+ twistJoint = child
+
+ cmds.connectAttr(blenderNode_Inverse + ".outputR", twistJoint + ".scale" + axisB)
+ cmds.connectAttr(blenderNode_Inverse + ".outputR", twistJoint + ".scale" + axisC)
+
+ cmds.connectAttr(blenderNode + ".outputR", rigJoints[0] + ".scale" + upAxis)
+
+ # setup drivenConst to only be active when stretch is on
+ for const in drivenConsts:
+ targets = cmds.getAttr(const + ".target", mi=True)
+ for each in targets:
+ attr = cmds.listConnections(const + ".target[" + str(each) + "].targetWeight", p=True)
+
+ cmds.setAttr(topCtrl + ".stretch", 1)
+ cmds.setDrivenKeyframe(attr[0], cd=topCtrl + ".stretch")
+
+ cmds.setAttr(topCtrl + ".stretch", 0)
+ if len(joints) == 3:
+ if const == drivenConst1:
+ if each == targets[0]:
+ cmds.setAttr(attr[0], 0)
+ if each == targets[1]:
+ cmds.setAttr(attr[0], 1)
+
+ if len(joints) == 4:
+ if each == targets[2]:
+ cmds.setAttr(attr[0], 1)
+ else:
+ cmds.setAttr(attr[0], 0)
+
+ if len(joints) == 5:
+ if const == drivenConst1:
+ if each == targets[2]:
+ cmds.setAttr(attr[0], 1)
+ else:
+ cmds.setAttr(attr[0], 0)
+
+ if const == drivenConst2:
+ if each == targets[1]:
+ cmds.setAttr(attr[0], 1)
+ else:
+ cmds.setAttr(attr[0], 0)
+
+ if const == drivenConst3:
+ if each == targets[2]:
+ cmds.setAttr(attr[0], 1)
+ else:
+ cmds.setAttr(attr[0], 0)
+
+ cmds.setDrivenKeyframe(attr[0], cd=topCtrl + ".stretch")
+
+ ###########################################################################################################
+ ###########################################################################################################
+ # ADDING TWiST
+ ###########################################################################################################
+ ###########################################################################################################
+
+ # add twist amount attrs and setup
+ cmds.select(topCtrl)
+ cmds.addAttr(longName='twist_amount', defaultValue=1, minValue=0, keyable=True)
+
+ # find number of spine joints and divide 1 by numSpineJoints
+ num = len(joints)
+ val = 1.0 / float(num)
+ twistamount = val
+
+ locGrp = cmds.group(empty=True, name=self.name + "_spineIK_twist_grp")
+ if includePelvis:
+ cmds.parent(locGrp, self.bodyAnim)
+
+ else:
+ cmds.parent(locGrp, self.spineCtrlGrp)
+
+ for i in range(int(num - 1)):
+
+ # create a locator that will be orient constrained between the body and chest
+ locator = cmds.spaceLocator(name=joints[i] + "_twistLoc")[0]
+ group = cmds.group(empty=True, name=joints[i] + "_twistLocGrp")
+ constraint = cmds.parentConstraint(joints[i], locator)[0]
+ cmds.delete(constraint)
+ constraint = cmds.parentConstraint(joints[i], group)[0]
+ cmds.delete(constraint)
+ cmds.parent(locator, group)
+ cmds.parent(group, locGrp)
+ cmds.setAttr(locator + ".v", 0, lock=True)
+
+ # duplicate the locator and parent it under the group. This will be the locator that takes the rotation x twist amount and gives us the final value
+
+ orientLoc = cmds.duplicate(locator, name=joints[i] + "_orientLoc")[0]
+ cmds.parent(orientLoc, locator)
+ cmds.makeIdentity(orientLoc, t=1, r=1, s=1, apply=True)
+
+ # set weights on constraint
+ firstValue = 1 - twistamount
+ secondValue = 1 - firstValue
+
+ # create constraints between body/chest
+ if includePelvis:
+ constraint = cmds.orientConstraint([self.bodyAnim, topCtrl], locator)[0]
+ cmds.setAttr(constraint + "." + self.bodyAnim + "W0", firstValue)
+ cmds.setAttr(constraint + "." + topCtrl + "W1", secondValue)
+
+ else:
+ # find module's parent bone
+ constraint = cmds.orientConstraint([rigJoints[i], topCtrl], locator)[0]
+ cmds.setAttr(constraint + "." + rigJoints[i] + "W0", firstValue)
+ cmds.setAttr(constraint + "." + topCtrl + "W1", secondValue)
+
+ # factor in twist amount
+ twistMultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=joints[i] + "_twist_amount")
+
+ # expose the twistAmount on the control as an attr
+ cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2X")
+ cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2Y")
+ cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2Z")
+ cmds.connectAttr(locator + ".rotate", twistMultNode + ".input1")
+
+ cmds.connectAttr(twistMultNode + ".output", orientLoc + ".rotate")
+
+ # constrain the spine joint to the orientLoc
+ if upAxis == "X":
+ skipped = ["y", "z"]
+ if upAxis == "Y":
+ skipped = ["x", "z"]
+ if upAxis == "Z":
+ skipped = ["x", "y"]
+
+ cmds.orientConstraint([locator, rigJoints[i]], orientLoc, mo=True)
+ cmds.orientConstraint(orientLoc, "twist_splineIK_" + joints[i])
+ twistamount = twistamount + val
+
+ # =======================================================================
+ # #connect controls up to blender nodes to drive driver joints
+ # =======================================================================
+ for joint in joints:
+
+ rigJnt = "twist_splineIK_" + joint
+
+ if joint == joints[len(joints) - 1]:
+ cmds.pointConstraint(rigJnt, "driver_" + joint, mo=True)
+ cmds.orientConstraint(topJoint, "driver_" + joint)
+
+ else:
+ cmds.pointConstraint(rigJnt, "driver_" + joint, mo=True)
+ cmds.orientConstraint(rigJnt, "driver_" + joint)
+
+ # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint
+ if cmds.objExists("master_anim"):
+ globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale")
+ cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1")
+ cmds.connectAttr(rigJnt + ".scale", globalScaleMult + ".input2")
+ riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output")
+ else:
+ riggingUtils.createConstraint(rigJnt, "driver_" + joint, "scale", False, 2, slot)
+
+ # =======================================================================
+ # #clean things up
+ # =======================================================================
+
+ # parent the components to the body anim or parent module bone
+
+ if includePelvis:
+ cmds.parent(midGrp, self.bodyAnim)
+ else:
+ cmds.parent(midGrp, self.spineCtrlGrp)
+
+ # ensure after parenting the midGrp that everything is still nice and zeroed out.
+ cmds.parent(midCtrl, world=True)
+ cmds.parent(midJoint, world=True)
+
+ for attr in [".rx", ".ry", ".rz"]:
+ cmds.setAttr(midGrp + attr, 0)
+
+ cmds.parent(midCtrl, midDriver)
+ cmds.makeIdentity(midCtrl, t=1, r=1, s=0, apply=True)
+ cmds.parent(midJoint, midCtrl)
+
+ # parent the chest ik space switcher follow node to the body anim or parent module bone
+ if includePelvis:
+ cmds.parent(spaceSwitchFollow, self.bodyAnim)
+ else:
+ cmds.parent(spaceSwitchFollow, self.spineCtrlGrp)
+
+ # ensure after parenting the space switcher follow for the ik chest, that everything is still nice and zeroed out.
+ cmds.parent(topCtrl, world=True)
+ cmds.parent(topJoint, world=True)
+ for attr in [".rx", ".ry", ".rz"]:
+ if cmds.getAttr(spaceSwitchFollow + attr) < 45:
+ if cmds.getAttr(spaceSwitchFollow + attr) > 0:
+ cmds.setAttr(spaceSwitchFollow + attr, 0)
+
+ if cmds.getAttr(spaceSwitchFollow + attr) >= 80:
+ if cmds.getAttr(spaceSwitchFollow + attr) < 90:
+ cmds.setAttr(spaceSwitchFollow + attr, 90)
+
+ if cmds.getAttr(spaceSwitchFollow + attr) > 90:
+ if cmds.getAttr(spaceSwitchFollow + attr) < 100:
+ cmds.setAttr(spaceSwitchFollow + attr, 90)
+
+ if cmds.getAttr(spaceSwitchFollow + attr) <= -80:
+ if cmds.getAttr(spaceSwitchFollow + attr) > -90:
+ cmds.setAttr(spaceSwitchFollow + attr, -90)
+
+ if cmds.getAttr(spaceSwitchFollow + attr) > -90:
+ if cmds.getAttr(spaceSwitchFollow + attr) < -100:
+ cmds.setAttr(spaceSwitchFollow + attr, -90)
+
+ cmds.parent(topCtrl, driverGrp)
+ cmds.makeIdentity(topCtrl, t=1, r=1, s=0, apply=True)
+ cmds.parent(topJoint, topCtrl)
+
+ # =======================================================================
+ # #ensure top spine joint stays pinned to top ctrl
+ # =======================================================================
+
+ children = cmds.listRelatives(rigJoints[len(rigJoints) - 1], children=True)
+ for child in children:
+ if child.find("twist") != -1:
+ twistJoint = child
+
+ topSpineBone = twistJoint.partition("twist_")[2]
+ topSpineJointConstraint = cmds.pointConstraint([topJoint, topSpineBone], twistJoint)[0]
+
+ # connect attr on top spine joint constraint
+ targets = cmds.pointConstraint(topSpineJointConstraint, q=True, weightAliasList=True)
+
+ cmds.connectAttr(topCtrl + ".stretch", topSpineJointConstraint + "." + targets[0])
+
+ conditionNode = cmds.shadingNode("condition", asUtility=True, name=self.name + "_twist_stretch_toggle")
+ cmds.connectAttr(topCtrl + ".stretch", conditionNode + ".firstTerm")
+ cmds.setAttr(conditionNode + ".secondTerm", 1)
+ cmds.setAttr(conditionNode + ".colorIfTrueR", 0)
+
+ minusNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=self.name + "_twist_stretch_minus")
+ cmds.setAttr(minusNode + ".operation", 2)
+ cmds.connectAttr(conditionNode + ".secondTerm", minusNode + ".input1D[0]")
+ cmds.connectAttr(topCtrl + ".stretch", minusNode + ".input1D[1]")
+ cmds.connectAttr(minusNode + ".output1D", topSpineJointConstraint + "." + targets[1])
+
+ # =======================================================================
+ # #create stretch meter attr
+ # =======================================================================
+ cmds.addAttr(topCtrl, longName='stretchFactor', keyable=True)
+ cmds.connectAttr(divideNode + ".outputX", topCtrl + ".stretchFactor")
+ cmds.setAttr(topCtrl + ".stretchFactor", lock=True)
+
+ cmds.addAttr(midCtrl, longName='stretchFactor', keyable=True)
+ cmds.connectAttr(topCtrl + ".stretchFactor", midCtrl + ".stretchFactor")
+ cmds.setAttr(midCtrl + ".stretchFactor", lock=True)
+
+ # =======================================================================
+ # #lock and hide attrs that should not be keyable
+ # =======================================================================
+
+ for control in [topCtrl, midCtrl]:
+ for attr in [".sx", ".sy", ".sz", ".v"]:
+ cmds.setAttr(control + attr, keyable=False, lock=True)
+
+ # =======================================================================
+ # #organize scene
+ # =======================================================================
+ IKgrp = cmds.group(empty=True, name=self.name + "_ik_grp")
+ cmds.parent(IKgrp, self.spineCtrlGrp)
+
+ cmds.parent(ikCurve, IKgrp)
+ cmds.parent(ikHandle, IKgrp)
+ cmds.parent(rigJoints[0], IKgrp)
+
+ for jnt in rigJoints:
+ cmds.setAttr(jnt + ".v", 0, lock=True)
+
+ for jnt in [botJoint, midJoint, topJoint]:
+ cmds.setAttr(jnt + ".v", 0, lock=True)
+
+ # =======================================================================
+ # #create matching nodes
+ # =======================================================================
+ chest_match_node = cmds.duplicate(topCtrl, po=True, name=topCtrl + "_MATCH")
+ cmds.parent(chest_match_node, topDriverJoint)
+
+ mid_match_node = cmds.duplicate(midCtrl, po=True, name=midCtrl + "_MATCH")
+ cmds.parent(mid_match_node, midDriverJoint)
+
+ # =======================================================================
+ # #setup auto spine
+ # =======================================================================
+ self.setupAutoSpine(textEdit, uiInst, builtRigs, networkNode, midDriver, midDriverTrans, topCtrl, botJoint)
+
+ # add created control info to module
+ if not cmds.objExists(networkNode + ".ikControls"):
+ cmds.addAttr(networkNode, ln="ikControls", dt="string")
+ jsonString = json.dumps([topCtrl, midCtrl])
+ cmds.setAttr(networkNode + ".ikControls", jsonString, type="string")
+
+ return [spaceSwitchFollow, midGrp]
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def setupAutoSpine(self, textEdit, uiInst, builtRigs, networkNode, midDriver, midDriverTrans, topCtrl, botJnt):
+
+ cmds.addAttr(topCtrl, longName='autoSpine', defaultValue=0, minValue=0, maxValue=1, keyable=True)
+ cmds.addAttr(topCtrl, longName='rotationInfluence', defaultValue=.25, minValue=0, maxValue=1, keyable=True)
+
+ topCtrlMultRY = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_autoSpine_top_driver_mult_ry")
+ topCtrlMultRZ = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_autoSpine_top_driver_mult_rz")
+ topCtrlMultSwitchRY = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_autoSpine_top_mult_switch_ry")
+ topCtrlMultSwitchRZ = cmds.shadingNode("multiplyDivide", asUtility=True,
+ name=self.name + "_autoSpine_top_mult_switch_rz")
+
+ # =======================================================================
+ # create a node that will track all world space translations and rotations on the chest IK anim
+ # =======================================================================
+ chestMasterTrackNode = cmds.spaceLocator(name=self.name + "_chest_ik_track_parent")[0]
+ constraint = cmds.parentConstraint(topCtrl, chestMasterTrackNode)[0]
+ cmds.delete(constraint)
+
+ chestTrackNode = cmds.spaceLocator(name=self.name + "_chest_ik_tracker")[0]
+ constraint = cmds.parentConstraint(topCtrl, chestTrackNode)[0]
+ cmds.delete(constraint)
+
+ cmds.parent(chestTrackNode, chestMasterTrackNode)
+ cmds.parentConstraint(topCtrl, chestTrackNode)
+
+ if cmds.getAttr(networkNode + ".includePelvis"):
+ cmds.parent(chestMasterTrackNode, self.bodyAnim)
+ else:
+ cmds.parent(chestMasterTrackNode, self.spineCtrlGrp)
+
+ # hide locator
+ cmds.setAttr(chestMasterTrackNode + ".v", 0)
+
+ botJntLoc = cmds.group(empty=True, name=self.name + "_botJnt_tracker")
+ constraint = cmds.parentConstraint(botJnt, botJntLoc)[0]
+ cmds.delete(constraint)
+ cmds.parent(botJntLoc, botJnt)
+ cmds.makeIdentity(botJntLoc, t=1, r=1, s=1, apply=True)
+ cmds.parentConstraint(botJnt, botJntLoc)[0]
+
+ # =======================================================================
+ # Rotate Y
+ # =======================================================================
+ cmds.connectAttr(chestTrackNode + ".ry", topCtrlMultRY + ".input1X")
+ cmds.connectAttr(topCtrl + ".rotationInfluence", topCtrlMultRY + ".input2X")
+
+ cmds.connectAttr(topCtrlMultRY + ".outputX", topCtrlMultSwitchRY + ".input1X")
+ cmds.connectAttr(topCtrl + ".autoSpine", topCtrlMultSwitchRY + ".input2X")
+ cmds.connectAttr(topCtrlMultSwitchRY + ".outputX", midDriver + ".tz")
+
+ # =======================================================================
+ # Rotate Z
+ # =======================================================================
+ multInverse = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_autoSpine_mult_rz_inverse")
+ cmds.connectAttr(topCtrl + ".rotationInfluence", multInverse + ".input1X")
+ cmds.setAttr(multInverse + ".input2X", -1)
+
+ cmds.connectAttr(chestTrackNode + ".rz", topCtrlMultRZ + ".input1X")
+ cmds.connectAttr(multInverse + ".outputX", topCtrlMultRZ + ".input2X")
+
+ cmds.connectAttr(topCtrlMultRZ + ".outputX", topCtrlMultSwitchRZ + ".input1X")
+ cmds.connectAttr(topCtrl + ".autoSpine", topCtrlMultSwitchRZ + ".input2X")
+ cmds.connectAttr(topCtrlMultSwitchRZ + ".outputX", midDriver + ".ty")
+
+ # =======================================================================
+ # Translate X
+ # =======================================================================
+
+ # Chest Control Translate X + Hip Control Translate X / 2 * autpSpine
+ autoSpineTXNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=midDriverTrans + "_TX_Avg")
+ cmds.setAttr(autoSpineTXNode + ".operation", 3)
+ autoSpineTX_MultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=midDriverTrans + "_TX_Mult")
+
+ cmds.connectAttr(topCtrl + ".translateX", autoSpineTXNode + ".input1D[0]")
+ cmds.connectAttr(botJntLoc + ".translateX", autoSpineTXNode + ".input1D[1]")
+ cmds.connectAttr(autoSpineTXNode + ".output1D", autoSpineTX_MultNode + ".input1X")
+ cmds.connectAttr(topCtrl + ".autoSpine", autoSpineTX_MultNode + ".input2X")
+ cmds.connectAttr(autoSpineTX_MultNode + ".outputX", midDriverTrans + ".translateX")
+
+ # =======================================================================
+ # Translate Y
+ # =======================================================================
+ autoSpineTYNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=midDriverTrans + "_TY_Avg")
+ cmds.setAttr(autoSpineTYNode + ".operation", 3)
+ autoSpineTY_MultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=midDriverTrans + "_TY_Mult")
+
+ cmds.connectAttr(chestTrackNode + ".translateY", autoSpineTYNode + ".input1D[0]")
+ cmds.connectAttr(botJntLoc + ".translateY", autoSpineTYNode + ".input1D[1]")
+ cmds.connectAttr(autoSpineTYNode + ".output1D", autoSpineTY_MultNode + ".input1X")
+ cmds.connectAttr(topCtrl + ".autoSpine", autoSpineTY_MultNode + ".input2X")
+ cmds.connectAttr(autoSpineTY_MultNode + ".outputX", midDriverTrans + ".translateY")
+
+ # =======================================================================
+ # Translate Z
+ # =======================================================================
+ autoSpineTZNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=midDriverTrans + "_TZ_Avg")
+ cmds.setAttr(autoSpineTZNode + ".operation", 3)
+ autoSpineTZ_MultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=midDriverTrans + "_TZ_Mult")
+
+ cmds.connectAttr(chestTrackNode + ".translateZ", autoSpineTZNode + ".input1D[0]")
+ cmds.connectAttr(botJntLoc + ".translateZ", autoSpineTZNode + ".input1D[1]")
+ cmds.connectAttr(autoSpineTZNode + ".output1D", autoSpineTZ_MultNode + ".input1X")
+ cmds.connectAttr(topCtrl + ".autoSpine", autoSpineTZ_MultNode + ".input2X")
+ cmds.connectAttr(autoSpineTZ_MultNode + ".outputX", midDriverTrans + ".translateZ")
+
+ cmds.setAttr(topCtrl + ".autoSpine", 1)
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def switchMode(self, mode, checkBox, range=False):
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ # are we matching?
+ if not range:
+ match = checkBox.isChecked()
+ else:
+ match = True
+
+ # if being called from match over frame range
+ if range:
+ if mode == matchData[1][0]:
+ mode = "FK"
+ if mode == matchData[1][1]:
+ mode = "IK"
+
+ # switch to FK mode
+ if mode == "FK":
+ # get current mode
+ currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode")
+ if currentMode == 0.0:
+ cmds.warning("Already in FK mode.")
+ return
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if match:
+ # get fk controls
+ controls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ controls.reverse()
+ # create a duplicate chain
+ topCtrl = controls[0]
+ topGrp = cmds.listRelatives(namespace + ":" + topCtrl, parent=True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world=True)
+
+ # match the fk controls to the corresponding joint
+
+ for control in controls:
+ joint = control.partition("fk_")[2].partition("_anim")[0]
+ joint = namespace + ":" + joint
+
+ constraint = cmds.parentConstraint(joint, control)[0]
+
+ translate = cmds.getAttr(control + ".translate")[0]
+ rotate = cmds.getAttr(control + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2],
+ type='double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ # delete dupes
+ cmds.delete(newControls[0])
+
+ # switch modes
+ if not range:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ # switch to IK mode
+ if mode == "IK":
+
+ # get current mode
+ currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode")
+ if currentMode == 1.0:
+ cmds.warning("Already in IK mode.")
+ return
+
+ if not match:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ if match:
+
+ # get IK controls
+ controls = json.loads(cmds.getAttr(networkNode + ".ikControls"))
+
+ # Chest
+ # create a duplicate chest anim
+ control = controls[0]
+ topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world=True)
+
+ # match the chest anim to the last spine joint
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ joint = fkControls[0].partition("_anim")[0].partition("fk_")[2]
+ joint = namespace + ":" + joint
+ constraint = cmds.parentConstraint(joint, control)[0]
+ cmds.delete(constraint)
+
+ # this will now give use good values
+ translate = cmds.getAttr(control + ".translate")[0]
+ rotate = cmds.getAttr(control + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2],
+ type='double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ # delete dupes
+ cmds.delete(newControls[0])
+
+ # set auto spine off
+ cmds.setAttr(namespace + ":" + control + ".autoSpine", 0)
+ cmds.setKeyframe(namespace + ":" + control + ".autoSpine")
+
+ # Mid Anim
+ # create a duplicate mid spine anim
+ control = controls[1]
+ topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0]
+ newControls = cmds.duplicate(topGrp)
+ cmds.parent(newControls[0], world=True)
+
+ # match the mid spibne anim to the mid spine joint
+ allJnts = self.returnCreatedJoints
+ joints = []
+ for jnt in allJnts:
+ if jnt.find("pelvis") == -1:
+ joints.append(jnt)
+
+ joint = "driver_" + joints[len(joints) / 2]
+ joint = namespace + ":" + joint
+ constraint = cmds.parentConstraint(joint, control)[0]
+ cmds.delete(constraint)
+
+ # this will now give use good values
+ translate = cmds.getAttr(control + ".translate")[0]
+ rotate = cmds.getAttr(control + ".rotate")[0]
+
+ cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2],
+ type='double3')
+ cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3')
+
+ cmds.setKeyframe(namespace + ":" + control)
+
+ # delete dupes
+ cmds.delete(newControls[0])
+
+ # switch modes
+ if not range:
+ cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0)
+ cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def resetRigControls(self, resetAll):
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+ namespace = cmds.getAttr(characterNode + ".namespace")
+
+ nonZeroAttrs = ["scale", "globalScale", "scaleX", "scaleY", "scaleZ", "twist_amount", "rotationInfluence",
+ "autoSpine"]
+
+ 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
+
+ try:
+ for each in data:
+ attrs = cmds.listAttr(namespace + ":" + each, keyable=True)
+ for attr in attrs:
+ if attr not in nonZeroAttrs:
+ try:
+ cmds.setAttr(namespace + ":" + each + "." + attr, 0)
+ except:
+ pass
+ else:
+ try:
+ cmds.setAttr(namespace + ":" + each + "." + attr, 1)
+ except:
+ pass
+ except:
+ cmds.warning("skipped " + str(control) + ". No valid controls found to reset.")
+
+ if not resetAll:
+ selection = cmds.ls(sl=True)
+ for each in selection:
+ attrs = cmds.listAttr(each, keyable=True)
+
+ for attr in attrs:
+ if attr not in nonZeroAttrs:
+
+ try:
+ cmds.setAttr(each + "." + attr, 0)
+ except:
+ pass
+ else:
+ try:
+ cmds.setAttr(each + "." + attr, 1)
+ except:
+ pass
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def getUpAxis(self, obj):
+
+ cmds.xform(obj, ws=True, relative=True, t=[0, 0, 10])
+ translate = cmds.getAttr(obj + ".translate")[0]
+ newTuple = (abs(translate[0]), abs(translate[1]), abs(translate[2]))
+ cmds.xform(obj, ws=True, relative=True, t=[0, 0, -10])
+
+ highestVal = max(newTuple)
+ axis = newTuple.index(highestVal)
+ upAxis = None
+
+ if axis == 0:
+ upAxis = "X"
+
+ if axis == 1:
+ upAxis = "Y"
+
+ if axis == 2:
+ upAxis = "Z"
+
+ return upAxis
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def importFBX(self, importMethod, character):
+
+ returnControls = []
+
+ # get basic info of node
+ networkNode = self.returnRigNetworkNode
+ moduleName = cmds.getAttr(networkNode + ".moduleName")
+ baseModuleName = cmds.getAttr(networkNode + ".baseName")
+
+ # find prefix/suffix of module name
+ prefixSuffix = moduleName.split(baseModuleName)
+ prefix = None
+ suffix = None
+
+ if prefixSuffix[0] != '':
+ prefix = prefixSuffix[0]
+ if prefixSuffix[1] != '':
+ suffix = prefixSuffix[1]
+
+ # get controls
+ pelvisControls = json.loads(cmds.getAttr(networkNode + ".pelvisControls"))
+ fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls"))
+ ikControls = json.loads(cmds.getAttr(networkNode + ".ikControls"))
+
+ # get joints
+ joints = cmds.getAttr(networkNode + ".Created_Bones")
+ splitJoints = joints.split("::")
+ createdJoints = []
+
+ for bone in splitJoints:
+ if bone != "":
+ createdJoints.append(bone)
+
+ # IMPORT (FK OR IK)
+ for joint in createdJoints:
+ if joint.find("pelvis") != -1:
+ cmds.parentConstraint(joint, character + ":" + pelvisControls[1])
+ returnControls.append(character + ":" + pelvisControls[1])
+
+ # IMPORT FK
+ if importMethod == "FK" or importMethod == "Both":
+ cmds.setAttr(character + ":" + moduleName + "_settings.mode", 0)
+
+ for joint in createdJoints:
+ if cmds.objExists(character + ":" + "fk_" + joint + "_anim"):
+ cmds.parentConstraint(joint, character + ":" + "fk_" + joint + "_anim")
+ returnControls.append(character + ":" + "fk_" + joint + "_anim")
+
+ # IMPORT IK
+ if importMethod == "IK" or importMethod == "Both":
+ cmds.setAttr(character + ":" + moduleName + "_settings.mode", 1)
+
+ topJoint = createdJoints[-1]
+ midJoint = createdJoints[(len(createdJoints)) / 2]
+
+ cmds.parentConstraint(topJoint, character + ":" + ikControls[0])
+ returnControls.append(character + ":" + ikControls[0])
+
+ cmds.parentConstraint(midJoint, character + ":" + ikControls[1])
+ returnControls.append(character + ":" + ikControls[1])
+
+ # IMPORT NONE
+ if importMethod == "None":
+ pass
+
+ return returnControls
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def resetRigControls(self, resetAll):
+
+ # 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
+ zeroAttrs = ["translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ"]
+ nonZeroAttrs = ["scaleX", "scaleY", "scaleZ"]
+
+ try:
+ for each in data:
+ attrs = cmds.listAttr(namespace + ":" + each, keyable=True)
+ for attr in attrs:
+ if attr in zeroAttrs:
+ cmds.setAttr(namespace + ":" + each + "." + attr, 0)
+ if attr in nonZeroAttrs:
+ cmds.setAttr(namespace + ":" + each + "." + attr, 1)
+ else:
+ pass
+ except:
+ cmds.warning("skipped " + str(control) + ". No valid controls found to reset.")
+
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+ def selectRigControls(self, mode):
+
+ controls = self.getControls()
+ if controls == None:
+ return
+ ikControls = ["chest_ik_anim", "mid_ik_anim"]
+
+ # get namespace
+ networkNode = self.returnRigNetworkNode
+ characterNode = cmds.listConnections(networkNode + ".parent")[0]
+
+ try:
+ namespace = cmds.getAttr(characterNode + ".namespace")
+ except:
+ namespace = ""
+
+ if mode == "all":
+ for control in controls:
+ cmds.select(namespace + ":" + control, add=True)
+
+ if mode == "fk":
+ for control in controls:
+ if control.find("fk_") == 0:
+ cmds.select(namespace + ":" + control, add=True)
+
+ if mode == "ik":
+ for control in controls:
+ for ikControl in ikControls:
+ if control.find(ikControl) != -1:
+ cmds.select(namespace + ":" + control, add=True)
diff --git a/Core/Scripts/RigModules/__init__.py b/Core/Scripts/RigModules/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Core/Scripts/RigModules/__init__.py