aboutsummaryrefslogtreecommitdiff
path: root/Core/Scripts/RigModules/ART_Torso.py
diff options
context:
space:
mode:
authorMobileMachine\jeremy <[email protected]>2017-06-06 22:59:03 -0400
committerMobileMachine\jeremy <[email protected]>2017-06-06 22:59:03 -0400
commit24725fa8681f906ab44d80687c09fecc171a2896 (patch)
tree312a601df29aca7f8db9f44082d96ebc7a679138 /Core/Scripts/RigModules/ART_Torso.py
parentInitial commit (diff)
downloadartv2-24725fa8681f906ab44d80687c09fecc171a2896.tar.xz
artv2-24725fa8681f906ab44d80687c09fecc171a2896.zip
Initial Submission
First submission of current state of ARTv2. Currently considered to be in Alpha. There are a couple of animation tools not implemented yet, and one module not implemented yet, as well as incomplete documentation.
Diffstat (limited to 'Core/Scripts/RigModules/ART_Torso.py')
-rw-r--r--Core/Scripts/RigModules/ART_Torso.py2394
1 files changed, 2394 insertions, 0 deletions
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)