diff options
| author | MobileMachine\jeremy <[email protected]> | 2017-06-06 22:59:03 -0400 |
|---|---|---|
| committer | MobileMachine\jeremy <[email protected]> | 2017-06-06 22:59:03 -0400 |
| commit | 24725fa8681f906ab44d80687c09fecc171a2896 (patch) | |
| tree | 312a601df29aca7f8db9f44082d96ebc7a679138 /Core/Scripts/RigModules | |
| parent | Initial commit (diff) | |
| download | artv2-24725fa8681f906ab44d80687c09fecc171a2896.tar.xz artv2-24725fa8681f906ab44d80687c09fecc171a2896.zip | |
Initial Submission
First submission of current state of ARTv2. Currently considered to be in Alpha. There are a couple of animation tools not implemented yet, and one module not implemented yet, as well as incomplete documentation.
Diffstat (limited to 'Core/Scripts/RigModules')
| -rw-r--r-- | Core/Scripts/RigModules/ART_Arm_Standard.py | 4863 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/ART_Chain.py | 294 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/ART_Head.py | 1068 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/ART_Leaf.py | 1414 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/ART_Leg_Standard.py | 3758 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/ART_Root.py | 246 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/ART_Torso.py | 2394 | ||||
| -rw-r--r-- | Core/Scripts/RigModules/__init__.py | 0 |
8 files changed, 14037 insertions, 0 deletions
diff --git a/Core/Scripts/RigModules/ART_Arm_Standard.py b/Core/Scripts/RigModules/ART_Arm_Standard.py new file mode 100644 index 0000000..a0e82ec --- /dev/null +++ b/Core/Scripts/RigModules/ART_Arm_Standard.py @@ -0,0 +1,4863 @@ +import json +import os +import time +import weakref +from functools import partial + +import maya.cmds as cmds + +import System.interfaceUtils as interfaceUtils +import System.riggingUtils as riggingUtils +import System.utils as utils +from System.ART_RigModule import ART_RigModule +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + +# file attributes +icon = "Modules/armStandard.png" +hoverIcon = "Modules/hover_armStandard.png" +search = "biped:arm" +className = "ART_Arm_Standard" +jointMover = "Core/JointMover/ART_Arm_Standard.ma" +baseName = "arm" +rigs = ["FK::IK"] +fbxImport = ["None", "FK", "IK", "Both"] +matchData = [True, ["Match FK to IK", "Match IK to FK"]] +controlTypes = [["fkControls", "FK"], ["ikControls", "IK"], ["upArmTwistControls", "FK"], ["loArmTwistControls", "FK"], + ["fkFingerControls", "FK"], ["ikFingerControls", "IK"], ["clavControls", "FK"], ["clavControls", "IK"]] +sorting = 0 + +# begin class +class ART_Arm_Standard(ART_RigModule): + _instances = set() + + def __init__(self, rigUiInst, moduleUserName): + + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + + self.__class__._instances.add(weakref.ref(self)) + + ART_RigModule.__init__(self, "ART_Arm_Standard_Module", "ART_Arm_Standard", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + # call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + # add custom attributes for this specific module + bones = "clavicle::upperarm::lowerarm::hand::thumb_metacarpal::thumb_proximal::thumb_distal::index_proximal::" + bones += "index_middle::index_distal::middle_proximal::middle_middle::middle_distal::ring_proximal::" + bones += "ring_middle::ring_distal::pinky_proximal::pinky_middle::pinky_distal::" + + cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".Created_Bones", bones, type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".canAim", True, lock=True) + + cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".aimMode", False, lock=True) + + # joint mover settings + cmds.addAttr(self.networkNode, sn="armTwists", keyable=False) + cmds.setAttr(self.networkNode + ".armTwists", 0, lock=True) + + cmds.addAttr(self.networkNode, sn="forearmTwists", keyable=False) + cmds.setAttr(self.networkNode + ".forearmTwists", 0, lock=True) + + cmds.addAttr(self.networkNode, sn="thumbJoints", keyable=False) + cmds.setAttr(self.networkNode + ".thumbJoints", 2, lock=True) + + cmds.addAttr(self.networkNode, sn="thumbMeta", keyable=False, at="bool") + cmds.setAttr(self.networkNode + ".thumbMeta", True, lock=True) + + cmds.addAttr(self.networkNode, sn="indexJoints", keyable=False) + cmds.setAttr(self.networkNode + ".indexJoints", 3, lock=True) + + cmds.addAttr(self.networkNode, sn="indexMeta", keyable=False, at="bool") + cmds.setAttr(self.networkNode + ".indexMeta", False, lock=True) + + cmds.addAttr(self.networkNode, sn="middleJoints", keyable=False) + cmds.setAttr(self.networkNode + ".middleJoints", 3, lock=True) + + cmds.addAttr(self.networkNode, sn="middleMeta", keyable=False, at="bool") + cmds.setAttr(self.networkNode + ".middleMeta", False, lock=True) + + cmds.addAttr(self.networkNode, sn="ringJoints", keyable=False) + cmds.setAttr(self.networkNode + ".ringJoints", 3, lock=True) + + cmds.addAttr(self.networkNode, sn="ringMeta", keyable=False, at="bool") + cmds.setAttr(self.networkNode + ".ringMeta", False, lock=True) + + cmds.addAttr(self.networkNode, sn="pinkyJoints", keyable=False) + cmds.setAttr(self.networkNode + ".pinkyJoints", 3, lock=True) + + cmds.addAttr(self.networkNode, sn="pinkyMeta", keyable=False, at="bool") + cmds.setAttr(self.networkNode + ".pinkyMeta", False, lock=True) + + cmds.addAttr(self.networkNode, sn="side", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".side", "Left", type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="includeClavicle", keyable=False, at="bool") + cmds.setAttr(self.networkNode + ".includeClavicle", True, lock=True) + + # rig creation settings + cmds.addAttr(self.networkNode, sn="buildFK", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".buildFK", True, lock=True) + + cmds.addAttr(self.networkNode, sn="buildIK_V1", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".buildIK_V1", True, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + networkNode = self.returnNetworkNode + + # groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 500, True) + + font = QtGui.QFont() + font.setPointSize(8) + + headerFont = QtGui.QFont() + headerFont.setPointSize(8) + headerFont.setBold(True) + + # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot + self.layout = QtWidgets.QVBoxLayout(self.groupBox) + self.frame = QtWidgets.QFrame(self.groupBox) + self.layout.addWidget(self.frame) + + self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) + self.frame.setMinimumSize(QtCore.QSize(320, 465)) + self.frame.setMaximumSize(QtCore.QSize(320, 465)) + + # add layout for custom settings + self.customSettingsLayout = QtWidgets.QVBoxLayout(self.frame) + + # mirror module + self.mirrorModLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.mirrorModLayout) + self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ") + self.mirrorModuleLabel.setFont(font) + self.mirrorModLayout.addWidget(self.mirrorModuleLabel) + + mirror = cmds.getAttr(networkNode + ".mirrorModule") + if mirror == "": + mirror = "None" + self.mirrorMod = QtWidgets.QLabel(mirror) + self.mirrorMod.setFont(font) + self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter) + self.mirrorModLayout.addWidget(self.mirrorMod) + + # current parent + self.currentParentMod = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.currentParentMod) + self.currentParentLabel = QtWidgets.QLabel("Current Parent: ") + self.currentParentLabel.setFont(font) + self.currentParentMod.addWidget(self.currentParentLabel) + + parent = cmds.getAttr(networkNode + ".parentModuleBone") + self.currentParent = QtWidgets.QLabel(parent) + self.currentParent.setFont(font) + self.currentParent.setAlignment(QtCore.Qt.AlignHCenter) + self.currentParentMod.addWidget(self.currentParent) + + # button layout for name/parent + self.buttonLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.buttonLayout) + self.changeNameBtn = QtWidgets.QPushButton("Change Name") + self.changeParentBtn = QtWidgets.QPushButton("Change Parent") + self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module") + self.buttonLayout.addWidget(self.changeNameBtn) + self.buttonLayout.addWidget(self.changeParentBtn) + self.buttonLayout.addWidget(self.mirrorModuleBtn) + self.changeNameBtn.setObjectName("blueButton") + self.changeParentBtn.setObjectName("blueButton") + self.mirrorModuleBtn.setObjectName("blueButton") + + # add side settings + self.sideLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.sideLayout) + self.sideLabel = QtWidgets.QLabel("Side: ") + self.sideLabel.setFont(font) + self.leftSideBtn = QtWidgets.QRadioButton("Left Side") + self.rightSideBtn = QtWidgets.QRadioButton("Right Side") + self.sideLayout.addWidget(self.sideLabel) + self.sideLayout.addWidget(self.leftSideBtn) + self.sideLayout.addWidget(self.rightSideBtn) + + # get current side + if cmds.getAttr(networkNode + ".side") == "Left": + self.leftSideBtn.setChecked(True) + if cmds.getAttr(networkNode + ".side") == "Right": + self.rightSideBtn.setChecked(True) + + self.leftSideBtn.clicked.connect(self.changeSide) + self.rightSideBtn.clicked.connect(self.changeSide) + + # coplanar mode and bake offsets layout + self.armToolsLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.armToolsLayout) + + # Coplanar mode + self.coplanarBtn = QtWidgets.QPushButton("Coplanar Mode") + self.coplanarBtn.setFont(headerFont) + self.armToolsLayout.addWidget(self.coplanarBtn) + self.coplanarBtn.setCheckable(True) + self.coplanarBtn.clicked.connect(self.coplanarMode) + self.coplanarBtn.setToolTip("[EXPERIMENTAL] Forces arm joints to always be planar for best IK setup") + + # Bake OFfsets + self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets") + self.bakeOffsetsBtn.setFont(headerFont) + self.armToolsLayout.addWidget(self.bakeOffsetsBtn) + self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets) + self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync") + + self.coplanarBtn.setObjectName("blueButton") + self.bakeOffsetsBtn.setObjectName("blueButton") + + # Clavicle Settings + spacerItem = QtWidgets.QSpacerItem(200, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.customSettingsLayout.addItem(spacerItem) + + self.clavicleCB = QtWidgets.QCheckBox("Include Clavicle?") + self.clavicleCB.setChecked(True) + self.customSettingsLayout.addWidget(self.clavicleCB) + + spacerItem = QtWidgets.QSpacerItem(200, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.customSettingsLayout.addItem(spacerItem) + + # Twist Bone Settings + self.twistSettingsLabel = QtWidgets.QLabel("Twist Bone Settings: ") + self.twistSettingsLabel.setFont(headerFont) + self.twistSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);") + self.customSettingsLayout.addWidget(self.twistSettingsLabel) + + self.separatorA = QtWidgets.QFrame() + self.separatorA.setFrameShape(QtWidgets.QFrame.HLine) + self.separatorA.setFrameShadow(QtWidgets.QFrame.Sunken) + self.customSettingsLayout.addWidget(self.separatorA) + + self.twistBonesLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.twistBonesLayout) + + self.twistForm = QtWidgets.QFormLayout() + self.upperarmTwistLabel = QtWidgets.QLabel("UpperArm: ") + self.upperarmTwistLabel.setFont(font) + self.twistForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.upperarmTwistLabel) + self.upperarmTwistNum = QtWidgets.QSpinBox() + self.upperarmTwistNum.setMaximum(3) + self.twistForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.upperarmTwistNum) + self.twistBonesLayout.addLayout(self.twistForm) + + self.lowerArmTwistForm = QtWidgets.QFormLayout() + self.lowerarmTwistLabel = QtWidgets.QLabel("LowerArm: ") + self.lowerarmTwistLabel.setFont(font) + self.lowerArmTwistForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.lowerarmTwistLabel) + self.lowerarmTwistNum = QtWidgets.QSpinBox() + self.lowerarmTwistNum.setMaximum(3) + self.lowerArmTwistForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.lowerarmTwistNum) + self.twistBonesLayout.addLayout(self.lowerArmTwistForm) + + # Hand Settings Section + self.handSettingsLabel = QtWidgets.QLabel("Hand Settings: ") + self.handSettingsLabel.setFont(headerFont) + self.handSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);") + self.customSettingsLayout.addWidget(self.handSettingsLabel) + + self.separatorB = QtWidgets.QFrame() + self.separatorB.setFrameShape(QtWidgets.QFrame.HLine) + self.separatorB.setFrameShadow(QtWidgets.QFrame.Sunken) + self.customSettingsLayout.addWidget(self.separatorB) + + # Thumb Settings: add VBoxLayout + self.fingerVBoxLayout = QtWidgets.QVBoxLayout() + self.customSettingsLayout.addLayout(self.fingerVBoxLayout) + + # THUMB + self.thumbLayout = QtWidgets.QHBoxLayout() + + self.thumbLabel = QtWidgets.QLabel("Thumb Joints: ") + self.thumbLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.thumbLabel.setMinimumSize(QtCore.QSize(100, 20)) + self.thumbLabel.setMaximumSize(QtCore.QSize(100, 20)) + self.thumbLayout.addWidget((self.thumbLabel)) + + self.thumbNum = QtWidgets.QSpinBox() + self.thumbNum.setMaximum(2) + self.thumbNum.setMinimumSize(QtCore.QSize(50, 20)) + self.thumbNum.setMaximumSize(QtCore.QSize(50, 20)) + self.thumbNum.setValue(2) + self.thumbNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.thumbLayout.addWidget(self.thumbNum) + + self.thumbMeta = QtWidgets.QCheckBox("Include Metacarpal") + self.thumbMeta.setChecked(True) + self.thumbMeta.setMinimumSize(QtCore.QSize(150, 20)) + self.thumbMeta.setMaximumSize(QtCore.QSize(150, 20)) + self.thumbLayout.addWidget(self.thumbMeta) + self.fingerVBoxLayout.addLayout(self.thumbLayout) + + # INDEX + self.indexLayout = QtWidgets.QHBoxLayout() + + self.indexLabel = QtWidgets.QLabel("Index Joints: ") + self.indexLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.indexLabel.setMinimumSize(QtCore.QSize(100, 20)) + self.indexLabel.setMaximumSize(QtCore.QSize(100, 20)) + self.indexLayout.addWidget((self.indexLabel)) + + self.indexNum = QtWidgets.QSpinBox() + self.indexNum.setMaximum(3) + self.indexNum.setValue(3) + self.indexNum.setMinimumSize(QtCore.QSize(50, 20)) + self.indexNum.setMaximumSize(QtCore.QSize(50, 20)) + self.indexNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.indexLayout.addWidget(self.indexNum) + + self.indexMeta = QtWidgets.QCheckBox("Include Metacarpal") + self.indexMeta.setMinimumSize(QtCore.QSize(150, 20)) + self.indexMeta.setMaximumSize(QtCore.QSize(150, 20)) + self.indexLayout.addWidget(self.indexMeta) + self.fingerVBoxLayout.addLayout(self.indexLayout) + + # MIDDLE + self.middleLayout = QtWidgets.QHBoxLayout() + + self.middleLabel = QtWidgets.QLabel("Middle Joints: ") + self.middleLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.middleLabel.setMinimumSize(QtCore.QSize(100, 20)) + self.middleLabel.setMaximumSize(QtCore.QSize(100, 20)) + self.middleLayout.addWidget((self.middleLabel)) + + self.middleNum = QtWidgets.QSpinBox() + self.middleNum.setMaximum(3) + self.middleNum.setValue(3) + self.middleNum.setMinimumSize(QtCore.QSize(50, 20)) + self.middleNum.setMaximumSize(QtCore.QSize(50, 20)) + self.middleNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.middleLayout.addWidget(self.middleNum) + + self.middleMeta = QtWidgets.QCheckBox("Include Metacarpal") + self.middleMeta.setMinimumSize(QtCore.QSize(150, 20)) + self.middleMeta.setMaximumSize(QtCore.QSize(150, 20)) + self.middleLayout.addWidget(self.middleMeta) + self.fingerVBoxLayout.addLayout(self.middleLayout) + + # RING + self.ringLayout = QtWidgets.QHBoxLayout() + + self.ringLabel = QtWidgets.QLabel("Ring Joints: ") + self.ringLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.ringLabel.setMinimumSize(QtCore.QSize(100, 20)) + self.ringLabel.setMaximumSize(QtCore.QSize(100, 20)) + self.ringLayout.addWidget((self.ringLabel)) + + self.ringNum = QtWidgets.QSpinBox() + self.ringNum.setMaximum(3) + self.ringNum.setValue(3) + self.ringNum.setMinimumSize(QtCore.QSize(50, 20)) + self.ringNum.setMaximumSize(QtCore.QSize(50, 20)) + self.ringNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.ringLayout.addWidget(self.ringNum) + + self.ringMeta = QtWidgets.QCheckBox("Include Metacarpal") + self.ringMeta.setMinimumSize(QtCore.QSize(150, 20)) + self.ringMeta.setMaximumSize(QtCore.QSize(150, 20)) + self.ringLayout.addWidget(self.ringMeta) + self.fingerVBoxLayout.addLayout(self.ringLayout) + + # PINKY + self.pinkyLayout = QtWidgets.QHBoxLayout() + + self.pinkyLabel = QtWidgets.QLabel("Pinky Joints: ") + self.pinkyLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.pinkyLabel.setMinimumSize(QtCore.QSize(100, 20)) + self.pinkyLabel.setMaximumSize(QtCore.QSize(100, 20)) + self.pinkyLayout.addWidget((self.pinkyLabel)) + + self.pinkyNum = QtWidgets.QSpinBox() + self.pinkyNum.setMaximum(3) + self.pinkyNum.setValue(3) + self.pinkyNum.setMinimumSize(QtCore.QSize(50, 20)) + self.pinkyNum.setMaximumSize(QtCore.QSize(50, 20)) + self.pinkyNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.pinkyLayout.addWidget(self.pinkyNum) + + self.pinkyMeta = QtWidgets.QCheckBox("Include Metacarpal") + self.pinkyMeta.setMinimumSize(QtCore.QSize(150, 20)) + self.pinkyMeta.setMaximumSize(QtCore.QSize(150, 20)) + self.pinkyLayout.addWidget(self.pinkyMeta) + self.fingerVBoxLayout.addLayout(self.pinkyLayout) + + # rebuild button + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.customSettingsLayout.addItem(spacerItem) + + self.applyButton = QtWidgets.QPushButton("Apply Changes") + self.customSettingsLayout.addWidget(self.applyButton) + self.applyButton.setFont(headerFont) + self.applyButton.setMinimumSize(QtCore.QSize(300, 40)) + self.applyButton.setMaximumSize(QtCore.QSize(300, 40)) + self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.applyButton.setEnabled(False) + + # button signal/slots + self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst)) + self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst)) + self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst)) + self.applyButton.clicked.connect(partial(self.applyModuleChanges, self)) + + # signal slot for groupbox checkbox + QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible) + self.groupBox.setChecked(False) + + # spinBox & checkbox signal/slots + self.upperarmTwistNum.valueChanged.connect(self.toggleButtonState) + self.lowerarmTwistNum.valueChanged.connect(self.toggleButtonState) + self.thumbNum.valueChanged.connect(self.toggleButtonState) + self.indexNum.valueChanged.connect(self.toggleButtonState) + self.middleNum.valueChanged.connect(self.toggleButtonState) + self.ringNum.valueChanged.connect(self.toggleButtonState) + self.pinkyNum.valueChanged.connect(self.toggleButtonState) + + self.pinkyMeta.stateChanged.connect(self.toggleButtonState) + self.ringMeta.stateChanged.connect(self.toggleButtonState) + self.middleMeta.stateChanged.connect(self.toggleButtonState) + self.indexMeta.stateChanged.connect(self.toggleButtonState) + self.thumbMeta.stateChanged.connect(self.toggleButtonState) + + self.clavicleCB.stateChanged.connect(self.toggleButtonState) + + # add custom skeletonUI settings name, parent, rig types to install, mirror module, thigh twist, calf twists, + # ball joint, toes, + # add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + # Populate the settings UI based on the network node attributes + self.updateSettingsUI() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pickerUI(self, center, animUI, networkNode, namespace): + + self.namespace = namespace + + # create qBrushes + yellowBrush = QtCore.Qt.yellow + blueBrush = QtGui.QColor(100, 220, 255) + purpleBrush = QtGui.QColor(111, 48, 161) + greenBrush = QtGui.QColor(0, 255, 30) + clearBrush = QtGui.QBrush(QtCore.Qt.black) + clearBrush.setStyle(QtCore.Qt.NoBrush) + side = cmds.getAttr(networkNode + ".side") + + # create the picker border item + if networkNode.find(":") != -1: + moduleNode = networkNode.partition(":")[2] + else: + moduleNode = networkNode + + borderItem = interfaceUtils.pickerBorderItem(center.x() - 80, center.y() - 130, 110, 260, clearBrush, + moduleNode) + + # get controls + ikControls = json.loads(cmds.getAttr(networkNode + ".ikControls")) + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + upArmTwistControls = json.loads(cmds.getAttr(networkNode + ".upArmTwistControls")) + loArmTwistControls = json.loads(cmds.getAttr(networkNode + ".loArmTwistControls")) + clavControls = [] + + if cmds.objExists(networkNode + ".clavControls"): + clavControls = json.loads(cmds.getAttr(networkNode + ".clavControls")) + + buttonData = [] + controls = [] + + # ======================================================================= + # ik buttons + # ======================================================================= + ikHandButton = interfaceUtils.pickerButton(20, 20, [50, 190], namespace + ikControls[0], yellowBrush, + borderItem) + buttonData.append([ikHandButton, namespace + ikControls[0], yellowBrush]) + controls.append(namespace + ikControls[0]) + + ikElbowButton = interfaceUtils.pickerButton(20, 20, [50, 100], namespace + ikControls[1], yellowBrush, + borderItem) + buttonData.append([ikElbowButton, namespace + ikControls[1], yellowBrush]) + controls.append(namespace + ikControls[0]) + + if len(clavControls) > 0: + ikClavButton = interfaceUtils.pickerButton(20, 20, [50, 10], namespace + clavControls[1], yellowBrush, + borderItem) + buttonData.append([ikClavButton, namespace + clavControls[1], yellowBrush]) + controls.append(namespace + clavControls[1]) + + # ======================================================================= + # fk buttons + # ======================================================================= + fkArmBtn = interfaceUtils.pickerButton(20, 60, [50, 35], namespace + fkControls[2], blueBrush, borderItem) + buttonData.append([fkArmBtn, namespace + fkControls[2], blueBrush]) + controls.append(namespace + fkControls[2]) + + fkElbowBtn = interfaceUtils.pickerButton(20, 60, [50, 125], namespace + fkControls[1], blueBrush, borderItem) + buttonData.append([fkElbowBtn, namespace + fkControls[1], blueBrush]) + controls.append(namespace + fkControls[1]) + + fkHandBtn = interfaceUtils.pickerButton(40, 40, [40, 215], namespace + fkControls[0], blueBrush, borderItem) + buttonData.append([fkHandBtn, namespace + fkControls[0], blueBrush]) + controls.append(namespace + fkControls[0]) + + if len(clavControls) > 0: + fkClavButton = interfaceUtils.pickerButton(20, 20, [25, 10], namespace + clavControls[0], blueBrush, + borderItem) + buttonData.append([fkClavButton, namespace + clavControls[0], blueBrush]) + controls.append(namespace + clavControls[0]) + + # ======================================================================= + # twist bones + # ======================================================================= + if upArmTwistControls != None: + if len(upArmTwistControls) > 0: + y = 35 + for i in range(len(upArmTwistControls)): + button = interfaceUtils.pickerButton(15, 15, [75, y], namespace + upArmTwistControls[i], + purpleBrush, borderItem) + buttonData.append([button, namespace + upArmTwistControls[i], purpleBrush]) + controls.append(namespace + upArmTwistControls[i]) + y = y + 22 + + if loArmTwistControls != None: + if len(loArmTwistControls) > 0: + y = 170 + for i in range(len(loArmTwistControls)): + button = interfaceUtils.pickerButton(15, 15, [75, y], namespace + loArmTwistControls[i], + purpleBrush, borderItem) + buttonData.append([button, namespace + loArmTwistControls[i], purpleBrush]) + controls.append(namespace + loArmTwistControls[i]) + y = y - 22 + + # ======================================================================= + # settings button + # ======================================================================= + settingsBtn = interfaceUtils.pickerButton(20, 20, [85, 235], namespace + self.name + "_settings", greenBrush, + borderItem) + buttonData.append([settingsBtn, namespace + ":" + self.name + "_settings", greenBrush]) + controls.append(namespace + ":" + self.name + "_settings") + interfaceUtils.addTextToButton("S", settingsBtn) + + # ======================================================================= + # #FINGERS !!!! THIS IS A SUB-PICKER !!!! + # ======================================================================= + + # if there are fingers, create a finger picker + fingerControls = json.loads(cmds.getAttr(networkNode + ".fkFingerControls")) + ikFingerControls = json.loads(cmds.getAttr(networkNode + ".ikFingerControls")) + + if len(fingerControls) > 0: + + name = cmds.getAttr(networkNode + ".moduleName") + fingerBorder = interfaceUtils.pickerBorderItem(center.x() + 35, center.y() - 75, 100, 100, clearBrush, + moduleNode, name + "_fingers") + fingerBorder.setParentItem(borderItem) + interfaceUtils.addTextToButton(side[0] + "_Fingers", fingerBorder, False, False, True) + + # create selection set lists + thumbFingers = [] + indexFingers = [] + middleFingers = [] + ringFingers = [] + pinkyFingers = [] + + metaCarpals = [] + distalKnuckles = [] + middleKnuckles = [] + proximalKnuckles = [] + fkFingerControls = [] + + fingerButtonData = [] + # ======================================================================= + # THUMB + # ======================================================================= + for finger in fingerControls: + if finger.find("thumb_metacarpal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20, 40], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + thumbFingers.append(namespace + finger) + + if finger.find("thumb_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20, 55], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + thumbFingers.append(namespace + finger) + + if finger.find("thumb_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20, 75], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + thumbFingers.append(namespace + finger) + + # ======================================================================= + # INDEX + # ======================================================================= + if finger.find("index_metacarpal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35, 25], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + indexFingers.append(namespace + finger) + metaCarpals.append(namespace + finger) + + if finger.find("index_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35, 40], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + indexFingers.append(namespace + finger) + proximalKnuckles.append(namespace + finger) + + if finger.find("index_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [35, 55], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + indexFingers.append(namespace + finger) + middleKnuckles.append(namespace + finger) + + if finger.find("index_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35, 75], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + indexFingers.append(namespace + finger) + distalKnuckles.append(namespace + finger) + + # ======================================================================= + # MIDDLE + # ======================================================================= + if finger.find("middle_metacarpal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50, 25], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + middleFingers.append(namespace + finger) + metaCarpals.append(namespace + finger) + + if finger.find("middle_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50, 40], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + middleFingers.append(namespace + finger) + proximalKnuckles.append(namespace + finger) + + if finger.find("middle_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [50, 55], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + middleFingers.append(namespace + finger) + middleKnuckles.append(namespace + finger) + + if finger.find("middle_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50, 75], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + middleFingers.append(namespace + finger) + distalKnuckles.append(namespace + finger) + + # ======================================================================= + # RING + # ======================================================================= + if finger.find("ring_metacarpal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65, 25], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + ringFingers.append(namespace + finger) + metaCarpals.append(namespace + finger) + + if finger.find("ring_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65, 40], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + ringFingers.append(namespace + finger) + proximalKnuckles.append(namespace + finger) + + if finger.find("ring_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [65, 55], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + ringFingers.append(namespace + finger) + middleKnuckles.append(namespace + finger) + + if finger.find("ring_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65, 75], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + ringFingers.append(namespace + finger) + distalKnuckles.append(namespace + finger) + + # ======================================================================= + # PINKY + # ======================================================================= + if finger.find("pinky_metacarpal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80, 25], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + pinkyFingers.append(namespace + finger) + metaCarpals.append(namespace + finger) + + if finger.find("pinky_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80, 40], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + pinkyFingers.append(namespace + finger) + proximalKnuckles.append(namespace + finger) + + if finger.find("pinky_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [80, 55], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + pinkyFingers.append(namespace + finger) + middleKnuckles.append(namespace + finger) + + if finger.find("pinky_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80, 75], namespace + finger, blueBrush, fingerBorder) + buttonData.append([button, namespace + finger, blueBrush]) + fingerButtonData.append([button, namespace + finger, blueBrush]) + controls.append(namespace + finger) + fkFingerControls.append(namespace + finger) + pinkyFingers.append(namespace + finger) + distalKnuckles.append(namespace + finger) + + # ======================================================================= + # IK FINGERS + # ======================================================================= + for finger in ikFingerControls: + + if finger.find("index_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35, 88], namespace + finger, yellowBrush, + fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("index_pv") != -1: + button = interfaceUtils.pickerButton(10, 6, [35, 67], namespace + finger, yellowBrush, fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("middle_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50, 88], namespace + finger, yellowBrush, + fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("middle_pv") != -1: + button = interfaceUtils.pickerButton(10, 6, [50, 67], namespace + finger, yellowBrush, fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("ring_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65, 88], namespace + finger, yellowBrush, + fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("ring_pv") != -1: + button = interfaceUtils.pickerButton(10, 6, [65, 67], namespace + finger, yellowBrush, fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("pinky_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80, 88], namespace + finger, yellowBrush, + fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("pinky_pv") != -1: + button = interfaceUtils.pickerButton(10, 6, [80, 67], namespace + finger, yellowBrush, fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("thumb_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20, 88], namespace + finger, yellowBrush, + fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("thumb_pv") != -1: + button = interfaceUtils.pickerButton(10, 6, [20, 67], namespace + finger, yellowBrush, fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + if finger.find("hand_global") != -1: + button = interfaceUtils.pickerButton(5, 98, [94, 2], namespace + finger, yellowBrush, fingerBorder) + buttonData.append([button, namespace + finger, yellowBrush]) + fingerButtonData.append([button, namespace + finger, yellowBrush]) + controls.append(namespace + finger) + button.setToolTip(finger) + + # ======================================================================= + # FINGER MASS SELECT BUTTONS + # ======================================================================= + metaCarpalAll_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 25], metaCarpals, greenBrush, fingerBorder) + metaCarpalAll_btn.setToolTip("select all metacarpal controls") + + proxiKnuckle_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 40], proximalKnuckles, greenBrush, + fingerBorder) + proxiKnuckle_btn.setToolTip("select all proximal knuckles") + midKnuckle_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 55], middleKnuckles, greenBrush, fingerBorder) + midKnuckle_btn.setToolTip("select all middle knuckles") + distKnuckle_btn = interfaceUtils.pickerButtonAll(10, 10, [5, 75], distalKnuckles, greenBrush, fingerBorder) + distKnuckle_btn.setToolTip("select all distal knuckles") + + thumbs_btn = interfaceUtils.pickerButtonAll(10, 10, [20, 5], thumbFingers, greenBrush, fingerBorder) + thumbs_btn.setToolTip("select all thumb controls") + indexes_btn = interfaceUtils.pickerButtonAll(10, 10, [35, 5], indexFingers, greenBrush, fingerBorder) + indexes_btn.setToolTip("select all index finger controls") + middles_btn = interfaceUtils.pickerButtonAll(10, 10, [50, 5], middleFingers, greenBrush, fingerBorder) + middles_btn.setToolTip("select all middle finger controls") + rings_btn = interfaceUtils.pickerButtonAll(10, 10, [65, 5], ringFingers, greenBrush, fingerBorder) + rings_btn.setToolTip("select all ring finger controls") + pinkys_btn = interfaceUtils.pickerButtonAll(10, 10, [80, 5], pinkyFingers, greenBrush, fingerBorder) + pinkys_btn.setToolTip("select all pinky finger controls") + + allFinger_btn = interfaceUtils.pickerButtonAll(12, 12, [5, 8], fkFingerControls, greenBrush, fingerBorder) + allFinger_btn.setToolTip("select all fk finger controls") + + # ======================================================================= + # go through button data, adding menu items + # ======================================================================= + for each in buttonData: + if each not in fingerButtonData: + button = each[0] + + fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png")))) + ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png")))) + zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png")))) + zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png")))) + selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png")))) + + switchAction = QtWidgets.QAction('Match when Switching', button.menu) + switchAction.setCheckable(True) + switchAction.setChecked(True) + + button.menu.addAction(selectIcon, "Select All Arm Controls", partial(self.selectRigControls, "all")) + button.menu.addAction(selectIcon, "Select FK Arm Controls", partial(self.selectRigControls, "fk")) + button.menu.addAction(selectIcon, "Select IK Arm Controls", partial(self.selectRigControls, "ik")) + button.menu.addSeparator() + + if len(clavControls) > 0: + if each[1] == namespace + clavControls[0] or each[1] == namespace + clavControls[1]: + button.menu.addAction(fkIcon, "(Clav) FK Mode", + partial(self.switchClavMode, "FK", switchAction)) + button.menu.addAction(ikIcon, "(Clav) IK Mode", + partial(self.switchClavMode, "IK", switchAction)) + + else: + button.menu.addAction(fkIcon, "(Arm) FK Mode", partial(self.switchMode, "FK", switchAction)) + button.menu.addAction(ikIcon, "(Arm) IK Mode", partial(self.switchMode, "IK", switchAction)) + + else: + button.menu.addAction(fkIcon, "(Arm) FK Mode", partial(self.switchMode, "FK", switchAction)) + button.menu.addAction(ikIcon, "(Arm) IK Mode", partial(self.switchMode, "IK", switchAction)) + + button.menu.addAction(switchAction) + + button.menu.addSeparator() + + button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True)) + button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False)) + + for each in fingerButtonData: + button = each[0] + + fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png")))) + ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png")))) + zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png")))) + zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png")))) + + button.menu.addAction(fkIcon, "FK Mode (Finger)", partial(self.switchFingerMode, "FK", each[1])) + button.menu.addAction(ikIcon, "IK Mode (Finger)", partial(self.switchFingerMode, "IK", each[1])) + + button.menu.addSeparator() + button.menu.addAction(fkIcon, "FK Mode (All Fingers)", partial(self.switchFingerMode, "FK", "All")) + button.menu.addAction(ikIcon, "IK Mode (All Fingers)", partial(self.switchFingerMode, "IK", "All")) + + button.menu.addSeparator() + button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True)) + button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False)) + + # ======================================================================= + # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5) + # ======================================================================= + scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)], + kws=True) + borderItem.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + # return data and set to mirror if side is right + if side == "Right": + return [borderItem, True, scriptJob] + else: + return [borderItem, False, scriptJob] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def toggleButtonState(self): + + state = self.applyButton.isEnabled() + if state == False: + self.applyButton.setEnabled(True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addJointMoverToOutliner(self): + + index = self.rigUiInst.treeWidget.topLevelItemCount() + self.outlinerWidgets = {} + + # Add the module to the tree widget in the outliner tab of the rig creator UI + self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget) + self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name) + foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground) + + # add the clavicle + self.outlinerWidgets[self.name + "_clavicle"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_clavicle"].setText(0, self.name + "_clavicle") + self.createGlobalMoverButton(self.name + "_clavicle", self.outlinerWidgets[self.name + "_clavicle"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_clavicle", self.outlinerWidgets[self.name + "_clavicle"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_clavicle", self.outlinerWidgets[self.name + "_clavicle"], + self.rigUiInst) + + # add the upperarm + self.outlinerWidgets[self.name + "_upperarm"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_upperarm"].setText(0, self.name + "_upperarm") + self.createGlobalMoverButton(self.name + "_upperarm", self.outlinerWidgets[self.name + "_upperarm"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_upperarm", self.outlinerWidgets[self.name + "_upperarm"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_upperarm", self.outlinerWidgets[self.name + "_upperarm"], + self.rigUiInst) + + # add the upperarm twists + self.outlinerWidgets[self.name + "_upperarm_twist_01"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_upperarm"]) + self.outlinerWidgets[self.name + "_upperarm_twist_01"].setText(0, self.name + "_upperarm_twist_01") + self.createOffsetMoverButton(self.name + "_upperarm_twist_01", + self.outlinerWidgets[self.name + "_upperarm_twist_01"], self.rigUiInst) + self.outlinerWidgets[self.name + "_upperarm_twist_01"].setHidden(True) + + self.outlinerWidgets[self.name + "_upperarm_twist_02"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_upperarm"]) + self.outlinerWidgets[self.name + "_upperarm_twist_02"].setText(0, self.name + "_upperarm_twist_02") + self.createOffsetMoverButton(self.name + "_upperarm_twist_02", + self.outlinerWidgets[self.name + "_upperarm_twist_02"], self.rigUiInst) + self.outlinerWidgets[self.name + "_upperarm_twist_02"].setHidden(True) + + self.outlinerWidgets[self.name + "_upperarm_twist_03"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_upperarm"]) + self.outlinerWidgets[self.name + "_upperarm_twist_03"].setText(0, self.name + "_upperarm_twist_03") + self.createOffsetMoverButton(self.name + "_upperarm_twist_03", + self.outlinerWidgets[self.name + "_upperarm_twist_03"], self.rigUiInst) + self.outlinerWidgets[self.name + "_upperarm_twist_03"].setHidden(True) + + # add the lowerarm + self.outlinerWidgets[self.name + "_lowerarm"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_upperarm"]) + self.outlinerWidgets[self.name + "_lowerarm"].setText(0, self.name + "_lowerarm") + self.createGlobalMoverButton(self.name + "_lowerarm", self.outlinerWidgets[self.name + "_lowerarm"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_lowerarm", self.outlinerWidgets[self.name + "_lowerarm"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_lowerarm", self.outlinerWidgets[self.name + "_lowerarm"], + self.rigUiInst) + + # add the lowerarm twists + self.outlinerWidgets[self.name + "_lowerarm_twist_01"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_lowerarm"]) + self.outlinerWidgets[self.name + "_lowerarm_twist_01"].setText(0, self.name + "_lowerarm_twist_01") + self.createOffsetMoverButton(self.name + "_lowerarm_twist_01", + self.outlinerWidgets[self.name + "_lowerarm_twist_01"], self.rigUiInst) + self.outlinerWidgets[self.name + "_lowerarm_twist_01"].setHidden(True) + + self.outlinerWidgets[self.name + "_lowerarm_twist_02"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_lowerarm"]) + self.outlinerWidgets[self.name + "_lowerarm_twist_02"].setText(0, self.name + "_lowerarm_twist_02") + self.createOffsetMoverButton(self.name + "_lowerarm_twist_02", + self.outlinerWidgets[self.name + "_lowerarm_twist_02"], self.rigUiInst) + self.outlinerWidgets[self.name + "_lowerarm_twist_02"].setHidden(True) + + self.outlinerWidgets[self.name + "_lowerarm_twist_03"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_lowerarm"]) + self.outlinerWidgets[self.name + "_lowerarm_twist_03"].setText(0, self.name + "_lowerarm_twist_03") + self.createOffsetMoverButton(self.name + "_lowerarm_twist_03", + self.outlinerWidgets[self.name + "_lowerarm_twist_03"], self.rigUiInst) + self.outlinerWidgets[self.name + "_lowerarm_twist_03"].setHidden(True) + + # add the hand + self.outlinerWidgets[self.name + "_hand"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_lowerarm"]) + self.outlinerWidgets[self.name + "_hand"].setText(0, self.name + "_hand") + self.createGlobalMoverButton(self.name + "_hand", self.outlinerWidgets[self.name + "_hand"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_hand", self.outlinerWidgets[self.name + "_hand"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_hand", self.outlinerWidgets[self.name + "_hand"], self.rigUiInst) + + # add the thumb + self.outlinerWidgets[self.name + "_thumb_metacarpal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_thumb_metacarpal"].setText(0, self.name + "_thumb_metacarpal") + self.createGlobalMoverButton(self.name + "_thumb_metacarpal", + self.outlinerWidgets[self.name + "_thumb_metacarpal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thumb_metacarpal", + self.outlinerWidgets[self.name + "_thumb_metacarpal"], self.rigUiInst) + + self.outlinerWidgets[self.name + "_thumb_proximal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_thumb_proximal"].setText(0, self.name + "_thumb_proximal") + self.createGlobalMoverButton(self.name + "_thumb_proximal", self.outlinerWidgets[self.name + "_thumb_proximal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thumb_proximal", self.outlinerWidgets[self.name + "_thumb_proximal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_thumb_proximal", self.outlinerWidgets[self.name + "_thumb_proximal"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_thumb_distal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_thumb_proximal"]) + self.outlinerWidgets[self.name + "_thumb_distal"].setText(0, self.name + "_thumb_distal") + self.createGlobalMoverButton(self.name + "_thumb_distal", self.outlinerWidgets[self.name + "_thumb_distal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thumb_distal", self.outlinerWidgets[self.name + "_thumb_distal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_thumb_distal", self.outlinerWidgets[self.name + "_thumb_distal"], + self.rigUiInst) + + # add the index finger + self.outlinerWidgets[self.name + "_index_metacarpal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_index_metacarpal"].setText(0, self.name + "_index_metacarpal") + self.createGlobalMoverButton(self.name + "_index_metacarpal", + self.outlinerWidgets[self.name + "_index_metacarpal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_metacarpal", + self.outlinerWidgets[self.name + "_index_metacarpal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_index_metacarpal"].setHidden(True) + + self.outlinerWidgets[self.name + "_index_proximal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_index_proximal"].setText(0, self.name + "_index_proximal") + self.createGlobalMoverButton(self.name + "_index_proximal", self.outlinerWidgets[self.name + "_index_proximal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_proximal", self.outlinerWidgets[self.name + "_index_proximal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_index_proximal", self.outlinerWidgets[self.name + "_index_proximal"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_index_middle"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_index_proximal"]) + self.outlinerWidgets[self.name + "_index_middle"].setText(0, self.name + "_index_middle") + self.createGlobalMoverButton(self.name + "_index_middle", self.outlinerWidgets[self.name + "_index_middle"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_middle", self.outlinerWidgets[self.name + "_index_middle"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_index_middle", self.outlinerWidgets[self.name + "_index_middle"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_index_distal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_index_middle"]) + self.outlinerWidgets[self.name + "_index_distal"].setText(0, self.name + "_index_distal") + self.createGlobalMoverButton(self.name + "_index_distal", self.outlinerWidgets[self.name + "_index_distal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_distal", self.outlinerWidgets[self.name + "_index_distal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_index_distal", self.outlinerWidgets[self.name + "_index_distal"], + self.rigUiInst) + + # add the middle finger + self.outlinerWidgets[self.name + "_middle_metacarpal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_middle_metacarpal"].setText(0, self.name + "_middle_metacarpal") + self.createGlobalMoverButton(self.name + "_middle_metacarpal", + self.outlinerWidgets[self.name + "_middle_metacarpal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_metacarpal", + self.outlinerWidgets[self.name + "_middle_metacarpal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_middle_metacarpal"].setHidden(True) + + self.outlinerWidgets[self.name + "_middle_proximal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_middle_proximal"].setText(0, self.name + "_middle_proximal") + self.createGlobalMoverButton(self.name + "_middle_proximal", + self.outlinerWidgets[self.name + "_middle_proximal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_proximal", + self.outlinerWidgets[self.name + "_middle_proximal"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_middle_proximal", self.outlinerWidgets[self.name + "_middle_proximal"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_middle_middle"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_middle_proximal"]) + self.outlinerWidgets[self.name + "_middle_middle"].setText(0, self.name + "_middle_middle") + self.createGlobalMoverButton(self.name + "_middle_middle", self.outlinerWidgets[self.name + "_middle_middle"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_middle", self.outlinerWidgets[self.name + "_middle_middle"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_middle_middle", self.outlinerWidgets[self.name + "_middle_middle"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_middle_distal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_middle_middle"]) + self.outlinerWidgets[self.name + "_middle_distal"].setText(0, self.name + "_middle_distal") + self.createGlobalMoverButton(self.name + "_middle_distal", self.outlinerWidgets[self.name + "_middle_distal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_distal", self.outlinerWidgets[self.name + "_middle_distal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_middle_distal", self.outlinerWidgets[self.name + "_middle_distal"], + self.rigUiInst) + + # add the ring finger + self.outlinerWidgets[self.name + "_ring_metacarpal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_ring_metacarpal"].setText(0, self.name + "_ring_metacarpal") + self.createGlobalMoverButton(self.name + "_ring_metacarpal", + self.outlinerWidgets[self.name + "_ring_metacarpal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_metacarpal", + self.outlinerWidgets[self.name + "_ring_metacarpal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_ring_metacarpal"].setHidden(True) + + self.outlinerWidgets[self.name + "_ring_proximal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_ring_proximal"].setText(0, self.name + "_ring_proximal") + self.createGlobalMoverButton(self.name + "_ring_proximal", self.outlinerWidgets[self.name + "_ring_proximal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_proximal", self.outlinerWidgets[self.name + "_ring_proximal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_ring_proximal", self.outlinerWidgets[self.name + "_ring_proximal"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_ring_middle"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_ring_proximal"]) + self.outlinerWidgets[self.name + "_ring_middle"].setText(0, self.name + "_ring_middle") + self.createGlobalMoverButton(self.name + "_ring_middle", self.outlinerWidgets[self.name + "_ring_middle"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_middle", self.outlinerWidgets[self.name + "_ring_middle"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_ring_middle", self.outlinerWidgets[self.name + "_ring_middle"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_ring_distal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_ring_middle"]) + self.outlinerWidgets[self.name + "_ring_distal"].setText(0, self.name + "_ring_distal") + self.createGlobalMoverButton(self.name + "_ring_distal", self.outlinerWidgets[self.name + "_ring_distal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_distal", self.outlinerWidgets[self.name + "_ring_distal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_ring_distal", self.outlinerWidgets[self.name + "_ring_distal"], + self.rigUiInst) + + # add the pinky finger + self.outlinerWidgets[self.name + "_pinky_metacarpal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_pinky_metacarpal"].setText(0, self.name + "_pinky_metacarpal") + self.createGlobalMoverButton(self.name + "_pinky_metacarpal", + self.outlinerWidgets[self.name + "_pinky_metacarpal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_metacarpal", + self.outlinerWidgets[self.name + "_pinky_metacarpal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_pinky_metacarpal"].setHidden(True) + + self.outlinerWidgets[self.name + "_pinky_proximal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_hand"]) + self.outlinerWidgets[self.name + "_pinky_proximal"].setText(0, self.name + "_pinky_proximal") + self.createGlobalMoverButton(self.name + "_pinky_proximal", self.outlinerWidgets[self.name + "_pinky_proximal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_proximal", self.outlinerWidgets[self.name + "_pinky_proximal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_pinky_proximal", self.outlinerWidgets[self.name + "_pinky_proximal"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_pinky_middle"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_pinky_proximal"]) + self.outlinerWidgets[self.name + "_pinky_middle"].setText(0, self.name + "_pinky_middle") + self.createGlobalMoverButton(self.name + "_pinky_middle", self.outlinerWidgets[self.name + "_pinky_middle"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_middle", self.outlinerWidgets[self.name + "_pinky_middle"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_pinky_middle", self.outlinerWidgets[self.name + "_pinky_middle"], + self.rigUiInst) + + self.outlinerWidgets[self.name + "_pinky_distal"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_pinky_middle"]) + self.outlinerWidgets[self.name + "_pinky_distal"].setText(0, self.name + "_pinky_distal") + self.createGlobalMoverButton(self.name + "_pinky_distal", self.outlinerWidgets[self.name + "_pinky_distal"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_distal", self.outlinerWidgets[self.name + "_pinky_distal"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_pinky_distal", self.outlinerWidgets[self.name + "_pinky_distal"], + self.rigUiInst) + + # create selection script job for module + self.createScriptJob() + + # update based on spinBox values + self.updateOutliner() + self.updateBoneCount() + self.rigUiInst.treeWidget.expandAll() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def aimMode_Setup(self, state): + + # get attributes needed + name = self.groupBox.title() + networkNode = self.returnNetworkNode + side = cmds.getAttr(networkNode + ".side") + + # setup aim vector details per side + armAim = [1, 0, 0] + armUp = [0, 0, 1] + handAim = [1, 0, 0] + handUp = [0, -1, 0] + + if side == "Right": + armAim = [-1, 0, 0] + armUp = [0, 0, -1] + handAim = [-1, 0, 0] + handUp = [0, 1, 0] + + # if passed in state is True: + if state: + # setup aim constraints + + # clavicle + cmds.aimConstraint(name + "_upperarm_lra", name + "_clavicle_mover_geo", aimVector=armAim, upVector=armUp, + wut="scene", wu=[0, 0, 1], mo=True) + cmds.aimConstraint(name + "_upperarm_lra", name + "_clavicle_mover_offset", aimVector=armAim, + upVector=armUp, wut="scene", wu=[0, 0, 1], mo=True) + + # upperarm + cmds.aimConstraint(name + "_lowerarm_lra", name + "_upperarm_mover_geo", aimVector=armAim, upVector=armUp, + skip="x", wut="scene", wu=[0, 0, 1], mo=True) + cmds.aimConstraint(name + "_lowerarm_lra", name + "_upperarm_mover_offset", aimVector=armAim, + skip="x", upVector=armUp, wut="scene", wu=[0, 0, 1], mo=True) + + # lowerarm + cmds.aimConstraint(name + "_hand_lra", name + "_lowerarm_mover_offset", aimVector=armAim, upVector=armUp, + wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + # index finger + if cmds.getAttr(name + "_index_metacarpal_mover_grp.v") == True: + cmds.aimConstraint(name + "_index_proximal_lra", name + "_index_metacarpal_mover_offset", + aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_index_proximal_mover_grp.v") == True: + cmds.aimConstraint(name + "_index_middle_lra", name + "_index_proximal_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_index_middle_lra", name + "_index_proximal_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_index_middle_mover_grp.v") == True: + cmds.aimConstraint(name + "_index_distal_lra", name + "_index_middle_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_index_distal_lra", name + "_index_middle_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + # middle finger + if cmds.getAttr(name + "_middle_metacarpal_mover_grp.v") == True: + cmds.aimConstraint(name + "_middle_proximal_lra", name + "_middle_metacarpal_mover_offset", + aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_middle_proximal_mover_grp.v") == True: + cmds.aimConstraint(name + "_middle_middle_lra", name + "_middle_proximal_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_middle_middle_lra", name + "_middle_proximal_mover_offset", + aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_middle_middle_mover_grp.v") == True: + cmds.aimConstraint(name + "_middle_distal_lra", name + "_middle_middle_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_middle_distal_lra", name + "_middle_middle_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + # ring finger + if cmds.getAttr(name + "_ring_metacarpal_mover_grp.v") == True: + cmds.aimConstraint(name + "_ring_proximal_lra", name + "_ring_metacarpal_mover_offset", + aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_ring_proximal_mover_grp.v") == True: + cmds.aimConstraint(name + "_ring_middle_lra", name + "_ring_proximal_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_ring_middle_lra", name + "_ring_proximal_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_ring_middle_mover_grp.v") == True: + cmds.aimConstraint(name + "_ring_distal_lra", name + "_ring_middle_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_ring_distal_lra", name + "_ring_middle_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + # pinky finger + if cmds.getAttr(name + "_pinky_metacarpal_mover_grp.v") == True: + cmds.aimConstraint(name + "_pinky_proximal_lra", name + "_pinky_metacarpal_mover_offset", + aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_pinky_proximal_mover_grp.v") == True: + cmds.aimConstraint(name + "_pinky_middle_lra", name + "_pinky_proximal_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_pinky_middle_lra", name + "_pinky_proximal_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_pinky_middle_mover_grp.v") == True: + cmds.aimConstraint(name + "_pinky_distal_lra", name + "_pinky_middle_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_pinky_distal_lra", name + "_pinky_middle_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + # thumb finger + if cmds.getAttr(name + "_thumb_metacarpal_mover_grp.v") == True: + cmds.aimConstraint(name + "_thumb_proximal_lra", name + "_thumb_metacarpal_mover_offset", + aimVector=handAim, upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + if cmds.getAttr(name + "_thumb_proximal_mover_grp.v") == True: + cmds.aimConstraint(name + "_thumb_distal_lra", name + "_thumb_proximal_mover_geo", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + cmds.aimConstraint(name + "_thumb_distal_lra", name + "_thumb_proximal_mover_offset", aimVector=handAim, + upVector=handUp, wut="scene", wu=[0, 0, 1], mo=True, skip=["x"]) + + # if passed in state is False: + if not state: + cmds.select(name + "_mover_grp", hi=True) + aimConstraints = cmds.ls(sl=True, exactType="aimConstraint") + + for constraint in aimConstraints: + cmds.lockNode(constraint, lock=False) + cmds.delete(constraint) + + self.bakeOffsets() + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def coplanarMode(self): + + # current selection + currentSelection = cmds.ls(sl=True) + + # get the state of the button + state = self.coplanarBtn.isChecked() + + # write the attribute on the module + networkNode = self.returnNetworkNode + + import System.utils as utils + aimState = cmds.getAttr(networkNode + ".aimMode") + if state: + + # lock out offset movers as they aren't to be used in coplanar mode + offsetMovers = self.returnJointMovers[1] + for mover in offsetMovers: + cmds.lockNode(mover, lock=False) + for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]: + try: + cmds.setAttr(mover + attr, lock=True) + except: + pass + + # fire script job that watches the coplanarIkHandle attributes, and when they change, snap to IK knee in tz + self.coplanarScriptJob1 = cmds.scriptJob(attributeChange=[self.name + "_coplanarIkHandle.translate", + partial(riggingUtils.coPlanarModeSnap, self, + self.name + "_coplanar_lowerarm", + self.name + "_lowerarm_mover_offset", + [self.name + "_coplanar_upperarm", + self.name + "_coplanar_lowerarm"], + [self.name + "_upperarm_mover_offset", + self.name + "_lowerarm_mover_offset"], + self.name + "_lowerarm_mover_offset", + [])], kws=True) + + # make sure aim mode is on + if not aimState: + self.aimMode_Setup(True) + + # reselect current selection + if len(currentSelection) > 0: + cmds.select(currentSelection) + + if not state: + # unlock all offset movers + offsetMovers = self.returnJointMovers[1] + for mover in offsetMovers: + for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]: + try: + cmds.setAttr(mover + attr, lock=False) + except: + pass + + cmds.lockNode(mover, lock=True) + + cmds.scriptJob(kill=self.coplanarScriptJob1) + self.aimMode_Setup(False) + + if aimState: + self.aimMode_Setup(True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateSettingsUI(self): + + # this function will update the settings UI when the UI is launched based on the network node settings + # in the scene + networkNode = self.returnNetworkNode + + upperarmTwists = cmds.getAttr(networkNode + ".armTwists") + lowerarmTwists = cmds.getAttr(networkNode + ".forearmTwists") + thumbJoints = cmds.getAttr(networkNode + ".thumbJoints") + indexJoints = cmds.getAttr(networkNode + ".indexJoints") + middleJoints = cmds.getAttr(networkNode + ".middleJoints") + ringJoints = cmds.getAttr(networkNode + ".ringJoints") + pinkyJoints = cmds.getAttr(networkNode + ".pinkyJoints") + includeClav = cmds.getAttr(networkNode + ".includeClavicle") + thumbMeta = cmds.getAttr(networkNode + ".thumbMeta") + indexMeta = cmds.getAttr(networkNode + ".indexMeta") + middleMeta = cmds.getAttr(networkNode + ".middleMeta") + ringMeta = cmds.getAttr(networkNode + ".ringMeta") + pinkyMeta = cmds.getAttr(networkNode + ".pinkyMeta") + + # update UI elements + self.upperarmTwistNum.setValue(upperarmTwists) + self.lowerarmTwistNum.setValue(lowerarmTwists) + self.clavicleCB.setChecked(includeClav) + + self.thumbNum.setValue(thumbJoints) + self.indexNum.setValue(indexJoints) + self.middleNum.setValue(middleJoints) + self.ringNum.setValue(ringJoints) + self.pinkyNum.setValue(pinkyJoints) + + self.thumbMeta.setChecked(thumbMeta) + self.indexMeta.setChecked(indexMeta) + self.middleMeta.setChecked(middleMeta) + self.ringMeta.setChecked(ringMeta) + self.pinkyMeta.setChecked(pinkyMeta) + + # apply changes + self.applyButton.setEnabled(False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateOutliner(self): + + # whenever changes are made to the module settings, update the outliner to show the new or removed movers + + # CLAVICLE + + if not self.clavicleCB.isChecked(): + self.outlinerWidgets[self.originalName + "_clavicle"].setHidden(True) + else: + self.outlinerWidgets[self.originalName + "_clavicle"].setHidden(False) + + # UPPERARM TWISTS + armTwists = self.upperarmTwistNum.value() + if armTwists == 0: + self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(True) + self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(True) + if armTwists == 1: + self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(True) + if armTwists == 2: + self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(True) + if armTwists == 3: + self.outlinerWidgets[self.originalName + "_upperarm_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_upperarm_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_upperarm_twist_03"].setHidden(False) + + # LOWERARM TWISTS + lowerarmTwists = self.lowerarmTwistNum.value() + if lowerarmTwists == 0: + self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(True) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(True) + if lowerarmTwists == 1: + self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(True) + if lowerarmTwists == 2: + self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(True) + if lowerarmTwists == 3: + self.outlinerWidgets[self.originalName + "_lowerarm_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_lowerarm_twist_03"].setHidden(False) + + # THUMB + thumbBones = self.thumbNum.value() + thumbMeta = self.thumbMeta.isChecked() + + if thumbBones == 0: + self.outlinerWidgets[self.originalName + "_thumb_proximal"].setHidden(True) + self.outlinerWidgets[self.originalName + "_thumb_distal"].setHidden(True) + if thumbBones == 1: + self.outlinerWidgets[self.originalName + "_thumb_proximal"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thumb_distal"].setHidden(True) + if thumbBones == 2: + self.outlinerWidgets[self.originalName + "_thumb_proximal"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thumb_distal"].setHidden(False) + + if thumbMeta: + self.outlinerWidgets[self.originalName + "_thumb_metacarpal"].setHidden(False) + if not thumbMeta: + self.outlinerWidgets[self.originalName + "_thumb_metacarpal"].setHidden(True) + + # FINGERS + fingers = [[self.indexNum, "index", self.indexMeta], [self.middleNum, "middle", self.middleMeta], + [self.ringNum, "ring", self.ringMeta], [self.pinkyNum, "pinky", self.pinkyMeta]] + + for finger in fingers: + value = finger[0].value() + meta = finger[2].isChecked() + + if value == 0: + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(True) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(True) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(True) + if value == 1: + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(True) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(True) + if value == 2: + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(True) + if value == 3: + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_proximal"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_middle"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_distal"].setHidden(False) + + if meta: + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_metacarpal"].setHidden(False) + if not meta: + self.outlinerWidgets[self.originalName + "_" + finger[1] + "_metacarpal"].setHidden(True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def applyModuleChanges(self, moduleInst): + + # get prefix/suffix + name = self.groupBox.title() + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + if len(prefix) > 0: + if prefix.find("_") == -1: + prefix = prefix + "_" + if len(suffix) > 0: + if suffix.find("_") == -1: + suffix = "_" + suffix + + # create list of the new created bones + armJoints = [] + + if self.clavicleCB.isChecked(): + armJoints.append(prefix + "clavicle" + suffix) + armJoints.append(prefix + "upperarm" + suffix) + else: + armJoints.append(prefix + "upperarm" + suffix) + + # upperarm twists + upperarmTwists = self.upperarmTwistNum.value() + for i in range(upperarmTwists): + armJoints.append(prefix + "upperarm_twist_0" + str(i + 1) + suffix) + + armJoints.append(prefix + "lowerarm" + suffix) + + # lowerarm twists + lowerarmTwists = self.lowerarmTwistNum.value() + for i in range(lowerarmTwists): + armJoints.append(prefix + "lowerarm_twist_0" + str(i + 1) + suffix) + + armJoints.append(prefix + "hand" + suffix) + + # FINGERS + thumbJoints = ["proximal", "distal"] + fingerJoints = ["proximal", "middle", "distal"] + + # thumb + thumbs = self.thumbNum.value() + thumbMeta = self.thumbMeta.isChecked() + if thumbMeta: + armJoints.append(prefix + "thumb_metacarpal" + suffix) + for i in range(thumbs): + armJoints.append(prefix + "thumb_" + thumbJoints[i] + suffix) + + # index + indexFingers = self.indexNum.value() + indexMeta = self.indexMeta.isChecked() + if indexMeta: + armJoints.append(prefix + "index_metacarpal" + suffix) + for i in range(indexFingers): + armJoints.append(prefix + "index_" + fingerJoints[i] + suffix) + + # middle + middleFingers = self.middleNum.value() + middleMeta = self.middleMeta.isChecked() + if middleMeta: + armJoints.append(prefix + "middle_metacarpal" + suffix) + for i in range(middleFingers): + armJoints.append(prefix + "middle_" + fingerJoints[i] + suffix) + + # ring + ringFingers = self.ringNum.value() + ringMeta = self.ringMeta.isChecked() + if ringMeta: + armJoints.append(prefix + "ring_metacarpal" + suffix) + for i in range(ringFingers): + armJoints.append(prefix + "ring_" + fingerJoints[i] + suffix) + + # pinky + pinkyFingers = self.pinkyNum.value() + pinkyMeta = self.pinkyMeta.isChecked() + if pinkyMeta: + armJoints.append(prefix + "pinky_metacarpal" + suffix) + for i in range(pinkyFingers): + armJoints.append(prefix + "pinky_" + fingerJoints[i] + suffix) + + # build attrString + attrString = "" + for bone in armJoints: + attrString += bone + "::" + + networkNode = self.returnNetworkNode + cmds.setAttr(networkNode + ".Created_Bones", lock=False) + cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True) + + # reset button + self.applyButton.setEnabled(False) + + # update joint mover + self.editJointMoverViaSpinBox(self.thumbNum, "thumb", True) + self.editJointMoverViaSpinBox(self.indexNum, "index", False) + self.editJointMoverViaSpinBox(self.middleNum, "middle", False) + self.editJointMoverViaSpinBox(self.ringNum, "ring", False) + self.editJointMoverViaSpinBox(self.pinkyNum, "pinky", False) + + self.editJointMoverTwistBones(self.upperarmTwistNum, "upperarm") + self.editJointMoverTwistBones(self.lowerarmTwistNum, "lowerarm") + + self.editJointMoverMetaCarpals(self.thumbMeta, "thumb") + self.editJointMoverMetaCarpals(self.indexMeta, "index") + self.editJointMoverMetaCarpals(self.middleMeta, "middle") + self.editJointMoverMetaCarpals(self.ringMeta, "ring") + self.editJointMoverMetaCarpals(self.pinkyMeta, "pinky") + + self.includeClavicle() + + # set network node attributes + cmds.setAttr(networkNode + ".armTwists", lock=False) + cmds.setAttr(networkNode + ".armTwists", upperarmTwists, lock=True) + + cmds.setAttr(networkNode + ".forearmTwists", lock=False) + cmds.setAttr(networkNode + ".forearmTwists", lowerarmTwists, lock=True) + + cmds.setAttr(networkNode + ".thumbJoints", lock=False) + cmds.setAttr(networkNode + ".thumbJoints", thumbs, lock=True) + + cmds.setAttr(networkNode + ".indexJoints", lock=False) + cmds.setAttr(networkNode + ".indexJoints", indexFingers, lock=True) + + cmds.setAttr(networkNode + ".middleJoints", lock=False) + cmds.setAttr(networkNode + ".middleJoints", middleFingers, lock=True) + + cmds.setAttr(networkNode + ".ringJoints", lock=False) + cmds.setAttr(networkNode + ".ringJoints", ringFingers, lock=True) + + cmds.setAttr(networkNode + ".pinkyJoints", lock=False) + cmds.setAttr(networkNode + ".pinkyJoints", pinkyFingers, lock=True) + + cmds.setAttr(networkNode + ".includeClavicle", lock=False) + cmds.setAttr(networkNode + ".includeClavicle", self.clavicleCB.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".thumbMeta", lock=False) + cmds.setAttr(networkNode + ".thumbMeta", self.thumbMeta.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".indexMeta", lock=False) + cmds.setAttr(networkNode + ".indexMeta", self.indexMeta.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".ringMeta", lock=False) + cmds.setAttr(networkNode + ".ringMeta", self.ringMeta.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".middleMeta", lock=False) + cmds.setAttr(networkNode + ".middleMeta", self.middleMeta.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".pinkyMeta", lock=False) + cmds.setAttr(networkNode + ".pinkyMeta", self.pinkyMeta.isChecked(), lock=True) + + # update outliner + self.updateOutliner() + self.updateBoneCount() + + # clear selection + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def editJointMoverViaSpinBox(self, uiWidget, searchKey, isThumb, *args): + + # uiWidget is the spinBox + # isThumb will be the special case, since there are only the three joints instead of the 4 + # searchKey is the basname (thumb, middle, ring, etc) + + # unlock bone representations + cmds.select(self.name + "_bone_representations", hi=True) + selection = cmds.ls(sl=True, type="transform") + + for each in selection: + cmds.setAttr(each + ".v", lock=False) + + # check number in spinBox + num = uiWidget.value() + + # set visibility on movers and geo depending on the value of num + for i in range(num + 1): + # purely for fanciness + time.sleep(.05) + cmds.refresh(force=True) + + if isThumb == False: + + moverList = ["_proximal", "_middle", "_distal"] + for mover in moverList: + if moverList.index(mover) <= i - 1: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1) + + if i == 0: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock=True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0) + + if isThumb == True: + + moverList = ["_proximal", "_distal"] + for mover in moverList: + if moverList.index(mover) <= i - 1: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1) + + if i == 0: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock=True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0) + + # relock bone representations + cmds.select(self.name + "_bone_representations", hi=True) + selection = cmds.ls(sl=True, type="transform") + + for each in selection: + cmds.setAttr(each + ".v", lock=True) + + # toggle mover vis + self.rigUiInst.setMoverVisibility() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def editJointMoverTwistBones(self, uiWidget, searchKey, *args): + + # check number in spinBox + num = uiWidget.value() + + for i in range(num + 1): + + if i == 0: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 0, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock=True) + + if i == 1: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock=True) + + if i == 2: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock=True) + + if i == 3: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 1, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def editJointMoverMetaCarpals(self, uiWidget, searchKey, *args): + + # uiWidget is the spinBox + # searchKey is the basname (index, middle, ring, etc) + + # unlock bone representations + cmds.select(self.name + "_bone_representations", hi=True) + selection = cmds.ls(sl=True, type="transform") + + for each in selection: + cmds.setAttr(each + ".v", lock=False) + + # toggle visibility + if uiWidget.isChecked(): + try: + cmds.parent(self.name + "_" + searchKey + "_proximal_mover_grp", + self.name + "_" + searchKey + "_metacarpal_mover") + except Exception, e: + print e + + cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", 1, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_bone_geo.v", 1) + + if not uiWidget.isChecked(): + try: + cmds.parent(self.name + "_" + searchKey + "_proximal_mover_grp", self.name + "_hand_mover") + except Exception, e: + print e + + cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_mover_grp.v", 0, lock=True) + cmds.setAttr(self.name + "_" + searchKey + "_metacarpal_bone_geo.v", 0) + + # relock bone representations + cmds.select(self.name + "_bone_representations", hi=True) + selection = cmds.ls(sl=True, type="transform") + + for each in selection: + cmds.setAttr(each + ".v", lock=True) + + # toggle mover vis + self.rigUiInst.setMoverVisibility() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def includeClavicle(self, *args): + state = self.clavicleCB.isChecked() + + if state == False: + + # hide clavicle mover controls + cmds.setAttr(self.name + "_clavicle_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_clavicle_mover_grp.v", 0, lock=True) + + # parent upperarm to mover_grp + try: + cmds.parent(self.name + "_upperarm_mover_grp", self.name + "_mover_grp") + except Exception, e: + print e + + if state == True: + + # show clavicle mover controls + cmds.setAttr(self.name + "_clavicle_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_clavicle_mover_grp.v", 1, lock=True) + + # parent upperarm to mover_grp + try: + cmds.parent(self.name + "_upperarm_mover_grp", self.name + "_clavicle_mover") + except Exception, e: + print e + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def changeSide(self): + + # gather information (current name, current parent, etc) + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + parent = cmds.getAttr(networkNode + ".parentModuleBone") + currentSide = cmds.getAttr(networkNode + ".side") + + if cmds.getAttr(networkNode + ".aimMode") == True: + self.aimMode_Setup(False) + + # call on base class delete + movers = self.returnJointMovers + + for moverGrp in movers: + for mover in moverGrp: + cmds.lockNode(mover, lock=False) + + cmds.delete(self.name + "_mover_grp") + + # figure out side + if currentSide == "Left": + cmds.setAttr(networkNode + ".side", lock=False) + cmds.setAttr(networkNode + ".side", "Right", type="string", lock=True) + side = "Right" + if currentSide == "Right": + cmds.setAttr(networkNode + ".side", lock=False) + cmds.setAttr(networkNode + ".side", "Left", type="string", lock=True) + side = "Left" + + # build new jmPath name + jmPath = jointMover.partition(".ma")[0] + "_" + side + ".ma" + self.jointMover_Build(jmPath) + + # parent the joint mover to the offset mover of the parent + mover = "" + + if parent == "root": + cmds.parent(name + "_mover_grp", "root_mover") + mover = "root_mover" + + else: + # find the parent mover name to parent to + networkNodes = utils.returnRigModules() + mover = utils.findMoverNodeFromJointName(networkNodes, parent) + if mover != None: + cmds.parent(name + "_mover_grp", mover) + + # create the connection geo between the two + childMover = utils.findOffsetMoverFromName(name) + riggingUtils.createBoneConnection(mover, childMover, name) + self.applyModuleChanges(self) + + self.aimMode_Setup(True) + + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def resetSettings(self): + for i in range(4): + + networkNode = self.returnNetworkNode + attrs = cmds.listAttr(networkNode, ud=True) + + for attr in attrs: + attrType = str(cmds.getAttr(networkNode + "." + attr, type=True)) + + if attrType == "double": + if attr.find("Joints") == -1: + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, 0, lock=True) + else: + if attr.find("thumb") != -1: + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, 2, lock=True) + else: + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, 3, lock=True) + + if attrType == "bool": + if attr.find("thumbMeta") != -1 or attr.find("includeClavicle") != -1: + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, True, lock=True) + + else: + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, False, lock=True) + + if attrType == "enum": + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, 0, lock=True) + + # relaunch the UI + self.updateSettingsUI() + self.applyModuleChanges(self) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pinModule(self, state): + + networkNode = self.returnNetworkNode + includeClav = cmds.getAttr(networkNode + ".includeClavicle") + + if state: + if includeClav: + topLevelMover = self.name + "_clavicle_mover_grp" + else: + topLevelMover = self.name + "_upperarm_mover_grp" + + loc = cmds.spaceLocator()[0] + cmds.setAttr(loc + ".v", False, lock=True) + constraint = cmds.parentConstraint(topLevelMover, loc)[0] + cmds.delete(constraint) + const = cmds.parentConstraint(loc, topLevelMover)[0] + + if not cmds.objExists(networkNode + ".pinConstraint"): + cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message") + + cmds.connectAttr(const + ".message", networkNode + ".pinConstraint") + + if not state: + connections = cmds.listConnections(networkNode + ".pinConstraint") + if len(connections) > 0: + constraint = connections[0] + cmds.delete(constraint) + + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skinProxyGeo(self): + + # get the network node + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + baseName = cmds.getAttr(networkNode + ".baseName") + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + # get this module's proxy geo meshes + cmds.select(name + "_mover_grp", hi=True) + proxyGeoMeshes = [] + selection = cmds.ls(sl=True) + for each in selection: + if each.find("proxy_geo") != -1: + parent = cmds.listRelatives(each, parent=True)[0] + if cmds.nodeType(each) == "transform": + proxyGeoMeshes.append(each) + + # skin the proxy geo meshes + for mesh in proxyGeoMeshes: + dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0] + cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False) + cmds.setAttr(dupeMesh + ".overrideDisplayType", 0) + + # create skinned geo group + if not cmds.objExists("skinned_proxy_geo"): + cmds.group(empty=True, name="skinned_proxy_geo") + + cmds.parent(dupeMesh, "skinned_proxy_geo") + + boneName = mesh.partition(name + "_")[2] + boneName = boneName.partition("_proxy_geo")[0] + joint = prefix + boneName + suffix + + if not cmds.objExists(joint): + cmds.delete(dupeMesh) + + else: + cmds.select([dupeMesh, joint]) + cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0, + normalizeWeights=True) + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildRigCustom(self, textEdit, uiInst): + + # get the network node and find out which rigs to build + networkNode = self.returnNetworkNode + buildFK = True + buildIK_V1 = True + + # have it build all rigs by default, unless there is an attr stating otherwise (backwards- compatability) + numRigs = 0 + if cmds.objExists(networkNode + ".buildFK"): + buildFK = cmds.getAttr(networkNode + ".buildFK") + if buildFK: + numRigs += 1 + if cmds.objExists(networkNode + ".buildIK_V1"): + buildIK_V1 = cmds.getAttr(networkNode + ".buildIK_V1") + if buildIK_V1: + numRigs += 1 + + builtRigs = [] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create groups and settings + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create the arm group + armJoints = self.getMainArmJoints() + self.armGroup = cmds.group(empty=True, name=self.name + "_group") + constraint = cmds.parentConstraint(armJoints[1][0], self.armGroup)[0] + cmds.delete(constraint) + + # create the arm settings group + self.armSettings = cmds.group(empty=True, name=self.name + "_settings") + cmds.parent(self.armSettings, self.armGroup) + for attr in (cmds.listAttr(self.armSettings, keyable=True)): + cmds.setAttr(self.armSettings + "." + attr, lock=True, keyable=False) + + # add mode attribute to settings + if numRigs > 1: + cmds.addAttr(self.armSettings, ln="mode", min=0, max=numRigs - 1, dv=0, keyable=True) + + # create the ctrl group (what will get the constraint to the parent) + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + self.armCtrlGrp = cmds.group(empty=True, name=self.name + "_arm_ctrl_grp") + + if cmds.getAttr(networkNode + ".includeClavicle"): + constraint = cmds.parentConstraint(armJoints[0], self.armCtrlGrp)[0] + else: + constraint = cmds.parentConstraint("driver_" + parentBone, self.armCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(self.armCtrlGrp, self.armGroup) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # build the rigs + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # FK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # if build FK was true, build the FK rig now + if buildFK: + self.buildFkArm(textEdit, uiInst, builtRigs, networkNode) + builtRigs.append(["FK", [self.armCtrlGrp]]) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # IK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + if buildIK_V1: + ikArmJoints = self.buildIkArm(textEdit, uiInst, builtRigs, networkNode) + builtRigs.append(["IK", [self.ikCtrlGrp]]) + + # =================================================================== + # #create upper arm twist rig + # =================================================================== + twistJoints = self.getTwistJoints(True, False) + + if cmds.getAttr(networkNode + ".side") == "Left": + twistCtrls = riggingUtils.createCounterTwistRig(twistJoints, self.name, networkNode, armJoints[1][0], + armJoints[1][1], self.armGroup, [-90, 0, 0]) + if cmds.getAttr(networkNode + ".side") == "Right": + twistCtrls = riggingUtils.createCounterTwistRig(twistJoints, self.name, networkNode, armJoints[1][0], + armJoints[1][1], self.armGroup, [90, 0, 0]) + + if not cmds.objExists(networkNode + ".upArmTwistControls"): + cmds.addAttr(networkNode, ln="upArmTwistControls", dt="string") + jsonString = json.dumps(twistCtrls) + cmds.setAttr(networkNode + ".upArmTwistControls", jsonString, type="string") + + # create lowerarm twist rig + twistJoints = self.getTwistJoints(False, True) + twistCtrls = riggingUtils.createTwistRig(twistJoints, self.name, networkNode, armJoints[1][1], armJoints[1][2], + self.armGroup, [-90, 0, 0]) + + if not cmds.objExists(networkNode + ".loArmTwistControls"): + cmds.addAttr(networkNode, ln="loArmTwistControls", dt="string") + jsonString = json.dumps(twistCtrls) + cmds.setAttr(networkNode + ".loArmTwistControls", jsonString, type="string") + + # ======================================================================= + # # #build finger rigs (if needed) + # ======================================================================= + # gather data on which fingers are available for rigging + fingers = self.getFingerJoints() + + # create finger group + self.fingerGrp = cmds.group(empty=True, name=self.name + "_finger_group") + constraint = cmds.parentConstraint(armJoints[1][2], self.fingerGrp)[0] + cmds.delete(constraint) + cmds.parent(self.fingerGrp, self.armGroup) + + fingerNodes = self.buildFingers(fingers, textEdit, uiInst, builtRigs, networkNode) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # CLAVICLE # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + if cmds.getAttr(networkNode + ".includeClavicle"): + clavData = self.buildClavicleRig(textEdit, uiInst, builtRigs, networkNode) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Hook up ArmCtrlGrp # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + if cmds.getAttr(networkNode + ".includeClavicle"): + armCtrlPointConst = \ + cmds.pointConstraint(["fk_" + armJoints[0] + "_anim", self.name + "_clav_follow"], self.armCtrlGrp)[0] + armCtrlOrientConst = \ + cmds.orientConstraint(["fk_" + armJoints[0] + "_anim", self.name + "_clav_follow"], self.armCtrlGrp)[0] + + attrData = [] + for connection in [armCtrlPointConst, armCtrlOrientConst]: + driveAttrs = [] + targets = cmds.getAttr(connection + ".target", mi=True) + if len(targets) > 1: + for each in targets: + driveAttrs.append( + cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p=True)) + + attrData.append(driveAttrs) + + # setup set driven keys on our moder attr and those target attributes + if cmds.getAttr(networkNode + ".includeClavicle"): + for i in range(numRigs): + cmds.setAttr(self.armSettings + ".clavMode", i) + + # go through attr data and zero out anything but the first element in the list + for data in attrData: + for each in data: + cmds.setAttr(each[0], 0) + + cmds.setAttr(data[i][0], 1) + + # set driven keys + for data in attrData: + for each in data: + cmds.setDrivenKeyframe(each[0], cd=self.armSettings + ".clavMode", itt="linear", ott="linear") + + # ======================================================================= + # # auto clav set driven keys for ik arm + # ======================================================================= + cmds.parent(ikArmJoints[0], self.armCtrlGrp) + if cmds.getAttr(networkNode + ".includeClavicle"): + if len(builtRigs) > 1: + # set elbow pose constraint keys based on arm mode + + elbowConstAttrs = [] + + targets = cmds.getAttr(clavData[0] + ".target", mi=True) + if len(targets) > 1: + for each in targets: + elbowConstAttrs.append( + cmds.listConnections(clavData[0] + ".target[" + str(each) + "].targetWeight", p=True)) + + for i in range(len(builtRigs)): + cmds.setAttr(self.armSettings + ".mode", i) + # go through attr data and zero out anything but the first element in the list + for data in elbowConstAttrs: + for each in data: + cmds.setAttr(each, 0) + + cmds.setAttr(elbowConstAttrs[i][0], 1) + + # set driven keys + for data in elbowConstAttrs: + for each in data: + cmds.setDrivenKeyframe(each, cd=self.armSettings + ".mode", itt="linear", ott="linear") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Hook up FK/IK Switching # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # mode + if numRigs > 1: + attrData = [] + rampData = [] + + """ CONSTRAINTS """ + # get the constraint connections on the driver joints for the arms + connections = [] + for joint in armJoints[1]: + connections.extend(list(set(cmds.listConnections("driver_" + joint, type="constraint")))) + ramps = (list(set(cmds.listConnections("driver_" + joint, type="ramp")))) + for ramp in ramps: + connections.append(ramp + ".uCoord") + + for connection in connections: + driveAttrs = [] + + if cmds.nodeType(connection) in ["pointConstraint", "orientConstraint"]: + + # get those constraint target attributes for each constraint connection + targets = cmds.getAttr(connection + ".target", mi=True) + if len(targets) > 1: + for each in targets: + driveAttrs.append( + cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", + p=True)) + + # add this data to our master list of constraint attribute data + attrData.append(driveAttrs) + else: + if cmds.nodeType(connection) == "ramp": + rampData.append(connection) + + rampData = list(set(rampData)) + + # setup set driven keys on our moder attr and those target attributes + for i in range(numRigs): + + cmds.setAttr(self.armSettings + ".mode", i) + + # go through attr data and zero out anything but the first element in the list + for data in attrData: + for each in data: + cmds.setAttr(each[0], 0) + + cmds.setAttr(data[i][0], 1) + + # set driven keys + for data in attrData: + for each in data: + cmds.setDrivenKeyframe(each[0], cd=self.armSettings + ".mode", itt="linear", ott="linear") + + """ RAMPS """ + # direct connect mode to uCoord value (only works if there are 2 rigs...) <- not sure if that is the case + # still + for data in rampData: + # create a multiply node that takes first input of 1/numRigs and 2nd of mode direct connection + multNode = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_" + data.partition(".uCoord")[0] + "_mult") + cmds.setAttr(multNode + ".input1X", float(float(1) / float(numRigs - 1))) + cmds.connectAttr(self.armSettings + ".mode", multNode + ".input2X") + cmds.connectAttr(multNode + ".outputX", data) + + # hook up control visibility + for i in range(len(builtRigs)): + cmds.setAttr(self.armSettings + ".mode", i) + for rig in builtRigs: + visNodes = rig[1] + for node in visNodes: + if node != None: + cmds.setAttr(node + ".v", 0) + + if builtRigs.index(rig) == i: + visNodes = rig[1] + for node in visNodes: + if node != None: + cmds.setAttr(node + ".v", 1) + + cmds.setDrivenKeyframe(visNodes, at="visibility", cd=self.armSettings + ".mode", itt="linear", + ott="linear") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Parent Under Offset Ctrl # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # parent under offset_anim if it exists(it always should) + if cmds.objExists("offset_anim"): + cmds.parent(self.armGroup, "offset_anim") + + # return data + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + try: + if cmds.getAttr(networkNode + ".includeClavicle"): + uiInst.rigData.append([self.name + "_auto_clav_grp", "driver_" + parentBone, numRigs]) + uiInst.rigData.append([self.clavCtrlGrp, "driver_" + parentBone, numRigs]) + + else: + uiInst.rigData.append([self.armCtrlGrp, "driver_" + parentBone, numRigs]) + except: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildClavicleRig(self, textEdit, uiInst, builtRigs, networkNode): + + # add clavicle mode to rig settings + cmds.addAttr(self.armSettings, ln="clavMode", min=0, max=1, dv=0, keyable=True) + + # Rig Joint + joints = self.getMainArmJoints() + clavJoint = joints[0] + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + + rigJnt = cmds.createNode("joint", name=self.name + "_clav_rigJnt") + const = cmds.parentConstraint(clavJoint, rigJnt)[0] + cmds.delete(const) + + cmds.setAttr(rigJnt + ".v", 0, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # FK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create rig control + data = riggingUtils.createControlFromMover(clavJoint, networkNode, True, False) + + fkControl = cmds.rename(data[0], "fk_" + clavJoint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + clavJoint + "_anim_grp") + riggingUtils.colorControl(fkControl) + + for attr in [".translateX", ".translateY", ".translateZ", ".scaleX", ".scaleY", ".scaleZ", ".visibility"]: + cmds.setAttr(fkControl + attr, lock=True, keyable=False) + + # create clav rig grp + self.clavCtrlGrp = cmds.group(empty=True, name=self.name + "_clav_ctrl_grp") + constraint = cmds.parentConstraint(parentBone, self.clavCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(self.clavCtrlGrp, self.armGroup) + + # parent fk clav to clav grp + cmds.parent(animGrp, self.clavCtrlGrp) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # IK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create rig control + ikControl = riggingUtils.createControl("arrow", 1, "ik_" + clavJoint + "_anim", True) + ikCtrlGrp = cmds.group(empty=True, name="ik_" + clavJoint + "_anim_grp") + + cmds.setAttr(ikControl + ".rotateX", -90) + cmds.makeIdentity(ikControl, t=1, r=1, s=1, apply=True) + + const = cmds.pointConstraint(joints[1][0], ikCtrlGrp)[0] + cmds.delete(const) + + const = cmds.pointConstraint(joints[1][0], ikControl)[0] + cmds.delete(const) + const = cmds.orientConstraint(joints[1][0], ikControl, skip=["x"])[0] + cmds.delete(const) + + cmds.parent(ikControl, ikCtrlGrp) + cmds.makeIdentity(ikControl, t=1, r=1, s=1, apply=True) + + upArmPiv = cmds.xform(joints[1][0], q=True, ws=True, rp=True) + cmds.xform(ikControl, ws=True, piv=upArmPiv) + cmds.xform(ikCtrlGrp, ws=True, piv=upArmPiv) + + riggingUtils.colorControl(ikControl) + + for attr in [".rotateX", ".rotateY", ".rotateZ", ".scaleX", ".scaleY", ".scaleZ", ".visibility"]: + cmds.setAttr(ikControl + attr, lock=True, keyable=False) + + # create the ik joint chain + startJnt = cmds.createNode("joint", name=self.name + "_clav_ik_start") + endJnt = cmds.createNode("joint", name=self.name + "_clav_ik_end") + pointJnt = cmds.createNode("joint", name=self.name + "_clav_follow") + + const = cmds.parentConstraint(clavJoint, startJnt)[0] + cmds.delete(const) + + const = cmds.parentConstraint(joints[1][0], endJnt)[0] + cmds.delete(const) + + const = cmds.parentConstraint(clavJoint, pointJnt)[0] + cmds.delete(const) + + cmds.parent(endJnt, startJnt) + + # hide joints + for jnt in [startJnt, endJnt, pointJnt]: + cmds.setAttr(jnt + ".v", 0, lock=True) + + # create the ikHandle + ikNodes = cmds.ikHandle(sj=startJnt, ee=endJnt, sol="ikSCsolver", name=self.name + "_clav_ikHandle")[0] + cmds.parent(ikNodes, ikControl) + cmds.setAttr(ikNodes + ".v", 0, lock=True) + cmds.setAttr(ikNodes + ".stickiness", 1) + cmds.setAttr(ikNodes + ".snapEnable", 1) + + # ======================================================================= + # #lastly, connect controls up to blender nodes to drive driver joints + # ======================================================================= + + rigJntPointConst = cmds.pointConstraint([fkControl, startJnt], rigJnt, mo=True)[0] + rigJointOrientConst = cmds.orientConstraint([fkControl, startJnt], rigJnt)[0] + + attrData = [] + for connection in [rigJntPointConst, rigJointOrientConst]: + driveAttrs = [] + targets = cmds.getAttr(connection + ".target", mi=True) + if len(targets) > 1: + for each in targets: + driveAttrs.append( + cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p=True)) + + attrData.append(driveAttrs) + + cmds.setAttr(rigJointOrientConst + ".interpType", 2) + + # setup set driven keys on our moder attr and those target attributes + for i in range(2): + cmds.setAttr(self.armSettings + ".clavMode", i) + + # go through attr data and zero out anything but the first element in the list + for data in attrData: + for each in data: + cmds.setAttr(each[0], 0) + + cmds.setAttr(data[i][0], 1) + + # set driven keys + for data in attrData: + for each in data: + cmds.setDrivenKeyframe(each[0], cd=self.armSettings + ".clavMode", itt="linear", ott="linear") + + # ======================================================================= + # #connect controls up to blender nodes to drive driver joints + # ======================================================================= + + cmds.pointConstraint(rigJnt, "driver_" + clavJoint, mo=True) + cmds.orientConstraint(rigJnt, "driver_" + clavJoint) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into + # input 2,and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=clavJoint + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(rigJnt + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + clavJoint, "scale", False, 2, 1, "output") + else: + riggingUtils.createConstraint(rigJnt, "driver_" + clavJoint, "scale", False, 2, 1) + + # ======================================================================= + # #add IK matcher under FK clav control + # ======================================================================= + ikMatchGrp = cmds.group(empty=True, name=self.name + "_ik_clav_matcher") + cmds.parent(ikMatchGrp, fkControl) + const = cmds.pointConstraint(ikControl, ikMatchGrp)[0] + cmds.delete(const) + + # ======================================================================= + # #hook up auto clavicle + # ======================================================================= + + # create the main grp to hold all auto clav contents + autoClavGrp = cmds.group(empty=True, name=self.name + "_auto_clav_grp") + constraint = cmds.parentConstraint("driver_" + parentBone, autoClavGrp)[0] + cmds.delete(constraint) + + # create invis arm chain + invisArmJnts = [] + for joint in joints[1]: + jnt = cmds.createNode("joint", name="auto_clav_" + joint) + const = cmds.parentConstraint(joint, jnt)[0] + cmds.delete(const) + invisArmJnts.append(jnt) + + invisArmJnts.reverse() + for i in range(len(invisArmJnts)): + try: + cmds.parent(invisArmJnts[i], invisArmJnts[i + 1]) + except IndexError: + pass + + cmds.setAttr(invisArmJnts[i] + ".v", 0, lock=True) + + invisArmJnts.reverse() + cmds.makeIdentity(invisArmJnts[0], t=0, r=1, s=0, apply=True) + cmds.parent(invisArmJnts[0], autoClavGrp) + + # create the invis upper arm fk control/grp + invisAnimGrp = cmds.group(empty=True, name="auto_clav_fk_" + joints[1][0] + "_anim_grp") + const = cmds.parentConstraint(joints[1][0], invisAnimGrp)[0] + cmds.delete(const) + + invisArmAnim = cmds.spaceLocator(name="auto_clav_fk_" + joints[1][0] + "_anim")[0] + const = cmds.parentConstraint(joints[1][0], invisArmAnim)[0] + cmds.delete(const) + cmds.setAttr(invisArmAnim + ".v", 0, lock=True) + + cmds.parent(invisArmAnim, invisAnimGrp) + cmds.parent(invisAnimGrp, autoClavGrp) + + # create orient loc/grp + orientLocGrp = cmds.group(empty=True, name=self.name + "_auto_clav_orient_loc_grp") + const = cmds.parentConstraint(joints[1][0], orientLocGrp)[0] + cmds.delete(const) + + orientLoc = cmds.spaceLocator(name=self.name + "_auto_clav_orient_loc")[0] + const = cmds.parentConstraint(joints[1][0], orientLoc)[0] + cmds.delete(const) + + cmds.parent(orientLoc, orientLocGrp) + cmds.parent(orientLocGrp, invisArmAnim) + + # orient constrain invis upper arm to orient loc + cmds.orientConstraint(orientLoc, invisArmJnts[0]) + + # connect real fk upperarm anim.rotate to invisArmAnim.rotate + side = cmds.getAttr(networkNode + ".side")[0] + if side == "L": + cmds.connectAttr("fk_" + joints[1][0] + "_anim.rotate", invisArmAnim + ".rotate") + else: + reverseMult = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_" + side + "_multNodeReverse") + cmds.setAttr(reverseMult + ".input2X", -1) + cmds.setAttr(reverseMult + ".input2Y", -1) + cmds.setAttr(reverseMult + ".input2Z", -1) + cmds.connectAttr("fk_" + joints[1][0] + "_anim.rotate", reverseMult + ".input1") + cmds.connectAttr(reverseMult + ".output", invisArmAnim + ".rotate") + + # create a locator that tracks our elbow position + currentElbowPose = cmds.spaceLocator(name=self.name + "_auto_clav_current_elbow_loc")[0] + const = cmds.parentConstraint(joints[1][1], currentElbowPose)[0] + cmds.delete(const) + cmds.setAttr(currentElbowPose + ".v", 0, lock=True) + + # create a group for that locator + currentPoseGrp = cmds.group(empty=True, name=self.name + "_auto_clav_current_elbow_grp") + const = cmds.parentConstraint(joints[1][1], currentPoseGrp)[0] + cmds.delete(const) + + cmds.parent(currentElbowPose, currentPoseGrp) + cmds.parent(currentPoseGrp, autoClavGrp) + + # point constraint locator grp to invis lower arm + cmds.pointConstraint(invisArmJnts[1], currentPoseGrp) + + # create switcher group + switcherGrp = cmds.group(empty=True, name=self.name + "_auto_clav_switcher_grp") + const = cmds.pointConstraint(invisArmJnts[0], switcherGrp)[0] + cmds.delete(const) + + cmds.parent(switcherGrp, autoClavGrp) + + # point constrain to autoClavGrp + cmds.pointConstraint(autoClavGrp, switcherGrp) + + # create ik master grp + ikMasterGrp = cmds.group(empty=True, name=self.name + "_auto_clav_ik_master_grp") + const = cmds.pointConstraint(invisArmJnts[0], ikMasterGrp)[0] + cmds.delete(const) + + cmds.parent(ikMasterGrp, switcherGrp) + cmds.makeIdentity(ikMasterGrp, t=1, r=1, s=1, apply=True) + + # create ik grp + ikGrp = cmds.group(empty=True, name=self.name + "_auto_clav_ik_grp") + const = cmds.pointConstraint(invisArmJnts[0], ikGrp)[0] + cmds.delete(const) + + cmds.parent(ikGrp, ikMasterGrp) + cmds.makeIdentity(ikGrp, t=1, r=1, s=1, apply=True) + + # connect ik clav anim.translate to this grp.translate + cmds.connectAttr(ikControl + ".translate", ikGrp + ".translate") + + # create parent space group for driven group + ikDrivenSpace = cmds.group(empty=True, name=self.name + "_auto_clav_ik_driven_space_grp") + const = cmds.parentConstraint(invisArmJnts[0], ikDrivenSpace)[0] + cmds.delete(const) + + cmds.parent(ikDrivenSpace, ikGrp) + + # create two more groups. ikDrivenGrp and autoClavTranslateGrp. drivenGrp is what will get the pose reader SDKs, + # autoClavTranslateGrp is what will carry the ikHandle + ikDrivenGrp = cmds.group(empty=True, name=self.name + "_auto_clav_ik_driven_grp") + const = cmds.parentConstraint(invisArmJnts[0], ikDrivenGrp)[0] + cmds.delete(const) + + cmds.parent(ikDrivenGrp, ikDrivenSpace) + cmds.makeIdentity(ikDrivenGrp, t=1, r=1, s=1, apply=True) + + # create parent space group for autoClavTranslateGrp + autoClavTransGrpSpace = cmds.group(empty=True, name=self.name + "_auto_clav_ik_trans_space_grp") + const = cmds.parentConstraint(invisArmJnts[0], autoClavTransGrpSpace)[0] + cmds.delete(const) + + cmds.parent(autoClavTransGrpSpace, ikGrp) + + autoClavTranslateGrp = cmds.group(empty=True, name=self.name + "_auto_clav_trans_grp") + const = cmds.parentConstraint(invisArmJnts[0], autoClavTranslateGrp)[0] + cmds.delete(const) + + cmds.parent(autoClavTranslateGrp, autoClavTransGrpSpace) + cmds.makeIdentity(autoClavTranslateGrp, t=1, r=1, s=1, apply=True) + + # parent the ik clav ikHandle under the autoClavTranslateGrp + cmds.parent(ikNodes, autoClavTranslateGrp) + + # add setting to arm settings for autoShoulders + cmds.addAttr(self.armSettings, ln="autoShoulders", min=0, max=1, dv=0, keyable=True) + + # connect ikDrivenGrp.translate to multDivide node input1, connect autoShoulders attr to input 2, + # connect output to autoClavTranslateGrp.translate + clavTransMult = cmds.shadingNode("multiplyDivide", name=self.name + "_clav_trans_mult", asUtility=True) + cmds.connectAttr(ikDrivenGrp + ".translate", clavTransMult + ".input1") + cmds.connectAttr(self.armSettings + ".autoShoulders", clavTransMult + ".input2X") + cmds.connectAttr(self.armSettings + ".autoShoulders", clavTransMult + ".input2Y") + cmds.connectAttr(self.armSettings + ".autoShoulders", clavTransMult + ".input2Z") + cmds.connectAttr(clavTransMult + ".output", autoClavTranslateGrp + ".translate") + + # make auto clav work for IK arm + ikArmAutoClavGrp = cmds.group(empty=True, name=self.name + "_ikArm_auto_clav_grp") + const = cmds.parentConstraint(self.ikHandCtrl, ikArmAutoClavGrp)[0] + cmds.delete(const) + + ikArmAutoClavLoc = cmds.spaceLocator(name=self.name + "_ikArm_auto_clav_loc")[0] + const = cmds.pointConstraint(joints[1][1], ikArmAutoClavLoc)[0] + cmds.delete(const) + cmds.setAttr(ikArmAutoClavLoc + ".v", 0, lock=True) + + cmds.parent(ikArmAutoClavGrp, self.ikHandCtrl) + cmds.parent(ikArmAutoClavLoc, ikArmAutoClavGrp) + + cmds.makeIdentity(ikArmAutoClavLoc, t=1, r=1, s=1, apply=True) + elbowLocConst = cmds.pointConstraint([invisArmJnts[1], ikArmAutoClavLoc], currentPoseGrp)[0] + + # aim ikArmAutoClavGrp to the IK PV + cmds.aimConstraint(self.name + "_ik_elbow_anim", ikArmAutoClavGrp, aimVector=[-1, 0, 0], upVector=[0, 0, 1], + wut="scene", wu=[0, 0, 1]) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Clean Up # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + cmds.parent(startJnt, autoClavGrp) + cmds.parent(ikCtrlGrp, autoClavGrp) + cmds.parent(pointJnt, autoClavGrp) + cmds.makeIdentity(pointJnt, t=0, r=1, s=0, apply=True) + cmds.pointConstraint(endJnt, pointJnt, mo=True) + + # create a clavicle grp + self.clavicleGrp = cmds.group(empty=True, name=self.name + "_clavicle_grp") + const = cmds.parentConstraint(self.armCtrlGrp, self.clavicleGrp)[0] + cmds.delete(const) + + cmds.parent(self.clavicleGrp, self.armGroup) + + # parent rigJnt to clavicle group + cmds.parent(rigJnt, self.clavicleGrp) + + # parent autoClavGrp and self.clavCtrlGrp to clavicle grp + cmds.parent(autoClavGrp, self.clavicleGrp) + cmds.parent(self.clavCtrlGrp, self.clavicleGrp) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # POSE READER # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + """ + Create vectors from the base locator, to the current locator, and from the base to a pose locator + Subtract the end position with the base. + Get the angle between the two vectors. compare the angle between the vectors to the max cone angle given. + """ + + cmds.loadPlugin('matrixNodes.dll') + # global + + baseLoc = cmds.spaceLocator(name=self.name + "_poseReader_Base")[0] + const = cmds.parentConstraint(self.name + "_base", baseLoc)[0] + cmds.delete(const) + cmds.parent(baseLoc, self.armGroup) + cmds.setAttr(baseLoc + ".v", 0, lock=True) + + baseDM = cmds.shadingNode("decomposeMatrix", asUtility=True, name=self.name + "_poseReader_base_matrix") + cmds.connectAttr(baseLoc + ".worldMatrix[0]", baseDM + ".inputMatrix") + + currentDM = cmds.shadingNode("decomposeMatrix", asUtility=True, name=self.name + "_poseReader_current_matrix") + cmds.connectAttr(self.name + "_auto_clav_current_elbow_loc.worldMatrix[0]", currentDM + ".inputMatrix") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Arm Up + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + upArmLoc = cmds.spaceLocator(name=self.name + "_poseReader_armUp_pose")[0] + const = cmds.parentConstraint(self.name + "_arm_up_pose", upArmLoc)[0] + cmds.delete(const) + cmds.parent(upArmLoc, self.armGroup) + cmds.setAttr(upArmLoc + ".v", 0, lock=True) + + armUpTargetDM = cmds.shadingNode("decomposeMatrix", asUtility=True, name=self.name + "_poseReader_armUp_target") + cmds.connectAttr(upArmLoc + ".worldMatrix[0]", armUpTargetDM + ".inputMatrix") + + # create plusMinusAverage node, set to subtract. armUpTargetDM.outputTranslate -> plusMinusAvg.input3D[0]. + # baseDM.outputTranslate -> plusMinusAvg.input3D[1] + armUpTargetPMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armUp_targetFromBase") + cmds.setAttr(armUpTargetPMA + ".operation", 2) + cmds.connectAttr(armUpTargetDM + ".outputTranslate", armUpTargetPMA + ".input3D[0]") + cmds.connectAttr(baseDM + ".outputTranslate", armUpTargetPMA + ".input3D[1]") + + # create plusMinusAverage node, set to subtract. currentDM.outputTranslate -> plusMinusAvg.input3D[0]. + # baseDM.outputTranslate -> plusMinusAvg.input3D[1] + armUpCurrentPMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armUp_currentFromBase") + cmds.setAttr(armUpCurrentPMA + ".operation", 2) + cmds.connectAttr(currentDM + ".outputTranslate", armUpCurrentPMA + ".input3D[0]") + cmds.connectAttr(baseDM + ".outputTranslate", armUpCurrentPMA + ".input3D[1]") + + # get angle between vectors + armUpAngleBetween = cmds.shadingNode("angleBetween", asUtility=True, name=self.name + "_armUp_AngleBetween") + cmds.connectAttr(armUpTargetPMA + ".output3D", armUpAngleBetween + ".vector1") + cmds.connectAttr(armUpCurrentPMA + ".output3D", armUpAngleBetween + ".vector2") + + # add attr to the base locator for armUpConeAngle + cmds.addAttr(baseLoc, ln="armUpConeAngle", keyable=True) + cmds.setAttr(baseLoc + ".armUpConeAngle", 180) + + # halve the cone angle + armUpMultDL = cmds.shadingNode("multDoubleLinear", asUtility=True, name=self.name + "_armUp_coneAngleMult") + cmds.connectAttr(baseLoc + ".armUpConeAngle", armUpMultDL + ".input1") + cmds.setAttr(armUpMultDL + ".input2", 0.5) + + # divide the angle between our vectors by the cone angle + armUpConeRatio = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_armUp_coneAngleRatio") + cmds.setAttr(armUpConeRatio + ".operation", 2) + + cmds.connectAttr(armUpAngleBetween + ".angle", armUpConeRatio + ".input1X") + cmds.connectAttr(armUpMultDL + ".output", armUpConeRatio + ".input2X") + + # create condition. If result > 1, use 1. If result < 1, use result + armUpCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_armUp_condition") + cmds.setAttr(armUpCondition + ".operation", 2) + + cmds.connectAttr(armUpConeRatio + ".outputX", armUpCondition + ".firstTerm") + cmds.setAttr(armUpCondition + ".secondTerm", 1) + cmds.setAttr(armUpCondition + ".colorIfTrueR", 1) + cmds.connectAttr(armUpConeRatio + ".outputX", armUpCondition + ".colorIfFalseR") + + # plug condition result into a new plusMinusAvg (subtract) input3D[1]. set input3D[0] to 1 + armUpReversePMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armUp_reverse") + cmds.setAttr(armUpReversePMA + ".operation", 2) + + cmds.connectAttr(armUpCondition + ".outColorR", armUpReversePMA + ".input1D[1]") + cmds.setAttr(armUpReversePMA + ".input1D[0]", 1) + + # add attr to base loc for armUp result + cmds.addAttr(baseLoc, ln="armUpResult", dv=0, min=0, max=1, keyable=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Arm Forward + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + armForwardLoc = cmds.spaceLocator(name=self.name + "_poseReader_armForward_pose")[0] + const = cmds.parentConstraint(self.name + "_arm_forward_pose", armForwardLoc)[0] + cmds.delete(const) + cmds.parent(armForwardLoc, self.armGroup) + cmds.setAttr(armForwardLoc + ".v", 0, lock=True) + + armForwardTargetDM = cmds.shadingNode("decomposeMatrix", asUtility=True, + name=self.name + "_poseReader_armForward_target") + cmds.connectAttr(armForwardLoc + ".worldMatrix[0]", armForwardTargetDM + ".inputMatrix") + + # create plusMinusAverage node, set to subtract. armUpTargetDM.outputTranslate -> plusMinusAvg.input3D[0]. + # baseDM.outputTranslate -> plusMinusAvg.input3D[1] + armForwardTargetPMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armForward_targetFromBase") + cmds.setAttr(armForwardTargetPMA + ".operation", 2) + cmds.connectAttr(armForwardTargetDM + ".outputTranslate", armForwardTargetPMA + ".input3D[0]") + cmds.connectAttr(baseDM + ".outputTranslate", armForwardTargetPMA + ".input3D[1]") + + # create plusMinusAverage node, set to subtract. currentDM.outputTranslate -> plusMinusAvg.input3D[0]. + # baseDM.outputTranslate -> plusMinusAvg.input3D[1] + armForwardCurrentPMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armForward_currentFromBase") + cmds.setAttr(armForwardCurrentPMA + ".operation", 2) + cmds.connectAttr(currentDM + ".outputTranslate", armForwardCurrentPMA + ".input3D[0]") + cmds.connectAttr(baseDM + ".outputTranslate", armForwardCurrentPMA + ".input3D[1]") + + # get angle between vectors + armForwardAngleBetween = cmds.shadingNode("angleBetween", asUtility=True, + name=self.name + "_armForward_AngleBetween") + cmds.connectAttr(armForwardTargetPMA + ".output3D", armForwardAngleBetween + ".vector1") + cmds.connectAttr(armForwardCurrentPMA + ".output3D", armForwardAngleBetween + ".vector2") + + # add attr to the base locator for armUpConeAngle + cmds.addAttr(baseLoc, ln="armForwardConeAngle", keyable=True) + cmds.setAttr(baseLoc + ".armForwardConeAngle", 180) + + # halve the cone angle + armForwardMultDL = cmds.shadingNode("multDoubleLinear", asUtility=True, + name=self.name + "_armForward_coneAngleMult") + cmds.connectAttr(baseLoc + ".armUpConeAngle", armForwardMultDL + ".input1") + cmds.setAttr(armForwardMultDL + ".input2", 0.5) + + # divide the angle between our vectors by the cone angle + armForwardConeRatio = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_armForward_coneAngleRatio") + cmds.setAttr(armForwardConeRatio + ".operation", 2) + + cmds.connectAttr(armForwardAngleBetween + ".angle", armForwardConeRatio + ".input1X") + cmds.connectAttr(armForwardMultDL + ".output", armForwardConeRatio + ".input2X") + + # create condition. If result > 1, use 1. If result < 1, use result + armForwardCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_armForward_condition") + cmds.setAttr(armForwardCondition + ".operation", 2) + + cmds.connectAttr(armForwardConeRatio + ".outputX", armForwardCondition + ".firstTerm") + cmds.setAttr(armForwardCondition + ".secondTerm", 1) + cmds.setAttr(armForwardCondition + ".colorIfTrueR", 1) + cmds.connectAttr(armForwardConeRatio + ".outputX", armForwardCondition + ".colorIfFalseR") + + # plug condition result into a new plusMinusAvg (subtract) input3D[1]. set input3D[0] to 1 + armForwardReversePMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armForward_reverse") + cmds.setAttr(armForwardReversePMA + ".operation", 2) + + cmds.connectAttr(armForwardCondition + ".outColorR", armForwardReversePMA + ".input1D[1]") + cmds.setAttr(armForwardReversePMA + ".input1D[0]", 1) + + # add attr to base loc for armUp result + cmds.addAttr(baseLoc, ln="armForwardResult", dv=0, min=0, max=1, keyable=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Arm Backward + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + armBackwardLoc = cmds.spaceLocator(name=self.name + "_poseReader_armBackward_pose")[0] + const = cmds.parentConstraint(self.name + "_arm_back_pose", armBackwardLoc)[0] + cmds.delete(const) + cmds.parent(armBackwardLoc, self.armGroup) + cmds.setAttr(armBackwardLoc + ".v", 0, lock=True) + + armBackwardTargetDM = cmds.shadingNode("decomposeMatrix", asUtility=True, + name=self.name + "_poseReader_armBackward_target") + cmds.connectAttr(armBackwardLoc + ".worldMatrix[0]", armBackwardTargetDM + ".inputMatrix") + + # create plusMinusAverage node, set to subtract. armUpTargetDM.outputTranslate -> plusMinusAvg.input3D[0]. + # baseDM.outputTranslate -> plusMinusAvg.input3D[1] + armBackwardTargetPMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armBackward_targetFromBase") + cmds.setAttr(armBackwardTargetPMA + ".operation", 2) + cmds.connectAttr(armBackwardTargetDM + ".outputTranslate", armBackwardTargetPMA + ".input3D[0]") + cmds.connectAttr(baseDM + ".outputTranslate", armBackwardTargetPMA + ".input3D[1]") + + # create plusMinusAverage node, set to subtract. currentDM.outputTranslate -> plusMinusAvg.input3D[0]. + # baseDM.outputTranslate -> plusMinusAvg.input3D[1] + armBackwardCurrentPMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armBackward_currentFromBase") + cmds.setAttr(armBackwardCurrentPMA + ".operation", 2) + cmds.connectAttr(currentDM + ".outputTranslate", armBackwardCurrentPMA + ".input3D[0]") + cmds.connectAttr(baseDM + ".outputTranslate", armBackwardCurrentPMA + ".input3D[1]") + + # get angle between vectors + armBackwardAngleBetween = cmds.shadingNode("angleBetween", asUtility=True, + name=self.name + "_armBackward_AngleBetween") + cmds.connectAttr(armBackwardTargetPMA + ".output3D", armBackwardAngleBetween + ".vector1") + cmds.connectAttr(armBackwardCurrentPMA + ".output3D", armBackwardAngleBetween + ".vector2") + + # add attr to the base locator for armUpConeAngle + cmds.addAttr(baseLoc, ln="armBackwardConeAngle", keyable=True) + cmds.setAttr(baseLoc + ".armBackwardConeAngle", 180) + + # halve the cone angle + armBackwardMultDL = cmds.shadingNode("multDoubleLinear", asUtility=True, + name=self.name + "_armBackward_coneAngleMult") + cmds.connectAttr(baseLoc + ".armUpConeAngle", armBackwardMultDL + ".input1") + cmds.setAttr(armBackwardMultDL + ".input2", 0.5) + + # divide the angle between our vectors by the cone angle + armBackwardConeRatio = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_armBackward_coneAngleRatio") + cmds.setAttr(armBackwardConeRatio + ".operation", 2) + + cmds.connectAttr(armBackwardAngleBetween + ".angle", armBackwardConeRatio + ".input1X") + cmds.connectAttr(armBackwardMultDL + ".output", armBackwardConeRatio + ".input2X") + + # create condition. If result > 1, use 1. If result < 1, use result + armBackwardCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_armBackward_condition") + cmds.setAttr(armBackwardCondition + ".operation", 2) + + cmds.connectAttr(armBackwardConeRatio + ".outputX", armBackwardCondition + ".firstTerm") + cmds.setAttr(armBackwardCondition + ".secondTerm", 1) + cmds.setAttr(armBackwardCondition + ".colorIfTrueR", 1) + cmds.connectAttr(armBackwardConeRatio + ".outputX", armBackwardCondition + ".colorIfFalseR") + + # plug condition result into a new plusMinusAvg (subtract) input3D[1]. set input3D[0] to 1 + armBackwardReversePMA = cmds.shadingNode("plusMinusAverage", asUtility=True, + name=self.name + "_poseReader_armBackward_reverse") + cmds.setAttr(armBackwardReversePMA + ".operation", 2) + + cmds.connectAttr(armBackwardCondition + ".outColorR", armBackwardReversePMA + ".input1D[1]") + cmds.setAttr(armBackwardReversePMA + ".input1D[0]", 1) + + # add attr to base loc for armUp result + cmds.addAttr(baseLoc, ln="armBackwardResult", dv=0, min=0, max=1, keyable=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # SET DRIVEN KEYS (pose reader) # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + side = cmds.getAttr(networkNode + ".side")[0] + + # arm up + cmds.setAttr(baseLoc + ".armUpResult", 0) + cmds.setAttr(ikDrivenGrp + ".translateZ", 0) + cmds.setDrivenKeyframe(ikDrivenGrp + ".translateZ", cd=baseLoc + ".armUpResult") + + cmds.setAttr(baseLoc + ".armUpResult", 1) + if side == "L": + cmds.setAttr(ikDrivenGrp + ".translateZ", cmds.getAttr(upArmLoc + ".translateZ")) + else: + cmds.setAttr(ikDrivenGrp + ".translateZ", cmds.getAttr(upArmLoc + ".translateZ") * -1) + cmds.setDrivenKeyframe(ikDrivenGrp + ".translateZ", cd=baseLoc + ".armUpResult") + + cmds.connectAttr(armUpReversePMA + ".output1D", baseLoc + ".armUpResult") + + # arm forward + cmds.setAttr(baseLoc + ".armForwardResult", 0.5) + cmds.setAttr(ikDrivenGrp + ".translateY", 0) + cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armForwardResult") + + cmds.setAttr(baseLoc + ".armForwardResult", 1) + if side == "L": + cmds.setAttr(ikDrivenGrp + ".translateY", cmds.getAttr(armForwardLoc + ".translateY") / 2) + else: + cmds.setAttr(ikDrivenGrp + ".translateY", (cmds.getAttr(armForwardLoc + ".translateY") / 2) * -1) + cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armForwardResult") + + cmds.connectAttr(armForwardReversePMA + ".output1D", baseLoc + ".armForwardResult") + + # arm backward + cmds.setAttr(baseLoc + ".armBackwardResult", 0.5) + cmds.setAttr(ikDrivenGrp + ".translateY", 0) + cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armBackwardResult") + + cmds.setAttr(baseLoc + ".armBackwardResult", 1) + if side == "L": + cmds.setAttr(ikDrivenGrp + ".translateY", cmds.getAttr(armBackwardLoc + ".translateY") / 2) + else: + cmds.setAttr(ikDrivenGrp + ".translateY", (cmds.getAttr(armBackwardLoc + ".translateY") / 2) * -1) + cmds.setDrivenKeyframe(ikDrivenGrp + ".translateY", cd=baseLoc + ".armBackwardResult") + + cmds.connectAttr(armBackwardReversePMA + ".output1D", baseLoc + ".armBackwardResult") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Hook Up Modes # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + cmds.setAttr(self.armSettings + ".clavMode", 0) + cmds.setAttr(animGrp + ".v", 1) + cmds.setAttr(ikCtrlGrp + ".v", 0) + cmds.setDrivenKeyframe([animGrp + ".v", ikCtrlGrp + ".v"], cd=self.armSettings + ".clavMode") + + cmds.setAttr(self.armSettings + ".clavMode", 1) + cmds.setAttr(animGrp + ".v", 0) + cmds.setAttr(ikCtrlGrp + ".v", 1) + cmds.setDrivenKeyframe([animGrp + ".v", ikCtrlGrp + ".v"], cd=self.armSettings + ".clavMode") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Add Data to Node # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # add created control info to module + if not cmds.objExists(networkNode + ".clavControls"): + cmds.addAttr(networkNode, ln="clavControls", dt="string") + clavCtrls = [fkControl, ikControl] + jsonString = json.dumps(clavCtrls) + cmds.setAttr(networkNode + ".clavControls", jsonString, type="string") + + return [elbowLocConst] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildFkArm(self, textEdit, uiInst, builtRigs, networkNode): + + # update progress + if textEdit != None: + textEdit.append(" Starting FK Arm Rig Build..") + + # build the rig + slot = len(builtRigs) + + # find the joints in the arm module that need rigging + joints = self.getMainArmJoints() + fkControls = [] + self.topNode = None + + for joint in joints[1]: + if joint.find("upperarm") != -1: + data = riggingUtils.createControlFromMover(joint, networkNode, True, True) + + fkControl = cmds.rename(data[0], "fk_" + joint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp") + spaceSwitcher = cmds.rename(data[2], "fk_" + joint + "_anim_space_switcher") + spaceSwitchFollow = cmds.rename(data[3], "fk_" + joint + "_anim_space_switcher_follow") + self.topNode = spaceSwitchFollow + + fkControls.append([spaceSwitchFollow, fkControl, joint]) + # color the control + riggingUtils.colorControl(fkControl) + + else: + data = riggingUtils.createControlFromMover(joint, networkNode, True, False) + + fkControl = cmds.rename(data[0], "fk_" + joint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp") + + fkControls.append([animGrp, fkControl, joint]) + + # color the control + riggingUtils.colorControl(fkControl) + + # create hierarchy + fkControls.reverse() + + for i in range(len(fkControls)): + try: + cmds.parent(fkControls[i][0], fkControls[i + 1][1]) + except IndexError: + pass + + # ======================================================================= + # #lastly, connect controls up to blender nodes to drive driver joints + # ======================================================================= + for each in fkControls: + control = each[1] + joint = each[2] + + cmds.pointConstraint(control, "driver_" + joint, mo=True) + cmds.orientConstraint(control, "driver_" + joint) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into + # input 2,and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(control + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output") + else: + riggingUtils.createConstraint(control, "driver_" + joint, "scale", False, 2, slot) + + # #======================================================================= + # clean up + # #======================================================================= + # parent top group into arm group + cmds.parent(self.topNode, self.armCtrlGrp) + + # lock attrs + for each in fkControls: + control = each[1] + for attr in [".scaleX", ".scaleY", ".scaleZ", ".visibility"]: + cmds.setAttr(control + attr, lock=True, keyable=False) + + fkRigData = [] + for each in fkControls: + fkRigData.append(each[1]) + + # add created control info to module + if not cmds.objExists(networkNode + ".fkControls"): + cmds.addAttr(networkNode, ln="fkControls", dt="string") + jsonString = json.dumps(fkRigData) + cmds.setAttr(networkNode + ".fkControls", jsonString, type="string") + + # update progress + if textEdit != None: + textEdit.setTextColor(QtGui.QColor(0, 255, 18)) + textEdit.append(" SUCCESS: FK Build Complete!") + textEdit.setTextColor(QtGui.QColor(255, 255, 255)) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildIkArm(self, textEdit, uiInst, builtRigs, networkNode): + + # update progress + if textEdit != None: + textEdit.append(" Starting IK Arm Rig Build..") + + # build the rig + slot = len(builtRigs) + + # find the joints in the arm module that need rigging + joints = self.getMainArmJoints() + ikControls = [] + + # ======================================================================= + # # create the ik arm joint chain + # ======================================================================= + + ikArmJoints = [] + for joint in joints[1]: + jnt = cmds.createNode("joint", name="ik_" + joint + "_jnt") + const = cmds.parentConstraint(joint, jnt)[0] + cmds.delete(const) + ikArmJoints.append(jnt) + + # create the wrist end joint + jnt = cmds.createNode("joint", name="ik_" + ikArmJoints[2] + "_end_jnt") + const = cmds.parentConstraint(ikArmJoints[2], jnt)[0] + cmds.delete(const) + ikArmJoints.append(jnt) + + # create hierarchy + ikArmJoints.reverse() + for i in range(len(ikArmJoints)): + try: + cmds.parent(ikArmJoints[i], ikArmJoints[i + 1]) + except IndexError: + pass + + ikArmJoints.reverse() + + cmds.setAttr(ikArmJoints[0] + ".v", 0, lock=True) + + # move hand end joint out a bit. If tx is negative, add -2, if positive, add 2 + cmds.makeIdentity(ikArmJoints[0], t=0, r=1, s=0, apply=True) + + if cmds.getAttr(ikArmJoints[2] + ".tx") > 0: + cmds.setAttr(ikArmJoints[3] + ".tx", 10) + else: + cmds.setAttr(ikArmJoints[3] + ".tx", -10) + + # ======================================================================= + # # connect controls up to blender nodes to drive driver joints + # ======================================================================= + for joint in joints[1]: + sourceBone = "ik_" + joint + "_jnt" + + cmds.pointConstraint(sourceBone, "driver_" + joint, mo=True) + cmds.orientConstraint(sourceBone, "driver_" + joint) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into + # input 2,and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(sourceBone + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output") + else: + riggingUtils.createConstraint(sourceBone, "driver_" + joint, "scale", False, 2, slot) + + # ======================================================================= + # # create fk matching joints + # ======================================================================= + fkMatchUpArm = cmds.duplicate(ikArmJoints[0], po=True, name="ik_" + joints[1][0] + "_fk_matcher")[0] + fkMatchLowArm = cmds.duplicate(ikArmJoints[1], po=True, name="ik_" + joints[1][1] + "_fk_matcher")[0] + fkMatchWrist = cmds.duplicate(ikArmJoints[2], po=True, name="ik_" + joints[1][2] + "_fk_matcher")[0] + + cmds.parent(fkMatchWrist, fkMatchLowArm) + cmds.parent(fkMatchLowArm, fkMatchUpArm) + + # constrain fk match joints + cmds.parentConstraint(ikArmJoints[0], fkMatchUpArm, mo=True) + cmds.parentConstraint(ikArmJoints[1], fkMatchLowArm, mo=True) + cmds.parentConstraint(ikArmJoints[2], fkMatchWrist, mo=True) + + # ======================================================================= + # # rotate order and preferred angle + # ======================================================================= + # set rotate order on ikUpArm + cmds.setAttr(ikArmJoints[0] + ".rotateOrder", 3) + + # set preferred angle on arm + cmds.setAttr(ikArmJoints[1] + ".preferredAngleZ", -90) + + # ======================================================================= + # # create the ik control + # ======================================================================= + handControlInfo = riggingUtils.createControlFromMover(joints[1][2], networkNode, True, True) + + cmds.parent(handControlInfo[0], world=True) + constraint = cmds.orientConstraint(self.name + "_ik_hand_ctrl_orient", handControlInfo[3])[0] + cmds.delete(constraint) + cmds.makeIdentity(handControlInfo[2], t=1, r=1, s=1, apply=True) + cmds.parent(handControlInfo[0], handControlInfo[1]) + cmds.makeIdentity(handControlInfo[0], t=1, r=1, s=1, apply=True) + + # rename the control info + self.ikHandCtrl = cmds.rename(handControlInfo[0], "ik_" + joints[1][2] + "_anim") + cmds.rename(handControlInfo[1], self.ikHandCtrl + "_grp") + cmds.rename(handControlInfo[2], self.ikHandCtrl + "_space_switcher") + spaceSwitcherFollow = cmds.rename(handControlInfo[3], self.ikHandCtrl + "_space_switcher_follow") + + fkMatchGrp = cmds.group(empty=True, name=self.ikHandCtrl + "_fkMatch_grp") + constraint = cmds.parentConstraint(fkMatchWrist, fkMatchGrp)[0] + cmds.delete(constraint) + + cmds.parent(fkMatchGrp, self.ikHandCtrl) + + fkMatch = cmds.group(empty=True, name=self.ikHandCtrl + "_fkMatch") + constraint = cmds.parentConstraint(fkMatchWrist, fkMatch)[0] + cmds.delete(constraint) + cmds.parent(fkMatch, fkMatchGrp) + + # create RP IK on arm and SC ik from wrist to wrist end + rpIkHandle = \ + cmds.ikHandle(name=self.name + "_rp_arm_ikHandle", solver="ikRPsolver", sj=ikArmJoints[0], ee=ikArmJoints[2])[0] + scIkHandle = \ + cmds.ikHandle(name=self.name + "_sc_hand_ikHandle", solver="ikSCsolver", sj=ikArmJoints[2], ee=ikArmJoints[3])[ + 0] + + cmds.parent(scIkHandle, rpIkHandle) + cmds.setAttr(rpIkHandle + ".v", 0) + cmds.setAttr(scIkHandle + ".v", 0) + + cmds.setAttr(rpIkHandle + ".stickiness", 1) + cmds.setAttr(rpIkHandle + ".snapEnable", 1) + + cmds.setAttr(scIkHandle + ".stickiness", 1) + cmds.setAttr(scIkHandle + ".snapEnable", 1) + + # parent IK to ik control + cmds.parent(rpIkHandle, self.ikHandCtrl) + + # ======================================================================= + # # create the ik pole vector + # ======================================================================= + ikPvCtrl = riggingUtils.createControl("sphere", 5, self.name + "_ik_elbow_anim", True) + constraint = cmds.pointConstraint(ikArmJoints[1], ikPvCtrl)[0] + cmds.delete(constraint) + + # create anim grp + ikPvCtrlGrp = cmds.group(empty=True, name=self.name + "_ik_elbow_anim_grp") + constraint = cmds.pointConstraint(ikArmJoints[1], ikPvCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(ikPvCtrl, ikPvCtrlGrp) + cmds.makeIdentity(ikPvCtrl, t=1, r=1, s=1, apply=True) + + # create space switcher + ikPvSpaceSwitch = cmds.duplicate(ikPvCtrlGrp, po=True, name=self.name + "_ik_elbow_anim_space_switcher")[0] + + # create space switcher follow + ikPvSpaceSwitchFollow = \ + cmds.duplicate(ikPvCtrlGrp, po=True, name=self.name + "_ik_elbow_anim_space_switcher_follow")[0] + + cmds.parent(ikPvSpaceSwitch, ikPvSpaceSwitchFollow) + cmds.parent(ikPvCtrlGrp, ikPvSpaceSwitch) + + # move out pv ctrl + scaleFactor = riggingUtils.getScaleFactor() + cmds.setAttr(ikPvCtrl + ".ty", 30 * scaleFactor) + + cmds.makeIdentity(ikPvCtrl, t=1, r=1, s=1, apply=True) + + # setup pole vector constraint + cmds.poleVectorConstraint(ikPvCtrl, rpIkHandle) + + # create the match group + pvMatchGrp = cmds.group(empty=True, name=ikPvCtrl + "_fkMatchGrp") + constraint = cmds.parentConstraint(ikPvCtrl, pvMatchGrp)[0] + cmds.delete(constraint) + + fk_controls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + cmds.parent(pvMatchGrp, fk_controls[1]) + + pvMatch = cmds.group(empty=True, name=ikPvCtrl + "_fkMatch") + constraint = cmds.parentConstraint(ikPvCtrl, pvMatch)[0] + cmds.delete(constraint) + + cmds.parent(pvMatch, pvMatchGrp) + + # ======================================================================= + # # setup squash and stretch + # ======================================================================= + # add attrs to the hand ctrl + cmds.addAttr(self.ikHandCtrl, longName=("stretch"), at='double', min=0, max=1, dv=0, keyable=True) + cmds.addAttr(self.ikHandCtrl, longName=("squash"), at='double', min=0, max=1, dv=0, keyable=True) + + # need to get the total length of the arm chain + totalDist = abs(cmds.getAttr(ikArmJoints[1] + ".tx") + cmds.getAttr(ikArmJoints[2] + ".tx")) + + # create a distanceBetween node + distBetween = cmds.shadingNode("distanceBetween", asUtility=True, name=self.name + "_ik_arm_distBetween") + + # get world positions of thigh and ik + baseGrp = cmds.group(empty=True, name=self.name + "_ik_arm_base_grp") + endGrp = cmds.group(empty=True, name=self.name + "_ik_arm_end_grp") + cmds.pointConstraint(ikArmJoints[0], baseGrp) + cmds.pointConstraint(self.ikHandCtrl, endGrp) + + # hook in group translates into distanceBetween node inputs + cmds.connectAttr(baseGrp + ".translate", distBetween + ".point1") + cmds.connectAttr(endGrp + ".translate", distBetween + ".point2") + + # create a condition node that will compare original length to current length + # if second term is greater than, or equal to the first term, the chain needs to stretch + ikArmCondition = cmds.shadingNode("condition", asUtility=True, name=self.name + "_ik_arm_stretch_condition") + cmds.setAttr(ikArmCondition + ".operation", 3) + cmds.connectAttr(distBetween + ".distance", ikArmCondition + ".secondTerm") + cmds.setAttr(ikArmCondition + ".firstTerm", totalDist) + + # hook up the condition node's return colors + cmds.setAttr(ikArmCondition + ".colorIfTrueR", totalDist) + cmds.connectAttr(distBetween + ".distance", ikArmCondition + ".colorIfFalseR") + + # add attr to foot control for stretch bias + cmds.addAttr(self.ikHandCtrl, ln="stretchBias", minValue=-1.0, maxValue=1.0, defaultValue=0.0, keyable=True) + + # add divide node so that instead of driving 0-1, we're actually only driving 0 - 0.2 + divNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_stretchBias_Div") + cmds.connectAttr(self.ikHandCtrl + ".stretchBias", divNode + ".input1X") + cmds.setAttr(divNode + ".operation", 2) + cmds.setAttr(divNode + ".input2X", 5) + + # create the add node and connect the stretchBias into it, adding 1 + addNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=self.name + "_stretchBias_Add") + cmds.connectAttr(divNode + ".outputX", addNode + ".input1D[0]") + cmds.setAttr(addNode + ".input1D[1]", 1.0) + + # connect output of addNode to new mult node input1x + stretchBiasMultNode = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_stretchBias_multNode") + cmds.connectAttr(addNode + ".output1D", stretchBiasMultNode + ".input1X") + + # create the mult/divide node(set to divide) that will take the original creation length as a static value in + # input2x,and the connected length into 1x. This will get the scale factor + armDistMultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_arm_dist_multNode") + cmds.setAttr(armDistMultNode + ".operation", 2) # divide + cmds.connectAttr(ikArmCondition + ".outColorR", armDistMultNode + ".input1X") + + # set input2x to totalDist + cmds.setAttr(stretchBiasMultNode + ".input2X", totalDist) + cmds.connectAttr(stretchBiasMultNode + ".outputX", armDistMultNode + ".input2X") + + # This differs from the original code. Instead of using a condition, I will use a blendColors node so that + # stretch % has an effect + + # create a blendColors node for stretch + blendResult = cmds.shadingNode("blendColors", asUtility=True, name=self.name + "_arm_stretch_scaleFactor") + cmds.setAttr(blendResult + ".color2R", 1) + cmds.connectAttr(armDistMultNode + ".outputX", blendResult + ".color1R") + cmds.connectAttr(self.ikHandCtrl + ".stretch", blendResult + ".blender") + + # create a blendColors node for squash + blendResultSquash = cmds.shadingNode("blendColors", asUtility=True, name=self.name + "_arm_squash_scaleFactor") + cmds.setAttr(blendResultSquash + ".color2R", 1) + cmds.connectAttr(armDistMultNode + ".outputX", blendResultSquash + ".color1R") + cmds.connectAttr(self.ikHandCtrl + ".squash", blendResultSquash + ".blender") + + # get the sqrt of the scale factor by creating a multiply node and setting it to power operation + powerNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_sqrt_scaleFactor") + cmds.setAttr(powerNode + ".operation", 3) + cmds.connectAttr(blendResultSquash + ".outputR", powerNode + ".input1X") + cmds.setAttr(powerNode + ".input2X", .5) + + # now divide 1 by that result + squashDivNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_squash_Value") + cmds.setAttr(squashDivNode + ".operation", 2) + cmds.setAttr(squashDivNode + ".input1X", 1) + cmds.connectAttr(powerNode + ".outputX", squashDivNode + ".input2X") + + # connect to arm joint scale attributes + cmds.connectAttr(blendResult + ".outputR", ikArmJoints[0] + ".sx") + cmds.connectAttr(blendResult + ".outputR", ikArmJoints[1] + ".sx") + + cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[1] + ".sy") + cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[1] + ".sz") + + cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[0] + ".sy") + cmds.connectAttr(squashDivNode + ".outputX", ikArmJoints[0] + ".sz") + + # ======================================================================= + # # color controls and lock attrs + # ======================================================================= + for control in [self.ikHandCtrl, ikPvCtrl]: + riggingUtils.colorControl(control) + + for attr in [".scaleX", ".scaleY", ".globalScale", ".visibility"]: + cmds.setAttr(self.ikHandCtrl + attr, lock=True, keyable=False) + + for attr in [".scaleX", ".scaleY", ".scaleZ", ".rotateX", ".rotateY", ".rotateZ", ".visibility"]: + cmds.setAttr(ikPvCtrl + attr, lock=True, keyable=False) + + # ======================================================================= + # # clean up IK nodes + # ======================================================================= + self.ikCtrlGrp = cmds.group(empty=True, name=self.name + "_arm_ik_ctrls_grp") + cmds.parent(self.ikCtrlGrp, self.armGroup) + + cmds.parent(ikPvSpaceSwitchFollow, self.ikCtrlGrp) + cmds.parent(spaceSwitcherFollow, self.ikCtrlGrp) + cmds.parent(fkMatchUpArm, self.ikCtrlGrp) + + cmds.parent(baseGrp, self.ikCtrlGrp) + cmds.parent(endGrp, self.ikCtrlGrp) + + # add created control info to module + ikRigData = [self.ikHandCtrl, ikPvCtrl] + if not cmds.objExists(networkNode + ".ikControls"): + cmds.addAttr(networkNode, ln="ikControls", dt="string") + jsonString = json.dumps(ikRigData) + cmds.setAttr(networkNode + ".ikControls", jsonString, type="string") + + # update progress + if textEdit != None: + textEdit.setTextColor(QtGui.QColor(0, 255, 18)) + textEdit.append(" SUCCESS: IK Build Complete!") + textEdit.setTextColor(QtGui.QColor(255, 255, 255)) + + return ikArmJoints + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildFingers(self, fingers, textEdit, uiInst, builtRigs, networkNode): + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # create groups + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + armJoints = self.getMainArmJoints() + fkFingerCtrlsGrp = cmds.group(empty=True, name=self.name + "_fk_finger_ctrls") + const = cmds.parentConstraint(armJoints[1][2], fkFingerCtrlsGrp)[0] + cmds.delete(const) + + handDrivenMasterGrp = cmds.duplicate(fkFingerCtrlsGrp, po=True, name=self.name + "_hand_driven_master_grp") + handDrivenGrp = cmds.duplicate(fkFingerCtrlsGrp, po=True, name=self.name + "_hand_driven_grp") + + cmds.parent(handDrivenMasterGrp, self.fingerGrp) + cmds.parent(handDrivenGrp, handDrivenMasterGrp) + cmds.parent(fkFingerCtrlsGrp, handDrivenGrp) + + # setup constraints/sdks on handDrivenGrp + const = cmds.parentConstraint("driver_" + armJoints[1][2], handDrivenGrp) + + fkRigInfo = [] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # create metacarpal controls + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + metaCarpals = [] + phalanges = [] + for each in fingers: + if each[0].find("metacarpal") != -1: + if each[0].find("thumb") == -1: + metaCarpals.append(each[0]) + + fingerData = [] + for finger in each: + if finger.find("metacarpal") == -1: + if each[0].find("thumb") == -1: + fingerData.append(finger) + + for finger in each: + if finger.find("thumb") != -1: + fingerData.append(finger) + + phalanges.append(fingerData) + + for metacarpal in metaCarpals: + data = riggingUtils.createControlFromMover(metacarpal, networkNode, True, False) + ctrl = cmds.rename(data[0], metacarpal + "_anim") + grp = cmds.rename(data[1], metacarpal + "_anim_grp") + cmds.parent(grp, handDrivenGrp) + + # color the control + riggingUtils.colorControl(ctrl) + fkRigInfo.append(ctrl) + + for attr in [".scaleX", ".scaleY", ".scaleZ", ".visibility"]: + cmds.setAttr(ctrl + attr, lock=True, keyable=False) + + # first create a group for the IK handles to go into + + ikHandlesGrp = cmds.group(empty=True, name=self.name + "_fkOrient_ikHandles_grp") + cmds.parent(ikHandlesGrp, handDrivenGrp) + + # setup constraints + const = cmds.parentConstraint([handDrivenGrp[0], self.fingerGrp], ikHandlesGrp)[0] + + # add attr (globalStick) + cmds.addAttr(self.armSettings, ln="globalSticky", dv=0, min=0, max=1, keyable=True) + + # set driven keys + cmds.setAttr(self.armSettings + ".globalSticky", 0) + cmds.setAttr(const + "." + handDrivenGrp[0] + "W0", 1) + cmds.setAttr(const + "." + self.fingerGrp + "W1", 0) + cmds.setDrivenKeyframe([const + "." + handDrivenGrp[0] + "W0", const + "." + self.fingerGrp + "W1"], + cd=self.armSettings + ".globalSticky", itt='linear', ott='linear') + + cmds.setAttr(self.armSettings + ".globalSticky", 1) + cmds.setAttr(const + "." + handDrivenGrp[0] + "W0", 0) + cmds.setAttr(const + "." + self.fingerGrp + "W1", 1) + cmds.setDrivenKeyframe([const + "." + handDrivenGrp[0] + "W0", const + "." + self.fingerGrp + "W1"], + cd=self.armSettings + ".globalSticky", itt='linear', ott='linear') + + cmds.setAttr(self.armSettings + ".globalSticky", 0) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # create the FK orient joints + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + fkOrients = [] + + for each in phalanges: + if len(each) > 0: + + # find tip locator name + nameData = self.returnPrefixSuffix + splitString = each[0] + if nameData[0] != None: + splitString = each[0].partition(nameData[0])[2] + + if nameData[1] != None: + splitString = splitString.partition(nameData[1])[0] + + splitString = splitString.partition("_")[0] + tipLoc = self.name + "_" + splitString + "_tip" + + # create base and end joints + baseJnt = cmds.createNode('joint', name="fk_orient_" + each[0] + "_jnt") + const = cmds.parentConstraint(each[0], baseJnt)[0] + cmds.delete(const) + + endJnt = cmds.createNode('joint', name="fk_orient_" + each[0] + "_end") + const = cmds.parentConstraint(tipLoc, endJnt)[0] + cmds.delete(const) + + cmds.parent(endJnt, baseJnt) + cmds.makeIdentity(baseJnt, t=0, r=1, s=0, apply=True) + cmds.setAttr(baseJnt + ".v", 0, lock=True) + + # create SC ik handles for each chain + ikNodes = cmds.ikHandle(sol="ikSCsolver", name=baseJnt + "_ikHandle", sj=baseJnt, ee=endJnt)[0] + cmds.parent(ikNodes, ikHandlesGrp) + cmds.setAttr(ikNodes + ".v", 0) + + # parent orient joint to metacarpal control if it exists + jntBaseName = self.getFingerBaseName(each[0]).partition("_")[0] + metaCtrl = "" + for each in metaCarpals: + if each.find(jntBaseName) != -1: + metaCtrl = each + "_anim" + + if cmds.objExists(metaCtrl): + cmds.parent(baseJnt, metaCtrl) + fkOrients.append(baseJnt) + else: + fkOrients.append(baseJnt) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # create FK controls for the phalanges + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + fkInfo = [] + for each in phalanges: + fingerData = [] + + for finger in each: + # create the FK control/anim grp/driven grp + data = riggingUtils.createControlFromMover(finger, networkNode, True, False) + ctrl = cmds.rename(data[0], finger + "_anim") + grp = cmds.rename(data[1], finger + "_anim_grp") + drivenGrp = cmds.group(empty=True, name=finger + "_driven_grp") + const = cmds.parentConstraint(grp, drivenGrp)[0] + cmds.delete(const) + + fkInfo.append([ctrl, finger]) + fkRigInfo.append(ctrl) + + # setup hierarchy + cmds.parent(drivenGrp, grp) + cmds.parent(ctrl, drivenGrp) + + cmds.makeIdentity(drivenGrp, t=1, r=1, s=1, apply=True) + fingerData.append(ctrl) + + # color control + riggingUtils.colorControl(ctrl) + + # lock attrs on ctrl + cmds.setAttr(ctrl + ".v", lock=True, keyable=False) + cmds.aliasAttr(ctrl + ".sz", rm=True) + + fingerData.reverse() + + for i in range(len(fingerData)): + try: + cmds.parent(fingerData[i] + "_grp", fingerData[i + 1]) + except IndexError: + pass + + fingerData.reverse() + + # parent FK control to metacarpal control if it exists + jntBaseName = self.getFingerBaseName(each[0]).partition("_")[0] + metaCtrl = "" + for each in metaCarpals: + if each.find(jntBaseName) != -1: + metaCtrl = each + "_anim" + + jntName = fingerData[0].partition("_anim")[0] + baseJnt = "fk_orient_" + jntName + "_jnt" + + # parent the control to the meta control or to the fk finger controls group + if cmds.objExists(metaCtrl): + if metaCtrl.find("thumb") == -1: + cmds.parent(fingerData[0] + "_grp", metaCtrl) + else: + cmds.parent(fingerData[0] + "_grp", fkFingerCtrlsGrp) + cmds.parent(baseJnt, fkFingerCtrlsGrp) + + else: + cmds.parent(fingerData[0] + "_grp", fkFingerCtrlsGrp) + cmds.parent(baseJnt, fkFingerCtrlsGrp) + + # add sticky attribute + if fingerData[0].find("thumb") == -1: + cmds.addAttr(fingerData[0], ln="sticky", defaultValue=0, minValue=0, maxValue=1, keyable=True) + + # setup the constraint between the fk finger orient joint and the ctrlGrp + + if metaCtrl == '': + masterObj = fkFingerCtrlsGrp + else: + masterObj = metaCtrl + + constraint = cmds.parentConstraint([masterObj, baseJnt], fingerData[0] + "_grp", mo=True)[0] + + # set driven keyframes on constraint + if cmds.objExists(fingerData[0] + ".sticky"): + cmds.setAttr(fingerData[0] + ".sticky", 1) + cmds.setAttr(constraint + "." + masterObj + "W0", 0) + cmds.setAttr(constraint + "." + baseJnt + "W1", 1) + cmds.setDrivenKeyframe([constraint + "." + masterObj + "W0", constraint + "." + baseJnt + "W1"], + cd=fingerData[0] + ".sticky", itt="linear", ott="linear") + + cmds.setAttr(fingerData[0] + ".sticky", 0) + cmds.setAttr(constraint + "." + masterObj + "W0", 1) + cmds.setAttr(constraint + "." + baseJnt + "W1", 0) + cmds.setDrivenKeyframe([constraint + "." + masterObj + "W0", constraint + "." + baseJnt + "W1"], + cd=fingerData[0] + ".sticky", itt="linear", ott="linear") + + # write FK data to network node + if len(fkRigInfo) > 0: + if not cmds.objExists(networkNode + ".fkFingerControls"): + cmds.addAttr(networkNode, ln="fkFingerControls", dt='string') + + jsonString = json.dumps(fkRigInfo) + cmds.setAttr(networkNode + ".fkFingerControls", jsonString, type="string") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # setup hand roll + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create our 4 locators(pivots) and position + pinkyPiv = cmds.spaceLocator(name=self.name + "_hand_pinky_pivot")[0] + thumbPiv = cmds.spaceLocator(name=self.name + "_hand_thumb_pivot")[0] + midPiv = cmds.spaceLocator(name=self.name + "_hand_mid_pivot")[0] + tipPiv = cmds.spaceLocator(name=self.name + "_hand_tip_pivot")[0] + + for piv in [pinkyPiv, thumbPiv, midPiv, tipPiv]: + cmds.setAttr(piv + ".v", 0) + + # posititon locators + + const = cmds.parentConstraint(self.name + "_pinky_pivot", pinkyPiv)[0] + cmds.delete(const) + const = cmds.parentConstraint(self.name + "_thumb_pivot", thumbPiv)[0] + cmds.delete(const) + const = cmds.parentConstraint(self.name + "_palm_pivot", midPiv)[0] + cmds.delete(const) + const = cmds.parentConstraint(self.name + "_middle_tip", tipPiv)[0] + cmds.delete(const) + + # create the control groups for the pivots so our values are zeroed + for each in [pinkyPiv, thumbPiv, midPiv, tipPiv]: + group = cmds.group(empty=True, name=each + "_grp") + constraint = cmds.parentConstraint(each, group)[0] + cmds.delete(constraint) + cmds.parent(each, group) + + # setup hierarchy + cmds.parent(thumbPiv + "_grp", pinkyPiv) + cmds.parent(tipPiv + "_grp", thumbPiv) + cmds.parent(midPiv + "_grp", tipPiv) + + # parent the arm IK handles under the midPiv locator + cmds.parent(self.name + "_rp_arm_ikHandle", midPiv) + cmds.parent(pinkyPiv + "_grp", self.ikHandCtrl) + + # add attrs to the IK hand control (side, roll, tip pivot) + cmds.addAttr(self.ikHandCtrl, longName="side", defaultValue=0, keyable=True) + cmds.addAttr(self.ikHandCtrl, longName="mid_bend", defaultValue=0, keyable=True) + cmds.addAttr(self.ikHandCtrl, longName="mid_swivel", defaultValue=0, keyable=True) + cmds.addAttr(self.ikHandCtrl, longName="tip_pivot", defaultValue=0, keyable=True) + cmds.addAttr(self.ikHandCtrl, longName="tip_swivel", defaultValue=0, keyable=True) + + # hook up attrs to pivot locators + cmds.connectAttr(self.ikHandCtrl + ".mid_bend", midPiv + ".rz") + cmds.connectAttr(self.ikHandCtrl + ".tip_pivot", tipPiv + ".rz") + + cmds.connectAttr(self.ikHandCtrl + ".mid_swivel", midPiv + ".ry") + cmds.connectAttr(self.ikHandCtrl + ".tip_swivel", tipPiv + ".ry") + + # set driven keys for side to side attr + + cmds.setAttr(self.ikHandCtrl + ".side", 0) + cmds.setAttr(pinkyPiv + ".rx", 0) + cmds.setAttr(thumbPiv + ".rx", 0) + cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd=self.ikHandCtrl + ".side", itt='linear', + ott='linear') + + cmds.setAttr(self.ikHandCtrl + ".side", 180) + cmds.setAttr(pinkyPiv + ".rx", -180) + cmds.setAttr(thumbPiv + ".rx", 0) + cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd=self.ikHandCtrl + ".side", itt='linear', + ott='linear') + + cmds.setAttr(self.ikHandCtrl + ".side", -180) + cmds.setAttr(pinkyPiv + ".rx", 0) + cmds.setAttr(thumbPiv + ".rx", 180) + cmds.setDrivenKeyframe([pinkyPiv + ".rx", thumbPiv + ".rx"], cd=self.ikHandCtrl + ".side", itt='linear', + ott='linear') + + cmds.setAttr(self.ikHandCtrl + ".side", 0) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # setup ik fingers (if applicable) + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + scaleFactor = riggingUtils.getScaleFactor() + ikInfo = [] + ikCtrlData = [] + + for each in phalanges: + if len(each) == 3: + ikJnts = [] + pvGrps = [] + + # create the IK finger joints + for bone in each: + jnt = cmds.createNode('joint', name="ik_" + bone + "_jnt") + const = cmds.parentConstraint(bone, jnt)[0] + cmds.delete(const) + ikJnts.append(jnt) + + # parent ik joints + ikJnts.reverse() + for i in range(len(ikJnts)): + try: + cmds.parent(ikJnts[i], ikJnts[i + 1]) + except IndexError: + pass + + # create the ik tip jnt + jnt = cmds.createNode('joint', name=ikJnts[0] + "_tip") + + # find tip locator name + nameData = self.returnPrefixSuffix + splitString = each[0] + if nameData[0] != None: + splitString = each[0].partition(nameData[0])[2] + + if nameData[1] != None: + splitString = splitString.partition(nameData[1])[0] + + jntType = splitString.partition("_")[0] + tipLoc = self.name + "_" + jntType + "_tip" + + const = cmds.parentConstraint(tipLoc, jnt)[0] + cmds.delete(const) + + cmds.parent(jnt, ikJnts[0]) + ikJnts.reverse() + ikJnts.append(jnt) + + cmds.makeIdentity(ikJnts[0], t=0, r=1, s=0, apply=True) + + # parent the ik to the handDrivenGrp + cmds.parent(ikJnts[0], handDrivenGrp) + cmds.setAttr(ikJnts[0] + ".v", 0, lock=True) + + # create the IK + ikNodes = \ + cmds.ikHandle(sol="ikRPsolver", name=self.name + jntType + "_ikHandle", sj=ikJnts[0], ee=ikJnts[2])[0] + ikTipNodes = \ + cmds.ikHandle(sol="ikSCsolver", name=self.name + jntType + "_tip_ikHandle", sj=ikJnts[2], ee=ikJnts[3])[ + 0] + cmds.setAttr(ikNodes + ".v", 0) + cmds.parent(ikTipNodes, ikNodes) + + # create the IK PV + poleVector = cmds.spaceLocator(name=self.name + "_" + jntType + "_pv_anim")[0] + constraint = cmds.parentConstraint(ikJnts[1], poleVector)[0] + cmds.delete(constraint) + riggingUtils.colorControl(poleVector) + + # create a pole vector group + pvGrp = cmds.group(empty=True, name=poleVector + "_grp") + constraint = cmds.parentConstraint(poleVector, pvGrp)[0] + cmds.delete(constraint) + pvGrps.append(pvGrp) + + # parent to the joint, and move out away from finger + cmds.parent(poleVector, ikJnts[1]) + + if cmds.getAttr(networkNode + ".side") == "Left": + cmds.setAttr(poleVector + ".ty", -40 * scaleFactor) + + if cmds.getAttr(networkNode + ".side") == "Right": + cmds.setAttr(poleVector + ".ty", 40 * scaleFactor) + + cmds.makeIdentity(poleVector, t=1, r=1, s=1, apply=True) + cmds.parent(poleVector, pvGrp, absolute=True) + cmds.makeIdentity(poleVector, t=1, r=1, s=1, apply=True) + + # create the IK finger controls + data = riggingUtils.createControlFromMover(each[2], networkNode, True, True) + ikFingerCtrl = cmds.rename(data[0], each[2] + "_ik_anim") + ikFingerGrp = cmds.rename(data[1], each[2] + "_ik_anim_grp") + spaceSwitcher = cmds.rename(data[2], each[2] + "_ik_anim_space_switcher") + spaceFollow = cmds.rename(data[3], each[2] + "_ik_anim_space_switcher_follow") + riggingUtils.colorControl(ikFingerCtrl) + ikCtrlData.append(ikFingerCtrl) + ikCtrlData.append(poleVector) + + # parent ik to ctrl + cmds.parent(ikNodes, ikFingerCtrl) + + # create the PV constraint + cmds.poleVectorConstraint(poleVector, ikNodes) + + # add attr to show pole vector control + cmds.addAttr(ikFingerCtrl, longName="poleVectorVis", defaultValue=0, minValue=0, maxValue=1, + keyable=True) + cmds.connectAttr(ikFingerCtrl + ".poleVectorVis", poleVector + ".v") + + for group in pvGrps: + cmds.parent(group, handDrivenGrp) + + # create the global IK control + if not cmds.objExists(armJoints[1][2] + "_global_ik_anim"): + globalIkAnim = riggingUtils.createControl("square", 30, armJoints[1][2] + "_global_ik_anim", True) + riggingUtils.colorControl(globalIkAnim) + + const = cmds.pointConstraint(midPiv, globalIkAnim)[0] + cmds.delete(const) + + globalIkGrp = cmds.group(empty=True, name=globalIkAnim + "_grp") + const = cmds.pointConstraint(midPiv, globalIkGrp)[0] + cmds.delete(const) + const = cmds.orientConstraint(self.ikHandCtrl, globalIkGrp)[0] + cmds.delete(const) + + cmds.parent(globalIkAnim, globalIkGrp) + cmds.makeIdentity(globalIkAnim, t=1, r=1, s=1, apply=True) + + # translate down in z + cmds.setAttr(globalIkAnim + ".tz", -5) + cmds.makeIdentity(globalIkAnim, t=1, r=1, s=1, apply=True) + + # reposition the grp to the control + cmds.parent(globalIkAnim, world=True) + constraint = cmds.pointConstraint(globalIkAnim, globalIkGrp)[0] + cmds.delete(constraint) + + cmds.parent(globalIkAnim, globalIkGrp) + cmds.makeIdentity(globalIkAnim, t=1, r=1, s=1, apply=True) + + # create a space switcher grp + globalIKSpaceFollow = \ + cmds.duplicate(globalIkGrp, po=True, name=globalIkAnim + "_space_switcher_follow")[0] + globalIKSpaceSwitch = cmds.duplicate(globalIkGrp, po=True, name=globalIkAnim + "_space_switcher")[0] + + globalMasterGrp = cmds.group(empty=True, name=self.name + "_global_finger_ik_grp") + const = cmds.parentConstraint(armJoints[1][2], globalMasterGrp)[0] + cmds.delete(const) + + cmds.parent(globalIKSpaceSwitch, globalIKSpaceFollow) + cmds.parent(globalIkGrp, globalIKSpaceSwitch) + cmds.parent(globalIKSpaceFollow, globalMasterGrp) + cmds.parent(globalMasterGrp, self.fingerGrp) + cmds.parentConstraint("driver_" + armJoints[1][2], globalMasterGrp, mo=True) + + # add global ctrl visibility attr + cmds.addAttr(self.armSettings, ln="globalIkVis", dv=0, min=0, max=1, keyable=True) + shape = cmds.listRelatives(globalIkAnim, shapes=True)[0] + cmds.connectAttr(self.armSettings + ".globalIkVis", shape + ".v") + + ikCtrlData.append(globalIkAnim) + + # parent ik control grps to this global control + cmds.parent(spaceFollow, globalIkAnim) + + # collect data per finger + ikInfo.append([globalIKSpaceFollow, globalIkAnim, ikJnts, jntType, spaceFollow, pvGrp]) + + # write IK data to network node + if len(ikCtrlData) > 0: + if not cmds.objExists(networkNode + ".ikFingerControls"): + cmds.addAttr(networkNode, ln="ikFingerControls", dt='string') + + jsonString = json.dumps(ikCtrlData) + cmds.setAttr(networkNode + ".ikFingerControls", jsonString, type="string") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # setup finger modes/driven keys + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + for each in ikInfo: + fkCtrl = each[2][0].partition("ik_")[2].rpartition("_jnt")[0] + "_anim_grp" + cmds.addAttr(self.armSettings, ln=each[3] + "_finger_mode", dv=0, min=0, max=1, keyable=True) + + cmds.setAttr(self.armSettings + "." + each[3] + "_finger_mode", 0) + cmds.setAttr(each[4] + ".v", 0) + cmds.setAttr(each[5] + ".v", 0) + cmds.setAttr(fkCtrl + ".v", 1) + cmds.setDrivenKeyframe([each[4] + ".v", each[5] + ".v", fkCtrl + ".v"], + cd=self.armSettings + "." + each[3] + "_finger_mode", itt='linear', ott='linear') + + cmds.setAttr(self.armSettings + "." + each[3] + "_finger_mode", 1) + cmds.setAttr(each[4] + ".v", 1) + cmds.setAttr(each[5] + ".v", 1) + cmds.setAttr(fkCtrl + ".v", 0) + cmds.setDrivenKeyframe([each[4] + ".v", each[5] + ".v", fkCtrl + ".v"], + cd=self.armSettings + "." + each[3] + "_finger_mode", itt='linear', ott='linear') + + cmds.setAttr(self.armSettings + "." + each[3] + "_finger_mode", 0) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # parent IK finger joints under metacarpals (if they exist) + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + for each in ikInfo: + metaCtrl = "" + jntBaseName = self.getFingerBaseName(each[2][0]).partition("_")[0] + for carpal in metaCarpals: + if carpal.find(jntBaseName) != -1: + metaCtrl = carpal + "_anim" + + if cmds.objExists(metaCtrl): + cmds.parent(each[2][0], metaCtrl) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # Hook up driver joints + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + for each in fkInfo: + fkCtrl = each[0] + jnt = each[1] + ikJnt = "ik_" + jnt + "_jnt" + driverJnt = "driver_" + jnt + + # find joint base name + nameData = self.returnPrefixSuffix + splitString = jnt + if nameData[0] != None: + splitString = jnt.partition(nameData[0])[2] + + if nameData[1] != None: + splitString = splitString.partition(nameData[1])[0] + + jntBaseName = splitString.partition("_")[0] + + if cmds.objExists(ikJnt): + pConst = cmds.parentConstraint([fkCtrl, ikJnt], driverJnt, mo=True)[0] + + # set driven keys + cmds.setAttr(self.armSettings + "." + jntBaseName + "_finger_mode", 0) + cmds.setAttr(pConst + "." + fkCtrl + "W0", 1) + cmds.setAttr(pConst + "." + ikJnt + "W1", 0) + cmds.setDrivenKeyframe([pConst + "." + fkCtrl + "W0", pConst + "." + ikJnt + "W1"], + cd=self.armSettings + "." + jntBaseName + "_finger_mode", itt='linear', + ott='linear') + + cmds.setAttr(self.armSettings + "." + jntBaseName + "_finger_mode", 1) + cmds.setAttr(pConst + "." + fkCtrl + "W0", 0) + cmds.setAttr(pConst + "." + ikJnt + "W1", 1) + cmds.setDrivenKeyframe([pConst + "." + fkCtrl + "W0", pConst + "." + ikJnt + "W1"], + cd=self.armSettings + "." + jntBaseName + "_finger_mode", itt='linear', + ott='linear') + + cmds.setAttr(self.armSettings + "." + jntBaseName + "_finger_mode", 0) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale + # into input 2, and plugs that into driver joint + slot = 0 + for each in [fkCtrl, ikJnt]: + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=jnt + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(each + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + jnt, "scale", False, 2, slot, + "output") + else: + riggingUtils.createConstraint(each, "driver_" + jnt, "scale", False, 2, slot) + + slot = slot + 1 + + else: + pConst = cmds.parentConstraint(fkCtrl, driverJnt)[0] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getMainArmJoints(self): + + clavicleJoint = None + upperarmJoint = None + lowerarmJoint = None + handJoint = None + + returnData = [] + + joints = self.returnCreatedJoints + + # clavicle + for joint in joints: + if joint.find("clavicle") != -1: + clavicleJoint = joint + + # upperarm + joints = self.returnCreatedJoints + for joint in joints: + if joint.find("upperarm") != -1: + if joint.find("twist") == -1: + upperarmJoint = joint + + # lowerarm + for joint in joints: + if joint.find("lowerarm") != -1: + if joint.find("twist") == -1: + lowerarmJoint = joint + + # hand + for joint in joints: + if joint.find("hand") != -1: + handJoint = joint + + returnData = [clavicleJoint, [upperarmJoint, lowerarmJoint, handJoint]] + return returnData + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getTwistJoints(self, upperarm, lowerarm): + + upperTwistBones = [] + lowerTwistBones = [] + + joints = self.returnCreatedJoints + + # upper arm + for joint in joints: + if joint.find("upperarm") != -1: + if joint.find("twist") != -1: + upperTwistBones.append(joint) + + # calf + for joint in joints: + if joint.find("lowerarm") != -1: + if joint.find("twist") != -1: + lowerTwistBones.append(joint) + + if upperarm: + return upperTwistBones + if lowerarm: + return lowerTwistBones + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getFingerJoints(self): + + joints = self.returnCreatedJoints + indexJoints = [] + middleJoints = [] + ringJoints = [] + pinkyJoints = [] + thumbJoints = [] + + for joint in joints: + + if joint.find("thumb") != -1: + thumbJoints.append(joint) + + if joint.find("index") != -1: + indexJoints.append(joint) + + if joint.find("middle") != -1: + if joint.find("index") == -1: + if joint.find("ring") == -1: + if joint.find("pinky") == -1: + middleJoints.append(joint) + + if joint.find("ring") != -1: + ringJoints.append(joint) + + if joint.find("pinky") != -1: + pinkyJoints.append(joint) + + returnData = [] + for each in [indexJoints, middleJoints, ringJoints, pinkyJoints, thumbJoints]: + if each != []: + returnData.append(each) + return returnData + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getFingerBaseName(self, finger): + + nameData = self.returnPrefixSuffix + if nameData[0] != None: + if nameData[1] != None: + jointName = finger.partition(nameData[0] + "_")[2].partition("_" + nameData[1])[0] + else: + jointName = finger.partition(nameData[0] + "_")[2] + else: + if nameData[1] != None: + jointName = finger.partition("_" + nameData[1])[0] + else: + jointName = finger.partition("_")[0] + + return jointName + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def switchClavMode(self, mode, checkBox, range=False): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + controls = json.loads(cmds.getAttr(networkNode + ".clavControls")) + + # are we matching? + if not range: + match = checkBox.isChecked() + else: + match = True + + # if being called from match over frame range + if range: + if mode == matchData[1][0]: + mode = "FK" + if mode == matchData[1][1]: + mode = "IK" + + if mode == "FK": + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode") + + if match: + dupe = cmds.duplicate(namespace + ":" + controls[0], rr=True, po=True)[0] + const = cmds.orientConstraint(namespace + ":" + self.name + "_clav_ik_start", dupe)[0] + cmds.delete(const) + + rotateXvalue = cmds.getAttr(dupe + ".rotateX") + rotateYvalue = cmds.getAttr(dupe + ".rotateY") + rotateZvalue = cmds.getAttr(dupe + ".rotateZ") + + cmds.setAttr(namespace + ":" + controls[0] + ".rotateX", rotateXvalue) + cmds.setAttr(namespace + ":" + controls[0] + ".rotateY", rotateYvalue) + cmds.setAttr(namespace + ":" + controls[0] + ".rotateZ", rotateZvalue) + + cmds.setKeyframe(namespace + ":" + controls[0]) + + cmds.delete(dupe) + cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode") + + if mode == "IK": + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode") + + if match: + dupe = cmds.duplicate(namespace + ":" + controls[1], rr=True)[0] + const = cmds.pointConstraint(namespace + ":" + self.name + "_ik_clav_matcher", dupe)[0] + cmds.delete(const) + + transXvalue = cmds.getAttr(dupe + ".translateX") + transYvalue = cmds.getAttr(dupe + ".translateY") + transZvalue = cmds.getAttr(dupe + ".translateZ") + + cmds.setAttr(namespace + ":" + controls[1] + ".translateX", transXvalue) + cmds.setAttr(namespace + ":" + controls[1] + ".translateY", transYvalue) + cmds.setAttr(namespace + ":" + controls[1] + ".translateZ", transZvalue) + + cmds.setKeyframe(namespace + ":" + controls[1]) + + cmds.delete(dupe) + + cmds.setAttr(namespace + ":" + self.name + "_settings.clavMode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.clavMode") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def switchMode(self, mode, checkBox, range=False): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + # are we matching? + if not range: + match = checkBox.isChecked() + else: + match = True + + # if being called from match over frame range + if range: + if mode == matchData[1][0]: + mode = "FK" + if mode == matchData[1][1]: + mode = "IK" + + # switch to FK mode + if mode == "FK": + # get current mode + currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode") + if currentMode == 0.0: + cmds.warning("Already in FK mode.") + return + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if match: + # get fk controls + controls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + + # create a duplicate chain + topCtrl = controls[2] + topGrp = cmds.listRelatives(namespace + ":" + topCtrl, parent=True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world=True) + + # match the fk controls to the corresponding joint + controls.reverse() + for control in controls: + joint = control.partition("fk_")[2].partition("_anim")[0] + joint = namespace + ":" + joint + + constraint = cmds.parentConstraint(joint, control)[0] + + translate = cmds.getAttr(control + ".translate")[0] + rotate = cmds.getAttr(control + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], + type='double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3') + + cmds.setKeyframe(namespace + ":" + control) + + # delete dupes + cmds.delete(newControls[0]) + + # switch modes + if not range: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + # switch to IK mode + if mode == "IK": + + # get current mode + currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode") + if currentMode == 1.0: + return + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if match: + + # get IK controls + controls = json.loads(cmds.getAttr(networkNode + ".ikControls")) + + # HAND + # create a duplicate hand anim + control = controls[0] + topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world=True) + + # duplicate the control once more and parent under the fkMatch node + matchCtrl = cmds.duplicate(control, po=True)[0] + cmds.parent(matchCtrl, control + "_fkMatch") + + # match the hand anim to the hand joint + joint = control.partition("ik_")[2].partition("_anim")[0] + joint = namespace + ":" + joint + constraint = cmds.parentConstraint(joint, control + "_fkMatch")[0] + cmds.delete(constraint) + + # unparent the match control from the fkMatch, and put it under the topGrp + cmds.parent(matchCtrl, topGrp) + + # this will now give use good values + translate = cmds.getAttr(matchCtrl + ".translate")[0] + rotate = cmds.getAttr(matchCtrl + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], + type='double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3') + + cmds.setKeyframe(namespace + ":" + control) + + # delete dupes + cmds.delete(newControls[0]) + cmds.delete(matchCtrl) + + # ELBOW + # create a duplicate elbow pv anim + control = controls[1] + topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world=True) + + # match to the pvMatch node + constraint = cmds.pointConstraint(namespace + ":" + control + "_fkMatch", control)[0] + cmds.delete(constraint) + + # this will now give use good values + translate = cmds.getAttr(control + ".translate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], + type='double3') + + cmds.setKeyframe(namespace + ":" + control) + + # delete dupes + cmds.delete(newControls[0]) + + # switch modes + if not range: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if range: + self.switchClavMode(mode, checkBox, True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def switchFingerMode(self, mode, finger, range=False): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + # switch to FK mode + if mode == "FK": + if finger == "All": + cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode") + + else: + if finger.partition(namespace)[2].find(":index") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode") + + if finger.partition(namespace)[2].find(":middle") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode") + + if finger.partition(namespace)[2].find(":ring") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode") + + if finger.partition(namespace)[2].find(":pinky") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode") + + if finger.partition(namespace)[2].find(":thumb") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode") + + if mode == "IK": + + if finger == "All": + cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode") + cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode") + + else: + if finger.partition(namespace)[2].find(":index") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.index_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.index_finger_mode") + + if finger.partition(namespace)[2].find(":middle") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.middle_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.middle_finger_mode") + + if finger.partition(namespace)[2].find(":ring") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.ring_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.ring_finger_mode") + + if finger.partition(namespace)[2].find(":pinky") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.pinky_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.pinky_finger_mode") + + if finger.partition(namespace)[2].find(":thumb") == 0: + # switch modes + cmds.setAttr(namespace + ":" + self.name + "_settings.thumb_finger_mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.thumb_finger_mode") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX(self, importMethod, character): + + returnControls = [] + + networkNode = self.returnRigNetworkNode + moduleName = cmds.getAttr(networkNode + ".moduleName") + + # find created joints + joints = cmds.getAttr(networkNode + ".Created_Bones") + + splitJoints = joints.split("::") + createdJoints = [] + armJoints = [] + clavJoint = None + + fingers = [] + if cmds.objExists(networkNode + ".fkFingerControls"): + fingers = json.loads(cmds.getAttr(networkNode + ".fkFingerControls")) + + for bone in splitJoints: + if bone != "": + createdJoints.append(bone) + + for joint in createdJoints: + if joint.find("upperarm") != -1: + if joint.find("twist") == -1: + upArmJnt = joint + armJoints.append(upArmJnt) + + if joint.find("lowerarm") != -1: + if joint.find("twist") == -1: + loArmJnt = joint + armJoints.append(loArmJnt) + + if joint.find("hand") != -1: + handJoint = joint + armJoints.append(handJoint) + + if joint.find("clavicle") != -1: + clavJoint = joint + + solveClav = False + + if cmds.getAttr(networkNode + ".includeClavicle"): + solveClav = True + clavControls = json.loads(cmds.getAttr(networkNode + ".clavControls")) + + # Handle Import Method/Constraints + if importMethod == "FK": + cmds.setAttr(character + ":" + moduleName + "_settings.mode", 0) + cmds.setAttr(character + ":" + moduleName + "_settings.clavMode", 0) + + if solveClav: + cmds.orientConstraint(clavJoint, character + ":" + clavControls[0]) + returnControls.append(character + ":" + clavControls[0]) + + for joint in armJoints: + cmds.orientConstraint(joint, character + ":fk_" + joint + "_anim") + returnControls.append(character + ":fk_" + joint + "_anim") + + if len(fingers) > 0: + for finger in fingers: + cmds.orientConstraint(finger.partition("_anim")[0], character + ":" + finger) + returnControls.append(character + ":" + finger) + + if importMethod == "IK": + + if solveClav: + cmds.pointConstraint(armJoints[0], character + ":" + clavControls[1]) + returnControls.append(character + ":" + clavControls[1]) + + cmds.parentConstraint(armJoints[2], character + ":ik_" + armJoints[2] + "_anim", mo=True) + returnControls.append(character + ":ik_" + armJoints[2] + "_anim") + + cmds.pointConstraint(armJoints[1], character + ":" + self.name + "_ik_elbow_anim", mo=True) + returnControls.append(character + ":" + self.name + "_ik_elbow_anim") + + if len(fingers) > 0: + for finger in fingers: + cmds.orientConstraint(finger.partition("_anim")[0], character + ":" + finger) + returnControls.append(character + ":" + finger) + + if importMethod == "Both": + if solveClav: + cmds.orientConstraint(clavJoint, character + ":" + clavControls[0]) + returnControls.append(character + ":" + clavControls[0]) + + cmds.pointConstraint(armJoints[0], character + ":" + clavControls[1]) + returnControls.append(character + ":" + clavControls[1]) + + cmds.parentConstraint(armJoints[2], character + ":ik_" + armJoints[2] + "_anim", mo=True) + returnControls.append(character + ":ik_" + armJoints[2] + "_anim") + + cmds.pointConstraint(armJoints[1], character + ":" + self.name + "_ik_elbow_anim", mo=True) + returnControls.append(character + ":" + self.name + "_ik_elbow_anim") + + for joint in armJoints: + cmds.orientConstraint(joint, character + ":fk_" + joint + "_anim") + returnControls.append(character + ":fk_" + joint + "_anim") + + if len(fingers) > 0: + for finger in fingers: + cmds.orientConstraint(finger.partition("_anim")[0], character + ":" + finger) + returnControls.append(character + ":" + finger) + + if importMethod == "None": + pass + + return returnControls + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def selectRigControls(self, mode): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + # list any attributes on the network node that contain "controls" + controls = cmds.listAttr(networkNode, st="*Controls") + fkControls = ["fkControls", "upArmTwistControls", "loArmTwistControls", "fkFingerControls", "clavControls"] + ikControls = ["ikControls", "ikFingerControls", "clavControls"] + + # get that data on that attr + for control in controls: + + # select all controls + if mode == "all": + data = json.loads(cmds.getAttr(networkNode + "." + control)) + if data != None: + for each in data: + cmds.select(namespace + ":" + each, add=True) + + # select fk controls + if mode == "fk": + if control in fkControls: + data = json.loads(cmds.getAttr(networkNode + "." + control)) + if data != None: + for each in data: + if each.find("fk") != -1: + cmds.select(namespace + ":" + each, add=True) + + # select ik controls + if mode == "ik": + if control in ikControls: + data = json.loads(cmds.getAttr(networkNode + "." + control)) + if data != None: + for each in data: + if each.find("fk") == -1: + cmds.select(namespace + ":" + each, add=True) diff --git a/Core/Scripts/RigModules/ART_Chain.py b/Core/Scripts/RigModules/ART_Chain.py new file mode 100644 index 0000000..7420c43 --- /dev/null +++ b/Core/Scripts/RigModules/ART_Chain.py @@ -0,0 +1,294 @@ +""" +Author: Jeremy Ernst + +=============== +File Attributes +=============== + * **icon:** This is the image file (125x75 .png) that gets used in the RigCreatorUI + + * **hoverIcon:** When you hover over the module in the module list, it will swap to this icon + (background changes to orange). There are .psd template files for these. + + * **search:** These are search terms that are accepted when searching the list of modules in the + RigCreatorUI + + * **class name:** The name of the class. + + * **jointMover:** The relative path to the joint mover file. Relative to the ARTv2 root directory. + + * **baseName:** The default name the module will get created with. Users can then add a prefix and/or + suffix to the base name. + + * **rigs:** This is a simple list of what rigs this module can build. This feature isn't implemented yet, + but the plan is to query this list and present these options to the user for them to select what rigs + they want to build for the module. Right now, it will build all rigs. + + * **fbxImport:** This is a list that will show the options for the module in the import mocap interface. + Normally, this list will have at least None and FK. + + * **matchData:** This is a list of options that will be presented for the module in a comboBox in the + match over frame range interface. First argument is a bool as to whether the module can or can't + match. The second arg is a list of strings to display for the match options. For example: + matchData = [True, ["Match FK to IK", "Match IK to FK"]] + + * **controlTypes:** This is a list of lists, where each item in the main list is a list comprised of the + name of the attribute that gets added to the network node that contains the control information. + The second arg in each list entry is a control type, like FK or IK. This is used in the select + rig controls interface for filtering out which controls on each module you want to select. On + this module, the values are: controlTypes = [["fkControls", "FK"]], which means that the + attribute that holds the control info is called fkControls, and those controls are of type FK. + + .. image:: /images/selectRigControls.png + +=============== +Class +=============== +""" +# file imports +import json +import os +from functools import partial + +import maya.cmds as cmds + +import System.interfaceUtils as interfaceUtils +import System.riggingUtils as riggingUtils +import System.utils as utils +from System.ART_RigModule import ART_RigModule +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + +# file attributes +icon = "Modules/chain.png" +hoverIcon = "Modules/hover_chain.png" +search = "chain" +className = "ART_Chain" +jointMover = "Core/JointMover/ART_Chain.ma" +baseName = "chain" +rigs = ["FK", "IK", "Dynamic"] +fbxImport = ["None", "FK", "IK", "Both"] +matchData = [True, ["Match FK to IK", "Match IK to FK"]] +controlTypes = [["fkControls", "FK"], ["ikControls", "IK"], ["dynControls", "FK"]] + + +class ART_Chain(ART_RigModule): + """This class creates the chain module, which can have a minimum of 2 joints and a maximum of 99.""" + + def __init__(self, rigUiInst, moduleUserName): + """Initiate the class, taking in the instance to the interface and the user specified name. + + :param rigUiInst: This is the rig creator interface instance being passed in. + :param moduleUserName: This is the name specified by the user on module creation. + + Instantiate the following class variables as well: + * **self.rigUiInst:** take the passed in interface instance and make it a class var + * **self.moduleUserName:** take the passed in moduleUserName and make it a class var + * **self.outlinerWidget:** an empty list that will hold all of the widgets added to the outliner + + Also, read the QSettings to find out where needed paths are. + """ + + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + + settings = QtCore.QSettings("Epic Games", "ARTv2") + self.toolsPath = settings.value("toolsPath") + + ART_RigModule.__init__(self, "ART_Chain_Module", "ART_Chain", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + """ + Add custom attributes this module needs to the network node. + + Always calls on base class function first, then extends with any attributes unique to the class. + """ + + # call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + # add custom attributes for this specific module + cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".Created_Bones", "joint_01::joint_02::joint_03::", type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".canAim", True, lock=True) + + cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".aimMode", False, lock=True) + + cmds.addAttr(self.networkNode, sn="numJoints", keyable=False) + cmds.setAttr(self.networkNode + ".numJoints", 3, lock=True) + + cmds.addAttr(self.networkNode, sn="hasDynamics", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".hasDynamics", False, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + """ + This is the UI for the module that has all of the configuration settings. + + :param name: user given name of module (prefix + base_name + suffix) + :param width: width of the skeleton settings groupBox. 335 usually + :param height: height of the skeleton settings groupBox. + :param checkable: Whether or not the groupBox can be collapsed. + + + Build the groupBox that contains all of the settings for this module. Parent the groupBox + into the main skeletonSettingsUI layout. + Lastly, call on updateSettingsUI to populate the UI based off of the network node values. + + .. image:: /images/skeletonSettings.png + + """ + # width, height, checkable + + networkNode = self.returnNetworkNode + font = QtGui.QFont() + font.setPointSize(8) + + headerFont = QtGui.QFont() + headerFont.setPointSize(8) + headerFont.setBold(True) + + # groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 288, True) + + # STANDARD BUTTONS + + # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot + self.mainLayout = QtWidgets.QVBoxLayout(self.groupBox) + self.frame = QtWidgets.QFrame(self.groupBox) + self.mainLayout.addWidget(self.frame) + self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) + self.frame.setMinimumSize(QtCore.QSize(320, 270)) + self.frame.setMaximumSize(QtCore.QSize(320, 270)) + + # create layout that is a child of the frame + self.layout = QtWidgets.QVBoxLayout(self.frame) + + # mirror module + self.mirrorModLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.mirrorModLayout) + self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ") + self.mirrorModuleLabel.setFont(font) + self.mirrorModLayout.addWidget(self.mirrorModuleLabel) + + mirror = cmds.getAttr(networkNode + ".mirrorModule") + if mirror == "": + mirror = "None" + self.mirrorMod = QtWidgets.QLabel(mirror) + self.mirrorMod.setFont(font) + self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter) + self.mirrorModLayout.addWidget(self.mirrorMod) + + # current parent + self.currentParentMod = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.currentParentMod) + self.currentParentLabel = QtWidgets.QLabel("Current Parent: ") + self.currentParentLabel.setFont(font) + self.currentParentMod.addWidget(self.currentParentLabel) + + parent = cmds.getAttr(networkNode + ".parentModuleBone") + self.currentParent = QtWidgets.QLabel(parent) + self.currentParent.setFont(font) + self.currentParent.setAlignment(QtCore.Qt.AlignHCenter) + self.currentParentMod.addWidget(self.currentParent) + + # button layout for name/parent + self.buttonLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.buttonLayout) + self.changeNameBtn = QtWidgets.QPushButton("Change Name") + self.changeParentBtn = QtWidgets.QPushButton("Change Parent") + self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module") + self.buttonLayout.addWidget(self.changeNameBtn) + self.buttonLayout.addWidget(self.changeParentBtn) + self.buttonLayout.addWidget(self.mirrorModuleBtn) + self.changeNameBtn.setObjectName("blueButton") + self.changeParentBtn.setObjectName("blueButton") + self.mirrorModuleBtn.setObjectName("blueButton") + + # button signal/slots + self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst)) + self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst)) + self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst)) + + # bake offsets button + self.bakeToolsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.bakeToolsLayout) + + # Bake OFfsets + self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets") + self.bakeOffsetsBtn.setFont(headerFont) + self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn) + self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets) + self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync") + self.bakeOffsetsBtn.setObjectName("blueButton") + + # Rig Settings + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.layout.addItem(spacerItem) + + self.hasDynamics = QtWidgets.QCheckBox("Has Dynamics") + self.layout.addWidget(self.hasDynamics) + self.hasDynamics.setChecked(False) + # self.hasDynamics.clicked.connect(partial(self.applyModuleChanges, self)) + + spacerItem = QtWidgets.QSpacerItem(20, 30, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.layout.addItem(spacerItem) + + # Number of joints in chain + self.numJointsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.numJointsLayout) + + self.numJointsLabel = QtWidgets.QLabel("Number of Joints in Chain: ") + self.numJointsLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.numJointsLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.numJointsLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.numJointsLayout.addWidget((self.numJointsLabel)) + + self.numJoints = QtWidgets.QSpinBox() + self.numJoints.setMaximum(99) + self.numJoints.setMinimum(2) + self.numJoints.setMinimumSize(QtCore.QSize(100, 20)) + self.numJoints.setMaximumSize(QtCore.QSize(100, 20)) + self.numJoints.setValue(3) + self.numJoints.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.numJointsLayout.addWidget(self.numJoints) + + # rebuild button + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.layout.addItem(spacerItem) + + self.applyButton = QtWidgets.QPushButton("Apply Changes") + self.layout.addWidget(self.applyButton) + self.applyButton.setFont(headerFont) + self.applyButton.setMinimumSize(QtCore.QSize(300, 40)) + self.applyButton.setMaximumSize(QtCore.QSize(300, 40)) + self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.applyButton.setEnabled(False) + self.applyButton.clicked.connect(partial(self.applyModuleChanges, self)) + + # signal slot for groupbox checkbox + QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible) + self.groupBox.setChecked(False) + + # add custom skeletonUI settings name, parent, rig types to install, mirror module, etc. + # add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + # Populate the settings UI based on the network node attributes + # self.updateSettingsUI() diff --git a/Core/Scripts/RigModules/ART_Head.py b/Core/Scripts/RigModules/ART_Head.py new file mode 100644 index 0000000..296701a --- /dev/null +++ b/Core/Scripts/RigModules/ART_Head.py @@ -0,0 +1,1068 @@ +""" +Author: Jeremy Ernst + +=============== +File Attributes +=============== + * **icon:** This is the image file (125x75 .png) that gets used in the RigCreatorUI + + * **hoverIcon:** When you hover over the module in the module list, it will swap to this icon + (background changes to orange). There are .psd template files for these. + + * **search:** These are search terms that are accepted when searching the list of modules in the + RigCreatorUI + + * **class name:** The name of the class. + + * **jointMover:** The relative path to the joint mover file. Relative to the ARTv2 root directory. + + * **baseName:** The default name the module will get created with. Users can then add a prefix and/or + suffix to the base name. + + * **rigs:** This is a simple list of what rigs this module can build. This feature isn't implemented yet, + but the plan is to query this list and present these options to the user for them to select what rigs + they want to build for the module. Right now, it will build all rigs. + + * **fbxImport:** This is a list that will show the options for the module in the import mocap interface. + Normally, this list will have at least None and FK. + + * **matchData:** This is a list of options that will be presented for the module in a comboBox in the + match over frame range interface. First argument is a bool as to whether the module can or can't + match. The second arg is a list of strings to display for the match options. For example: + matchData = [True, ["Match FK to IK", "Match IK to FK"]] + + * **controlTypes:** This is a list of lists, where each item in the main list is a list comprised of the + name of the attribute that gets added to the network node that contains the control information. + The second arg in each list entry is a control type, like FK or IK. This is used in the select + rig controls interface for filtering out which controls on each module you want to select. On + this module, the values are: controlTypes = [["fkControls", "FK"]], which means that the + attribute that holds the control info is called fkControls, and those controls are of type FK. + + .. image:: /images/selectRigControls.png + +=============== +Class +=============== +""" +# file imports +import json +import os +from functools import partial + +import maya.cmds as cmds + +import System.interfaceUtils as interfaceUtils +import System.riggingUtils as riggingUtils +import System.utils as utils +from System.ART_RigModule import ART_RigModule +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + +# file attributes +icon = "Modules/head.png" +hoverIcon = "Modules/hover_head.png" +search = "biped:head:neck" +className = "ART_Head" +jointMover = "Core/JointMover/ART_Head_1Neck.ma" +baseName = "Head" +rigs = ["FK"] +fbxImport = ["None", "FK"] +matchData = [False, None] # This is for matching over frame range options. (Matching between rigs of the module) +controlTypes = [["fkControls", "FK"]] + + +class ART_Head(ART_RigModule): + """This class creates the head module""" + + def __init__(self, rigUiInst, moduleUserName): + """Initiate the class, taking in the instance to the interface and the user specified name. + + :param rigUiInst: This is the rig creator interface instance being passed in. + :param moduleUserName: This is the name specified by the user on module creation. + + Instantiate the following class variables as well: + * **self.rigUiInst:** take the passed in interface instance and make it a class var + * **self.moduleUserName:** take the passed in moduleUserName and make it a class var + * **self.outlinerWidget:** an empty list that will hold all of the widgets added to the outliner + + Also, read the QSettings to find out where needed paths are. + """ + + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + + settings = QtCore.QSettings("Epic Games", "ARTv2") + self.toolsPath = settings.value("toolsPath") + + ART_RigModule.__init__(self, "ART_Head_Module", "ART_Head", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + """ + Add custom attributes this module needs to the network node. + + Always calls on base class function first, then extends with any attributes unique to the class. + """ + + # call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + # add custom attributes for this specific module + cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".Created_Bones", "neck_01::head::", type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".canAim", False, lock=True) + + cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".aimMode", False, lock=True) + + cmds.addAttr(self.networkNode, sn="neckJoints", keyable=False) + cmds.setAttr(self.networkNode + ".neckJoints", 1, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + """ + This is the UI for the module that has all of the configuration settings. + + :param name: user given name of module (prefix + base_name + suffix) + :param width: width of the skeleton settings groupBox. 335 usually + :param height: height of the skeleton settings groupBox. + :param checkable: Whether or not the groupBox can be collapsed. + + + Build the groupBox that contains all of the settings for this module. Parent the groupBox + into the main skeletonSettingsUI layout. + Lastly, call on updateSettingsUI to populate the UI based off of the network node values. + + .. image:: /images/skeletonSettings.png + + """ + # width, height, checkable + + networkNode = self.returnNetworkNode + font = QtGui.QFont() + font.setPointSize(8) + + headerFont = QtGui.QFont() + headerFont.setPointSize(8) + headerFont.setBold(True) + + # groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 228, True) + + # STANDARD BUTTONS + + # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot + self.mainLayout = QtWidgets.QVBoxLayout(self.groupBox) + self.frame = QtWidgets.QFrame(self.groupBox) + self.mainLayout.addWidget(self.frame) + self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) + self.frame.setMinimumSize(QtCore.QSize(320, 210)) + self.frame.setMaximumSize(QtCore.QSize(320, 210)) + + # create layout that is a child of the frame + self.layout = QtWidgets.QVBoxLayout(self.frame) + + # current parent + self.currentParentMod = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.currentParentMod) + self.currentParentLabel = QtWidgets.QLabel("Current Parent: ") + self.currentParentLabel.setFont(font) + self.currentParentMod.addWidget(self.currentParentLabel) + + parent = cmds.getAttr(networkNode + ".parentModuleBone") + self.currentParent = QtWidgets.QLabel(parent) + self.currentParent.setFont(font) + self.currentParent.setAlignment(QtCore.Qt.AlignHCenter) + self.currentParentMod.addWidget(self.currentParent) + + # button layout for name/parent + self.buttonLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.buttonLayout) + self.changeNameBtn = QtWidgets.QPushButton("Change Name") + self.changeParentBtn = QtWidgets.QPushButton("Change Parent") + self.buttonLayout.addWidget(self.changeNameBtn) + self.buttonLayout.addWidget(self.changeParentBtn) + self.changeNameBtn.setObjectName("blueButton") + self.changeParentBtn.setObjectName("blueButton") + + # bake offsets button + self.bakeToolsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.bakeToolsLayout) + + # Bake OFfsets + self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets") + self.bakeOffsetsBtn.setFont(headerFont) + self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn) + self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets) + self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync") + + self.bakeOffsetsBtn.setObjectName("blueButton") + + # button signal/slots + self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst)) + self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst)) + + # Number of Neck Bones + self.neckLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.neckLayout) + + self.numNeckBonesLabel = QtWidgets.QLabel("Number of Neck Bones: ") + self.numNeckBonesLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.numNeckBonesLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.numNeckBonesLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.neckLayout.addWidget((self.numNeckBonesLabel)) + + self.numNeck = QtWidgets.QSpinBox() + self.numNeck.setMaximum(3) + self.numNeck.setMinimum(1) + self.numNeck.setMinimumSize(QtCore.QSize(100, 20)) + self.numNeck.setMaximumSize(QtCore.QSize(100, 20)) + self.numNeck.setValue(1) + self.numNeck.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.neckLayout.addWidget(self.numNeck) + + # rebuild button + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.layout.addItem(spacerItem) + + self.applyButton = QtWidgets.QPushButton("Apply Changes") + self.layout.addWidget(self.applyButton) + self.applyButton.setFont(headerFont) + self.applyButton.setMinimumSize(QtCore.QSize(300, 40)) + self.applyButton.setMaximumSize(QtCore.QSize(300, 40)) + self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.applyButton.setEnabled(False) + self.applyButton.clicked.connect(partial(self.applyModuleChanges, self)) + + # spinBox & checkbox signal/slots + self.numNeck.valueChanged.connect(self.toggleButtonState) + + # signal slot for groupbox checkbox + QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible) + self.groupBox.setChecked(False) + + # add custom skeletonUI settings name, parent, rig types to install, mirror module, etc. + # add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + # Populate the settings UI based on the network node attributes + self.updateSettingsUI() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateSettingsUI(self): + + """ + Update the skeleton settings UI based on the network node values for this module. + """ + + networkNode = self.returnNetworkNode + numNeck = cmds.getAttr(networkNode + ".neckJoints") + + # update UI elements + self.numNeck.setValue(numNeck) + + # apply changes + self.applyButton.setEnabled(False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateNeck(self, attachedModules, oldNum): + + """ + Take the number of neck bones value and rebuild the joint mover. + + The head module has 3 joint mover files, 1 for each possible neck number. When the number of neck bones is + changed, the current module has its information stored (placement, etc), the module is then deleted, + the new joint mover path is constructed and brought in, and lastly it resolves any dependency issues. + (Like if there was a leaf joint as a child of a neck bone that no longer exists) + + :param attachedModules: self.checkForDependencies() + :param oldNum: the existing amount of neck bones prior to the update + """ + + # gather information (current name, current parent, etc) + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + parent = cmds.getAttr(networkNode + ".parentModuleBone") + newNum = int(cmds.getAttr(networkNode + ".neckJoints")) + + # call on base class delete + movers = self.returnJointMovers + for moverGrp in movers: + for mover in moverGrp: + cmds.lockNode(mover, lock=False) + + # store mover positions (movers = [all global, all offset, all geo]) + basePositions = {} + + for each in movers: + for mover in each: + attrs = cmds.listAttr(mover, keyable=True) + attrValues = [] + for attr in attrs: + value = cmds.getAttr(mover + "." + attr) + attrValues.append([attr, value]) + basePositions[mover] = attrValues + + # delete joint mover + cmds.delete(self.name + "_mover_grp") + + # build new jmPath name + jmPath = jointMover.partition(".ma")[0].rpartition("_")[0] + "_" + str(newNum) + "Neck.ma" # ART_Head_1Neck + self.jointMover_Build(jmPath) + + # apply base positions + for key in basePositions: + + mover = key + attrList = basePositions.get(key) + + for attr in attrList: + if cmds.objExists(mover): + cmds.setAttr(mover + "." + attr[0], attr[1]) + + # parent the joint mover to the offset mover of the parent + mover = "" + + if parent == "root": + mover = "root_mover" + + else: + # find the parent mover name to parent to + networkNodes = utils.returnRigModules() + mover = utils.findMoverNodeFromJointName(networkNodes, parent) + + # delete the old constraint and create the new one + if cmds.objExists(self.name + "_mover_grp_parentConstraint*"): + cmds.delete(self.name + "_mover_grp_parentConstraint*") + + if mover is not None: + cmds.parentConstraint(mover, self.name + "_mover_grp", mo=True) + + if cmds.objExists(self.name + "_mover_grp_scaleConstraint*"): + cmds.delete(self.name + "_mover_grp_scaleConstraint*") + + if mover is not None: + cmds.scaleConstraint(mover, self.name + "_mover_grp", mo=True) + + # create the connection geo between the two + childMover = utils.findOffsetMoverFromName(name) + riggingUtils.createBoneConnection(mover, childMover, name) + self.applyModuleChanges(self) + cmds.select(clear=True) + + # if there were any module dependencies, fix those now. + if len(attachedModules) > 0: + elementList = [] + + for each in attachedModules: + elementList.append([each[2], " -> parent changed from: ", each[1], " to: ", "root\n"]) + currentParent = cmds.listRelatives(each[2] + "_mover_grp", parent=True)[0] + if currentParent != "root_mover": + cmds.parentConstraint("root_mover", each[2] + "_mover_grp", mo=True) + cmds.scaleConstraint("root_mover", each[2] + "_mover_grp", mo=True) + cmds.setAttr(each[0] + ".parentModuleBone", lock=False) + cmds.setAttr(each[0] + ".parentModuleBone", "root", type="string", lock=True) + + # then, update settings UI for those dependency modules to display new parent info + modules = self.getAllModules + + if each[0] in modules: + modName = cmds.getAttr(each[0] + ".moduleName") + + for modInst in self.rigUiInst.moduleInstances: + if modInst.networkNode == each[0]: + # find the current groupBox for this module + for i in range(self.rigUiInst.moduleSettingsLayout.count()): + if type(self.rigUiInst.moduleSettingsLayout.itemAt( + i).widget()) == QtWidgets.QGroupBox: + if self.rigUiInst.moduleSettingsLayout.itemAt(i).widget().title() == modName: + self.rigUiInst.moduleSettingsLayout.itemAt(i).widget().setParent(None) + + # relaunch the skeleton settings UI with new info + modInst.skeletonSettings_UI(modName) + + # create the connection geo between the two + mover = "root_mover" + childMover = utils.findOffsetMoverFromName(each[2]) + riggingUtils.createBoneConnection(mover, childMover, each[2]) + each[3].applyModuleChanges(each[3]) + cmds.select(clear=True) + + # warn user about changes + winParent = interfaceUtils.getMainWindow() + win = interfaceUtils.DialogMessage("Attention!", + "The following modules have had their parent changed due to the change\ + in this module's structure:", + elementList, 5, winParent) + win.show() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def applyModuleChanges(self, moduleInst): + + """ + Update the scene after the settings are changed in the skeleton settings UI. + + This means also updating the created_bones attr, updating the joint mover if needed, + running self.updateNeck, updating the outliner, and updating the bone count. + + :param moduleInst: self (usually, but there are cases like templates where an inst on disc is passed in.) + """ + + networkNode = self.returnNetworkNode + + # get prefix/suffix + name = self.groupBox.title() + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + if len(prefix) > 0: + if prefix.find("_") == -1: + prefix = prefix + "_" + if len(suffix) > 0: + if suffix.find("_") == -1: + suffix = "_" + suffix + + # create list of the new created bones + joints = [] + + # get current neck value + currentNum = int(cmds.getAttr(networkNode + ".neckJoints")) + + # get new neck value + uiNeckVal = self.numNeck.value() + + if uiNeckVal != currentNum: + # update neck value, and call on update neck + cmds.setAttr(networkNode + ".neckJoints", lock=False) + cmds.setAttr(networkNode + ".neckJoints", uiNeckVal, lock=True) + + # look for any attached modules + attachedModules = self.checkForDependencies() + self.updateNeck(attachedModules, currentNum) + + for i in range(uiNeckVal): + joints.append(prefix + "neck_0" + str(i + 1) + suffix) + + joints.append(prefix + "head" + suffix) + + # build attrString + attrString = "" + for bone in joints: + attrString += bone + "::" + + networkNode = self.returnNetworkNode + cmds.setAttr(networkNode + ".Created_Bones", lock=False) + cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True) + + # reset button + self.applyButton.setEnabled(False) + + # update outliner + self.updateOutliner() + self.updateBoneCount() + + # clear selection + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def toggleButtonState(self): + + """Toggle the state of the Apply Changes button.""" + + state = self.applyButton.isEnabled() + if state is False: + self.applyButton.setEnabled(True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addJointMoverToOutliner(self): + + """ + Add the joint movers for this module to the outliner. + + Depending on the module settings, different joint movers may or may not be added. Also, each "joint" usually + has three movers: global, offset, and geo. However, not all joints do, so this method is also used to specify + which joint movers for each joint are added to the outliner. + + .. image:: /images/outliner.png + + """ + index = self.rigUiInst.treeWidget.topLevelItemCount() + + # Add the module to the tree widget in the outliner tab of the rig creator UI + self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget) + self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name) + foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground) + + # add the neck 01 + self.outlinerWidgets[self.name + "_neck_01"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_neck_01"].setText(0, self.name + "_neck_01") + self.createGlobalMoverButton(self.name + "_neck_01", self.outlinerWidgets[self.name + "_neck_01"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_neck_01", self.outlinerWidgets[self.name + "_neck_01"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_neck_01", self.outlinerWidgets[self.name + "_neck_01"], self.rigUiInst) + + # add neck 02 + self.outlinerWidgets[self.name + "_neck_02"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_neck_01"]) + self.outlinerWidgets[self.name + "_neck_02"].setText(0, self.name + "_neck_02") + self.createGlobalMoverButton(self.name + "_neck_02", self.outlinerWidgets[self.name + "_neck_02"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_neck_02", self.outlinerWidgets[self.name + "_neck_02"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_neck_02", self.outlinerWidgets[self.name + "_neck_02"], self.rigUiInst) + + # add neck 03 + self.outlinerWidgets[self.name + "_neck_03"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_neck_02"]) + self.outlinerWidgets[self.name + "_neck_03"].setText(0, self.name + "_neck_03") + self.createGlobalMoverButton(self.name + "_neck_03", self.outlinerWidgets[self.name + "_neck_03"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_neck_03", self.outlinerWidgets[self.name + "_neck_03"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_neck_03", self.outlinerWidgets[self.name + "_neck_03"], self.rigUiInst) + + # add head + self.outlinerWidgets[self.name + "_head"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_head"].setText(0, self.name + "_head") + self.createGlobalMoverButton(self.name + "_head", self.outlinerWidgets[self.name + "_head"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_head", self.outlinerWidgets[self.name + "_head"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_head", self.outlinerWidgets[self.name + "_head"], self.rigUiInst) + + # create selection script job for module + self.createScriptJob() + + # update based on spinBox values + self.updateOutliner() + self.updateBoneCount() + self.rigUiInst.treeWidget.expandAll() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateOutliner(self): + """ + Whenever changes are made to the module settings, update the outliner to show the new or removed movers + """ + + # NECK + numNeck = self.numNeck.value() + if numNeck == 1: + self.outlinerWidgets[self.originalName + "_neck_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_neck_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_neck_03"].setHidden(True) + + if numNeck == 2: + self.outlinerWidgets[self.originalName + "_neck_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_neck_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_neck_03"].setHidden(True) + + if numNeck == 3: + self.outlinerWidgets[self.originalName + "_neck_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_neck_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_neck_03"].setHidden(False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pinModule(self, state): + """ + Pin the module in place so the parent does not move the module. Each module has to define how it needs to be + pinned. + """ + networkNode = self.returnNetworkNode + topLevelMover = self.name + "_neck_01_mover_grp" + + if state: + + loc = cmds.spaceLocator()[0] + cmds.setAttr(loc + ".v", False, lock=True) + constraint = cmds.parentConstraint(topLevelMover, loc)[0] + cmds.delete(constraint) + const = cmds.parentConstraint(loc, topLevelMover)[0] + + if not cmds.objExists(networkNode + ".pinConstraint"): + cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message") + + cmds.connectAttr(const + ".message", networkNode + ".pinConstraint") + + if not state: + + connections = cmds.listConnections(networkNode + ".pinConstraint") + if len(connections) > 0: + constraint = connections[0] + cmds.delete(constraint) + + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skinProxyGeo(self): + """ + Skin the proxy geo brought in by the module. Each module has to define how it wants to skin its proxy geo. + """ + + # get the network node + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + baseName = cmds.getAttr(networkNode + ".baseName") + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + if len(prefix) > 0: + if prefix.find("_") == -1: + prefix = prefix + "_" + if len(suffix) > 0: + if suffix.find("_") == -1: + suffix = "_" + suffix + + # get this module's proxy geo meshes + cmds.select(name + "_mover_grp", hi=True) + proxyGeoMeshes = [] + selection = cmds.ls(sl=True) + for each in selection: + if each.find("proxy_geo") != -1: + parent = cmds.listRelatives(each, parent=True)[0] + if cmds.nodeType(each) == "transform": + proxyGeoMeshes.append(each) + + # skin the proxy geo meshes + for mesh in proxyGeoMeshes: + dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0] + cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False) + cmds.setAttr(dupeMesh + ".overrideDisplayType", 0) + + # create skinned geo group + if not cmds.objExists("skinned_proxy_geo"): + cmds.group(empty=True, name="skinned_proxy_geo") + + cmds.parent(dupeMesh, "skinned_proxy_geo") + + boneName = mesh.partition(name + "_")[2] + boneName = boneName.partition("_proxy_geo")[0] + joint = prefix + boneName + suffix + + if not cmds.objExists(joint): + cmds.delete(dupeMesh) + + else: + cmds.select([dupeMesh, joint]) + cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0, + normalizeWeights=True) + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildRigCustom(self, textEdit, uiInst): + """ + Build the rigs for this module. + + This method defines what rigs are built and how they are built when the asset is published. It posts any build + info to the passed in textEdit. + + :param textEdit: passed in text edit that the rig build can post updates to + :param uiInst: passed in instance of the buildProgressUI + """ + + if textEdit is not None: + textEdit.append(" Building " + self.name + " Rig..") + + # get the created joints + networkNode = self.returnNetworkNode + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + joints = self.returnCreatedJoints + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create groups and settings + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create the rig group + self.rigGrp = cmds.group(empty=True, name=self.name + "_group") + constraint = cmds.parentConstraint(parentBone, self.rigGrp)[0] + cmds.delete(constraint) + + # create the rig settings group + self.rigSettings = cmds.group(empty=True, name=self.name + "_settings") + cmds.parent(self.rigSettings, self.rigGrp) + for attr in (cmds.listAttr(self.rigSettings, keyable=True)): + cmds.setAttr(self.rigSettings + "." + attr, lock=True, keyable=False) + + # create the ctrl group (what will get the constraint to the parent) + self.rigCtrlGrp = cmds.group(empty=True, name=self.name + "_ctrl_grp") + constraint = cmds.parentConstraint(parentBone, self.rigCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(self.rigCtrlGrp, self.rigGrp) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Build the FK Neck Rig + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + fkControls = [] + self.topNode = None + + # get number of neck bones + numNeck = cmds.getAttr(networkNode + ".neckJoints") + neckJoints = [] + for i in range(len(joints) - 1): + neckJoints.append(joints[i]) + + # create FK controls for neck joints, adding space switching to base neck joint + for joint in neckJoints: + if joint == joints[0]: + data = riggingUtils.createControlFromMover(joint, networkNode, True, True) + + fkControl = cmds.rename(data[0], "fk_" + joint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp") + spaceSwitcher = cmds.rename(data[2], "fk_" + joint + "_anim_space_switcher") + spaceSwitchFollow = cmds.rename(data[3], "fk_" + joint + "_anim_space_switcher_follow") + self.topNode = spaceSwitchFollow + + fkControls.append([spaceSwitchFollow, fkControl, joint]) + # color the control + riggingUtils.colorControl(fkControl, 18) + + else: + data = riggingUtils.createControlFromMover(joint, networkNode, True, False) + + fkControl = cmds.rename(data[0], "fk_" + joint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp") + + fkControls.append([animGrp, fkControl, joint]) + + # color the control + riggingUtils.colorControl(fkControl, 18) + + # create hierarchy + fkControls.reverse() + + for i in range(len(fkControls)): + try: + cmds.parent(fkControls[i][0], fkControls[i + 1][1]) + except IndexError: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Build the FK Head Rig + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + headJoint = joints[-1] + data = riggingUtils.createControlFromMover(headJoint, networkNode, True, True) + + headControl = cmds.rename(data[0], "fk_" + headJoint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + headJoint + "_anim_grp") + spaceSwitcher = cmds.rename(data[2], "fk_" + headJoint + "_anim_space_switcher") + spaceSwitchFollow = cmds.rename(data[3], "fk_" + headJoint + "_anim_space_switcher_follow") + + # color the control + riggingUtils.colorControl(headControl, 17) + + # parent head to neck + lastNeck = fkControls[0][1] + cmds.parent(spaceSwitchFollow, lastNeck) + + fkControls.append([animGrp, headControl, headJoint]) + + # parent head rig to rigGrp + cmds.parent(self.topNode, self.rigCtrlGrp) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # lock attrs + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + for each in fkControls: + control = each[1] + if control != headControl: + for attr in [".scaleX", ".scaleY", ".globalScale", ".visibility"]: + cmds.setAttr(control + attr, lock=True, keyable=False) + else: + for attr in [".visibility"]: + cmds.setAttr(control + attr, lock=True, keyable=False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # hook up to driver skeleton + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + for each in fkControls: + control = each[1] + joint = each[2] + + cmds.pointConstraint(control, "driver_" + joint, mo=True) + cmds.orientConstraint(control, "driver_" + joint) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale + # into input 2, and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(control + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, 0, "output") + else: + riggingUtils.createConstraint(control, "driver_" + joint, "scale", False, 2, 0) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # add info to module + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + fkRigData = [] + for each in fkControls: + fkRigData.append(each[1]) + + # add created control info to module + if not cmds.objExists(networkNode + ".fkControls"): + cmds.addAttr(networkNode, ln="fkControls", dt="string") + jsonString = json.dumps(fkRigData) + cmds.setAttr(networkNode + ".fkControls", jsonString, type="string") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Parent Under Offset Ctrl # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # parent under offset_anim if it exists(it always should) + if cmds.objExists("offset_anim"): + cmds.parent(self.rigGrp, "offset_anim") + + # return data + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + try: + uiInst.rigData.append([self.rigCtrlGrp, "driver_" + parentBone, 1]) + except: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # update progress + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + if textEdit is not None: + textEdit.setTextColor(QtGui.QColor(0, 255, 18)) + textEdit.append(" SUCCESS: FK Build Complete!") + textEdit.setTextColor(QtGui.QColor(255, 255, 255)) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pickerUI(self, center, animUI, networkNode, namespace): + """ + Build the animation picker for the module. + + + :param center: the center of the QGraphicsScene + :param animUI: the instance of the AnimationUI + :param networkNode: the module's network node + :param namespace: the namespace of the character + + """ + + self.namespace = namespace + neckJoints = cmds.getAttr(networkNode + ".neckJoints") + + # create qBrushes + yellowBrush = QtCore.Qt.yellow + blueBrush = QtGui.QColor(100, 220, 255) + greenBrush = QtGui.QColor(0, 255, 30) + clearBrush = QtGui.QBrush(QtCore.Qt.black) + clearBrush.setStyle(QtCore.Qt.NoBrush) + + # create the picker border item + if networkNode.find(":") != -1: + moduleNode = networkNode.partition(":")[2] + else: + moduleNode = networkNode + + borderItem = interfaceUtils.pickerBorderItem(center.x() - 50, center.y() - 50, 100, 100, clearBrush, moduleNode) + + # get controls + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + fkControls.reverse() + buttonData = [] + + # create buttons + headButton = interfaceUtils.pickerButtonCustom(100, 100, + [[10, 60], [30, 60], [40, 40], [40, 10], [35, 5], [30, 0], + [10, 0], [5, 5], [0, 10], [0, 40], [10, 60]], [30, 5], + namespace + fkControls[0], yellowBrush, borderItem) + buttonData.append([headButton, namespace + fkControls[0], yellowBrush]) + + if neckJoints == 1: + neck1Button = interfaceUtils.pickerButtonCustom(100, 100, + [[5, 55], [8, 63], [32, 63], [35, 55], [40, 85], [0, 85], + [5, 55]], [30, 5], namespace + fkControls[1], blueBrush, + borderItem) + buttonData.append([neck1Button, namespace + fkControls[1], blueBrush]) + + if neckJoints == 2: + neck1Button = interfaceUtils.pickerButtonCustom(100, 100, + [[5, 55], [8, 63], [32, 63], [35, 55], [37, 68], [3, 68], + [5, 55]], [30, 5], namespace + fkControls[1], blueBrush, + borderItem) + buttonData.append([neck1Button, namespace + fkControls[1], blueBrush]) + + neck2Button = interfaceUtils.pickerButtonCustom(100, 100, [[3, 70], [37, 70], [40, 80], [0, 80]], [30, 5], + namespace + fkControls[2], blueBrush, borderItem) + buttonData.append([neck2Button, namespace + fkControls[2], blueBrush]) + + if neckJoints == 3: + neck1Button = interfaceUtils.pickerButtonCustom(100, 100, + [[5, 55], [8, 63], [32, 63], [35, 55], [37, 68], [3, 68], + [5, 55]], [30, 5], namespace + fkControls[1], blueBrush, + borderItem) + buttonData.append([neck1Button, namespace + fkControls[1], blueBrush]) + + neck2Button = interfaceUtils.pickerButtonCustom(100, 100, [[3, 70], [37, 70], [38, 76], [2, 76]], [30, 5], + namespace + fkControls[2], blueBrush, borderItem) + buttonData.append([neck2Button, namespace + fkControls[2], blueBrush]) + + neck3Button = interfaceUtils.pickerButtonCustom(100, 100, [[2, 78], [38, 78], [40, 84], [0, 84]], [30, 5], + namespace + fkControls[3], blueBrush, borderItem) + buttonData.append([neck3Button, namespace + fkControls[3], blueBrush]) + + # ======================================================================= + # go through button data, adding menu items + # ======================================================================= + for each in buttonData: + button = each[0] + + zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png")))) + zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png")))) + selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png")))) + + button.menu.addAction(selectIcon, "Select All Controls", partial(self.selectRigControls)) + button.menu.addSeparator() + + button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True)) + button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False)) + + # ======================================================================= + # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5) + # ======================================================================= + scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)], + kws=True) + borderItem.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + return [borderItem, False, scriptJob] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX(self, importMethod, character): + """ + Import FBX motion onto this module's rig controls. + + :param importMethod: The import method to be used (options defined in the file attributes) + :param character: the namespace of the character + + Each module has to define what import methods it offers (at the very top of the module file) and then define + how motion is imported using those methods. + """ + + returnControls = [] + + # get basic info of node + networkNode = self.returnRigNetworkNode + moduleName = cmds.getAttr(networkNode + ".moduleName") + baseModuleName = cmds.getAttr(networkNode + ".baseName") + + # find prefix/suffix of module name + prefixSuffix = moduleName.split(baseModuleName) + prefix = None + suffix = None + + if prefixSuffix[0] != '': + prefix = prefixSuffix[0] + if prefixSuffix[1] != '': + suffix = prefixSuffix[1] + + # get joints + joints = cmds.getAttr(networkNode + ".Created_Bones") + splitJoints = joints.split("::") + createdJoints = [] + + for bone in splitJoints: + if bone != "": + createdJoints.append(bone) + + # IMPORT FK + if importMethod == "FK": + + for joint in createdJoints: + if cmds.objExists(character + ":" + "fk_" + joint + "_anim"): + cmds.parentConstraint(joint, character + ":" + "fk_" + joint + "_anim") + returnControls.append(character + ":" + "fk_" + joint + "_anim") + + # IMPORT NONE + if importMethod == "None": + pass + + return returnControls diff --git a/Core/Scripts/RigModules/ART_Leaf.py b/Core/Scripts/RigModules/ART_Leaf.py new file mode 100644 index 0000000..0350d11 --- /dev/null +++ b/Core/Scripts/RigModules/ART_Leaf.py @@ -0,0 +1,1414 @@ +import json +import os +from functools import partial + +import maya.cmds as cmds + +import System.interfaceUtils as interfaceUtils +import System.utils as utils +from System.ART_RigModule import ART_RigModule +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + +# file attributes +icon = "Modules/leafJoint.png" +hoverIcon = "Modules/hover_leafJoint.png" +search = "jnt:joint:leaf" +className = "ART_Leaf" +jointMover = "Core/JointMover/ART_Leaf.ma" +baseName = "jnt" +fbxImport = ["None", "FK"] +matchData = [False, None] # This is for matching over frame range options. (Matching between rigs of the module) +controlTypes = [["leafControls", "FK"]] + + +class ART_Leaf(ART_RigModule): + def __init__(self, rigUiInst, moduleUserName): + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + + settings = QtCore.QSettings("Epic Games", "ARTv2") + self.toolsPath = settings.value("toolsPath") + + ART_RigModule.__init__(self, "ART_Leaf_Module", "ART_Leaf", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + # call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + # add custom attributes for this specific module + cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".Created_Bones", "jnt", type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".canAim", False, lock=True) + + cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".aimMode", False, lock=True) + + cmds.addAttr(self.networkNode, sn="controlType", at="enum", + en="Circle:Square:Triangle:Cube:Sphere:Cylinder:Arrow", keyable=False) + cmds.setAttr(self.networkNode + ".controlType", 0, lock=True) + + cmds.addAttr(self.networkNode, sn="proxyShape", at="enum", en="Cube:Cylinder:Capsule:Sphere:Cone", + keyable=False) + cmds.setAttr(self.networkNode + ".proxyShape", 0, lock=True) + + cmds.addAttr(self.networkNode, sn="hasDynamics", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".hasDynamics", False, lock=True) + + cmds.addAttr(self.networkNode, sn="transX", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".transX", True, lock=True) + + cmds.addAttr(self.networkNode, sn="transY", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".transY", True, lock=True) + + cmds.addAttr(self.networkNode, sn="transZ", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".transZ", True, lock=True) + + cmds.addAttr(self.networkNode, sn="rotX", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".rotX", True, lock=True) + + cmds.addAttr(self.networkNode, sn="rotY", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".rotY", True, lock=True) + + cmds.addAttr(self.networkNode, sn="rotZ", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".rotZ", True, lock=True) + + cmds.addAttr(self.networkNode, sn="scaleX", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".scaleX", True, lock=True) + + cmds.addAttr(self.networkNode, sn="scaleY", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".scaleY", True, lock=True) + + cmds.addAttr(self.networkNode, sn="scaleZ", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".scaleZ", True, lock=True) + + cmds.addAttr(self.networkNode, sn="customAttrs", dt="string", keyable=False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + + networkNode = self.returnNetworkNode + + # groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 438, True) + + font = QtGui.QFont() + font.setPointSize(8) + + headerFont = QtGui.QFont() + headerFont.setPointSize(8) + headerFont.setBold(True) + + # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot + self.mainLayout = QtWidgets.QVBoxLayout(self.groupBox) + self.frame = QtWidgets.QFrame(self.groupBox) + self.mainLayout.addWidget(self.frame) + self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) + self.frame.setMinimumSize(QtCore.QSize(320, 420)) + self.frame.setMaximumSize(QtCore.QSize(320, 420)) + + # create layout that is a child of the frame + self.layout = QtWidgets.QVBoxLayout(self.frame) + + # mirror module + self.mirrorModLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.mirrorModLayout) + self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ") + self.mirrorModuleLabel.setFont(font) + self.mirrorModLayout.addWidget(self.mirrorModuleLabel) + + mirror = cmds.getAttr(networkNode + ".mirrorModule") + if mirror == "": + mirror = "None" + self.mirrorMod = QtWidgets.QLabel(mirror) + self.mirrorMod.setFont(font) + self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter) + self.mirrorModLayout.addWidget(self.mirrorMod) + + # current parent + self.currentParentMod = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.currentParentMod) + self.currentParentLabel = QtWidgets.QLabel("Current Parent: ") + self.currentParentLabel.setFont(font) + self.currentParentMod.addWidget(self.currentParentLabel) + + parent = cmds.getAttr(networkNode + ".parentModuleBone") + self.currentParent = QtWidgets.QLabel(parent) + self.currentParent.setFont(font) + self.currentParent.setAlignment(QtCore.Qt.AlignHCenter) + self.currentParentMod.addWidget(self.currentParent) + + # button layout for name/parent + self.buttonLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.buttonLayout) + self.changeNameBtn = QtWidgets.QPushButton("Change Name") + self.changeParentBtn = QtWidgets.QPushButton("Change Parent") + self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module") + self.buttonLayout.addWidget(self.changeNameBtn) + self.buttonLayout.addWidget(self.changeParentBtn) + self.buttonLayout.addWidget(self.mirrorModuleBtn) + self.changeNameBtn.setObjectName("blueButton") + self.changeParentBtn.setObjectName("blueButton") + self.mirrorModuleBtn.setObjectName("blueButton") + + # button signal/slots + self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst)) + self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst)) + self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst)) + + # bake offsets button + self.bakeToolsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.bakeToolsLayout) + + # Bake OFfsets + self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets") + self.bakeOffsetsBtn.setFont(headerFont) + self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn) + self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets) + self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync") + self.bakeOffsetsBtn.setObjectName("blueButton") + + # settings for control shape + self.controlShapeLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.controlShapeLayout) + + self.controlShapeLabel = QtWidgets.QLabel("Control Type: ") + self.controlShapeLabel.setFont(font) + self.controlShapeLayout.addWidget(self.controlShapeLabel) + + self.controlShapeType = QtWidgets.QComboBox() + self.controlShapeLayout.addWidget(self.controlShapeType) + self.controlShapeType.addItem("Circle") + self.controlShapeType.addItem("Square") + self.controlShapeType.addItem("Triangle") + self.controlShapeType.addItem("Cube") + self.controlShapeType.addItem("Sphere") + self.controlShapeType.addItem("Cylinder") + self.controlShapeType.addItem("Arrow") + + # settings for proxy geo shape + self.proxyShapeLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.proxyShapeLayout) + + self.proxyShapeLabel = QtWidgets.QLabel("Proxy Shape: ") + self.proxyShapeLabel.setFont(font) + self.proxyShapeLayout.addWidget(self.proxyShapeLabel) + + self.proxyShapeType = QtWidgets.QComboBox() + self.proxyShapeLayout.addWidget(self.proxyShapeType) + self.proxyShapeType.addItem("Cube") + self.proxyShapeType.addItem("Cylinder") + self.proxyShapeType.addItem("Capsule") + self.proxyShapeType.addItem("Sphere") + self.proxyShapeType.addItem("Cone") + + # Rig Settings + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.layout.addItem(spacerItem) + + self.hasDynamics = QtWidgets.QCheckBox("Has Dynamics") + self.layout.addWidget(self.hasDynamics) + self.hasDynamics.setChecked(False) + self.hasDynamics.clicked.connect(partial(self.applyModuleChanges, self)) + + spacerItem = QtWidgets.QSpacerItem(20, 15, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.layout.addItem(spacerItem) + + label = QtWidgets.QLabel("Keyable Attributes:") + label.setFont(headerFont) + self.layout.addWidget(label) + + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.MinimumExpanding) + self.layout.addItem(spacerItem) + + # TRANSLATES + self.translateSettingsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.translateSettingsLayout) + + self.txAttr = QtWidgets.QCheckBox("TranslateX") + self.txAttr.setChecked(True) + self.translateSettingsLayout.addWidget(self.txAttr) + self.txAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + self.tyAttr = QtWidgets.QCheckBox("TranslateY") + self.tyAttr.setChecked(True) + self.translateSettingsLayout.addWidget(self.tyAttr) + self.tyAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + self.tzAttr = QtWidgets.QCheckBox("TranslateZ") + self.tzAttr.setChecked(True) + self.translateSettingsLayout.addWidget(self.tzAttr) + self.tzAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + # ROTATES + self.rotateSettingsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.rotateSettingsLayout) + + self.rxAttr = QtWidgets.QCheckBox("RotateX") + self.rxAttr.setChecked(True) + self.rotateSettingsLayout.addWidget(self.rxAttr) + self.rxAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + self.ryAttr = QtWidgets.QCheckBox("RotateY") + self.ryAttr.setChecked(True) + self.rotateSettingsLayout.addWidget(self.ryAttr) + self.ryAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + self.rzAttr = QtWidgets.QCheckBox("RotateZ") + self.rzAttr.setChecked(True) + self.rotateSettingsLayout.addWidget(self.rzAttr) + self.rzAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + # SCALES + self.scaleSettingsLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(self.scaleSettingsLayout) + + self.sxAttr = QtWidgets.QCheckBox("ScaleX") + self.sxAttr.setChecked(True) + self.scaleSettingsLayout.addWidget(self.sxAttr) + self.sxAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + self.syAttr = QtWidgets.QCheckBox("ScaleY") + self.syAttr.setChecked(True) + self.scaleSettingsLayout.addWidget(self.syAttr) + self.syAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + self.szAttr = QtWidgets.QCheckBox("ScaleZ") + self.szAttr.setChecked(True) + self.scaleSettingsLayout.addWidget(self.szAttr) + self.szAttr.clicked.connect(partial(self.applyModuleChanges, self)) + + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) + self.layout.addItem(spacerItem) + + # signal slot for groupbox checkbox + QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible) + self.groupBox.setChecked(False) + + # add custom attributes + buttonLayout = QtWidgets.QHBoxLayout() + self.layout.addLayout(buttonLayout) + + self.addAttrBtn = QtWidgets.QPushButton("Add Custom Attribute") + buttonLayout.addWidget(self.addAttrBtn) + self.addAttrBtn.clicked.connect(self.customAttr_UI) + + self.removeAttrBtn = QtWidgets.QPushButton("Remove Selected Attr") + buttonLayout.addWidget(self.removeAttrBtn) + self.removeAttrBtn.clicked.connect(self.removeCustomAttr) + + self.customAttrsList = QtWidgets.QListWidget() + self.layout.addWidget(self.customAttrsList) + + # add custom skeletonUI settings name, parent, rig types to install, mirror module, thigh twist, calf twists, + # ball joint, toes, + # add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + # Populate the settings UI based on the network node attributes + self.updateSettingsUI() + + # hook up combo box signals + self.controlShapeType.currentIndexChanged.connect(partial(self.changeControlShape)) + self.proxyShapeType.currentIndexChanged.connect(partial(self.changeProxyGeo)) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def removeCustomAttr(self): + + selected = self.customAttrsList.currentRow() + selectedText = json.loads(self.customAttrsList.item(selected).text()) + self.customAttrsList.takeItem(selected) + + # remove custom attr info from network node attr + networkNode = self.returnNetworkNode + newList = [] + + if cmds.objExists(networkNode + ".customAttrs"): + + data = json.loads(cmds.getAttr(networkNode + ".customAttrs")) + + if selectedText in data: + for each in data: + if each != selectedText: + newList.append(each) + + jsonString = json.dumps(newList) + cmds.setAttr(networkNode + ".customAttrs", lock=False) + cmds.setAttr(networkNode + ".customAttrs", jsonString, type="string", lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def customAttr_UI(self): + + # load stylesheet + styleSheetFile = utils.returnNicePath(self.toolsPath, "Core/Scripts/Interfaces/StyleSheets/mainScheme.qss") + f = open(styleSheetFile, "r") + self.style = f.read() + f.close() + + if cmds.window("pyART_customAttr_UI_Win", exists=True): + cmds.deleteUI("pyART_customAttr_UI_Win", wnd=True) + + # create window + self.custAttr_mainWin = QtWidgets.QMainWindow(self.rigUiInst) + self.custAttr_mainWin.setMinimumSize(300, 180) + self.custAttr_mainWin.setMaximumSize(300, 180) + self.custAttr_mainWin.setWindowTitle("Add Attribute") + self.custAttr_mainWin.setStyleSheet(self.style) + self.custAttr_mainWin.setObjectName("pyART_customAttr_UI_Win") + + # frame and layout + self.custAttr_frame = QtWidgets.QFrame() + self.custAttr_mainWin.setCentralWidget(self.custAttr_frame) + + mainLayout = QtWidgets.QVBoxLayout(self.custAttr_frame) + + # attribute name + nameLayout = QtWidgets.QHBoxLayout() + mainLayout.addLayout(nameLayout) + + label = QtWidgets.QLabel("Attribute Name:") + label.setStyleSheet("background: transparent;") + nameLayout.addWidget(label) + + self.custAttr_attrName = QtWidgets.QLineEdit() + nameLayout.addWidget(self.custAttr_attrName) + + # attribute type + typeLayout = QtWidgets.QHBoxLayout() + mainLayout.addLayout(typeLayout) + + label = QtWidgets.QLabel("Attribute Type:") + label.setStyleSheet("background: transparent;") + typeLayout.addWidget(label) + + self.custAttr_attrType = QtWidgets.QComboBox() + typeLayout.addWidget(self.custAttr_attrType) + + self.custAttr_attrType.addItem("Float") + self.custAttr_attrType.addItem("Bool") + self.custAttr_attrType.currentIndexChanged.connect(self.customAttr_UI_attrType) + + # min/max/default + valueLayout = QtWidgets.QHBoxLayout() + mainLayout.addLayout(valueLayout) + + self.custAttr_minField = QtWidgets.QLineEdit() + self.custAttr_minField.setPlaceholderText("Min") + valueLayout.addWidget(self.custAttr_minField) + + self.custAttr_maxField = QtWidgets.QLineEdit() + self.custAttr_maxField.setPlaceholderText("Max") + valueLayout.addWidget(self.custAttr_maxField) + + self.custAttr_defaultField = QtWidgets.QLineEdit() + self.custAttr_defaultField.setPlaceholderText("Default") + valueLayout.addWidget(self.custAttr_defaultField) + + # Ok/Cancel buttons + buttonLayout = QtWidgets.QHBoxLayout() + mainLayout.addLayout(buttonLayout) + + self.custAttr_AcceptBTN = QtWidgets.QPushButton("Accept") + buttonLayout.addWidget(self.custAttr_AcceptBTN) + self.custAttr_AcceptBTN.setObjectName("blueButton") + self.custAttr_AcceptBTN.clicked.connect(self.customAttr_UI_Accept) + + self.custAttr_CancelBTN = QtWidgets.QPushButton("Cancel") + buttonLayout.addWidget(self.custAttr_CancelBTN) + self.custAttr_CancelBTN.setObjectName("blueButton") + + # show window + self.custAttr_mainWin.show() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def customAttr_UI_attrType(self): + + if self.custAttr_attrType.currentText() == "Float": + self.custAttr_minField.setVisible(True) + self.custAttr_maxField.setVisible(True) + + if self.custAttr_attrType.currentText() == "Bool": + self.custAttr_minField.setVisible(False) + self.custAttr_maxField.setVisible(False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def customAttr_UI_Accept(self): + + # data list + data = [] + networkNode = self.returnNetworkNode + + # get name + name = self.custAttr_attrName.text() + try: + existingData = json.loads(cmds.getAttr(networkNode + ".customAttrs")) + + # double check that name is valid and doesn't already exist + for each in existingData: + if isinstance(each, list): + attrName = each[0] + if attrName == name: + cmds.warning("Attribute with given name already exists on this module.") + return + else: + attrName = existingData[0] + if attrName == name: + cmds.warning("Attribute with given name already exists on this module.") + return + except: + pass + + data.append(name) + + # get type + type = self.custAttr_attrType.currentText() + data.append(type) + + if type == "Float": + + # get min/max + minValue = self.custAttr_minField.text() + maxValue = self.custAttr_maxField.text() + + if minValue != "" and maxValue != "": + # validate + try: + minValue = float(minValue) + maxValue = float(maxValue) + + if minValue > maxValue: + cmds.warning("Min Value cannot be larger than the maximum value") + return + + except: + cmds.warning("Min or Max contain non-integers") + return + + data.append(minValue) + data.append(maxValue) + + # get default + defaultValue = self.custAttr_defaultField.text() + + try: + defaultValue = float(defaultValue) + + if type == "Float": + if minValue != "" and maxValue != "": + if defaultValue > maxValue or defaultValue < minValue: + cmds.warning("Default value not in range") + return + + if type == "Bool": + if defaultValue > 1 or defaultValue < 0: + cmds.warning("Default value must be a 0 or 1") + return + except: + cmds.warning("Default value is a non-integer.") + return + + data.append(defaultValue) + + # close UI + cmds.deleteUI("pyART_customAttr_UI_Win", wnd=True) + + jsonString = json.dumps(data) + + # add to list + self.customAttrsList.addItem(jsonString) + + # add to network node, get existing value + newList = [] + try: + existingData = json.loads(cmds.getAttr(networkNode + ".customAttrs")) + if len(existingData) > 0: + if isinstance(existingData[0], list): + for each in existingData: + newList.append(each) + except: + pass + + newList.append(data) + jsonString = json.dumps(newList) + cmds.setAttr(networkNode + ".customAttrs", lock=False) + cmds.setAttr(networkNode + ".customAttrs", jsonString, type="string", lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addJointMoverToOutliner(self): + + index = self.rigUiInst.treeWidget.topLevelItemCount() + + # Add the module to the tree widget in the outliner tab of the rig creator UI + self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget) + self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name) + foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground) + + # add the buttons + self.createGlobalMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst) + self.createOffsetMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst) + self.createMeshMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst) + + # create selection script job for module + self.updateBoneCount() + self.createScriptJob() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def mirrorTransformations_Custom(self): + + networkNode = self.returnNetworkNode + mirrorModule = cmds.getAttr(networkNode + ".mirrorModule") + moduleName = cmds.getAttr(networkNode + ".moduleName") + + for mover in [self.name + "_mover", self.name + "_mover_offset", self.name + "_mover_geo"]: + mirrorMover = mover.replace(moduleName, mirrorModule) + for attr in [".ty", ".tz", ".ry", ".rz"]: + value = cmds.getAttr(mirrorMover + attr) + cmds.setAttr(mirrorMover + attr, value * -1) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def applyModuleChanges(self, moduleInst, *args): + + networkNode = self.returnNetworkNode + + # translations + cmds.setAttr(networkNode + ".transX", lock=False) + cmds.setAttr(networkNode + ".transX", self.txAttr.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".transY", lock=False) + cmds.setAttr(networkNode + ".transY", self.tyAttr.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".transZ", lock=False) + cmds.setAttr(networkNode + ".transZ", self.tzAttr.isChecked(), lock=True) + + # rotations + cmds.setAttr(networkNode + ".rotX", lock=False) + cmds.setAttr(networkNode + ".rotX", self.rxAttr.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".rotY", lock=False) + cmds.setAttr(networkNode + ".rotY", self.ryAttr.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".rotZ", lock=False) + cmds.setAttr(networkNode + ".rotZ", self.rzAttr.isChecked(), lock=True) + + # scales + cmds.setAttr(networkNode + ".scaleX", lock=False) + cmds.setAttr(networkNode + ".scaleX", self.sxAttr.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".scaleY", lock=False) + cmds.setAttr(networkNode + ".scaleY", self.syAttr.isChecked(), lock=True) + + cmds.setAttr(networkNode + ".scaleZ", lock=False) + cmds.setAttr(networkNode + ".scaleZ", self.szAttr.isChecked(), lock=True) + + # dynamics + cmds.setAttr(networkNode + ".hasDynamics", lock=False) + cmds.setAttr(networkNode + ".hasDynamics", self.hasDynamics.isChecked(), lock=True) + + # shapes + cmds.setAttr(networkNode + ".controlType", lock=False) + cmds.setAttr(networkNode + ".controlType", self.controlShapeType.currentIndex(), lock=True) + + cmds.setAttr(networkNode + ".proxyShape", lock=False) + cmds.setAttr(networkNode + ".proxyShape", self.proxyShapeType.currentIndex(), lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateSettingsUI(self): + + cmds.refresh(force=True) + networkNode = self.returnNetworkNode + + # shapes + controlShape = cmds.getAttr(networkNode + ".controlType") + self.controlShapeType.setCurrentIndex(controlShape) + + proxyShape = cmds.getAttr(networkNode + ".proxyShape") + self.proxyShapeType.setCurrentIndex(proxyShape) + + # transformations + self.txAttr.setChecked(cmds.getAttr(networkNode + ".transX")) + self.tyAttr.setChecked(cmds.getAttr(networkNode + ".transY")) + self.tzAttr.setChecked(cmds.getAttr(networkNode + ".transZ")) + + self.rxAttr.setChecked(cmds.getAttr(networkNode + ".rotX")) + self.ryAttr.setChecked(cmds.getAttr(networkNode + ".rotY")) + self.rzAttr.setChecked(cmds.getAttr(networkNode + ".rotZ")) + + self.sxAttr.setChecked(cmds.getAttr(networkNode + ".scaleX")) + self.syAttr.setChecked(cmds.getAttr(networkNode + ".scaleY")) + self.szAttr.setChecked(cmds.getAttr(networkNode + ".scaleZ")) + + # has dynamics + self.hasDynamics.setChecked(cmds.getAttr(networkNode + ".hasDynamics")) + + # custom attrs + self.customAttrsList.clear() + try: + data = json.loads(cmds.getAttr(networkNode + ".customAttrs")) + + if isinstance(data[0], list): + for each in data: + jsonString = json.dumps(each) + self.customAttrsList.addItem(jsonString) + else: + jsonString = json.dumps(data) + self.customAttrsList.addItem(jsonString) + except: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def changeProxyGeo(self, *args): + + currentSelection = cmds.ls(sl=True) + + # get new proxy geo value from comboBox + newShape = self.proxyShapeType.currentText() + + # construct the path + path = os.path.join(self.toolsPath, "Core/JointMover/controls/") + fullPath = os.path.join(path, "proxy_" + newShape + ".ma") + fullPath = utils.returnFriendlyPath(fullPath) + + # import the file + cmds.file(fullPath, i=True, iv=True, type="mayaAscii", rnn=True) + + # assign materials if they exist, removing duplicate materials + materials = [["*_blue_m", "blue_m"], ["*_green_m", "green_m"], ["*_red_m", "red_m"], ["*_white_m", "white_m"], + ["*_proxy_shader_tan", "proxy_shader_tan"], ["*_proxy_shader_black", "proxy_shader_black"]] + deleteMaterials = [] + for material in materials: + try: + # select materials for the joint mover + cmds.select(material[0]) + foundMaterials = cmds.ls(sl=True) + + # loop through each color material (dupes) + for mat in foundMaterials: + cmds.hyperShade(objects=mat) + assignedGeo = cmds.ls(sl=True) + + # select the geo and the original material, and assign + originalMaterial = material[1] + for geo in assignedGeo: + cmds.select([geo, originalMaterial]) + cmds.hyperShade(assign=originalMaterial) + + # delete the material no longer needed + deleteMaterials.append(mat) + except: + pass + + # delete all deleteMaterials + for mat in deleteMaterials: + cmds.delete(mat) + + # parent under mover_geo + cmds.parent("proxy_geo", self.name + "_mover_geo", r=True) + + # delete old proxy geo + cmds.delete(self.name + "_proxy_geo") + proxy = cmds.rename("proxy_geo", self.name + "_proxy_geo") + + cmds.setAttr(proxy + ".overrideEnabled", True, lock=True) + cmds.setAttr(proxy + ".overrideDisplayType", 2) + + # apply module changes + self.applyModuleChanges(self) + + # re-select selection + cmds.select(currentSelection) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def changeControlShape(self, *args): + + currentSelection = cmds.ls(sl=True) + + # get new proxy geo value from comboBox + newShape = self.controlShapeType.currentText() + + # construct the path + path = os.path.join(self.toolsPath, "Core/JointMover/controls/") + fullPath = os.path.join(path, "shape_" + newShape + ".ma") + fullPath = utils.returnFriendlyPath(fullPath) + + # import the file + cmds.file(fullPath, i=True, iv=True, type="mayaAscii", rnn=True) + + # replace the shape node of each mover with the new ones from the file + for mover in ["_mover", "_mover_offset", "_mover_geo"]: + newMoverShape = cmds.listRelatives("shape_curve" + mover, children=True)[0] + + cmds.parent(newMoverShape, self.name + mover, r=True, shape=True) + cmds.delete(self.name + mover + "Shape") + cmds.rename(newMoverShape, self.name + mover + "Shape") + + cmds.delete("shape_curve" + mover) + + # refresh UI to capture new mover shapes and set thier visibility + self.rigUiInst.setMoverVisibility() + + # apply module changes + self.applyModuleChanges(self) + + # re-select selection + cmds.select(currentSelection) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pinModule(self, state): + + networkNode = self.returnNetworkNode + topLevelMover = self.name + "_mover" + + if state: + + loc = cmds.spaceLocator()[0] + cmds.setAttr(loc + ".v", False, lock=True) + constraint = cmds.parentConstraint(topLevelMover, loc)[0] + cmds.delete(constraint) + const = cmds.parentConstraint(loc, topLevelMover)[0] + attrs = cmds.listAttr(topLevelMover, keyable=True) + + for attr in attrs: + try: + cmds.setAttr(topLevelMover + "." + attr, keyable=False, lock=True) + except: + pass + if not cmds.objExists(networkNode + ".pinConstraint"): + cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message") + + cmds.connectAttr(const + ".message", networkNode + ".pinConstraint") + + if not state: + attrs = cmds.listAttr(topLevelMover, keyable=True) + for attr in attrs: + try: + cmds.setAttr(topLevelMover + "." + attr, lock=True) + except: + pass + + connections = cmds.listConnections(networkNode + ".pinConstraint") + if len(connections) > 0: + constraint = connections[0] + cmds.delete(constraint) + + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skinProxyGeo(self): + + # get the network node + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + baseName = cmds.getAttr(networkNode + ".baseName") + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + # get this module's proxy geo meshes + cmds.select(name + "_mover_grp", hi=True) + proxyGeoMeshes = [] + selection = cmds.ls(sl=True) + for each in selection: + if each.find("proxy_geo") != -1: + parent = cmds.listRelatives(each, parent=True)[0] + if cmds.nodeType(each) == "transform": + proxyGeoMeshes.append(each) + + # skin the proxy geo meshes + for mesh in proxyGeoMeshes: + dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0] + cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False) + cmds.setAttr(dupeMesh + ".overrideDisplayType", 0) + + # create skinned geo group + if not cmds.objExists("skinned_proxy_geo"): + cmds.group(empty=True, name="skinned_proxy_geo") + + cmds.parent(dupeMesh, "skinned_proxy_geo") + + boneName = mesh.partition(name + "_")[2] + boneName = boneName.partition("_proxy_geo")[0] + joint = name + + if not cmds.objExists(joint): + cmds.delete(dupeMesh) + + else: + cmds.select([dupeMesh, joint]) + cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0, + normalizeWeights=True) + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildRigCustom(self, textEdit, uiInst): + + if textEdit is not None: + textEdit.append(" Building " + self.name + " Rig..") + + # get the created joint + networkNode = self.returnNetworkNode + joint = cmds.getAttr(networkNode + ".Created_Bones") + joint = joint.replace("::", "") + globalMover = joint + "_mover" + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + + # determine the rigs to be built + numRigs = 1 + if cmds.getAttr(networkNode + ".hasDynamics"): + numRigs += 1 + + builtRigs = [] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create groups and settings + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create the rig group + self.rigGrp = cmds.group(empty=True, name=self.name + "_group") + constraint = cmds.parentConstraint(globalMover, self.rigGrp)[0] + cmds.delete(constraint) + + # create the rig settings group + self.rigSettings = cmds.group(empty=True, name=self.name + "_settings") + cmds.parent(self.rigSettings, self.rigGrp) + for attr in (cmds.listAttr(self.rigSettings, keyable=True)): + cmds.setAttr(self.rigSettings + "." + attr, lock=True, keyable=False) + + # add mode attribute to settings + cmds.addAttr(self.rigSettings, ln="mode", min=0, max=numRigs - 1, dv=0, keyable=True) + + # create the ctrl group (what will get the constraint to the parent) + self.rigCtrlGrp = cmds.group(empty=True, name=self.name + "_ctrl_grp") + constraint = cmds.parentConstraint(parentBone, self.rigCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(self.rigCtrlGrp, self.rigGrp) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # build the rigs + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # FK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # find the mover, duplicate it to create the rig control + dupe = cmds.duplicate(globalMover, rr=True)[0] + utils.deleteChildren(dupe) + parent = cmds.listRelatives(dupe, parent=True) + if parent is not None: + cmds.parent(dupe, world=True) + + # turn on visiblity of the control + cmds.setAttr(dupe + ".v", 1) + + # ensure pivot is correct + piv = cmds.xform(joint, q=True, ws=True, rp=True) + cmds.xform(dupe, ws=True, rp=piv) + + # rename the control + fkControl = cmds.rename(dupe, joint + "_anim") + + # create an anim group for the control + controlGrp = cmds.group(empty=True, name=joint + "_anim_grp") + constraint = cmds.parentConstraint(joint, controlGrp)[0] + cmds.delete(constraint) + + # create the space switcher group + spaceSwitchFollow = cmds.duplicate(controlGrp, po=True, name=fkControl + "_space_switcher_follow")[0] + spaceSwitch = cmds.duplicate(controlGrp, po=True, name=fkControl + "_space_switcher")[0] + + utils.deleteChildren(spaceSwitchFollow) + utils.deleteChildren(spaceSwitch) + + cmds.parent(spaceSwitch, spaceSwitchFollow) + cmds.parent(controlGrp, spaceSwitch) + + # parent the control under the controlGrp + cmds.parent(fkControl, controlGrp) + cmds.parent(spaceSwitchFollow, self.rigCtrlGrp) + + # freeze transformations on the control + cmds.makeIdentity(fkControl, t=1, r=1, s=1, apply=True) + + # color the control + cmds.setAttr(fkControl + ".overrideEnabled", 1) + cmds.setAttr(fkControl + ".overrideColor", 18) + + # constrain joint + cmds.parentConstraint(fkControl, "driver_" + joint) + cmds.scaleConstraint(fkControl, "driver_" + joint) + + # parent under offset_anim if it exists(it always should) + if cmds.objExists("offset_anim"): + cmds.parent(self.rigGrp, "offset_anim") + + # check settings and lock attributes that need locking + if not cmds.getAttr(networkNode + ".transX"): + cmds.setAttr(fkControl + ".tx", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".transY"): + cmds.setAttr(fkControl + ".ty", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".transZ"): + cmds.setAttr(fkControl + ".tz", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".rotX"): + cmds.setAttr(fkControl + ".rx", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".rotY"): + cmds.setAttr(fkControl + ".ry", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".rotZ"): + cmds.setAttr(fkControl + ".rz", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".scaleX"): + cmds.setAttr(fkControl + ".sx", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".scaleY"): + cmds.setAttr(fkControl + ".sy", lock=True, keyable=False) + + if not cmds.getAttr(networkNode + ".scaleZ"): + cmds.setAttr(fkControl + ".sz", lock=True, keyable=False) + + # lock visibility regardless + cmds.setAttr(fkControl + ".v", lock=True, keyable=False) + + # check for custom attributes and add them if they exist + try: + data = json.loads(cmds.getAttr(networkNode + ".customAttrs")) + print data + for each in data: + attrName = each[0] + attrType = each[1] + + if attrType == "Bool": + value = each[2] + + if not cmds.objExists(fkControl + "." + attrName): + cmds.addAttr(fkControl, ln=attrName, at="bool", keyable=True, dv=value) + + if attrType == "Float": + minVal = each[2] + maxVal = each[3] + hasMin = True + hasMax = True + + if minVal == '': + hasMin = False + minVal = 0 + + if maxVal == '': + hasMax = False + maxVal = 0 + + if not cmds.objExists(fkControl + "." + attrName): + + if hasMin is False and hasMax is False: + cmds.addAttr(fkControl, ln=attrName, at="float", keyable=True, dv=float(each[4])) + if hasMin is False and hasMax is True: + cmds.addAttr(fkControl, ln=attrName, at="float", keyable=True, max=float(maxVal), + dv=float(each[4])) + if hasMin is True and hasMax is False: + cmds.addAttr(fkControl, ln=attrName, at="float", keyable=True, min=float(minVal), + dv=float(each[4])) + + except Exception, e: + print e + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Dynamics # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + if cmds.getAttr(networkNode + ".hasDynamics"): + cubeGrp = cmds.group(empty=True, name=self.name + "_dyn_grp") + const = cmds.parentConstraint(joint, cubeGrp)[0] + cmds.delete(const) + cmds.parent(cubeGrp, self.rigGrp) + + # make grp pivot same as parent bone + piv = cmds.xform(parentBone, q=True, ws=True, rp=True) + cmds.xform(cubeGrp, ws=True, piv=piv) + cmds.parentConstraint("driver_" + parentBone, cubeGrp, mo=True) + + # creation: cube rigid body in same spot as leaf joint + self.rigidCube = cmds.polyCube(name=self.name + "_dyn_obj")[0] + const = cmds.parentConstraint(joint, self.rigidCube)[0] + cmds.delete(const) + + cmds.setAttr(self.rigidCube + ".v", 0, lock=True) + cmds.parent(self.rigidCube, cubeGrp) + cmds.makeIdentity(self.rigidCube, t=1, r=1, s=1, apply=True) + + # usually this is done automatically, but for some reason, this damn cube would not add the attr + # properly in the loop. so..hax + cmds.addAttr(self.rigidCube, ln="sourceModule", dt="string") + + # create the rigid body + cmds.select(self.rigidCube) + rigidBody = cmds.rigidBody(act=True, m=1, damping=0.1, staticFriction=0.2, dynamicFriction=0.2, + bounciness=0.6, layer=0, tesselationFactor=200) + + # create the spring constraint + cmds.select(self.rigidCube) + spring = cmds.constrain(spring=True, stiffness=100, damping=1.0, i=0) + cmds.refresh(force=True) + cmds.setAttr(spring + ".v", 0, lock=True) + + # position spring + pos = cmds.xform(joint, q=True, ws=True, t=True) + + cmds.setAttr(spring + ".translateX", pos[0]) + cmds.setAttr(spring + ".translateY", pos[1]) + cmds.setAttr(spring + ".translateZ", pos[2]) + cmds.refresh(force=True) + + cmds.parent(spring, "driver_" + parentBone) + + # create a group that is point constrained to the cube, but orient constrained to the parent bone + tracker = cmds.group(empty=True, name=self.name + "_dyn_tracker") + const = cmds.parentConstraint(joint, tracker)[0] + cmds.delete(const) + + cmds.parent(tracker, self.rigGrp) + cmds.pointConstraint(self.rigidCube, tracker) + orientConst = cmds.orientConstraint("driver_" + parentBone, tracker, mo=True)[0] + + # constrain joint + cmds.parentConstraint(tracker, "driver_" + joint) + cmds.scaleConstraint(tracker, "driver_" + joint) + + # add relevant settings to the settings node + cmds.addAttr(self.rigSettings, ln="mass", keyable=True, dv=1) + cmds.addAttr(self.rigSettings, ln="bounciness", keyable=True, dv=0.6, min=0, max=2) + cmds.addAttr(self.rigSettings, ln="damping", keyable=True, dv=0.97, min=-10, max=10) + cmds.addAttr(self.rigSettings, ln="springDamping", keyable=True, dv=1.0, min=-10, max=10) + cmds.addAttr(self.rigSettings, ln="springStiffness", keyable=True, dv=500, min=0) + cmds.addAttr(self.rigSettings, ln="orientToParent", keyable=True, dv=1, min=0, max=1) + + # then hook them up + cmds.connectAttr(self.rigSettings + ".mass", rigidBody + ".mass") + cmds.connectAttr(self.rigSettings + ".bounciness", rigidBody + ".bounciness") + cmds.connectAttr(self.rigSettings + ".damping", rigidBody + ".damping") + cmds.connectAttr(self.rigSettings + ".springStiffness", spring + ".springStiffness") + cmds.connectAttr(self.rigSettings + ".springDamping", spring + ".springDamping") + cmds.connectAttr(self.rigSettings + ".orientToParent", orientConst + ".driver_" + parentBone + "W0") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # SETTINGS # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # mode + if numRigs > 1: + attrData = [] + + """ CONSTRAINTS """ + # get the constraint connections on the driver joints for the leaf + connections = [] + connections.extend(list(set(cmds.listConnections("driver_" + joint, type="constraint")))) + + for connection in connections: + driveAttrs = [] + + if cmds.nodeType(connection) in ["parentConstraint", "scaleConstraint"]: + + # get those constraint target attributes for each constraint connection + targets = cmds.getAttr(connection + ".target", mi=True) + if len(targets) > 1: + for each in targets: + driveAttrs.append( + cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p=True)) + + # add this data to our master list of constraint attribute data + attrData.append(driveAttrs) + + # setup set driven keys on our moder attr and those target attributes + for i in range(numRigs): + cmds.setAttr(self.rigSettings + ".mode", i) + + # go through attr data and zero out anything but the first element in the list + for data in attrData: + for each in data: + cmds.setAttr(each[0], 0) + + cmds.setAttr(data[i][0], 1) + + # set driven keys + for data in attrData: + for each in data: + cmds.setDrivenKeyframe(each[0], cd=self.rigSettings + ".mode", itt="linear", ott="linear") + + # hook up control visibility + cmds.setAttr(self.rigSettings + ".mode", 0) + cmds.setAttr(controlGrp + ".v", 1) + cmds.setDrivenKeyframe(controlGrp, at="visibility", cd=self.rigSettings + ".mode", itt="linear", + ott="linear") + + cmds.setAttr(self.rigSettings + ".mode", 1) + cmds.setAttr(controlGrp + ".v", 0) + cmds.setDrivenKeyframe(controlGrp, at="visibility", cd=self.rigSettings + ".mode", itt="linear", + ott="linear") + + cmds.setAttr(self.rigSettings + ".mode", 0) + + controls = [fkControl] + if not cmds.objExists(networkNode + ".leafControls"): + cmds.addAttr(networkNode, ln="leafControls", dt="string") + jsonString = json.dumps(controls) + cmds.setAttr(networkNode + ".leafControls", jsonString, type="string") + + # return data + try: + uiInst.rigData.append([self.rigCtrlGrp, "driver_" + parentBone, numRigs]) + + except: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pickerUI(self, center, animUI, networkNode, namespace): + + # create qBrushes + blueBrush = QtGui.QColor(100, 220, 255) + clearBrush = QtGui.QBrush(QtCore.Qt.black) + clearBrush.setStyle(QtCore.Qt.NoBrush) + + # create border item + if networkNode.find(":") != -1: + moduleNode = networkNode.partition(":")[2] + else: + moduleNode = networkNode + borderItem = interfaceUtils.pickerBorderItem(center.x() - 40, center.y() - 70, 50, 50, clearBrush, moduleNode) + + # get controls + networkNode = self.returnNetworkNode + controls = json.loads(cmds.getAttr(networkNode + ".leafControls")) + + # anim button + button = interfaceUtils.pickerButton(30, 30, [10, 2], namespace + controls[0], blueBrush, borderItem) + button.setToolTip(self.name) + + # add right click menu to select settings + fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png")))) + button.menu.addAction(fkIcon, "Settings", partial(self.selectSettings, namespace)) + button.menu.addAction("Change Button Color", partial(self.changeButtonColor, animUI, button, borderItem, + namespace + controls[0])) + + # ======================================================================= + # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5) + # ======================================================================= + scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, + [[button, namespace + controls[0], blueBrush]])], + kws=True) + + borderItem.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + return [borderItem, False, scriptJob] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def changeButtonColor(self, animUI, button, border, control, color=None): + """ + Leaf joints give the user the option to change the button's color. This function will remove the existing + scriptJob, set the new button color, and create a new scriptJob with that information. + + :param animUI: The animation UI instance + :param button: The button whose color we wish to set. + :param border: The border item of the button that holds the scriptJob number to kill + :param control: The control this button selects. + """ + print color, control + # launch a color dialog to get a new color + if color is None: + newColor = QtGui.QColorDialog.getColor() + else: + newColor = color + + # delete the existing scriptJob + scriptJob = border.data(5) + cmds.scriptJob(kill=scriptJob) + animUI.selectionScriptJobs.remove(scriptJob) + + # set the button color + button.brush.setColor(newColor) + + # create the new scriptJob + scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, + [[button, control, newColor]])], + kws=True) + border.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def selectSettings(self, namespace): + + cmds.select(namespace + self.name + "_settings") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pasteSettings(self): + + # this shit right here is so hacky. For some reason, paste and reset have to run multiple times to get + # everything + # and I haven't taken the time to figure out why + for i in range(4): + + tempDir = cmds.internalVar(userTmpDir=True) + clipboardFile = os.path.normcase(os.path.join(tempDir, "ART_clipboard.txt")) + + if os.path.exists(clipboardFile): + # load the data + json_file = open(clipboardFile) + data = json.load(json_file) + json_file.close() + + # attempt to paste data if module type is the same + networkNode = self.returnNetworkNode + moduleType = cmds.getAttr(networkNode + ".moduleType") + if moduleType == data[0][1]: + + for each in data: + attr = each[0] + value = each[1] + attrType = str(cmds.getAttr(networkNode + "." + attr, type=True)) + + if attrType != "string": + cmds.setAttr(networkNode + "." + attr, lock=False) + cmds.setAttr(networkNode + "." + attr, value, lock=True) + + if attr == "customAttrs": + cmds.setAttr(networkNode + "." + attr, lock=False) + try: + cmds.setAttr(networkNode + "." + attr, value, type="string", lock=True) + except: + pass + + # relaunch the UI + self.updateSettingsUI() + self.applyModuleChanges(self) + else: + cmds.warning("No data in clipboard") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX(self, importMethod, character): + + returnControls = [] + + networkNode = self.returnRigNetworkNode + control = json.loads(cmds.getAttr(networkNode + ".leafControls")) + joints = cmds.getAttr(networkNode + ".Created_Bones") + joint = joints.partition("::")[0] + + if importMethod == "FK": + cmds.parentConstraint(joint, character + ":" + control[0]) + returnControls.append(character + ":" + control[0]) + + if importMethod == "None": + pass + + return returnControls diff --git a/Core/Scripts/RigModules/ART_Leg_Standard.py b/Core/Scripts/RigModules/ART_Leg_Standard.py new file mode 100644 index 0000000..75db728 --- /dev/null +++ b/Core/Scripts/RigModules/ART_Leg_Standard.py @@ -0,0 +1,3758 @@ +import maya.cmds as cmds +import os, time, json, weakref +from functools import partial + + +from System.ART_RigModule import ART_RigModule +from System import mathUtils +from System import utils +from System import riggingUtils +import System.interfaceUtils as interfaceUtils + + +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + + +#file attributes +icon = "Modules/legStandard.png" +hoverIcon = "Modules/hover_legStandard.png" +search = "biped:leg" +className = "ART_Leg_Standard" +jointMover = "Core/JointMover/ART_Leg_Standard.ma" +baseName = "leg" +rigs = ["FK::IK"] +fbxImport = ["None", "FK", "IK", "Both"] +matchData = [True, ["Match FK to IK", "Match IK to FK"]] +controlTypes = [["fkControls", "FK"], ["ikV1Controls", "IK"], ["thighTwistControls", "FK"], ["calfTwistControls", "FK"], ["toeControls", "FK"]] + +#begin class +class ART_Leg_Standard(ART_RigModule): + + _instances = set() + + def __init__(self, rigUiInst, moduleUserName): + + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + + + self.__class__._instances.add(weakref.ref(self)) + + + ART_RigModule.__init__(self, "ART_Leg_Standard_Module", "ART_Leg_Standard", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + #call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + #add custom attributes for this specific module + cmds.addAttr(self.networkNode, sn = "Created_Bones", dt = "string", keyable = False) + cmds.setAttr(self.networkNode + ".Created_Bones", "thigh::calf::foot::ball::", type = "string", lock = True) + + cmds.addAttr(self.networkNode, sn = "baseName", dt = "string", keyable = False) + cmds.setAttr(self.networkNode + ".baseName", baseName , type = "string", lock = True) + + cmds.addAttr(self.networkNode, sn = "canAim", at = "bool", keyable = False) + cmds.setAttr(self.networkNode + ".canAim", True, lock = True) + + cmds.addAttr(self.networkNode, sn = "aimMode", at = "bool", keyable = False) + cmds.setAttr(self.networkNode + ".aimMode", False, lock = True) + + #joint mover settings + cmds.addAttr(self.networkNode, sn = "thighTwists", keyable = False) + cmds.setAttr(self.networkNode + ".thighTwists", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "calfTwists", keyable = False) + cmds.setAttr(self.networkNode + ".calfTwists", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "bigToeJoints", keyable = False) + cmds.setAttr(self.networkNode + ".bigToeJoints", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "bigToeMeta", keyable = False, at = "bool") + cmds.setAttr(self.networkNode + ".bigToeMeta", False, lock = True) + + cmds.addAttr(self.networkNode, sn = "indexToeJoints", keyable = False) + cmds.setAttr(self.networkNode + ".indexToeJoints", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "indexToeMeta", keyable = False, at = "bool") + cmds.setAttr(self.networkNode + ".indexToeMeta", False, lock = True) + + cmds.addAttr(self.networkNode, sn = "middleToeJoints", keyable = False) + cmds.setAttr(self.networkNode + ".middleToeJoints", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "middleToeMeta", keyable = False, at = "bool") + cmds.setAttr(self.networkNode + ".middleToeMeta", False, lock = True) + + cmds.addAttr(self.networkNode, sn = "ringToeJoints", keyable = False) + cmds.setAttr(self.networkNode + ".ringToeJoints", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "ringToeMeta", keyable = False, at = "bool") + cmds.setAttr(self.networkNode + ".ringToeMeta", False, lock = True) + + cmds.addAttr(self.networkNode, sn = "pinkyToeJoints", keyable = False) + cmds.setAttr(self.networkNode + ".pinkyToeJoints", 0, lock = True) + + cmds.addAttr(self.networkNode, sn = "pinkyToeMeta", keyable = False, at = "bool") + cmds.setAttr(self.networkNode + ".pinkyToeMeta", False, lock = True) + + cmds.addAttr(self.networkNode, sn = "includeBall", at = "bool", keyable = False) + cmds.setAttr(self.networkNode + ".includeBall", True, lock = True) + + cmds.addAttr(self.networkNode, sn = "side", dt = "string", keyable = False) + cmds.setAttr(self.networkNode + ".side", "Left", type = "string", lock = True) + + #rig creation settings + cmds.addAttr(self.networkNode, sn = "buildFK", at = "bool", keyable = False) + cmds.setAttr(self.networkNode + ".buildFK", True, lock = True) + + cmds.addAttr(self.networkNode, sn = "buildIK_V1", at = "bool", keyable = False) + cmds.setAttr(self.networkNode + ".buildIK_V1", True, lock = True) + + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + networkNode = self.returnNetworkNode + + #groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 480, True) + + font = QtGui.QFont() + font.setPointSize(8) + + headerFont = QtGui.QFont() + headerFont.setPointSize(8) + headerFont.setBold(True) + + + #create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot + self.layout = QtWidgets.QVBoxLayout(self.groupBox) + self.frame = QtWidgets.QFrame(self.groupBox) + self.layout.addWidget(self.frame) + + self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) + self.frame.setMinimumSize(QtCore.QSize(320, 445)) + self.frame.setMaximumSize(QtCore.QSize(320, 445)) + + + #add layout for custom settings + self.customSettingsLayout = QtWidgets.QVBoxLayout(self.frame) + + #mirror module + self.mirrorModLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.mirrorModLayout) + self.mirrorModuleLabel = QtWidgets.QLabel("Mirror Module: ") + self.mirrorModuleLabel.setFont(font) + self.mirrorModLayout.addWidget(self.mirrorModuleLabel) + + mirror = cmds.getAttr(networkNode +".mirrorModule") + if mirror == "": + mirror = "None" + self.mirrorMod = QtWidgets.QLabel(mirror) + self.mirrorMod.setFont(font) + self.mirrorMod.setAlignment(QtCore.Qt.AlignHCenter) + self.mirrorModLayout.addWidget(self.mirrorMod) + + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.customSettingsLayout.addItem(spacerItem) + + #current parent + self.currentParentMod = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.currentParentMod) + self.currentParentLabel = QtWidgets.QLabel("Current Parent: ") + self.currentParentLabel.setFont(font) + self.currentParentMod.addWidget(self.currentParentLabel) + + parent = cmds.getAttr(networkNode +".parentModuleBone") + self.currentParent = QtWidgets.QLabel(parent) + self.currentParent.setFont(font) + self.currentParent.setAlignment(QtCore.Qt.AlignHCenter) + self.currentParentMod.addWidget(self.currentParent) + + + #button layout for name/parent + self.buttonLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.buttonLayout) + self.changeNameBtn = QtWidgets.QPushButton("Change Name") + self.changeParentBtn = QtWidgets.QPushButton("Change Parent") + self.mirrorModuleBtn = QtWidgets.QPushButton("Mirror Module") + self.buttonLayout.addWidget(self.changeNameBtn) + self.buttonLayout.addWidget(self.changeParentBtn) + self.buttonLayout.addWidget(self.mirrorModuleBtn) + self.changeNameBtn.setObjectName("blueButton") + self.changeParentBtn.setObjectName("blueButton") + self.mirrorModuleBtn.setObjectName("blueButton") + + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.customSettingsLayout.addItem(spacerItem) + + #add side settings + self.sideLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.sideLayout) + self.sideLabel = QtWidgets.QLabel("Side: ") + self.sideLabel.setFont(font) + self.leftSideBtn = QtWidgets.QRadioButton("Left Side") + self.rightSideBtn = QtWidgets.QRadioButton("Right Side") + self.sideLayout.addWidget(self.sideLabel) + self.sideLayout.addWidget(self.leftSideBtn) + self.sideLayout.addWidget(self.rightSideBtn) + + #get current side + if cmds.getAttr(networkNode + ".side") == "Left": + self.leftSideBtn.setChecked(True) + if cmds.getAttr(networkNode + ".side") == "Right": + self.rightSideBtn.setChecked(True) + + self.leftSideBtn.clicked.connect(self.changeSide) + self.rightSideBtn.clicked.connect(self.changeSide) + + spacerItem = QtWidgets.QSpacerItem(20, 80, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.customSettingsLayout.addItem(spacerItem) + + + #coplanar mode and bake offsets layout + self.legToolsLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.legToolsLayout) + + #Coplanar mode + self.coplanarBtn = QtWidgets.QPushButton("Coplanar Mode") + self.coplanarBtn.setFont(headerFont) + self.legToolsLayout.addWidget(self.coplanarBtn) + self.coplanarBtn.setCheckable(True) + self.coplanarBtn.clicked.connect(self.coplanarMode) + self.coplanarBtn.setToolTip("[EXPERIMENTAL] Forces leg joints to always be planar for best IK setup") + + #Bake OFfsets + self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets") + self.bakeOffsetsBtn.setFont(headerFont) + self.legToolsLayout.addWidget(self.bakeOffsetsBtn) + self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets) + self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync") + + self.coplanarBtn.setObjectName("blueButton") + self.bakeOffsetsBtn.setObjectName("blueButton") + + #Twist Bones Section + self.twistSettingsLabel = QtWidgets.QLabel("Twist Bone Settings: ") + self.twistSettingsLabel.setFont(headerFont) + self.twistSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);") + self.customSettingsLayout.addWidget(self.twistSettingsLabel) + + self.separatorA = QtWidgets.QFrame() + self.separatorA.setFrameShape(QtWidgets.QFrame.HLine) + self.separatorA.setFrameShadow(QtWidgets.QFrame.Sunken) + self.customSettingsLayout.addWidget(self.separatorA) + + #twist bones HBoxLayout + self.twistBonesLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.twistBonesLayout) + + self.twistForm = QtWidgets.QFormLayout() + self.thighTwistLabel = QtWidgets.QLabel("Thigh Twists: ") + self.thighTwistLabel.setFont(font) + self.twistForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.thighTwistLabel) + self.thighTwistNum = QtWidgets.QSpinBox() + self.thighTwistNum.setMaximum(3) + self.twistForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.thighTwistNum) + self.twistBonesLayout.addLayout(self.twistForm) + + + self.calfForm = QtWidgets.QFormLayout() + self.calfTwistLabel = QtWidgets.QLabel("Calf Twists: ") + self.calfTwistLabel.setFont(font) + self.calfForm.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.calfTwistLabel) + self.calfTwistNum = QtWidgets.QSpinBox() + self.calfTwistNum.setMaximum(3) + self.calfForm.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.calfTwistNum) + self.twistBonesLayout.addLayout(self.calfForm) + + + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.customSettingsLayout.addItem(spacerItem) + + #Feet Settings Section + self.feetSettingsLabel = QtWidgets.QLabel("Foot Settings: ") + self.feetSettingsLabel.setFont(headerFont) + self.feetSettingsLabel.setStyleSheet("color: rgb(25, 175, 255);") + self.customSettingsLayout.addWidget(self.feetSettingsLabel) + + self.separatorB = QtWidgets.QFrame() + self.separatorB.setFrameShape(QtWidgets.QFrame.HLine) + self.separatorB.setFrameShadow(QtWidgets.QFrame.Sunken) + self.customSettingsLayout.addWidget(self.separatorB) + + + self.ballJoint = QtWidgets.QCheckBox("Include Ball Joint?") + self.ballJoint.setChecked(True) + self.customSettingsLayout.addWidget(self.ballJoint) + + + #Toe Settings: add VBoxLayout + self.toeVBoxLayout = QtWidgets.QVBoxLayout() + self.customSettingsLayout.addLayout(self.toeVBoxLayout) + + #BIG TOE + self.bigToeLayout = QtWidgets.QHBoxLayout() + + self.bigToeLabel = QtWidgets.QLabel("Big Toe Joints: ") + self.bigToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.bigToeLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.bigToeLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.bigToeLayout.addWidget((self.bigToeLabel)) + + + self.bigToeNum = QtWidgets.QSpinBox() + self.bigToeNum.setMaximum(2) + self.bigToeNum.setMinimumSize(QtCore.QSize(50, 20)) + self.bigToeNum.setMaximumSize(QtCore.QSize(50, 20)) + self.bigToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.bigToeLayout.addWidget(self.bigToeNum) + + self.bigToeMeta = QtWidgets.QCheckBox("Include Metatarsal") + self.bigToeLayout.addWidget(self.bigToeMeta) + self.toeVBoxLayout.addLayout(self.bigToeLayout) + + + + #INDEX TOE + self.indexToeLayout = QtWidgets.QHBoxLayout() + + self.indexToeLabel = QtWidgets.QLabel("Index Toe Joints: ") + self.indexToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.indexToeLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.indexToeLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.indexToeLayout.addWidget((self.indexToeLabel)) + + self.indexToeNum = QtWidgets.QSpinBox() + self.indexToeNum.setMaximum(3) + self.indexToeNum.setMinimumSize(QtCore.QSize(50, 20)) + self.indexToeNum.setMaximumSize(QtCore.QSize(50, 20)) + self.indexToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.indexToeLayout.addWidget((self.indexToeNum)) + + self.indexToeMeta = QtWidgets.QCheckBox("Include Metatarsal") + self.indexToeLayout.addWidget(self.indexToeMeta) + self.toeVBoxLayout.addLayout(self.indexToeLayout) + + #MIDDLE TOE + self.middleToeLayout = QtWidgets.QHBoxLayout() + + self.middleToeLabel = QtWidgets.QLabel("Middle Toe Joints: ") + self.middleToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.middleToeLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.middleToeLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.middleToeLayout.addWidget(self.middleToeLabel) + + self.middleToeNum = QtWidgets.QSpinBox() + self.middleToeNum.setMaximum(3) + self.middleToeNum.setMinimumSize(QtCore.QSize(50, 20)) + self.middleToeNum.setMaximumSize(QtCore.QSize(50, 20)) + self.middleToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.middleToeLayout.addWidget(self.middleToeNum) + + self.middleToeMeta = QtWidgets.QCheckBox("Include Metatarsal") + self.middleToeLayout.addWidget(self.middleToeMeta) + self.toeVBoxLayout.addLayout(self.middleToeLayout) + + #RING TOE + self.ringToeLayout = QtWidgets.QHBoxLayout() + + self.ringToeLabel = QtWidgets.QLabel("Ring Toe Joints: ") + self.ringToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.ringToeLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.ringToeLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.ringToeLayout.addWidget(self.ringToeLabel) + + self.ringToeNum = QtWidgets.QSpinBox() + self.ringToeNum.setMaximum(3) + self.ringToeNum.setMinimumSize(QtCore.QSize(50, 20)) + self.ringToeNum.setMaximumSize(QtCore.QSize(50, 20)) + self.ringToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.ringToeLayout.addWidget(self.ringToeNum) + + self.ringToeMeta = QtWidgets.QCheckBox("Include Metatarsal") + self.ringToeLayout.addWidget(self.ringToeMeta) + self.toeVBoxLayout.addLayout(self.ringToeLayout) + + + #PINKY TOE + self.pinkyToeLayout = QtWidgets.QHBoxLayout() + + self.pinkyToeLabel = QtWidgets.QLabel("Pinky Toe Joints: ") + self.pinkyToeLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.pinkyToeLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.pinkyToeLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.pinkyToeLayout.addWidget(self.pinkyToeLabel) + + self.pinkyToeNum = QtWidgets.QSpinBox() + self.pinkyToeNum.setMaximum(3) + self.pinkyToeNum.setMinimumSize(QtCore.QSize(50, 20)) + self.pinkyToeNum.setMaximumSize(QtCore.QSize(50, 20)) + self.pinkyToeNum.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.pinkyToeLayout.addWidget(self.pinkyToeNum) + + self.pinkyToeMeta = QtWidgets.QCheckBox("Include Metatarsal") + self.pinkyToeLayout.addWidget(self.pinkyToeMeta) + self.toeVBoxLayout.addLayout(self.pinkyToeLayout) + + + #rebuild button + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.customSettingsLayout.addItem(spacerItem) + + self.applyButton = QtWidgets.QPushButton("Apply Changes") + self.customSettingsLayout.addWidget(self.applyButton) + self.applyButton.setFont(headerFont) + self.applyButton.setMinimumSize(QtCore.QSize(300, 40)) + self.applyButton.setMaximumSize(QtCore.QSize(300, 40)) + self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.applyButton.setEnabled(False) + + + + #SIGNALS/SLOTS + + #signal slot for groupbox checkbox + QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible) + self.groupBox.setChecked(False) + + #button signal/slots + self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst)) + self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst)) + self.mirrorModuleBtn.clicked.connect(partial(self.setMirrorModule, self, self.rigUiInst)) + self.applyButton.clicked.connect(partial(self.applyModuleChanges, self)) + + #spinBox & checkbox signal/slots + self.thighTwistNum.valueChanged.connect(self.toggleButtonState) + self.calfTwistNum.valueChanged.connect(self.toggleButtonState) + self.bigToeNum.valueChanged.connect(self.toggleButtonState) + self.indexToeNum.valueChanged.connect(self.toggleButtonState) + self.middleToeNum.valueChanged.connect(self.toggleButtonState) + self.ringToeNum.valueChanged.connect(self.toggleButtonState) + self.pinkyToeNum.valueChanged.connect(self.toggleButtonState) + self.ballJoint.stateChanged.connect(self.toggleButtonState) + self.ballJoint.stateChanged.connect(partial(self.includeBallJoint, True)) + + self.pinkyToeMeta.stateChanged.connect(self.toggleButtonState) + self.ringToeMeta.stateChanged.connect(self.toggleButtonState) + self.middleToeMeta.stateChanged.connect(self.toggleButtonState) + self.indexToeMeta.stateChanged.connect(self.toggleButtonState) + self.bigToeMeta.stateChanged.connect(self.toggleButtonState) + + #add custom skeletonUI settings name, parent, rig types to install, mirror module, thigh twist, calf twists, ball joint, toes, + #add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + #Populate the settings UI based on the network node attributes + self.updateSettingsUI() + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pickerUI(self, center, animUI, networkNode, namespace): + + self.namespace = namespace + + #create qBrushes + yellowBrush = QtCore.Qt.yellow + blueBrush = QtGui.QColor(100,220,255) + purpleBrush = QtGui.QColor(111,48,161) + greenBrush = QtGui.QColor(0,255,30) + clearBrush = QtGui.QBrush(QtCore.Qt.black) + clearBrush.setStyle(QtCore.Qt.NoBrush) + side = cmds.getAttr(networkNode + ".side") + + #create the picker border item + if networkNode.find(":") != -1: + moduleNode = networkNode.partition(":")[2] + else: + moduleNode = networkNode + + borderItem = interfaceUtils.pickerBorderItem(center.x() - 75, center.y() - 130, 150, 260, clearBrush, moduleNode) + + #get controls + ikControls = json.loads(cmds.getAttr(networkNode + ".ikV1Controls")) #["ik_foot_anim", "leg_heel_ctrl", "leg_toe_tip_ctrl", "leg_toe_wiggle_ctrl"] + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) #["fk_thigh_anim", "fk_calf_anim", "fk_foot_anim", "fk_ball_anim"] + thighTwistControls = json.loads(cmds.getAttr(networkNode + ".thighTwistControls")) + calfTwistControls = json.loads(cmds.getAttr(networkNode + ".calfTwistControls")) + + buttonData = [] + controls = [] + + #ik buttons + ikFootBtn = interfaceUtils.pickerButton(30, 30, [30,225], namespace + ikControls[0], yellowBrush, borderItem) + buttonData.append([ikFootBtn, namespace + ikControls[0], yellowBrush]) + controls.append(namespace + ikControls[0]) + + + + ikHeelBtn = interfaceUtils.pickerButton(20, 20, [5,235], namespace + ikControls[1], yellowBrush, borderItem) + buttonData.append([ikHeelBtn, namespace + ikControls[1], yellowBrush]) + controls.append(namespace + ikControls[1]) + + ikToeTipBtn = interfaceUtils.pickerButton(20, 20, [135,235], namespace + ikControls[2], yellowBrush, borderItem) + buttonData.append([ikToeTipBtn, namespace + ikControls[2], yellowBrush]) + controls.append(namespace + ikControls[2]) + + ikToeWiggleBtn = interfaceUtils.pickerButton(20, 20, [97,200], namespace + ikControls[3], yellowBrush, borderItem) + buttonData.append([ikToeWiggleBtn, namespace + ikControls[3], yellowBrush]) + controls.append(namespace + ikControls[3]) + + #fk buttons + fkThighBtn = interfaceUtils.pickerButton(30, 100, [30,10], namespace + fkControls[0], blueBrush, borderItem) + buttonData.append([fkThighBtn, namespace + fkControls[0], blueBrush]) + controls.append(namespace + fkControls[0]) + + fkCalfBtn = interfaceUtils.pickerButton(30, 90, [30,122], namespace + fkControls[1], blueBrush, borderItem) + buttonData.append([fkCalfBtn, namespace + fkControls[1], blueBrush]) + controls.append(namespace + fkControls[1]) + + fkFootBtn = interfaceUtils.pickerButton(30, 30, [62,225], namespace + fkControls[2], blueBrush, borderItem) + buttonData.append([fkFootBtn, namespace + fkControls[2], blueBrush]) + controls.append(namespace + fkControls[2]) + + if len(fkControls) == 4: + fkBallBtn = interfaceUtils.pickerButton(30, 30, [97,225], namespace + fkControls[3], blueBrush, borderItem) + buttonData.append([fkBallBtn, namespace + fkControls[3], blueBrush]) + controls.append(namespace + fkControls[3]) + + #thigh twists + if thighTwistControls != None: + if len(thighTwistControls) > 0: + y = 20 + for i in range(len(thighTwistControls)): + button = interfaceUtils.pickerButton(20, 20, [5, y], namespace + thighTwistControls[i], purpleBrush, borderItem) + buttonData.append([button, namespace + thighTwistControls[i], purpleBrush]) + controls.append(namespace + thighTwistControls[i]) + y = y + 30 + + + if calfTwistControls != None: + if len(calfTwistControls) > 0: + y = 192 + for i in range(len(calfTwistControls)): + button = interfaceUtils.pickerButton(20, 20, [5, y], namespace + calfTwistControls[i], purpleBrush, borderItem) + buttonData.append([button, namespace + calfTwistControls[i], purpleBrush]) + controls.append(namespace + calfTwistControls[i]) + y = y - 30 + + + + + #======================================================================= + # #TOES !!!! THIS IS A SUB-PICKER !!!! + #======================================================================= + + #if there are toes, create a toe picker + toeControls = json.loads(cmds.getAttr(networkNode + ".toeControls")) + if len(toeControls) > 0: + + name = cmds.getAttr(networkNode + ".moduleName") + toeBorder = interfaceUtils.pickerBorderItem(center.x() + 35, center.y() - 75, 100, 100, clearBrush, moduleNode, name + "_toes") + toeBorder.setParentItem(borderItem) + interfaceUtils.addTextToButton(side[0] + "_Toes", toeBorder, False, True, False) + + + #create selection set lists + bigToes = [] + indexToes = [] + middleToes = [] + ringToes = [] + pinkyToes = [] + + metaTarsals = [] + distalKnuckles = [] + middleKnuckles = [] + proximalKnuckles = [] + + #BIG TOE + for toe in toeControls: + if toe.find("bigtoe_metatarsal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20,75], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + bigToes.append(namespace + toe) + metaTarsals.append(namespace + toe) + + if toe.find("bigtoe_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20,40], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + bigToes.append(namespace + toe) + proximalKnuckles.append(namespace + toe) + + if toe.find("bigtoe_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [20,25], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + bigToes.append(namespace + toe) + distalKnuckles.append(namespace + toe) + + + #INDEX TOE + if toe.find("index_metatarsal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35,75], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + indexToes.append(namespace + toe) + metaTarsals.append(namespace + toe) + + if toe.find("index_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35,55], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + indexToes.append(namespace + toe) + proximalKnuckles.append(namespace + toe) + + if toe.find("index_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [35,40], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + indexToes.append(namespace + toe) + middleKnuckles.append(namespace + toe) + + if toe.find("index_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [35,25], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + indexToes.append(namespace + toe) + distalKnuckles.append(namespace + toe) + + + #MIDDLE TOE + if toe.find("middle_metatarsal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50,75], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + middleToes.append(namespace + toe) + metaTarsals.append(namespace + toe) + + if toe.find("middle_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50,55], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + middleToes.append(namespace + toe) + proximalKnuckles.append(namespace + toe) + + if toe.find("middle_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [50,40], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + middleToes.append(namespace + toe) + middleKnuckles.append(namespace + toe) + + if toe.find("middle_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [50,25], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + middleToes.append(namespace + toe) + distalKnuckles.append(namespace + toe) + + + #RING TOE + if toe.find("ring_metatarsal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65,75], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + ringToes.append(namespace + toe) + metaTarsals.append(namespace + toe) + + if toe.find("ring_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65,55], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + ringToes.append(namespace + toe) + proximalKnuckles.append(namespace + toe) + + if toe.find("ring_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [65,40], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + ringToes.append(namespace + toe) + middleKnuckles.append(namespace + toe) + + if toe.find("ring_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [65,25], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + ringToes.append(namespace + toe) + distalKnuckles.append(namespace + toe) + + + #PINKY TOE + if toe.find("pinky_metatarsal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80,75], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + pinkyToes.append(namespace + toe) + metaTarsals.append(namespace + toe) + + if toe.find("pinky_proximal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80,55], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + pinkyToes.append(namespace + toe) + proximalKnuckles.append(namespace + toe) + + if toe.find("pinky_middle") != -1: + button = interfaceUtils.pickerButton(10, 10, [80,40], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + pinkyToes.append(namespace + toe) + middleKnuckles.append(namespace + toe) + + if toe.find("pinky_distal") != -1: + button = interfaceUtils.pickerButton(10, 10, [80,25], namespace + toe, blueBrush, toeBorder) + buttonData.append([button, namespace + toe, blueBrush]) + controls.append(namespace + toe) + pinkyToes.append(namespace + toe) + distalKnuckles.append(namespace + toe) + + + #TOE MASS SELECT BUTTONS + interfaceUtils.pickerButtonAll(10, 10, [5,75], metaTarsals, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [5,55], proximalKnuckles, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [5,40], middleKnuckles, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [5,25], distalKnuckles, greenBrush, toeBorder) + + interfaceUtils.pickerButtonAll(10, 10, [20,5], bigToes, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [35,5], indexToes, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [50,5], middleToes, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [65,5], ringToes, greenBrush, toeBorder) + interfaceUtils.pickerButtonAll(10, 10, [80,5], pinkyToes, greenBrush, toeBorder) + + + + + + + #settings button + settingsBtn = interfaceUtils.pickerButton(20, 20, [65,40], namespace + self.name + "_settings", greenBrush, borderItem) + buttonData.append([settingsBtn, namespace + ":" + self.name + "_settings", greenBrush]) + controls.append(namespace + ":" + self.name + "_settings") + interfaceUtils.addTextToButton("S", settingsBtn) + + + #go through button data, adding menu items + for each in buttonData: + button = each[0] + + fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png")))) + ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png")))) + zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png")))) + zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png")))) + selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png")))) + + switchAction = QtWidgets.QAction('Match when Switching', button.menu) + switchAction.setCheckable(True) + switchAction.setChecked(True) + + button.menu.addAction(selectIcon, "Select All Leg Controls", partial(self.selectRigControls, "all")) + button.menu.addAction(selectIcon, "Select FK Leg Controls", partial(self.selectRigControls, "fk")) + button.menu.addAction(selectIcon, "Select IK Leg Controls", partial(self.selectRigControls, "ik")) + button.menu.addSeparator() + + button.menu.addAction(fkIcon, "FK Mode", partial(self.switchMode, "FK", switchAction)) + button.menu.addAction(ikIcon, "IK Mode", partial(self.switchMode, "IK", switchAction)) + button.menu.addAction(switchAction) + + button.menu.addSeparator() + button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True)) + button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False)) + + + #select all button + interfaceUtils.pickerButtonAll(20, 20, [65,10], controls, greenBrush, borderItem) + + + #======================================================================= + # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5) + #======================================================================= + scriptJob = cmds.scriptJob(event = ["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)], kws = True) + borderItem.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + #return data and set to mirror if side is right + if side == "Right": + return [borderItem, True, scriptJob] + else: + return [borderItem, False, scriptJob] + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildRigCustom(self, textEdit, uiInst): + + """ + The base class gets a buildRig function called from the buildProgressUI. This function has some pre/post functionality that labels new nodes created by the buildRigCustom + method. Each derived class will need to have a buildRigCustom implemented. This method should call on any rig building functions for that module. + + -each module should have its own settings group : self.name + "_settings" + -each module should have something similar to the builtRigs list, which is a list that holds what rigs have been built (NOT, which are going to BE built, but the ones that already have) + -this list looks something like this: [["FK", [nodesToHide]],["IK", [nodesToHide]]] + -this is used when it's time to setup the mode switching + -each module should also, at the very least, write to an attribute, what controls have been created for that module. + -right now, I have it as 2 attrs on the leg. This should probably just be changed to 1 controls attr, or keep what I have and add the controls attr which combines the previous? + -This would made looking up controls per module consistent, but may not be necessary? + """ + #TO DO: investigate if controls attrs should be made consistent across all modules + + + #get the network node and find out which rigs to build + networkNode = self.returnNetworkNode + buildFK = True + buildIK_V1 = True + + #have it build all rigs by default, unless there is an attr stating otherwise (backwards- compatability) + numRigs = 0 + if cmds.objExists(networkNode + ".buildFK"): + buildFK = cmds.getAttr(networkNode + ".buildFK") + if buildFK: + numRigs += 1 + if cmds.objExists(networkNode + ".buildIK_V1"): + buildIK_V1 = cmds.getAttr(networkNode + ".buildIK_V1") + if buildIK_V1: + numRigs += 1 + + + #find the joints in the leg module that need rigging + joints = self.getMainLegJoints() + + builtRigs = [] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + #create groups and settings + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + #create the leg group + legJoints = self.getMainLegJoints() + self.legGroup = cmds.group(empty = True, name = self.name + "_group") + constraint = cmds.parentConstraint(legJoints[0], self.legGroup)[0] + cmds.delete(constraint) + + #create the leg settings group + self.legSettings = cmds.group(empty = True, name = self.name + "_settings") + cmds.parent(self.legSettings, self.legGroup) + for attr in(cmds.listAttr(self.legSettings, keyable = True)): + cmds.setAttr(self.legSettings + "." + attr, lock = True, keyable = False) + + #add mode attribute to settings + if numRigs > 1: + cmds.addAttr(self.legSettings, ln = "mode", min = 0, max = numRigs - 1, dv = 0, keyable = True) + + #create the ctrl group (what will get the constraint to the parent) + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + self.legCtrlGrp = cmds.group(empty = True, name = self.name + "_leg_ctrl_grp") + constraint = cmds.parentConstraint(parentBone, self.legCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(self.legCtrlGrp, self.legGroup) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + #build the rigs + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # FK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + #if build FK was true, build the FK rig now + if buildFK: + + #update progress + if textEdit != None: + textEdit.append(" Starting FK Rig Build..") + + #build the rig + slot = len(builtRigs) + fkRigData = riggingUtils.createFkRig(joints, networkNode, numRigs, slot) + self.topNode = fkRigData[0] + + builtRigs.append(["FK", [self.topNode]]) + + #parent top node into leg group + if self.topNode != None: + cmds.parent(self.topNode, self.legCtrlGrp) + + #lock attrs + for each in fkRigData[1]: + for attr in [".scaleX", ".scaleY",".scaleZ", ".visibility"]: + cmds.setAttr(each + attr, lock = True, keyable = False) + + #add created control info to module + if not cmds.objExists(networkNode + ".fkControls"): + cmds.addAttr(networkNode, ln = "fkControls", dt = "string") + jsonString = json.dumps(fkRigData[1]) + cmds.setAttr(networkNode + ".fkControls", jsonString, type = "string") + + #update progress + if textEdit != None: + textEdit.setTextColor(QtGui.QColor(0,255,18)) + textEdit.append(" SUCCESS: FK Build Complete!") + textEdit.setTextColor(QtGui.QColor(255,255,255)) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # IK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + #if build IK was true, build the IK rig now + if buildIK_V1: + + #update progress + if textEdit != None: + textEdit.append(" Starting IK (version 1) Rig Build..") + + #build the rig + slot = len(builtRigs) + ikInfo = self.buildIkRig(numRigs, slot) + builtRigs.append(["IK", [self.ikFootCtrl + "_grp", ikInfo[1]]]) + + + #lock attributes on controls + for each in ikInfo[0]: + for attr in [".visibility", ".scaleX", ".scaleY", ".scaleZ"]: + cmds.setAttr(each + attr, lock = True, keyable = False) + + if each != self.ikFootCtrl: + for attr in [".translateX", ".translateY", ".translateZ"]: + cmds.setAttr(each + attr, lock = True, keyable = False) + + #add created control info to module + if not cmds.objExists(networkNode + ".ikV1Controls"): + cmds.addAttr(networkNode, ln = "ikV1Controls", dt = "string") + jsonString = json.dumps(ikInfo[0]) + cmds.setAttr(networkNode + ".ikV1Controls", jsonString, type = "string") + + #update progress + if textEdit != None: + textEdit.setTextColor(QtGui.QColor(0,255,18)) + textEdit.append(" SUCCESS: IK Build Complete!") + textEdit.setTextColor(QtGui.QColor(255,255,255)) + + + + #=================================================================== + # #create thigh twist rig + #=================================================================== + twistJoints = self.getLegTwistJoints(True, False) + twistCtrls = riggingUtils.createCounterTwistRig(twistJoints, self.name, networkNode, legJoints[0], legJoints[1], self.name + "_group") + + if not cmds.objExists(networkNode + ".thighTwistControls"): + cmds.addAttr(networkNode, ln = "thighTwistControls", dt = "string" ) + jsonString = json.dumps(twistCtrls) + cmds.setAttr(networkNode + ".thighTwistControls", jsonString, type = "string") + + #create calf twist rig + twistJoints = self.getLegTwistJoints(False, True) + twistCtrls = riggingUtils.createTwistRig(twistJoints, self.name, networkNode, legJoints[1], legJoints[2], self.name + "_group") + + if not cmds.objExists(networkNode + ".calfTwistControls"): + cmds.addAttr(networkNode, ln = "calfTwistControls", dt = "string" ) + jsonString = json.dumps(twistCtrls) + cmds.setAttr(networkNode + ".calfTwistControls", jsonString, type = "string") + + #======================================================================= + # # #build toe rigs (if needed) + #======================================================================= + prefix = self.name.partition(baseName)[0] + suffix = self.name.partition(baseName)[2] + + #lists of toe joints + bigToeJoints = ["proximal_phalange", "distal_phalange"] + toeJoints = ["proximal_phalange", "middle_phalange", "distal_phalange"] + + + #loop through our toe attrs, building the toe rig as we go + for attr in [[".bigToeJoints", "bigtoe", ".bigToeMeta"], [".indexToeJoints", "index", ".indexToeMeta"], [".middleToeJoints", "middle", ".middleToeMeta"], [".ringToeJoints", "ring", ".ringToeMeta"], [".pinkyToeJoints", "pinky", ".pinkyToeMeta"]]: + metaValue = cmds.getAttr(networkNode + attr[2]) + + value = cmds.getAttr(networkNode + attr[0]) + toes = [] + + if metaValue: + toes.append(prefix + attr[1] + "_metatarsal" + suffix) + + if attr[0] != ".bigToeJoints": + for i in range(int(value)): + toes.append(prefix + attr[1] + "_" + toeJoints[i] + suffix) + + #build toe rigs + self.buildToeRigs(toes) + + else: + for i in range(int(value)): + toes.append(prefix + attr[1] + "_" + bigToeJoints[i] + suffix) + #build toe rigs + self.buildToeRigs(toes) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + #hook up settings + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + #mode + if numRigs > 1: + attrData = [] + rampData = [] + + """ CONSTRAINTS """ + #get the constraint connections on the driver joints for the legs + connections = [] + for joint in legJoints: + connections.extend(list(set(cmds.listConnections("driver_" + joint, type = "constraint")))) + ramps = (list(set(cmds.listConnections("driver_" + joint, type = "ramp")))) + for ramp in ramps: + connections.append(ramp + ".uCoord") + + + for connection in connections: + driveAttrs = [] + + if cmds.nodeType(connection) in ["pointConstraint", "orientConstraint"]: + + #get those constraint target attributes for each constraint connection + targets = cmds.getAttr(connection + ".target", mi = True) + if len(targets) > 1: + for each in targets: + driveAttrs.append(cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", p = True)) + + #add this data to our master list of constraint attribute data + attrData.append(driveAttrs) + else: + if cmds.nodeType(connection) == "ramp": + rampData.append(connection) + + rampData = list(set(rampData)) + + + #setup set driven keys on our moder attr and those target attributes + for i in range(numRigs): + + cmds.setAttr(self.legSettings + ".mode", i) + + #go through attr data and zero out anything but the first element in the list + for data in attrData: + for each in data: + cmds.setAttr(each[0], 0) + + cmds.setAttr(data[i][0], 1) + + #set driven keys + for data in attrData: + for each in data: + cmds.setDrivenKeyframe(each[0], cd = self.legSettings + ".mode", itt = "linear", ott = "linear") + + """ RAMPS """ + #direct connect mode to uCoord value (only works if there are 2 rigs...) <- not sure if that is the case still + for data in rampData: + #create a multiply node that takes first input of 1/numRigs and 2nd of mode direct connection + multNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_" + data.partition(".uCoord")[0] + "_mult") + cmds.setAttr(multNode + ".input1X", float(float(1)/float(numRigs - 1))) + cmds.connectAttr(self.legSettings + ".mode", multNode + ".input2X") + cmds.connectAttr(multNode + ".outputX", data) + + + """ + builtRigs is a list of the rigs that have been built, but each element has the label of what rig was built, and nodes to hide as the second element, + like so: ["FK", [topNode]] + -the second element is a list of nodes. for FK, there is only 1 item in this list. + + each element in the builtRigs list should coincide with the mode #, so if FK is element 0 in built rigs, mode 0 should be FK. + """ + #hook up control visibility + for i in range(len(builtRigs)): + cmds.setAttr(self.legSettings + ".mode", i) + for rig in builtRigs: + visNodes = rig[1] + for node in visNodes: + if node != None: + cmds.setAttr(node + ".v", 0) + + if builtRigs.index(rig) == i: + visNodes = rig[1] + for node in visNodes: + if node != None: + cmds.setAttr(node + ".v", 1) + + + cmds.setDrivenKeyframe(visNodes, at = "visibility", cd = self.legSettings + ".mode", itt = "linear", ott = "linear") + + + + + #parent under offset_anim if it exists(it always should) + if cmds.objExists("offset_anim"): + cmds.parent(self.legGroup, "offset_anim") + + #return data + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + try: + uiInst.rigData.append([self.legCtrlGrp, "driver_" + parentBone, numRigs]) + except: + pass + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildIkRig(self, numRigs, slot): + + networkNode = self.returnNetworkNode + + #get main leg joints to duplicate for IK leg rig + legJoints = self.getMainLegJoints() + + self.ikThigh = cmds.duplicate(legJoints[0], po = True, name = "ikV1_" + legJoints[0] + "_joint")[0] + self.ikCalf = cmds.duplicate(legJoints[1], po = True, name = "ikV1_" + legJoints[1] + "_joint")[0] + self.ikFoot = cmds.duplicate(legJoints[2], po = True, name = "ikV1_" + legJoints[2] + "_joint")[0] + + + for joint in [self.ikThigh, self.ikCalf, self.ikFoot]: + parent = cmds.listRelatives(joint, parent = True) + if parent != None: + cmds.parent(joint, world = True) + + #create heirarchy + cmds.parent(self.ikFoot, self.ikCalf) + cmds.parent(self.ikCalf, self.ikThigh) + + #freeze rotates + cmds.makeIdentity(self.ikThigh, t = 0, r = 1, s = 0, apply = True) + + #hook up driver joints to these ik joints + i = 0 + for joint in [self.ikThigh, self.ikCalf, self.ikFoot]: + cmds.pointConstraint(joint, "driver_" + legJoints[i]) + cmds.orientConstraint(joint, "driver_" + legJoints[i]) + + + #plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = legJoints[i] + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(joint + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + legJoints[i], "scale", False, numRigs, slot, "output") + else: + riggingUtils.createConstraint(joint, "driver_" + legJoints[i], "scale", False, numRigs, slot) + + + cmds.setAttr(joint + ".v", 0, lock = True) + i += 1 + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create the no-flip setup # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # 1.) Create the No-Flip Bone Chain + noFlipBegin = cmds.createNode("joint", name = self.name + "_noFlip_begin_joint") + noFlipEnd = cmds.createNode("joint", name = self.name + "_noFlip_end_joint") + noFlipGrp = cmds.group(empty = True, name = self.name + "_noFlip_joints_grp") + + cmds.setAttr(noFlipBegin + ".v", 0, lock = True) + cmds.setAttr(noFlipEnd + ".v", 0, lock = True) + cmds.parent(noFlipEnd, noFlipBegin) + + + constraint = cmds.parentConstraint(self.ikThigh, noFlipGrp)[0] + cmds.delete(constraint) + constraint = cmds.parentConstraint(self.ikThigh, noFlipBegin)[0] + cmds.delete(constraint) + constraint = cmds.parentConstraint(self.ikFoot, noFlipEnd)[0] + cmds.delete(constraint) + + #zero out all but tx on noFlipEnd + cmds.setAttr(noFlipEnd + ".ty", 0) + cmds.setAttr(noFlipEnd + ".tz", 0) + + + cmds.parent(noFlipBegin, noFlipGrp) + cmds.makeIdentity(noFlipBegin, t = 0, r = 1, s = 0, apply = True) + + #set the preferred angle + cmds.setAttr(noFlipBegin + ".preferredAngleZ", 90) + + + # 2.) create target loc/grp + targetGrp = cmds.group(empty = True, name = self.name + "_noFlip_target_grp") + targetLoc = cmds.spaceLocator(name = self.name + "_noFlip_target_loc")[0] + cmds.setAttr(targetLoc + ".v", 0, lock = True) + + cmds.parent(targetLoc, targetGrp) + + constraint = cmds.pointConstraint(noFlipBegin, targetGrp)[0] + cmds.delete(constraint) + constraint = cmds.pointConstraint(noFlipEnd, targetLoc)[0] + cmds.delete(constraint) + + # 3.) create the aim loc/grp + aimNodes = cmds.duplicate(targetGrp, name = self.name + "_noFlip_aim_grp", rc = True) + aimGrp = aimNodes[0] + aimLoc = aimNodes[1] + aimLoc = cmds.rename(aimLoc, self.name + "_noFlip_aim_loc") + + #find the world position of the aimGrp + worldPos = cmds.xform(aimGrp, q = True, ws = True, t = True) + + #find the bone length of the noFlip chain + length = cmds.getAttr(noFlipEnd + ".tx") + + #now create the world position of where the aim locator needs to be + if worldPos[0] >= 0: + aimLocPos = [worldPos[0] + abs(length), worldPos[1], worldPos[2]] + if worldPos[0] < 0: + aimLocPos = [(abs(worldPos[0]) + abs(length)) * -1, worldPos[1], worldPos[2]] + + #rotate the aim grp in 90 in every axis until the world position of the aim locator matches the passed in aimLocPos + self.rotateAimGrp(int(aimLocPos[0]), aimGrp, aimLoc) + + # 4.) Connect TX and TZ of aimLoc to targetLoc + cmds.connectAttr(targetLoc + ".tx", aimLoc + ".tx") + cmds.connectAttr(targetLoc + ".tz", aimLoc + ".tz") + + # 5.) set limits on aimLoc translateZ + currentValue = cmds.getAttr(aimLoc + ".tz") + cmds.transformLimits(aimLoc, etz = [1, 1], tz = [currentValue, -10]) + + # 6.) Create RP IK for noFlip bone chain + ikNodes = cmds.ikHandle(name = self.name + "_noFlip_ikHandle", solver = "ikRPsolver", sj = noFlipBegin, ee = noFlipEnd) + cmds.setAttr(ikNodes[0] + ".v", 0, lock = True) + + # 7.) pointConstraint IKHandle to targetLoc + cmds.pointConstraint(targetLoc, ikNodes[0]) + + # 8.) snap target loc to ankle + constraint = cmds.pointConstraint(self.ikFoot, targetLoc)[0] + cmds.delete(constraint) + + # 9.) pole vector constraint between ikHandle and aimLoc + cmds.poleVectorConstraint(aimLoc, ikNodes[0]) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create the foot control # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + footControlInfo = riggingUtils.createControlFromMover(legJoints[2], networkNode, False, True) + + cmds.parent(footControlInfo[0], world = True) + constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", footControlInfo[3])[0] + cmds.delete(constraint) + cmds.makeIdentity(footControlInfo[2], t = 1, r= 1, s = 1, apply = True) + cmds.parent(footControlInfo[0], footControlInfo[1]) + cmds.makeIdentity(footControlInfo[0], t = 1, r= 1, s = 1, apply = True) + + #rename the control info + self.ikFootCtrl = cmds.rename(footControlInfo[0], "ik_" + legJoints[2] + "_anim") + cmds.rename(footControlInfo[1], self.ikFootCtrl + "_grp") + cmds.rename(footControlInfo[2], self.ikFootCtrl + "_space_switcher") + spaceSwitcherFollow = cmds.rename(footControlInfo[3], self.ikFootCtrl + "_space_switcher_follow") + + #Create leg RP IK + legIkNodes = cmds.ikHandle(name = self.name + "_noFlip_ikHandle", solver = "ikRPsolver", sj = self.ikThigh, ee = self.ikFoot) + cmds.setAttr(legIkNodes[0] + ".v", 0, lock = True) + + #parent ik under the foot control + cmds.parent(legIkNodes[0], self.ikFootCtrl) + + #create a FK matcher node + fkMatchGrp = cmds.group(empty = True, name = "ik_" + legJoints[2] + "_anim_fkMatchGrp") + constr = cmds.parentConstraint(self.ikFoot, fkMatchGrp)[0] + cmds.delete(constr) + cmds.parent(fkMatchGrp, self.ikFootCtrl) + + fkMatch = cmds.group(empty = True, name = "ik_" + legJoints[2] + "_anim_fkMatch") + constr = cmds.parentConstraint(self.ikFoot, fkMatch)[0] + cmds.delete(constr) + cmds.parent(fkMatch, fkMatchGrp) + + #point constraint target loc to foot ctrl + cmds.pointConstraint(self.ikFootCtrl, targetLoc) + + #color the foot control + riggingUtils.colorControl(self.ikFootCtrl) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create the leg chain PV # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + noFlipVectorLoc = cmds.spaceLocator(name = self.name + "_noFlip_pv_loc")[0] + noFlipVectorGrp = cmds.group(empty = True, name = self.name + "_noFlip_pv_grp") + cmds.setAttr(noFlipVectorLoc + ".v", 0, lock = True) + + constraint = cmds.pointConstraint([noFlipBegin, noFlipEnd], noFlipVectorLoc)[0] + cmds.delete(constraint) + constraint = cmds.pointConstraint(targetLoc, noFlipVectorGrp)[0] + cmds.delete(constraint) + + #get the length of the leg + legLength = abs(cmds.getAttr(noFlipEnd + ".tx")) + + #use that length to push out the noFlipVectorLoc in front + cmds.parent(noFlipVectorLoc, self.ikCalf) + cmds.setAttr(noFlipVectorLoc + ".translate", 0,0,0, type = "double3") + cmds.setAttr(noFlipVectorLoc + ".rotate", 0,0,0, type = "double3") + + #get the forward vector for the knee and set the length of the leg on the noFlipVectorLoc translateY + forwardVector = cmds.xform(self.ikThigh, q = True, ws = True, ro = True)[1] + if forwardVector < 0: + cmds.setAttr(noFlipVectorLoc + ".ty", (legLength * -1)) + else: + cmds.setAttr(noFlipVectorLoc + ".ty", legLength) + + #parent noFlipVectorLoc and constrain the grp to the no flip end joint + cmds.parent(noFlipVectorLoc, noFlipVectorGrp) + cmds.makeIdentity(noFlipVectorLoc, t = 1, r = 1, s = 1, apply = True) + cmds.parentConstraint(noFlipEnd, noFlipVectorGrp, mo = True) + + #pole vector constrain the ikHandle for the leg to the vectorLoc + cmds.poleVectorConstraint(noFlipVectorLoc, legIkNodes[0]) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create the knee vector display # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + kneeControl = riggingUtils.createControl("arrow", 1.25, self.name + "_ik_knee_anim") + constraint = cmds.pointConstraint(self.ikCalf, kneeControl)[0] + cmds.delete(constraint) + + kneeGrp = cmds.group(empty = True, name = self.name + "_ik_knee_anim_grp") + constraint = cmds.pointConstraint(self.ikCalf, kneeGrp)[0] + cmds.delete(constraint) + + cmds.parent(kneeControl, kneeGrp) + cmds.makeIdentity(kneeControl, t = 1, r = 1, s = 1, apply = True) + + cmds.pointConstraint(self.ikCalf, kneeGrp, mo = True) + cmds.setAttr(kneeControl + ".overrideEnabled", 1) + cmds.setAttr(kneeControl + ".overrideDisplayType", 2) + + cmds.aimConstraint(noFlipVectorLoc, kneeGrp, aim = [0, -1, 0], u = [0, 0, 1], wut = "vector", wu = [0, 0, 1]) + cmds.orientConstraint(self.ikCalf, kneeControl, mo = True) + + #color the control + riggingUtils.colorControl(kneeControl) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create the foot rig # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + ballExists = False + + #create ball and toe joints + if len(legJoints) == 4: + if cmds.objExists(legJoints[3]): + ballExists = True + + + cmds.select(clear = True) + + #select vertices influenced by foot and ball joint + selection = [] + skinClusters = cmds.ls(type = "skinCluster") + for skin in skinClusters: + infs = cmds.skinCluster(skin, q = True, wi = True) + if legJoints[2] in infs: + cmds.skinCluster(skin, edit = True, siv = legJoints[2]) + selection.extend(cmds.ls(sl = True, flatten = True)) + + if len(legJoints) == 4: + if legJoints[3] in infs: + cmds.skinCluster(skin, edit = True, siv = legJoints[3]) + selection.extend(cmds.ls(sl = True, flatten = True)) + + #get the bounds of the foot to find the foot length + cmds.select(selection) + try: + bounds = cmds.exactWorldBoundingBox(cmds.ls(sl = True), ce = True, ii = True) + length = abs(bounds[1] - bounds[4]) + except: + pass + + cmds.select(clear = True) + + # # # + #create ball and toe joint + # # # + + #ball joint creation + if ballExists: + self.ikBallJoint = cmds.createNode("joint", name = "ikV1_" + legJoints[3] + "_joint") + constraint = cmds.parentConstraint(legJoints[3], self.ikBallJoint)[0] + cmds.delete(constraint) + cmds.move(0, moveZ = True, ws = True) + + + #if there is no ball joint, we need to create one and place it approx. where it should go + else: + baseName = cmds.getAttr(networkNode + ".baseName") + nameData = self.name.split(baseName) + + self.ikBallJoint = cmds.createNode("joint", name = "ikV1_" + nameData[0] + "ball" + nameData[1] + "_joint") + constraint = cmds.pointConstraint(self.name + "_toe_pivot_mover", self.ikBallJoint)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_inside_pivot_mover_orient", self.ikBallJoint)[0] + cmds.delete(constraint) + + cmds.setAttr(self.ikBallJoint + ".v", 0, lock = True) + + #toe joint creation + baseName = cmds.getAttr(networkNode + ".baseName") + nameData = self.name.split(baseName) + + self.ikToeJoint = cmds.createNode("joint", name = "ikV1_" + nameData[0] + "toe" + nameData[1] + "_joint") + constraint = cmds.pointConstraint(self.name + "_toe_pivot_mover", self.ikToeJoint)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_ball_mover", self.ikToeJoint)[0] + cmds.delete(constraint) + + cmds.setAttr(self.ikToeJoint + ".v", 0, lock = True) + + #parent ball and toe joints into ik joint hierarchy + cmds.parent(self.ikToeJoint, self.ikBallJoint) + cmds.parent(self.ikBallJoint, self.ikFoot) + cmds.makeIdentity(self.ikBallJoint, t = 0, r = 1, s = 0, apply = True) + + #constrain driver ball joint to ik ball joint + if ballExists: + + cmds.pointConstraint(self.ikBallJoint, "driver_" + legJoints[3]) + cmds.orientConstraint(self.ikBallJoint, "driver_" + legJoints[3]) + #plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = legJoints[i] + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(joint + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + legJoints[i], "scale", False, numRigs, slot, "output") + else: + riggingUtils.createConstraint(joint, "driver_" + legJoints[i], "scale", False, numRigs, slot) + + + #create the SC IK for the ball -> toe + ballIKNodes = cmds.ikHandle(name = self.name + "_ikHandle_ball", solver = "ikSCsolver", sj = self.ikFoot, ee = self.ikBallJoint) + toeIKNodes = cmds.ikHandle(name = self.name + "_ikHandle_toe", solver = "ikSCsolver", sj = self.ikBallJoint, ee = self.ikToeJoint) + cmds.setAttr(ballIKNodes[0] + ".v", 0, lock = True) + cmds.setAttr(toeIKNodes[0] + ".v", 0, lock = True) + + #create the locators we need for the foot rig + toeTipPivot = cmds.spaceLocator(name = self.name + "_ik_foot_toe_tip_pivot")[0] + insidePivot = cmds.spaceLocator(name = self.name + "_ik_foot_inside_pivot")[0] + outsidePivot = cmds.spaceLocator(name = self.name + "_ik_foot_outside_pivot")[0] + heelPivot = cmds.spaceLocator(name = self.name + "_ik_foot_heel_pivot")[0] + toePivot = cmds.spaceLocator(name = self.name + "_ik_foot_toe_pivot")[0] + ballPivot = cmds.spaceLocator(name = self.name + "_ik_foot_ball_pivot")[0] + masterBallPivot = cmds.spaceLocator(name = self.name + "_master_foot_ball_pivot")[0] + + + #create the controls + heelControl = riggingUtils.createControl("arrowOnBall", 1, self.name + "_heel_ctrl") + toeWiggleControl = riggingUtils.createControl("arrowOnBall", 1.5, self.name + "_toe_wiggle_ctrl") + toeControl = riggingUtils.createControl("arrowOnBall", 1, self.name + "_toe_tip_ctrl") + + #orient controls in worldspace correctly + cmds.setAttr(heelControl + ".rx", -90) + cmds.setAttr(toeControl + ".rx", 90) + cmds.makeIdentity(heelControl, t = 0, r = 1, s = 0, apply = True) + cmds.makeIdentity(toeControl, t = 0, r = 1, s = 0, apply = True) + + #position controls + constraint = cmds.parentConstraint(self.name + "_heel_pivot_orient", heelControl)[0] + cmds.delete(constraint) + + constraint = cmds.pointConstraint(self.name + "_toe_pivot_mover", toeControl)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_toe_pivot_orient", toeControl)[0] + cmds.delete(constraint) + + + constraint = cmds.pointConstraint(self.ikBallJoint, toeWiggleControl)[0] + cmds.delete(constraint) + + constraint = cmds.orientConstraint(self.name + "_toe_pivot_orient", toeWiggleControl)[0] + cmds.delete(constraint) + + #create control groups and orient controls properly + + #heelControl + heelCtrlGrp = cmds.group(empty = True, name = self.name + "_heel_ctrl_grp") + constraint = cmds.parentConstraint(heelControl, heelCtrlGrp)[0] + cmds.delete(constraint) + cmds.parent(heelControl, heelCtrlGrp) + cmds.makeIdentity(heelControl, t = 1, r = 1, s = 1, apply = True) + + #toeControl + toeCtrlGrp = cmds.group(empty = True, name = self.name + "_toe_tip_ctrl_grp") + constraint = cmds.pointConstraint(toeControl, toeCtrlGrp)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.ikToeJoint, toeCtrlGrp)[0] + cmds.delete(constraint) + cmds.makeIdentity(toeControl, t = 0, r = 1, s = 0, apply = True) + cmds.setAttr(toeControl + ".rx", -90) + cmds.parent(toeControl, toeCtrlGrp) + cmds.makeIdentity(toeControl, t = 1, r = 1, s = 1, apply = True) + + #toeWiggleControl + toeWiggleCtrlGrp = cmds.group(empty = True, name = self.name + "_toe_wiggle_ctrl_grp") + constraint = cmds.pointConstraint(self.ikBallJoint, toeWiggleCtrlGrp)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.ikBallJoint, toeWiggleCtrlGrp)[0] + cmds.delete(constraint) + cmds.parent(toeWiggleControl, toeWiggleCtrlGrp) + cmds.setAttr(toeWiggleControl + ".rx", -90) + cmds.makeIdentity(toeWiggleControl, t = 1, r = 1, s = 1, apply = True) + + if not ballExists: + cmds.setAttr(toeWiggleControl + ".v", 0, lock = True) + + #place the pivot locators + constraint = cmds.pointConstraint(heelControl, heelPivot)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", heelPivot)[0] + cmds.delete(constraint) + + constraint = cmds.pointConstraint(toeWiggleControl, ballPivot)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", ballPivot)[0] + cmds.delete(constraint) + + constraint = cmds.pointConstraint(toeWiggleControl, masterBallPivot)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", masterBallPivot)[0] + cmds.delete(constraint) + + constraint = cmds.pointConstraint(toeControl, toeTipPivot)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", toeTipPivot)[0] + cmds.delete(constraint) + + constraint = cmds.pointConstraint(toeControl, toePivot)[0] + cmds.delete(constraint) + constraint = cmds.orientConstraint(self.name + "_ik_foot_ctrl_orient", toePivot)[0] + cmds.delete(constraint) + + constraint = cmds.parentConstraint(self.name + "_inside_pivot_mover_orient", insidePivot)[0] + cmds.delete(constraint) + + constraint = cmds.parentConstraint(self.name + "_outside_pivot_mover_orient", outsidePivot)[0] + cmds.delete(constraint) + + + #create groups for each pivot and parent the pivot to the corresponding group + for piv in [heelPivot, ballPivot, toeTipPivot, toePivot, insidePivot, outsidePivot, masterBallPivot]: + pivGrp = cmds.group(empty = True, name = piv + "_grp") + constraint = cmds.parentConstraint(piv, pivGrp)[0] + cmds.delete(constraint) + cmds.parent(piv, pivGrp) + shape = cmds.listRelatives(piv, shapes = True)[0] + cmds.setAttr(shape + ".v", 0) + + + #setup pivot hierarchy + cmds.parent(toeWiggleCtrlGrp, toePivot) + cmds.parent(ballPivot + "_grp", toePivot) + cmds.parent(toePivot + "_grp", heelPivot) + cmds.parent(heelPivot + "_grp", outsidePivot) + cmds.parent(outsidePivot + "_grp", insidePivot) + cmds.parent(insidePivot + "_grp", toeTipPivot) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create the set driven keys # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + #get the side attribute + side = cmds.getAttr(networkNode + ".side") + + # # # FOOT ROLL # # # + cmds.setAttr(heelControl + ".rz", 0) + cmds.setAttr(heelPivot + ".rx", 0) + cmds.setAttr(toePivot + ".rx", 0) + cmds.setAttr(ballPivot + ".rx", 0) + cmds.setDrivenKeyframe([heelPivot + ".rx", toePivot + ".rx", ballPivot + ".rx"], cd = heelControl + ".rz", itt = "linear", ott = "linear") + + cmds.setAttr(heelControl + ".rz", -90) + cmds.setAttr(heelPivot + ".rx", 0) + cmds.setAttr(toePivot + ".rx", 0) + cmds.setAttr(ballPivot + ".rx", 90) + cmds.setDrivenKeyframe([heelPivot + ".rx", toePivot + ".rx", ballPivot + ".rx"], cd = heelControl + ".rz", itt = "linear", ott = "linear") + + cmds.setAttr(heelControl + ".rz", 90) + cmds.setAttr(heelPivot + ".rx", -90) + cmds.setAttr(toePivot + ".rx", 0) + cmds.setAttr(ballPivot + ".rx", 0) + cmds.setDrivenKeyframe([heelPivot + ".rx", toePivot + ".rx", ballPivot + ".rx"], cd = heelControl + ".rz", itt = "linear", ott = "linear") + + cmds.setAttr(heelControl + ".rz", 0) + cmds.setAttr(heelPivot + ".rx", 0) + cmds.setAttr(toePivot + ".rx", 0) + cmds.setAttr(ballPivot + ".rx", 0) + + # # # HEEL CONTROL RX & RY # # # + cmds.connectAttr(heelControl + ".rx", ballPivot + ".rz") + cmds.connectAttr(heelControl + ".ry", ballPivot + ".ry") + + # # # TOE CONTROL RY & RZ # # # + if side == "Left": + cmds.connectAttr(toeControl + ".ry", toeTipPivot + ".rz") + + else: + toeRzMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_toeTipPivot_RZ_mult") + cmds.setAttr(toeRzMult + ".input2X", -1) + cmds.connectAttr(toeControl + ".ry", toeRzMult + ".input1X") + cmds.connectAttr(toeRzMult + ".outputX", toeTipPivot + ".rz") + + toeRxMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_toeTipPivot_RX_mult") + cmds.setAttr(toeRxMult + ".input2X", -1) + cmds.connectAttr(toeControl + ".rz", toeRxMult + ".input1X") + cmds.connectAttr(toeRxMult + ".outputX", toeTipPivot + ".rx") + + # # # FOOT SIDE TO SIDE # # # + cmds.setAttr(toeControl + ".rx", 0) + cmds.setAttr(insidePivot + ".rx", 0) + cmds.setAttr(outsidePivot + ".rx", 0) + cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear") + + cmds.setAttr(toeControl + ".rx", -90) + cmds.setAttr(insidePivot + ".rx", 0) + cmds.setAttr(outsidePivot + ".rx", -90) + cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear") + + cmds.setAttr(toeControl + ".rx", 90) + cmds.setAttr(insidePivot + ".rx", 90) + cmds.setAttr(outsidePivot + ".rx", 0) + cmds.setDrivenKeyframe([insidePivot + ".rx", outsidePivot + ".rx"], cd = toeControl + ".rx", itt = "linear", ott = "linear") + + cmds.setAttr(toeControl + ".rx", 0) + cmds.setAttr(insidePivot + ".rx", 0) + cmds.setAttr(outsidePivot + ".rx", 0) + + #parent the IK nodes into the foot rig setup + cmds.parent(legIkNodes[0], ballPivot) + cmds.parent(ballIKNodes[0], ballPivot) + cmds.parent(toeIKNodes[0], toeWiggleControl) + + cmds.parent([toeTipPivot + "_grp", heelControl + "_grp", toeControl + "_grp"], masterBallPivot) + cmds.parent(masterBallPivot + "_grp", self.ikFootCtrl) + + #add the heel pivot and ball pivot attrs to the foot control + cmds.addAttr(heelControl, longName= ( "heelPivot" ), defaultValue=0, keyable = True) + cmds.addAttr(heelControl, longName= ( "ballPivot" ), defaultValue=0, keyable = True) + + #setup heel and ball pivot + if side == "Left": + cmds.connectAttr(heelControl + ".heelPivot", heelPivot + ".rz") + cmds.connectAttr(heelControl + ".ballPivot", masterBallPivot + ".rz") + + else: + heelPivotMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_heelPivotMult") + cmds.setAttr(heelPivotMult + ".input2X", -1) + cmds.connectAttr(heelControl + ".heelPivot", heelPivotMult + ".input1X") + cmds.connectAttr(heelPivotMult + ".outputX", heelPivot + ".rz") + + ballPivotMult = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_ballPivotMult") + cmds.setAttr(ballPivotMult + ".input2X", -1) + cmds.connectAttr(heelControl + ".ballPivot", ballPivotMult + ".input1X") + cmds.connectAttr(ballPivotMult + ".outputX", masterBallPivot + ".rz") + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # connect ik twist attr to custom attr on foot ctrl # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + cmds.addAttr(self.ikFootCtrl, longName=("knee_twist"), at = 'double', keyable = True) + + if side == "Right": + cmds.connectAttr(self.ikFootCtrl + ".knee_twist", legIkNodes[0] + ".twist") + else: + twistMultNode = cmds.shadingNode("multiplyDivide", name = self.name + "ik_knee_twistMultNode", asUtility = True) + cmds.connectAttr(self.ikFootCtrl + ".knee_twist", twistMultNode + ".input1X") + cmds.setAttr(twistMultNode + ".input2X", -1) + cmds.connectAttr(twistMultNode + ".outputX", legIkNodes[0] + ".twist") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # setup ik squash and stretch # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + + """ + Note about stretch bias, since this part is really confusing: + + the math goes like this: + if the current leg length > original leg length, then the leg needs to stretch (if attr is on) + 1.) take the stretch bias attr from the foot control and divide by 5. + -Why 5? It's just an arbitrary number. The point of stretch bias is to essentially add onto the original length, + so that when we divide current by original, we get a slightly smaller number than we normally would. If stretch bias is 0, this returns 0. If 1, then .2 + 2.) Take that result and add 1. + -Why? So that we aren't dividing the current length by 0 (original length * that result). At most, we would divide it by current length/(original * 1.2) + -At least would be current length /(original * 1) + 3.) Take the add node result (1 + stretch bias output) and multiply it by original length + 4.) Take the current length and put that into input1 of a new mult node + 5.) Take the result of step 3 and put it into input 2. Set operation to divide + 6.) This gets us current/(original * stretch bias output) + 7.) Lastly, create a blendColors node passing in color 1r as 1.0, and 2r as the scale factor + 8.) Pass in the stretch attr into blender. if stretch is .5, given 1 and 1.3, result is 1.15. That is the scale to be applied to joints. + """ + + + + #add attrs to the foot ctrl + cmds.addAttr(self.ikFootCtrl, longName=("stretch"), at = 'double',min = 0, max = 1, dv = 0, keyable = True) + cmds.addAttr(self.ikFootCtrl, longName=("squash"), at = 'double',min = 0, max = 1, dv = 0, keyable = True) + cmds.addAttr(self.ikFootCtrl, longName=("toeCtrlVis"), at = 'bool', dv = 0, keyable = True) + + #need to get the total length of the leg chain + totalDist = abs(cmds.getAttr(self.ikCalf + ".tx" ) + cmds.getAttr(self.ikFoot + ".tx")) + + #create a distanceBetween node + distBetween = cmds.shadingNode("distanceBetween", asUtility = True, name = self.name + "_ik_leg_distBetween") + + #get world positions of thigh and ik + baseGrp = cmds.group(empty = True, name = self.name + "_ik_leg_base_grp") + endGrp = cmds.group(empty = True, name = self.name + "_ik_leg_end_grp") + cmds.pointConstraint(self.ikThigh, baseGrp) + cmds.pointConstraint(self.ikFootCtrl, endGrp) + + #hook in group translates into distanceBetween node inputs + cmds.connectAttr(baseGrp + ".translate", distBetween + ".point1") + cmds.connectAttr(endGrp + ".translate", distBetween + ".point2") + + + #create a condition node that will compare original length to current length + #if second term is greater than, or equal to the first term, the chain needs to stretch + ikLegCondition = cmds.shadingNode("condition", asUtility = True, name = self.name + "_ik_leg_stretch_condition") + cmds.setAttr(ikLegCondition + ".operation", 3) + cmds.connectAttr(distBetween + ".distance", ikLegCondition + ".secondTerm") + cmds.setAttr(ikLegCondition + ".firstTerm", totalDist) + + + #hook up the condition node's return colors + cmds.setAttr(ikLegCondition + ".colorIfTrueR", totalDist) + cmds.connectAttr(distBetween + ".distance", ikLegCondition + ".colorIfFalseR") + + #add attr to foot control for stretch bias + cmds.addAttr(self.ikFootCtrl, ln = "stretchBias", minValue = -1.0, maxValue = 1.0, defaultValue = 0.0, keyable = True) + + #add divide node so that instead of driving 0-1, we're actually only driving 0 - 0.2 + divNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_stretchBias_Div") + cmds.connectAttr(self.ikFootCtrl + ".stretchBias", divNode + ".input1X") + cmds.setAttr(divNode + ".operation", 2) + cmds.setAttr(divNode + ".input2X", 5) + + #create the add node and connect the stretchBias into it, adding 1 + addNode = cmds.shadingNode("plusMinusAverage", asUtility = True, name = self.name + "_stretchBias_Add") + cmds.connectAttr(divNode + ".outputX", addNode + ".input1D[0]") + cmds.setAttr(addNode + ".input1D[1]", 1.0) + + #connect output of addNode to new mult node input1x + stretchBiasMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_stretchBias_multNode") + cmds.connectAttr(addNode + ".output1D", stretchBiasMultNode + ".input1X") + + #create the mult/divide node(set to divide) that will take the original creation length as a static value in input2x, and the connected length into 1x. This will get the scale factor + legDistMultNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_leg_dist_multNode") + cmds.setAttr(legDistMultNode + ".operation", 2) #divide + cmds.connectAttr(ikLegCondition + ".outColorR", legDistMultNode + ".input1X") + + #set input2x to totalDist + cmds.setAttr(stretchBiasMultNode + ".input2X", totalDist) + cmds.connectAttr(stretchBiasMultNode + ".outputX", legDistMultNode + ".input2X") + + + """ This differs from the original code. Instead of using a condition, I will use a blendColors node so that stretch % has an effect """ + + #create a blendColors node for stretch + blendResult = cmds.shadingNode("blendColors", asUtility = True, name = self.name + "_leg_stretch_scaleFactor") + cmds.setAttr(blendResult + ".color2R", 1) + cmds.connectAttr(legDistMultNode + ".outputX", blendResult + ".color1R") + cmds.connectAttr(self.ikFootCtrl + ".stretch", blendResult + ".blender") + + #create a blendColors node for squash + blendResultSquash = cmds.shadingNode("blendColors", asUtility = True, name = self.name + "_leg_squash_scaleFactor") + cmds.setAttr(blendResultSquash + ".color2R", 1) + cmds.connectAttr(legDistMultNode + ".outputX", blendResultSquash + ".color1R") + cmds.connectAttr(self.ikFootCtrl + ".squash", blendResultSquash + ".blender") + + #get the sqrt of the scale factor by creating a multiply node and setting it to power operation + powerNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_sqrt_scaleFactor") + cmds.setAttr(powerNode + ".operation", 3) + cmds.connectAttr(blendResultSquash + ".outputR", powerNode + ".input1X") + cmds.setAttr(powerNode + ".input2X", .5) + + #now divide 1 by that result + squashDivNode = cmds.shadingNode("multiplyDivide", asUtility = True, name = self.name + "_squash_Value") + cmds.setAttr(squashDivNode + ".operation", 2) + cmds.setAttr(squashDivNode + ".input1X", 1) + cmds.connectAttr(powerNode + ".outputX", squashDivNode + ".input2X") + + + #connect to leg joint scale attributes + cmds.connectAttr(blendResult + ".outputR", self.ikThigh + ".sx") + cmds.connectAttr(blendResult + ".outputR", self.ikCalf + ".sx") + + cmds.connectAttr(squashDivNode + ".outputX", self.ikCalf + ".sy") + cmds.connectAttr(squashDivNode + ".outputX", self.ikCalf + ".sz") + + cmds.connectAttr(squashDivNode + ".outputX", self.ikThigh + ".sy") + cmds.connectAttr(squashDivNode + ".outputX", self.ikThigh + ".sz") + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # clean up # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + cmds.parent([targetGrp, aimGrp, noFlipVectorGrp], noFlipGrp) + cmds.parent([self.ikThigh, noFlipGrp], self.legCtrlGrp) + + ikGrp = cmds.group(name = self.name + "_ik_group", empty = True) + cmds.parent([spaceSwitcherFollow, ikNodes[0], kneeGrp], ikGrp) + + cmds.parent([spaceSwitcherFollow, ikGrp, baseGrp, endGrp], self.legGroup) + + return [[self.ikFootCtrl, heelControl, toeControl, toeWiggleControl], kneeGrp] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildToeRigs(self, joints): + + networkNode = self.returnNetworkNode + + #number of rigs. Might need to be pulled from a setting in the future + buildFK = True + buildIK = False #later feature? Skip for now. + numRigs = 0 + + if buildFK: + numRigs += 1 + if buildIK: + numRigs += 1 + + if numRigs > 1: + cmds.addAttr(self.legSettings, ln = "toeRigMode", min = 0, max = numRigs - 1, dv = 0, keyable = True) + + if numRigs >= 1: + #setup visibility to leg settings toe mode (will need to add attribute first) + if not cmds.objExists(self.legSettings + ".toeCtrlVis"): + cmds.addAttr(self.legSettings, ln = "toeCtrlVis", min = 0, max = 1, dv = 0, keyable = True) + + #build the fk rig if needed + if buildFK: + + if not cmds.objExists(self.name + "_toe_rig_grp"): + toeRigGrp = cmds.group(empty = True, name = self.name + "_toe_rig_grp") + cmds.parent(toeRigGrp, self.legGroup) + + #create the control from the mover + fkToeNodes = riggingUtils.createFkRig(joints, networkNode, numRigs, 0) + + if not cmds.objExists(networkNode + ".toeControls"): + cmds.addAttr(networkNode, ln = "toeControls", dt = "string") + jsonString = json.dumps(fkToeNodes[1]) + cmds.setAttr(networkNode + ".toeControls", jsonString, type = "string") + + else: + currentData = json.loads(cmds.getAttr(networkNode + ".toeControls")) + currentData.extend(fkToeNodes[1]) + jsonString = json.dumps(currentData) + cmds.setAttr(networkNode + ".toeControls", jsonString, type = "string") + + for toe in fkToeNodes[1]: + + + #default color + color = 18 + + #first, let's color controls + currentColor = cmds.getAttr(toe + ".overrideColor") + if currentColor == 13: + color = 4 + + cmds.setAttr(toe + ".overrideColor", color) + + #next, duplicate the toe group for each toe, parent under the toe grp, freeze transforms, and parent the toe control under it + drivenGrp = cmds.duplicate(toe + "_grp", po = True, name = toe + "_driven_grp") + cmds.parent(drivenGrp, toe + "_grp") + cmds.makeIdentity(drivenGrp, t = 1, r = 1, s = 1, apply = True) + cmds.parent(toe, drivenGrp) + + #need to find the top most group node's parent, and unparent the top most group node from it + #parent under the toe rig grp and parentConstraint to original parent's driver joint + parent = cmds.listRelatives(toe + "_grp", parent = True) + + if parent == None: + cmds.parent(toe + "_grp", self.name + "_toe_rig_grp") + + #get the joint the parent is driving + joint = toe.partition("fk_")[2].partition("_anim")[0] + parent = cmds.listRelatives(joint, parent = True)[0] + driverJnt = "driver_" + parent + cmds.parentConstraint(driverJnt, toe + "_grp", mo = True) + + + #setup set connections on toes for toe ctrl vis + cmds.connectAttr(self.legSettings + ".toeCtrlVis", toe + "_grp.v") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def rotateAimGrp(self, aimLocPos, aimGrp, aimLoc): + + for attr in [".rotateX", ".rotateY", ".rotateZ"]: + cmds.setAttr(aimGrp + attr, 90) + currentVal = int(cmds.xform(aimLoc, q = True, ws = True, t = True)[0]) + if currentVal == aimLocPos: + return + else: + cmds.setAttr(aimGrp + attr, -90) + currentVal = int(cmds.xform(aimLoc, q = True, ws = True, t = True)[0]) + if currentVal == aimLocPos: + return + else: + cmds.setAttr(aimGrp + attr, 0) + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getMainLegJoints(self): + + thighJoint = None + calfJoint = None + footJoint = None + ballJoint = None + + returnData = [] + + #thigh + joints = self.returnCreatedJoints + for joint in joints: + if joint.find("thigh") != -1: + if joint.find("twist") == -1: + thighJoint = joint + returnData.append(thighJoint) + + #calf + for joint in joints: + if joint.find("calf") != -1: + if joint.find("twist") == -1: + calfJoint = joint + returnData.append(calfJoint) + + #foot + for joint in joints: + if joint.find("foot") != -1: + footJoint = joint + returnData.append(footJoint) + + #ball + for joint in joints: + if joint.find("ball") != -1: + ballJoint = joint + returnData.append(ballJoint) + + return returnData + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getLegTwistJoints(self, thighTwists, calfTwists): + + thighTwistBones = [] + calfTwistBones = [] + + joints = self.returnCreatedJoints + + + #thigh + for joint in joints: + if joint.find("thigh") != -1: + if joint.find("twist") != -1: + thighTwistBones.append(joint) + + #calf + for joint in joints: + if joint.find("calf") != -1: + if joint.find("twist") != -1: + calfTwistBones.append(joint) + + + if thighTwists: + return thighTwistBones + if calfTwists: + return calfTwistBones + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def setAttrViaInterface(self, attr, checkbox): + + networkNode = self.returnNetworkNode + + state = checkbox.isChecked() + + cmds.setAttr(networkNode + "." + attr, lock = False) + cmds.setAttr(networkNode + "." + attr, state, lock = True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def mirrorTransformations_Custom(self): + + networkNode = self.returnNetworkNode + mirrorModule = cmds.getAttr(networkNode + ".mirrorModule") + moduleName = cmds.getAttr(networkNode + ".moduleName") + + for mover in [self.name + "_toe_pivot_mover", self.name + "_heel_pivot_mover"]: + for attr in [".rotateY", ".rotateZ"]: + value = cmds.getAttr(mover + attr) + mirrorMover = mover.replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + attr, value * -1) + + for attr in [".translateY", ".translateZ"]: + value = cmds.getAttr(mover + attr) + mirrorMover = mover.replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + attr, value) + + for mover in [self.name + "_outside_pivot_mover", self.name + "_inside_pivot_mover"]: + for attr in [".rotateX", ".rotateZ"]: + value = cmds.getAttr(mover + attr) + mirrorMover = mover.replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + attr, value * -1) + + #outside translates + value = cmds.getAttr(self.name + "_outside_pivot_mover.tz") + mirrorMover = (self.name + "_outside_pivot_mover").replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + ".tz", value) + + value = cmds.getAttr(self.name + "_outside_pivot_mover.ty") + mirrorMover = (self.name + "_outside_pivot_mover").replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + ".ty", value) + + #inside translates + value = cmds.getAttr(self.name + "_inside_pivot_mover.tz") + mirrorMover = (self.name + "_inside_pivot_mover").replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + ".tz", value) + + value = cmds.getAttr(self.name + "_inside_pivot_mover.tx") + mirrorMover = (self.name + "_inside_pivot_mover").replace(moduleName, mirrorModule) + cmds.setAttr(mirrorMover + ".tx", value) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def includeBallJoint(self, apply, *args): + state = self.ballJoint.isChecked() + + self.bigToeNum.setEnabled(state) + self.indexToeNum.setEnabled(state) + self.middleToeNum.setEnabled(state) + self.ringToeNum.setEnabled(state) + self.pinkyToeNum.setEnabled(state) + + if state == False: + #set values back to 0 + self.bigToeNum.setValue(0) + self.indexToeNum.setValue(0) + self.middleToeNum.setValue(0) + self.ringToeNum.setValue(0) + self.pinkyToeNum.setValue(0) + + #show ball to toe bone geo + cmds.setAttr(self.name + "_noToes_bone_geo.v", lock = False) + cmds.setAttr(self.name + "_noToes_bone_geo.v", 1, lock = True) + + #hide ball mover controls + cmds.setAttr(self.name + "_ball_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_ball_mover_grp.v", 0, lock = True) + + + if state == True: + #show ball mover controls + cmds.setAttr(self.name + "_ball_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_ball_mover_grp.v", 1, lock = True) + + #apply changes + if apply: + self.applyModuleChanges(self) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def toggleButtonState(self): + + state = self.applyButton.isEnabled() + if state == False: + self.applyButton.setEnabled(True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def editMetaTarsals(self, uiWidget, searchKey, *args): + + #uiWidget is the spinBox + #isBigToe will be the special case, since there are only the three joints instead of the 4 + #searchKey is the basname (bigToe, middle, ring, etc) + + #unlock bone representations + cmds.select(self.name + "_bone_representations", hi = True) + selection = cmds.ls(sl = True, type = "transform") + + for each in selection: + cmds.setAttr(each + ".v", lock = False) + + + #toggle visibility + if uiWidget.isChecked(): + try: + cmds.parent(self.name + "_" + searchKey + "_proximal_phalange_mover_grp", self.name + "_" + searchKey + "_metatarsal_mover") + except Exception, e: + print e + + cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_bone_geo.v", 1) + + + if not uiWidget.isChecked(): + try: + cmds.parent(self.name + "_" + searchKey + "_proximal_phalange_mover_grp", self.name + "_ball_mover") + except Exception, e: + print e + + cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_mover_grp.v", 0, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_metatarsal_bone_geo.v", 0) + + #relock bone representations + cmds.select(self.name + "_bone_representations", hi = True) + selection = cmds.ls(sl = True, type = "transform") + + for each in selection: + cmds.setAttr(each + ".v", lock = True) + + #toggle mover vis + self.rigUiInst.setMoverVisibility() + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def editJointMoverViaSpinBox(self, uiWidget, searchKey, isBigToe, *args): + + #uiWidget is the spinBox + #isBigToe will be the special case, since there are only the three joints instead of the 4 + #searchKey is the basname (bigToe, middle, ring, etc) + + #unlock bone representations + cmds.select(self.name + "_bone_representations", hi = True) + selection = cmds.ls(sl = True, type = "transform") + + for each in selection: + cmds.setAttr(each + ".v", lock = False) + + #check number in spinBox + num = uiWidget.value() + + #set visibility on movers and geo depending on the value of num + for i in range(num + 1): + #purely for fanciness + time.sleep(.05) + cmds.refresh(force = True) + + if isBigToe == False: + + moverList = ["_proximal_phalange", "_middle_phalange", "_distal_phalange"] + for mover in moverList: + if moverList.index(mover) <= i -1: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1) + + if i == 0: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock = True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0) + + if isBigToe == True: + + moverList = ["_proximal_phalange", "_distal_phalange"] + for mover in moverList: + if moverList.index(mover) <= i -1: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", True) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 1) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 1) + + if i == 0: + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_offset", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_mover_geo", False) + self.toggleShapeVis(self.name + "_" + searchKey + mover + "_lra", False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + mover + "_mover_grp.v", 0, lock = True) + cmds.setAttr(self.name + "_" + searchKey + mover + "_bone_geo.v", 0) + cmds.setAttr(self.name + "_" + searchKey + mover + "_proxy_geo.v", 0) + + + #relock bone representations + cmds.select(self.name + "_bone_representations", hi = True) + selection = cmds.ls(sl = True, type = "transform") + + for each in selection: + cmds.setAttr(each + ".v", lock = True) + + #toggle mover vis + self.rigUiInst.setMoverVisibility() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def editJointMoverTwistBones(self, uiWidget, searchKey, *args): + + #check number in spinBox + num = uiWidget.value() + + for i in range(num + 1): + + if i == 0: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 0, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock = True) + + if i == 1: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 0, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock = True) + + if i == 2: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 0, lock = True) + + if i == 3: + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_01_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_02_mover_grp.v", 1, lock = True) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", lock = False) + cmds.setAttr(self.name + "_" + searchKey + "_twist_03_mover_grp.v", 1, lock = True) + + + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addJointMoverToOutliner(self): + + index = self.rigUiInst.treeWidget.topLevelItemCount() + + #Add the module to the tree widget in the outliner tab of the rig creator UI + self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget) + self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name) + foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground) + + #add the thigh + self.outlinerWidgets[self.name + "_thigh"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_thigh"].setText(0, self.name + "_thigh") + self.createGlobalMoverButton(self.name + "_thigh", self.outlinerWidgets[self.name + "_thigh"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thigh", self.outlinerWidgets[self.name + "_thigh"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_thigh", self.outlinerWidgets[self.name + "_thigh"], self.rigUiInst) + + #add the thigh twists + self.outlinerWidgets[self.name + "_thigh_twist_01"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"]) + self.outlinerWidgets[self.name + "_thigh_twist_01"].setText(0, self.name + "_thigh_twist_01") + #self.createGlobalMoverButton(self.name + "_thigh_twist_01", self.outlinerWidgets[self.name + "_thigh_twist_01"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thigh_twist_01", self.outlinerWidgets[self.name + "_thigh_twist_01"], self.rigUiInst) + #self.createMeshMoverButton(self.name + "_thigh_twist_01", self.outlinerWidgets[self.name + "_thigh_twist_01"], self.rigUiInst) + self.outlinerWidgets[self.name + "_thigh_twist_01"].setHidden(True) + + self.outlinerWidgets[self.name + "_thigh_twist_02"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"]) + self.outlinerWidgets[self.name + "_thigh_twist_02"].setText(0, self.name + "_thigh_twist_02") + #self.createGlobalMoverButton(self.name + "_thigh_twist_02", self.outlinerWidgets[self.name + "_thigh_twist_02"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thigh_twist_02", self.outlinerWidgets[self.name + "_thigh_twist_02"], self.rigUiInst) + #self.createMeshMoverButton(self.name + "_thigh_twist_02", self.outlinerWidgets[self.name + "_thigh_twist_02"], self.rigUiInst) + self.outlinerWidgets[self.name + "_thigh_twist_02"].setHidden(True) + + self.outlinerWidgets[self.name + "_thigh_twist_03"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"]) + self.outlinerWidgets[self.name + "_thigh_twist_03"].setText(0, self.name + "_thigh_twist_03") + #self.createGlobalMoverButton(self.name + "_thigh_twist_03", self.outlinerWidgets[self.name + "_thigh_twist_03"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_thigh_twist_03", self.outlinerWidgets[self.name + "_thigh_twist_03"], self.rigUiInst) + #self.createMeshMoverButton(self.name + "_thigh_twist_03", self.outlinerWidgets[self.name + "_thigh_twist_03"], self.rigUiInst) + self.outlinerWidgets[self.name + "_thigh_twist_03"].setHidden(True) + + #add the calf + self.outlinerWidgets[self.name + "_calf"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_thigh"] ) + self.outlinerWidgets[self.name + "_calf"].setText(0, self.name + "_calf") + self.createGlobalMoverButton(self.name + "_calf", self.outlinerWidgets[self.name + "_calf"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_calf", self.outlinerWidgets[self.name + "_calf"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_calf", self.outlinerWidgets[self.name + "_calf"], self.rigUiInst) + + #add the calf twists + self.outlinerWidgets[self.name + "_calf_twist_01"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] ) + self.outlinerWidgets[self.name + "_calf_twist_01"].setText(0, self.name + "_calf_twist_01") + #self.createGlobalMoverButton(self.name + "_calf_twist_01", self.outlinerWidgets[self.name + "_calf_twist_01"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_calf_twist_01", self.outlinerWidgets[self.name + "_calf_twist_01"], self.rigUiInst) + #self.createMeshMoverButton(self.name + "_calf_twist_01", self.outlinerWidgets[self.name + "_calf_twist_01"], self.rigUiInst) + self.outlinerWidgets[self.name + "_calf_twist_01"].setHidden(True) + + self.outlinerWidgets[self.name + "_calf_twist_02"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] ) + self.outlinerWidgets[self.name + "_calf_twist_02"].setText(0, self.name + "_calf_twist_02") + #self.createGlobalMoverButton(self.name + "_calf_twist_02", self.outlinerWidgets[self.name + "_calf_twist_02"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_calf_twist_02", self.outlinerWidgets[self.name + "_calf_twist_02"], self.rigUiInst) + #self.createMeshMoverButton(self.name + "_calf_twist_02", self.outlinerWidgets[self.name + "_calf_twist_02"], self.rigUiInst) + self.outlinerWidgets[self.name + "_calf_twist_02"].setHidden(True) + + self.outlinerWidgets[self.name + "_calf_twist_03"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] ) + self.outlinerWidgets[self.name + "_calf_twist_03"].setText(0, self.name + "_calf_twist_03") + #self.createGlobalMoverButton(self.name + "_calf_twist_03", self.outlinerWidgets[self.name + "_calf_twist_03"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_calf_twist_03", self.outlinerWidgets[self.name + "_calf_twist_03"], self.rigUiInst) + #self.createMeshMoverButton(self.name + "_calf_twist_03", self.outlinerWidgets[self.name + "_calf_twist_03"], self.rigUiInst) + self.outlinerWidgets[self.name + "_calf_twist_03"].setHidden(True) + + #add the foot + self.outlinerWidgets[self.name + "_foot"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_calf"] ) + self.outlinerWidgets[self.name + "_foot"].setText(0, self.name + "_foot") + self.createGlobalMoverButton(self.name + "_foot", self.outlinerWidgets[self.name + "_foot"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_foot", self.outlinerWidgets[self.name + "_foot"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_foot", self.outlinerWidgets[self.name + "_foot"], self.rigUiInst) + + #add the ball + self.outlinerWidgets[self.name + "_ball"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_foot"] ) + self.outlinerWidgets[self.name + "_ball"].setText(0, self.name + "_ball") + self.createGlobalMoverButton(self.name + "_ball", self.outlinerWidgets[self.name + "_ball"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ball", self.outlinerWidgets[self.name + "_ball"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_ball", self.outlinerWidgets[self.name + "_ball"], self.rigUiInst) + + #add the big toes + self.outlinerWidgets[self.name + "_bigtoe_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_bigtoe_metatarsal"].setText(0, self.name + "_bigtoe_metatarsal") + self.createGlobalMoverButton(self.name + "_bigtoe_metatarsal", self.outlinerWidgets[self.name + "_bigtoe_metatarsal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_bigtoe_metatarsal", self.outlinerWidgets[self.name + "_bigtoe_metatarsal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_bigtoe_metatarsal"].setHidden(True) + + self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"].setText(0, self.name + "_bigtoe_proximal_phalange") + self.createGlobalMoverButton(self.name + "_bigtoe_proximal_phalange", self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_bigtoe_proximal_phalange", self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_bigtoe_proximal_phalange", self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_bigtoe_proximal_phalange"] ) + self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"].setText(0, self.name + "_bigtoe_distal_phalange") + self.createGlobalMoverButton(self.name + "_bigtoe_distal_phalange", self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_bigtoe_distal_phalange", self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_bigtoe_distal_phalange", self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_bigtoe_distal_phalange"].setHidden(True) + + #add the index toes + self.outlinerWidgets[self.name + "_index_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_index_metatarsal"].setText(0, self.name + "_index_metatarsal") + self.createGlobalMoverButton(self.name + "_index_metatarsal", self.outlinerWidgets[self.name + "_index_metatarsal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_metatarsal", self.outlinerWidgets[self.name + "_index_metatarsal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_index_metatarsal"].setHidden(True) + + self.outlinerWidgets[self.name + "_index_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_index_proximal_phalange"].setText(0, self.name + "_index_proximal_phalange") + self.createGlobalMoverButton(self.name + "_index_proximal_phalange", self.outlinerWidgets[self.name + "_index_proximal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_proximal_phalange", self.outlinerWidgets[self.name + "_index_proximal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_index_proximal_phalange", self.outlinerWidgets[self.name + "_index_proximal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_index_proximal_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_index_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_index_proximal_phalange"] ) + self.outlinerWidgets[self.name + "_index_middle_phalange"].setText(0, self.name + "_index_middle_phalange") + self.createGlobalMoverButton(self.name + "_index_middle_phalange", self.outlinerWidgets[self.name + "_index_middle_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_middle_phalange", self.outlinerWidgets[self.name + "_index_middle_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_index_middle_phalange", self.outlinerWidgets[self.name + "_index_middle_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_index_middle_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_index_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_index_middle_phalange"] ) + self.outlinerWidgets[self.name + "_index_distal_phalange"].setText(0, self.name + "_index_distal_phalange") + self.createGlobalMoverButton(self.name + "_index_distal_phalange", self.outlinerWidgets[self.name + "_index_distal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_index_distal_phalange", self.outlinerWidgets[self.name + "_index_distal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_index_distal_phalange", self.outlinerWidgets[self.name + "_index_distal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_index_distal_phalange"].setHidden(True) + + + #add the middle toes + self.outlinerWidgets[self.name + "_middle_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_middle_metatarsal"].setText(0, self.name + "_middle_metatarsal") + self.createGlobalMoverButton(self.name + "_middle_metatarsal", self.outlinerWidgets[self.name + "_middle_metatarsal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_metatarsal", self.outlinerWidgets[self.name + "_middle_metatarsal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_middle_metatarsal"].setHidden(True) + + self.outlinerWidgets[self.name + "_middle_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_middle_proximal_phalange"].setText(0, self.name + "_middle_proximal_phalange") + self.createGlobalMoverButton(self.name + "_middle_proximal_phalange", self.outlinerWidgets[self.name + "_middle_proximal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_proximal_phalange", self.outlinerWidgets[self.name + "_middle_proximal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_middle_proximal_phalange", self.outlinerWidgets[self.name + "_middle_proximal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_middle_proximal_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_middle_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_middle_proximal_phalange"] ) + self.outlinerWidgets[self.name + "_middle_middle_phalange"].setText(0, self.name + "_middle_middle_phalange") + self.createGlobalMoverButton(self.name + "_middle_middle_phalange", self.outlinerWidgets[self.name + "_middle_middle_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_middle_phalange", self.outlinerWidgets[self.name + "_middle_middle_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_middle_middle_phalange", self.outlinerWidgets[self.name + "_middle_middle_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_middle_middle_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_middle_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_middle_middle_phalange"] ) + self.outlinerWidgets[self.name + "_middle_distal_phalange"].setText(0, self.name + "_middle_distal_phalange") + self.createGlobalMoverButton(self.name + "_middle_distal_phalange", self.outlinerWidgets[self.name + "_middle_distal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_middle_distal_phalange", self.outlinerWidgets[self.name + "_middle_distal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_middle_distal_phalange", self.outlinerWidgets[self.name + "_middle_distal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_middle_distal_phalange"].setHidden(True) + + + #add the ring toes + self.outlinerWidgets[self.name + "_ring_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_ring_metatarsal"].setText(0, self.name + "_ring_metatarsal") + self.createGlobalMoverButton(self.name + "_ring_metatarsal", self.outlinerWidgets[self.name + "_ring_metatarsal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_metatarsal", self.outlinerWidgets[self.name + "_ring_metatarsal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_ring_metatarsal"].setHidden(True) + + self.outlinerWidgets[self.name + "_ring_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_ring_proximal_phalange"].setText(0, self.name + "_ring_proximal_phalange") + self.createGlobalMoverButton(self.name + "_ring_proximal_phalange", self.outlinerWidgets[self.name + "_ring_proximal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_proximal_phalange", self.outlinerWidgets[self.name + "_ring_proximal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_ring_proximal_phalange", self.outlinerWidgets[self.name + "_ring_proximal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_ring_proximal_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_ring_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ring_proximal_phalange"] ) + self.outlinerWidgets[self.name + "_ring_middle_phalange"].setText(0, self.name + "_ring_middle_phalange") + self.createGlobalMoverButton(self.name + "_ring_middle_phalange", self.outlinerWidgets[self.name + "_ring_middle_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_middle_phalange", self.outlinerWidgets[self.name + "_ring_middle_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_ring_middle_phalange", self.outlinerWidgets[self.name + "_ring_middle_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_ring_middle_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_ring_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ring_middle_phalange"] ) + self.outlinerWidgets[self.name + "_ring_distal_phalange"].setText(0, self.name + "_ring_distal_phalange") + self.createGlobalMoverButton(self.name + "_ring_distal_phalange", self.outlinerWidgets[self.name + "_ring_distal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_ring_distal_phalange", self.outlinerWidgets[self.name + "_ring_distal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_ring_distal_phalange", self.outlinerWidgets[self.name + "_ring_distal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_ring_distal_phalange"].setHidden(True) + + + #add the pinky toes + self.outlinerWidgets[self.name + "_pinky_metatarsal"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_pinky_metatarsal"].setText(0, self.name + "_pinky_metatarsal") + self.createGlobalMoverButton(self.name + "_pinky_metatarsal", self.outlinerWidgets[self.name + "_pinky_metatarsal"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_metatarsal", self.outlinerWidgets[self.name + "_pinky_metatarsal"], self.rigUiInst) + self.outlinerWidgets[self.name + "_pinky_metatarsal"].setHidden(True) + + self.outlinerWidgets[self.name + "_pinky_proximal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_ball"] ) + self.outlinerWidgets[self.name + "_pinky_proximal_phalange"].setText(0, self.name + "_pinky_proximal_phalange") + self.createGlobalMoverButton(self.name + "_pinky_proximal_phalange", self.outlinerWidgets[self.name + "_pinky_proximal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_proximal_phalange", self.outlinerWidgets[self.name + "_pinky_proximal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_pinky_proximal_phalange", self.outlinerWidgets[self.name + "_pinky_proximal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_pinky_proximal_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_pinky_middle_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_pinky_proximal_phalange"] ) + self.outlinerWidgets[self.name + "_pinky_middle_phalange"].setText(0, self.name + "_pinky_middle_phalange") + self.createGlobalMoverButton(self.name + "_pinky_middle_phalange", self.outlinerWidgets[self.name + "_pinky_middle_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_middle_phalange", self.outlinerWidgets[self.name + "_pinky_middle_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_pinky_middle_phalange", self.outlinerWidgets[self.name + "_pinky_middle_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_pinky_middle_phalange"].setHidden(True) + + self.outlinerWidgets[self.name + "_pinky_distal_phalange"] = QtWidgets.QTreeWidgetItem(self.outlinerWidgets[self.name + "_pinky_middle_phalange"] ) + self.outlinerWidgets[self.name + "_pinky_distal_phalange"].setText(0, self.name + "_pinky_distal_phalange") + self.createGlobalMoverButton(self.name + "_pinky_distal_phalange", self.outlinerWidgets[self.name + "_pinky_distal_phalange"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pinky_distal_phalange", self.outlinerWidgets[self.name + "_pinky_distal_phalange"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_pinky_distal_phalange", self.outlinerWidgets[self.name + "_pinky_distal_phalange"], self.rigUiInst) + self.outlinerWidgets[self.name + "_pinky_distal_phalange"].setHidden(True) + + + #create selection script job for module + self.createScriptJob() + + #update based on spinBox values + self.updateOutliner() + self.updateBoneCount() + self.rigUiInst.treeWidget.expandAll() + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateSettingsUI(self): + + #this function will update the settings UI when the UI is launched based on the network node settings in the scene + networkNode = self.returnNetworkNode + + thighTwists = cmds.getAttr(networkNode + ".thighTwists") + calfTwists = cmds.getAttr(networkNode + ".calfTwists") + bigToes = cmds.getAttr(networkNode + ".bigToeJoints") + indexToes = cmds.getAttr(networkNode + ".indexToeJoints") + middleToes = cmds.getAttr(networkNode + ".middleToeJoints") + ringToes = cmds.getAttr(networkNode + ".ringToeJoints") + pinkyToes = cmds.getAttr(networkNode + ".pinkyToeJoints") + includeBall = cmds.getAttr(networkNode + ".includeBall") + bigToeMeta = cmds.getAttr(networkNode + ".bigToeMeta") + indexToeMeta = cmds.getAttr(networkNode + ".indexToeMeta") + middleToeMeta = cmds.getAttr(networkNode + ".middleToeMeta") + ringToeMeta = cmds.getAttr(networkNode + ".ringToeMeta") + pinkyToeMeta = cmds.getAttr(networkNode + ".pinkyToeMeta") + + #update UI elements + self.thighTwistNum.setValue(thighTwists) + self.calfTwistNum.setValue(calfTwists) + self.ballJoint.setChecked(includeBall) + + self.bigToeNum.setValue(bigToes) + self.indexToeNum.setValue(indexToes) + self.middleToeNum.setValue(middleToes) + self.ringToeNum.setValue(ringToes) + self.pinkyToeNum.setValue(pinkyToes) + + self.bigToeMeta.setChecked(bigToeMeta) + self.indexToeMeta.setChecked(indexToeMeta) + self.middleToeMeta.setChecked(middleToeMeta) + self.ringToeMeta.setChecked(ringToeMeta) + self.pinkyToeMeta.setChecked(pinkyToeMeta) + + #apply changes + self.applyButton.setEnabled(False) + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateOutliner(self): + + #whenever changes are made to the module settings, update the outliner to show the new or removed movers + + #THIGH TWISTS + thighTwists = self.thighTwistNum.value() + if thighTwists == 0: + self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(True) + self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(True) + if thighTwists == 1: + self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(True) + if thighTwists == 2: + self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(True) + if thighTwists == 3: + self.outlinerWidgets[self.originalName + "_thigh_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thigh_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_thigh_twist_03"].setHidden(False) + + #CALF TWISTS + calfTwists = self.calfTwistNum.value() + if calfTwists == 0: + self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(True) + self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(True) + if calfTwists == 1: + self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(True) + self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(True) + if calfTwists == 2: + self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(True) + if calfTwists == 3: + self.outlinerWidgets[self.originalName + "_calf_twist_01"].setHidden(False) + self.outlinerWidgets[self.originalName + "_calf_twist_02"].setHidden(False) + self.outlinerWidgets[self.originalName + "_calf_twist_03"].setHidden(False) + + #BALL JOINT + ballJoint = self.ballJoint.isChecked() + if ballJoint: + self.outlinerWidgets[self.originalName + "_ball"].setHidden(False) + else: + self.outlinerWidgets[self.originalName + "_ball"].setHidden(True) + + + #BIG TOES + bigToes = self.bigToeNum.value() + bigToeMeta = self.bigToeMeta.isChecked() + + if bigToes == 0: + self.outlinerWidgets[self.originalName + "_bigtoe_proximal_phalange"].setHidden(True) + self.outlinerWidgets[self.originalName + "_bigtoe_distal_phalange"].setHidden(True) + if bigToes == 1: + self.outlinerWidgets[self.originalName + "_bigtoe_proximal_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_bigtoe_distal_phalange"].setHidden(True) + if bigToes == 2: + self.outlinerWidgets[self.originalName + "_bigtoe_proximal_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_bigtoe_distal_phalange"].setHidden(False) + + if bigToeMeta: + self.outlinerWidgets[self.originalName + "_bigtoe_metatarsal"].setHidden(False) + if not bigToeMeta: + self.outlinerWidgets[self.originalName + "_bigtoe_metatarsal"].setHidden(True) + + toes = [[self.indexToeNum, "index", self.indexToeMeta],[self.middleToeNum, "middle", self.middleToeMeta],[self.ringToeNum, "ring", self.ringToeMeta],[self.pinkyToeNum, "pinky", self.pinkyToeMeta]] + + #OTHER TOES + for toe in toes: + value = toe[0].value() + meta = toe[2].isChecked() + + if value == 0: + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(True) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(True) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(True) + if value == 1: + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(True) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(True) + if value == 2: + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(True) + if value == 3: + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_proximal_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_middle_phalange"].setHidden(False) + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_distal_phalange"].setHidden(False) + + if meta: + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_metatarsal"].setHidden(False) + if not meta: + self.outlinerWidgets[self.originalName + "_" + toe[1] + "_metatarsal"].setHidden(True) + + + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def resetSettings(self): + + networkNode = self.returnNetworkNode + attrs = cmds.listAttr(networkNode, ud = True, hd = True) + + for attr in attrs: + attrType = str(cmds.getAttr(networkNode + "." + attr, type = True)) + + if attrType == "double": + cmds.setAttr(networkNode + "." + attr, lock = False) + cmds.setAttr(networkNode + "." + attr, 0, lock = True) + + if attrType == "bool": + if attr.find("Meta") != -1: + cmds.setAttr(networkNode + "." + attr, lock = False) + cmds.setAttr(networkNode + "." + attr, False, lock = True) + if attr.find("Meta") == -1: + cmds.setAttr(networkNode + "." + attr, lock = False) + cmds.setAttr(networkNode + "." + attr, True, lock = True) + + + #relaunch the UI + self.updateSettingsUI() + self.applyModuleChanges(self) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def applyModuleChanges(self, moduleInst): + + #create an array of the created bones that fit a format [thighName, thighTwistA, thighTwistB, thighTwistC, calfName, etc] + createdBones = self.returnCreatedJoints + #list all base names of spinBox/checkBox joints + removeBones = ["ball", "thigh_twist_0", "calf_twist_0", "pinky", "index", "bigtoe", "ring", "middle"] + + removeList = [] + for bone in createdBones: + for removeBone in removeBones: + if bone.find(removeBone) != -1: + removeList.append(bone) + + + keepBones = [] + for bone in createdBones: + if bone not in removeList: + keepBones.append(bone) + + #get prefix/suffix + name = self.groupBox.title() + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + if len(prefix) > 0: + if prefix.find("_") == -1: + prefix = prefix + "_" + if len(suffix) > 0: + if suffix.find("_") == -1: + suffix = "_" + suffix + + legJoints = [keepBones[0]] + + #get thigh twists, calf twists, and toes + thighTwists = self.thighTwistNum.value() + for i in range(thighTwists): + legJoints.append(prefix + "thigh_twist_0" + str(i + 1) + suffix) + legJoints.append(keepBones[1]) + + calfTwists = self.calfTwistNum.value() + for i in range(calfTwists): + legJoints.append(prefix + "calf_twist_0" + str(i + 1) + suffix) + legJoints.append(keepBones[2]) + + ballJoint = self.ballJoint.isChecked() + if ballJoint: + legJoints.append(prefix + "ball" + suffix) + + #toes + bigToes = self.bigToeNum.value() + bigToeJoints = ["proximal_phalange", "distal_phalange"] + toeJoints = ["proximal_phalange", "middle_phalange", "distal_phalange"] + for i in range(bigToes): + legJoints.append(prefix + "bigtoe_" + bigToeJoints[i] + suffix) + + indexToes = self.indexToeNum.value() + for i in range(indexToes): + legJoints.append(prefix + "index_" + toeJoints[i] + suffix) + + middleToes = self.middleToeNum.value() + for i in range(middleToes): + legJoints.append(prefix + "middle_" + toeJoints[i] + suffix) + + ringToes = self.ringToeNum.value() + for i in range(ringToes): + legJoints.append(prefix + "ring_" + toeJoints[i] + suffix) + + pinkyToes = self.pinkyToeNum.value() + for i in range(pinkyToes): + legJoints.append(prefix + "pinky_" + toeJoints[i] + suffix) + + #metatarsals + if self.bigToeMeta.isChecked(): + legJoints.append(prefix + "bigtoe_metatarsal" + suffix) + if self.indexToeMeta.isChecked(): + legJoints.append(prefix + "index_metatarsal" + suffix) + if self.middleToeMeta.isChecked(): + legJoints.append(prefix + "middle_metatarsal" + suffix) + if self.ringToeMeta.isChecked(): + legJoints.append(prefix + "ring_metatarsal" + suffix) + if self.pinkyToeMeta.isChecked(): + legJoints.append(prefix + "pinky_metatarsal" + suffix) + + + #build attrString + attrString = "" + for bone in legJoints: + attrString += bone + "::" + + networkNode = self.returnNetworkNode + cmds.setAttr(networkNode + ".Created_Bones", lock = False) + cmds.setAttr(networkNode + ".Created_Bones", attrString, type = "string", lock = True) + + #reset button + self.applyButton.setEnabled(False) + + #hide/show noToes geo based on numToes + numToes = 0 + for each in [self.bigToeNum, self.indexToeNum, self.middleToeNum, self.ringToeNum, self.pinkyToeNum]: + value = each.value() + if value > 0: + numToes += 1 + cmds.setAttr(self.name + "_noToes_bone_geo.v", lock = False) + if numToes > 0: + cmds.setAttr(self.name + "_noToes_bone_geo.v", 0, lock = True) + else: + cmds.setAttr(self.name + "_noToes_bone_geo.v", 1, lock = True) + + #update joint mover + self.editJointMoverViaSpinBox(self.bigToeNum, "bigtoe", True) + self.editJointMoverViaSpinBox(self.indexToeNum, "index", False) + self.editJointMoverViaSpinBox(self.middleToeNum, "middle", False) + self.editJointMoverViaSpinBox(self.ringToeNum, "ring", False) + self.editJointMoverViaSpinBox(self.pinkyToeNum, "pinky", False) + + self.editJointMoverTwistBones(self.thighTwistNum, "thigh") + self.editJointMoverTwistBones(self.calfTwistNum, "calf") + + self.includeBallJoint(False) + + self.editMetaTarsals(self.bigToeMeta, "bigtoe") + self.editMetaTarsals(self.indexToeMeta, "index") + self.editMetaTarsals(self.middleToeMeta, "middle") + self.editMetaTarsals(self.ringToeMeta, "ring") + self.editMetaTarsals(self.pinkyToeMeta, "pinky") + + + #set network node attributes + cmds.setAttr(networkNode + ".thighTwists", lock = False) + cmds.setAttr(networkNode + ".thighTwists", thighTwists, lock = True) + + cmds.setAttr(networkNode + ".calfTwists", lock = False) + cmds.setAttr(networkNode + ".calfTwists", calfTwists, lock = True) + + cmds.setAttr(networkNode + ".bigToeJoints", lock = False) + cmds.setAttr(networkNode + ".bigToeJoints", bigToes, lock = True) + + cmds.setAttr(networkNode + ".indexToeJoints", lock = False) + cmds.setAttr(networkNode + ".indexToeJoints", indexToes, lock = True) + + cmds.setAttr(networkNode + ".middleToeJoints", lock = False) + cmds.setAttr(networkNode + ".middleToeJoints", middleToes, lock = True) + + cmds.setAttr(networkNode + ".ringToeJoints", lock = False) + cmds.setAttr(networkNode + ".ringToeJoints", ringToes, lock = True) + + cmds.setAttr(networkNode + ".pinkyToeJoints", lock = False) + cmds.setAttr(networkNode + ".pinkyToeJoints", pinkyToes, lock = True) + + cmds.setAttr(networkNode + ".includeBall", lock = False) + cmds.setAttr(networkNode + ".includeBall", ballJoint, lock = True) + + cmds.setAttr(networkNode + ".bigToeMeta", lock = False) + cmds.setAttr(networkNode + ".bigToeMeta", self.bigToeMeta.isChecked(), lock = True) + + cmds.setAttr(networkNode + ".indexToeMeta", lock = False) + cmds.setAttr(networkNode + ".indexToeMeta", self.indexToeMeta.isChecked(), lock = True) + + cmds.setAttr(networkNode + ".ringToeMeta", lock = False) + cmds.setAttr(networkNode + ".ringToeMeta", self.ringToeMeta.isChecked(), lock = True) + + cmds.setAttr(networkNode + ".middleToeMeta", lock = False) + cmds.setAttr(networkNode + ".middleToeMeta", self.middleToeMeta.isChecked(), lock = True) + + cmds.setAttr(networkNode + ".pinkyToeMeta", lock = False) + cmds.setAttr(networkNode + ".pinkyToeMeta", self.pinkyToeMeta.isChecked(), lock = True) + + #update outliner + self.updateOutliner() + self.updateBoneCount() + + #clear selection + cmds.select(clear = True) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pinModule(self, state): + + networkNode = self.returnNetworkNode + + if state: + topLevelMover = self.name + "_thigh_mover_grp" + loc = cmds.spaceLocator()[0] + cmds.setAttr(loc + ".v", False, lock = True) + constraint = cmds.parentConstraint(topLevelMover, loc)[0] + cmds.delete(constraint) + const = cmds.parentConstraint(loc, topLevelMover)[0] + + + if not cmds.objExists(networkNode + ".pinConstraint"): + cmds.addAttr(networkNode, ln = "pinConstraint", keyable = True, at = "message") + + cmds.connectAttr(const + ".message", networkNode + ".pinConstraint") + + if not state: + connections = cmds.listConnections(networkNode + ".pinConstraint") + if len(connections) > 0: + constraint = connections[0] + cmds.delete(constraint) + + cmds.select(clear = True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skinProxyGeo(self): + + #get the network node + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + baseName = cmds.getAttr(networkNode + ".baseName") + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + #get this module's proxy geo meshes + cmds.select(name + "_mover_grp", hi = True) + proxyGeoMeshes = [] + selection = cmds.ls(sl = True) + for each in selection: + if each.find("proxy_geo") != -1: + parent = cmds.listRelatives(each, parent = True)[0] + if parent != name + "_noToes_bone_geo": + if cmds.nodeType(each) == "transform": + proxyGeoMeshes.append(each) + + + #skin the proxy geo meshes + for mesh in proxyGeoMeshes: + dupeMesh = cmds.duplicate(mesh, name = "skin_" + mesh)[0] + cmds.setAttr(dupeMesh + ".overrideEnabled", lock = False) + cmds.setAttr(dupeMesh + ".overrideDisplayType", 0) + + #create skinned geo group + if not cmds.objExists("skinned_proxy_geo"): + cmds.group(empty = True, name = "skinned_proxy_geo") + + cmds.parent(dupeMesh, "skinned_proxy_geo") + + boneName = mesh.partition(name + "_")[2] + boneName = boneName.partition("_proxy_geo")[0] + joint = prefix + boneName + suffix + + if not cmds.objExists(joint): + cmds.delete(dupeMesh) + + else: + cmds.select([dupeMesh, joint]) + cmds.skinCluster(tsb = True, maximumInfluences = 1, obeyMaxInfluences = True, bindMethod = 0, skinMethod = 0, normalizeWeights = True) + cmds.select(clear = True) + + + + #SPECIAL CASE FOR TOES/NO TOES + numToes = 0 + for attr in ["bigToeJoints", "indexToeJoints", "middleToeJoints", "ringToeJoints", "pinkyToeJoints"]: + value = cmds.getAttr(networkNode + "." + attr) + if value > 0: + numToes += 1 + + if numToes == 0: + if cmds.getAttr(networkNode + ".includeBall") == False: + joint = prefix + "foot" + suffix + else: + joint = prefix + "ball" + suffix + + #dupe the toe_proxy geo + dupeMesh = cmds.duplicate(name + "_toe_proxy_geo")[0] + cmds.select(dupeMesh, hi = True) + cmds.delete(constraints = True) + cmds.parent(dupeMesh, "skinned_proxy_geo") + + #skin the geo + if not cmds.objExists(joint): + cmds.delete(dupeMesh) + + else: + cmds.select([dupeMesh, joint]) + cmds.skinCluster(tsb = True, maximumInfluences = 1, obeyMaxInfluences = True, bindMethod = 0, skinMethod = 0, normalizeWeights = True) + cmds.select(clear = True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def changeSide(self): + + #gather information (current name, current parent, etc) + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + parent = cmds.getAttr(networkNode + ".parentModuleBone") + currentSide = cmds.getAttr(networkNode + ".side") + + if cmds.getAttr(networkNode + ".aimMode") == True: + self.aimMode_Setup(False) + + #call on base class delete + cmds.select(self.name + "_mover_grp", hi = True) + nodes = cmds.ls(sl = True) + for node in nodes: + cmds.lockNode(lock = False) + cmds.delete(self.name + "_mover_grp") + + + #figure out side + if currentSide == "Left": + cmds.setAttr(networkNode + ".side", lock = False) + cmds.setAttr(networkNode + ".side", "Right", type = "string", lock = True) + side = "Right" + if currentSide == "Right": + cmds.setAttr(networkNode + ".side", lock = False) + cmds.setAttr(networkNode + ".side", "Left", type = "string", lock = True) + side = "Left" + + + #build new jmPath name + jmPath = jointMover.partition(".ma")[0] + "_" + side + ".ma" + self.jointMover_Build(jmPath) + + #parent the joint mover to the offset mover of the parent + mover = "" + + if parent == "root": + cmds.parent(name + "_mover_grp", "root_mover") + mover = "root_mover" + + else: + #find the parent mover name to parent to + networkNodes = utils.returnRigModules() + mover = utils.findMoverNodeFromJointName(networkNodes, parent) + if mover != None: + cmds.parent(name + "_mover_grp", mover) + + #create the connection geo between the two + childMover = utils.findOffsetMoverFromName(name) + rigging.createBoneConnection(mover, childMover, name) + self.applyModuleChanges(self) + + self.aimMode_Setup(True) + + + cmds.select(clear = True) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def aimMode_Setup(self, state): + + #get attributes needed + name = self.groupBox.title() + networkNode = self.returnNetworkNode + side = cmds.getAttr(networkNode + ".side") + + #setup aim vector details per side + legAim = [-1, 0, 0] + legUp = [1, 0, 0] + ballAim = [0, -1, 0] + toeAim = [1, 0, 0] + toeUp = [0, 1, 0] + + if side == "Right": + legAim = [1, 0, 0] + legUp = [-1, 0, 0] + ballAim = [0, 1, 0] + toeAim = [-1, 0, 0] + toeUp = [0, -1, 0] + + #if passed in state is True: + if state: + #setup aim constraints + + #mesh movers on thigh/calf + cmds.aimConstraint(name + "_calf_lra", name + "_thigh_mover_geo", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1], mo = True) + cmds.aimConstraint(name + "_foot_lra", name + "_calf_mover_geo", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1], mo = True) + + + cmds.aimConstraint(name + "_calf_mover_offset", name + "_thigh_mover_offset", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1]) + cmds.aimConstraint(name + "_foot_mover_offset", name + "_calf_mover_offset", aimVector = legAim, upVector = legUp, wut = "scene", wu = [0, 0, 1]) + + #ball + if cmds.getAttr(name + "_ball_mover_grp.v") == True: + cmds.aimConstraint(name + "_ball_mover_offset", name + "_foot_mover_offset", aimVector = ballAim, upVector = legUp, wut = "scene", wu = [0, 0, 1], mo = True) + + #big toe + if cmds.getAttr(name + "_bigtoe_proximal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_bigtoe_proximal_phalange_mover_offset", name + "_bigtoe_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_bigtoe_distal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_bigtoe_distal_phalange_mover_offset", name + "_bigtoe_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + + #index toe + if cmds.getAttr(name + "_index_proximal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_index_proximal_phalange_mover_offset", name + "_index_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_index_middle_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_index_middle_phalange_mover_offset", name + "_index_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_index_distal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_index_distal_phalange_mover_offset", name + "_index_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + + #middle toe + if cmds.getAttr(name + "_middle_proximal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_middle_proximal_phalange_mover_offset", name + "_middle_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_middle_middle_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_middle_middle_phalange_mover_offset", name + "_middle_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_middle_distal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_middle_distal_phalange_mover_offset", name + "_middle_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + + #ring toe + if cmds.getAttr(name + "_ring_proximal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_ring_proximal_phalange_mover_offset", name + "_ring_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_ring_middle_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_ring_middle_phalange_mover_offset", name + "_ring_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_ring_distal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_ring_distal_phalange_mover_offset", name + "_ring_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + + #pinky toe + if cmds.getAttr(name + "_pinky_proximal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_pinky_proximal_phalange_mover_offset", name + "_pinky_metatarsal_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_pinky_middle_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_pinky_middle_phalange_mover_offset", name + "_pinky_proximal_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + if cmds.getAttr(name + "_pinky_distal_phalange_mover_grp.v") == True: + cmds.aimConstraint(name + "_pinky_distal_phalange_mover_offset", name + "_pinky_middle_phalange_mover_offset", aimVector = toeAim, upVector = toeUp, wut = "scene", wu = [0, 0, 1]) + + #if passed in state is False: + if not state: + cmds.select(name + "_mover_grp", hi = True) + aimConstraints = cmds.ls(sl = True, exactType = "aimConstraint") + + for constraint in aimConstraints: + cmds.lockNode(constraint, lock = False) + cmds.delete(constraint) + + self.bakeOffsets() + cmds.select(clear = True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def coplanarMode(self): + + #current selection + currentSelection = cmds.ls(sl = True) + + #get the state of the button + state = self.coplanarBtn.isChecked() + + #write the attribute on the module + networkNode = self.returnNetworkNode + + import System.utils as utils + + aimState = cmds.getAttr(networkNode + ".aimMode") + + if state: + + + #lock out offset movers as they aren't to be used in coplanar mode + offsetMovers = self.returnJointMovers[1] + for mover in offsetMovers: + cmds.lockNode(mover, lock = False) + for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]: + try: + cmds.setAttr(mover + attr, lock = True) + except: + pass + + #fire script job that watches the coplanarIkHandle attributes, and when they change, snap to IK knee in tz + self.coplanarScriptJob1 = cmds.scriptJob(attributeChange = [self.name + "_coplanarIkHandle.translate", partial(riggingUtils.coPlanarModeSnap, self, self.name + "_coplanar_knee", self.name + "_calf_mover_offset", [self.name + "_coplanar_thigh", self.name + "_coplanar_knee"], [self.name + "_thigh_mover_offset", self.name + "_calf_mover_offset"], self.name + "_foot_mover", [])], kws = True) + + #make sure aim mode is on + if not aimState: + self.aimMode_Setup(True) + + + #reselect current selection + if len(currentSelection) > 0: + cmds.select(currentSelection) + + if not state: + #unlock all offset movers + offsetMovers = self.returnJointMovers[1] + for mover in offsetMovers: + for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]: + try: + cmds.setAttr(mover + attr, lock = False) + + except: + pass + + cmds.lockNode(mover, lock = True) + + cmds.scriptJob(kill = self.coplanarScriptJob1) + self.aimMode_Setup(False) + + if aimState: + self.aimMode_Setup(True) + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def setupModelPoseForRig(self): + + createdConstraints = [] + + legJoints = self.getMainLegJoints() + + thighMover = self.name + "_thigh_mover_offset" + calfMover = self.name + "_calf_mover_offset" + footMover = self.name + "_foot_mover_offset" + + footCtrlConst = cmds.parentConstraint(footMover, self.ikFootCtrl, mo = True)[0] + createdConstraints.append(footCtrlConst) + + fkThighConst = cmds.parentConstraint(thighMover, "fk_" + legJoints[0] + "_anim")[0] + createdConstraints.append(fkThighConst) + + fkCalfConst = cmds.parentConstraint(calfMover, "fk_" + legJoints[1] + "_anim")[0] + createdConstraints.append(fkCalfConst) + + fkFootConst = cmds.parentConstraint(footMover, "fk_" + legJoints[2] + "_anim")[0] + createdConstraints.append(fkFootConst) + + + if len(legJoints) == 4: + if legJoints[3] != None: + ballMover = self.name + "_ball_mover_offset" + + fkBallConst = cmds.parentConstraint(ballMover, "fk_" + legJoints[3] + "_anim")[0] + createdConstraints.append(fkBallConst) + + return createdConstraints + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def matchModelPose(self): + + #match the knee twist attribute to the offset mover for the knee + legJoints = self.getMainLegJoints() + + #first create locators + loc1 = cmds.spaceLocator(name = self.name + "_matchLoc1")[0] + loc2 = cmds.spaceLocator(name = self.name + "_matchLoc2")[0] + + constraint = cmds.parentConstraint(self.name + "_calf_mover_offset", loc1)[0] + cmds.delete(constraint) + cmds.parent(loc1, self.name + "_calf_mover_offset") + + constraint = cmds.parentConstraint(legJoints[1], loc2)[0] + cmds.delete(constraint) + cmds.parent(loc2, legJoints[1]) + + cmds.move(0, -30, 0, loc1, os = True, r = True) + cmds.move(0, -30, 0, loc2, os = True, r = True) + + for x in range(1500): + angle = mathUtils.getAngleBetween(loc1, loc2) + if abs(angle) > .1: + self.matchKneeTwist(angle, loc1, loc2) + else: + break + + cmds.delete(loc1) + cmds.delete(loc2) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def matchKneeTwist(self, angle, object1, object2): + + currentVal = cmds.getAttr(self.ikFootCtrl + ".knee_twist") + cmds.setAttr(self.ikFootCtrl + ".knee_twist", currentVal + .25) + + newAngle = mathUtils.getAngleBetween(object1, object2) + if newAngle > angle: + cmds.setAttr(self.ikFootCtrl + ".knee_twist", currentVal - .5) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX(self, importMethod, character): + + returnControls = [] + + networkNode = self.returnRigNetworkNode + fkControls = cmds.getAttr(networkNode + ".fkControls") + ikControls = cmds.getAttr(networkNode + ".ikV1Controls") + moduleName = cmds.getAttr(networkNode + ".moduleName") + + + #find created joints + joints = cmds.getAttr(networkNode + ".Created_Bones") + + splitJoints = joints.split("::") + createdJoints = [] + legJoints = [] + + for bone in splitJoints: + if bone != "": + createdJoints.append(bone) + + for joint in createdJoints: + if joint.find("thigh") != -1: + if joint.find("twist") == -1: + thighJoint = joint + legJoints.append(thighJoint) + + if joint.find("calf") != -1: + if joint.find("twist") == -1: + calfJoint = joint + legJoints.append(calfJoint) + + if joint.find("foot") != -1: + footJoint = joint + legJoints.append(footJoint) + + if joint.find("ball") != -1: + ballJoint = joint + legJoints.append(ballJoint) + + + #Handle Import Method/Constraints + if importMethod == "FK": + cmds.setAttr(character + ":" + moduleName + "_settings.mode", 0) + + for joint in legJoints: + cmds.parentConstraint(joint, character + ":fk_" + joint + "_anim") + returnControls.append(character + ":fk_" + joint + "_anim") + + + if importMethod == "IK": + cmds.parentConstraint(legJoints[2], character + ":ik_" + legJoints[2] + "_anim", mo = True) + returnControls.append(character + ":ik_" + legJoints[2] + "_anim") + + if importMethod == "Both": + cmds.parentConstraint(legJoints[2], character + ":ik_" + legJoints[2] + "_anim", mo = True) + returnControls.append(character + ":ik_" + legJoints[2] + "_anim") + + for joint in legJoints: + cmds.parentConstraint(joint, character + ":fk_" + joint + "_anim") + returnControls.append(character + ":fk_" + joint + "_anim") + + + if importMethod == "None": + pass + + return returnControls + + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX_post(self, importMethod, character): + + #get leg joints/controls + legJoints = self.getMainLegJoints() + self.ikFootCtrl = character + ":ik_" + legJoints[2] + "_anim" + + cmds.refresh(force = True) + + #get start and end frames + start = cmds.playbackOptions(q = True, min = True) + end = cmds.playbackOptions(q = True, max = True) + + if importMethod == "IK" or importMethod == "Both": + for i in range(int(start), int(end) + 1): + cmds.currentTime(i) + self.ikKneeMatch(character, legJoints[1], legJoints[0], character + ":" + legJoints[1]) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def switchMode(self, mode, checkBox, range = False): + + #get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + #are we matching? + if not range: + match = checkBox.isChecked() + else: + match = True + + #if being called from match over frame range + if range: + if mode == matchData[1][0]: + mode = "FK" + if mode == matchData[1][1]: + mode = "IK" + + + #switch to FK mode + if mode == "FK": + #get current mode + currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode") + if currentMode == 0.0: + cmds.warning("Already in FK mode.") + return + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if match: + #get fk controls + controls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + + #create a duplicate chain + topCtrl = controls[0] + topGrp = cmds.listRelatives(namespace + ":" + topCtrl, parent = True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world = True) + + + #match the fk controls to the corresponding joint + for control in controls: + joint = control.partition("fk_")[2].partition("_anim")[0] + joint = namespace + ":" + joint + constraint = cmds.parentConstraint(joint, control)[0] + cmds.delete(constraint) + + translate = cmds.getAttr(control + ".translate")[0] + rotate = cmds.getAttr(control + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], type = 'double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type = 'double3') + + cmds.setKeyframe(namespace + ":" + control) + + #delete dupes + cmds.delete(newControls[0]) + + #switch modes + if not range: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + + #switch to IK mode + if mode == "IK": + + #get current mode + currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode") + if currentMode == 1.0: + return + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if match: + + #get IK controls + controls = json.loads(cmds.getAttr(networkNode + ".ikV1Controls")) + + #create a duplicate foot anim + control = controls[0] + topGrp = cmds.listRelatives(namespace + ":" + control, parent = True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world = True) + + + #duplicate the control once more and parent under the fkMatch node + matchCtrl = cmds.duplicate(control, po = True)[0] + cmds.parent(matchCtrl, control + "_fkMatch") + + #match the foot anim to the foot joint + joint = control.partition("ik_")[2].partition("_anim")[0] + joint = namespace + ":" + joint + constraint = cmds.parentConstraint(joint, control + "_fkMatch")[0] + cmds.delete(constraint) + + #unparent the match control from the fkMatch, and put it under the topGrp + cmds.parent(matchCtrl, topGrp) + + #this will now give use good values + translate = cmds.getAttr(matchCtrl + ".translate")[0] + rotate = cmds.getAttr(matchCtrl + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], type = 'double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type = 'double3') + + cmds.setKeyframe(namespace + ":" + control) + + #delete dupes + cmds.delete(newControls[0]) + cmds.delete(matchCtrl) + + + #match the toe wiggle control to the ball (if applicable) + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + if len(fkControls) > 3: + toeWiggle = controls[3] + ball = fkControls[3] + + rotate = cmds.getAttr(namespace + ":" + ball + ".rotate")[0] + cmds.setAttr(namespace + ":" + toeWiggle + ".rotate", rotate[0], rotate[1], rotate[2], type = 'double3') + + + #match the knee twist + legJoints = self.getMainLegJoints() + self.ikKneeMatch(namespace, namespace + ":" + legJoints[1], namespace + ":" + legJoints[0], namespace + ":ikV1_" + legJoints[1] + "_joint") + + + #switch modes + if not range: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def ikKneeMatch(self, character, startJoint, middleJoint, endJoint): + + #get leg joints/controls + legJoints = self.getMainLegJoints() + self.ikFootCtrl = character + ":ik_" + legJoints[2] + "_anim" + + #create locators + startPoint = cmds.spaceLocator()[0] + cmds.parentConstraint(startJoint, startPoint)[0] + + midPoint = cmds.spaceLocator()[0] + cmds.parentConstraint(middleJoint, midPoint)[0] + + endPoint = cmds.spaceLocator()[0] + cmds.parentConstraint(endJoint, endPoint)[0] + + #create angle node and hook up attrs to locs + angleDimNode = cmds.createNode("angleDimension") + cmds.connectAttr(startPoint + ".translate", angleDimNode + ".startPoint") + cmds.connectAttr(midPoint + ".translate", angleDimNode + ".middlePoint") + cmds.connectAttr(endPoint + ".translate", angleDimNode + ".endPoint") + + + #find general direction to go in + origAngle = cmds.getAttr(angleDimNode + ".angle") + + direction = 1 + if origAngle != 0: + cmds.setAttr(self.ikFootCtrl + ".knee_twist", 1) + newAngle = cmds.getAttr(angleDimNode + ".angle") + + if newAngle > origAngle: + direction = -1 + + + #reset knee twist + cmds.setAttr(self.ikFootCtrl + ".knee_twist", 0) + + + #HIDE EVERYTHING + panels = cmds.getPanel( type = "modelPanel") + for panel in panels: + editor = cmds.modelPanel(panel, q = True, modelEditor = True) + cmds.modelEditor(editor, edit = True, allObjects = 0) + + + #find best angle + for x in range(3000): + + angle = cmds.getAttr(angleDimNode + ".angle") + + if angle > 0.5: + currentVal = cmds.getAttr(self.ikFootCtrl + ".knee_twist") + cmds.setAttr(self.ikFootCtrl + ".knee_twist", currentVal + direction) + cmds.refresh() + + else: + cmds.setKeyframe(self.ikFootCtrl + ".knee_twist") + cmds.delete([startPoint, midPoint, endPoint]) + cmds.delete(cmds.listRelatives(angleDimNode, parent = True)[0]) + break + + #SHOW EVERYTHING + panels = cmds.getPanel( type = "modelPanel") + for panel in panels: + editor = cmds.modelPanel(panel, q = True, modelEditor = True) + cmds.modelEditor(editor, edit = True, allObjects = 1) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def selectRigControls(self, mode): + + + #get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + #list any attributes on the network node that contain "controls" + controls = cmds.listAttr(networkNode, st = "*Controls") + fkControls = ["fkControls", "thighTwistControls", "calfTwistControls"] + ikControls = ["ikV1Controls"] + + #get that data on that attr + for control in controls: + + #select all controls + if mode == "all": + data = json.loads(cmds.getAttr(networkNode + "." + control)) + if data != None: + for each in data: + cmds.select(namespace + ":" + each, add = True) + + #select fk controls + if mode == "fk": + if control in fkControls: + data = json.loads(cmds.getAttr(networkNode + "." + control)) + if data != None: + for each in data: + if each.find("fk") != -1: + cmds.select(namespace + ":" + each, add = True) + + #select ik controls + if mode == "ik": + if control in ikControls: + data = json.loads(cmds.getAttr(networkNode + "." + control)) + if data != None: + for each in data: + if each.find("fk") == -1: + cmds.select(namespace + ":" + each, add = True) + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + @classmethod + def getinstances(cls): + for ref in cls._instances: + obj = ref() + + diff --git a/Core/Scripts/RigModules/ART_Root.py b/Core/Scripts/RigModules/ART_Root.py new file mode 100644 index 0000000..74d3ea5 --- /dev/null +++ b/Core/Scripts/RigModules/ART_Root.py @@ -0,0 +1,246 @@ +#standard imports +import maya.cmds as cmds +import json +from functools import partial +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + +#external imports +from System.ART_RigModule import ART_RigModule +import System.riggingUtils as riggingUtils +import System.interfaceUtils as interfaceUtils + +#file attributes +icon = "Core/Icons/Modules/root.png" +search = "Root" +className = "ART_Root" +baseName = "root" +fbxImport = ["None", "Root Motion: Offset", "Root Motion: Master", "Root Motion: Root"] +matchData = [False, None] +controlTypes = [["rootControls", "FK"]] + + +class ART_Root(ART_RigModule): + + def __init__(self, rigUiInst, moduleUserName): + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + + ART_RigModule.__init__(self, "ART_Root_Module", "ART_Root", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + #call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + #add custom attributes for this specific module + cmds.addAttr(self.networkNode, sn = "Created_Bones", dt = "string", keyable = False) + cmds.setAttr(self.networkNode + ".Created_Bones", "root", type = "string", lock = True) + + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + #groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 85, False) + + #add a label to the root module saying this module cannot be edited or removed + self.layout = QtWidgets.QVBoxLayout(self.groupBox) + self.label = QtWidgets.QLabel("All rigs must have a root module. This module cannot be edited or removed.") + self.layout.addWidget(self.label) + self.label.setGeometry(QtCore.QRect(10, 20, 300, 60)) + self.label.setMinimumHeight(60) + self.label.setWordWrap(True) + + + #add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pickerUI(self, center, animUI, networkNode, namespace): + + #create qBrushes + yellowBrush = QtCore.Qt.yellow + blueBrush = QtGui.QColor(100,220,255) + purpleBrush = QtGui.QColor(111,48,161) + clearBrush = QtGui.QBrush(QtCore.Qt.black) + clearBrush.setStyle(QtCore.Qt.NoBrush) + + #create border item + if networkNode.find(":") != -1: + moduleNode = networkNode.partition(":")[2] + else: + moduleNode = networkNode + borderItem = interfaceUtils.pickerBorderItem(center.x() - 40, center.y() - 70, 50, 98, clearBrush, moduleNode) + + #get controls + namespace + networkNode = self.returnNetworkNode + controls = json.loads(cmds.getAttr(networkNode + ".rootControls")) + + #master anim button + masterBtn = interfaceUtils.pickerButton(30, 30, [10,2], namespace + controls[0], yellowBrush, borderItem) + interfaceUtils.addTextToButton("M", masterBtn) + + #offset anim button + offsetBtn = interfaceUtils.pickerButton(30, 30, [10,34], namespace + controls[1], blueBrush, borderItem) + interfaceUtils.addTextToButton("O", offsetBtn) + + #root anim button + rootBtn = interfaceUtils.pickerButton(30, 30, [10,66], namespace + controls[2], purpleBrush, borderItem) + interfaceUtils.addTextToButton("R", rootBtn) + + #======================================================================= + # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5) + #======================================================================= + scriptJob = cmds.scriptJob(event = ["SelectionChanged", partial(self.selectionScriptJob_animUI,[[masterBtn,namespace + controls[0], yellowBrush],[offsetBtn, namespace + controls[1], blueBrush],[rootBtn, namespace + controls[2], purpleBrush]])], kws = True) + borderItem.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + return [borderItem, False, scriptJob] + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addJointMoverToOutliner(self): + + index = self.rigUiInst.treeWidget.topLevelItemCount() + + #Add the module to the tree widget in the outliner tab of the rig creator UI + self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget) + self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name) + foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground) + #add the buttons + self.createGlobalMoverButton(self.name, self.outlinerWidgets[self.name + "_treeModule"], self.rigUiInst) + + #create selection script job for module + self.updateBoneCount() + self.createScriptJob() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildRigCustom(self, textEdit, uiInst): + + if textEdit != None: + textEdit.append(" Building Root Rig..") + + #get the created joint + networkNode = self.returnNetworkNode + rootJoint = cmds.getAttr(networkNode + ".Created_Bones") + + #create the rig grp + rigGrp = cmds.group(empty = True, name = "rig_grp") + + + #Need to build 3 controls, the master, the offset, and the root control + masterControls = riggingUtils.createControlFromMover(rootJoint, networkNode, False, True) + + #rename controls + masterControl = cmds.rename(masterControls[0], "master_anim") + masterCtrlGrp = cmds.rename(masterControls[1], "master_anim_grp") + masterSpaceSwitch = cmds.rename(masterControls[2], "master_anim_space_switcher") + masterSpace = cmds.rename(masterControls[3], "master_anim_space_switcher_follow") + + cmds.parent(masterSpace, rigGrp) + #scale masterControl + cmds.setAttr(masterControl + ".scale", 2, 2, 2, type = "double3") + cmds.makeIdentity(masterControl, t = 1, r = 1, s = 1, apply = True) + + #alias attr master control + cmds.aliasAttr("globalScale", masterControl + ".scaleZ") + cmds.connectAttr(masterControl + ".globalScale", masterControl + ".scaleX") + cmds.connectAttr(masterControl + ".globalScale", masterControl + ".scaleY") + cmds.setAttr(masterControl + ".scaleX", keyable = False) + cmds.setAttr(masterControl + ".scaleY", keyable = False) + cmds.setAttr(masterControl + ".visibility", lock = True, keyable = False) + + #create offset anim control + offsetAnim = riggingUtils.createControl("circle", 40, "offset_anim", False) + cmds.parent(offsetAnim, masterControl) + cmds.setAttr(offsetAnim + ".overrideEnabled", 1) + cmds.setAttr(offsetAnim + ".overrideColor", 18) + + for attr in [".visibility", ".scaleX", ".scaleY", ".scaleZ"]: + cmds.setAttr(offsetAnim + attr, lock = True, keyable = False) + + #create the root control + rootAnim = riggingUtils.createControl("sphere", 5, "root_anim", False) + cmds.parent(rootAnim, offsetAnim) + cmds.makeIdentity(rootAnim, t = 1, r = 1, s = 1, apply = True) + cmds.setAttr(rootAnim + ".overrideEnabled", 1) + cmds.setAttr(rootAnim + ".overrideColor", 30) + cmds.parentConstraint(rootAnim, "driver_root") + cmds.scaleConstraint(rootAnim, "driver_root") + + for attr in [".visibility", ".scaleX", ".scaleY", ".scaleZ"]: + cmds.setAttr(rootAnim + attr, lock = True, keyable = False) + + if not cmds.objExists(networkNode + ".rootControls"): + cmds.addAttr(networkNode, ln = "rootControls", dt = "string") + + controlList = [masterControl, offsetAnim, rootAnim] + jsonString = json.dumps(controlList) + cmds.setAttr(networkNode + ".rootControls", jsonString, type = "string") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX(self, importMethod, character): + + returnControls = [] + + if importMethod == "Root Motion: Offset": + + cmds.parentConstraint("root", character + ":" + "offset_anim") + returnControls.append(character + ":" + "offset_anim") + + + if importMethod == "Root Motion: Master": + cmds.parentConstraint("root", character + ":" + "master_anim") + returnControls.append(character + ":" + "master_anim") + + if importMethod == "Root Motion: Root": + cmds.parentConstraint("root", character + ":" + "root_anim") + returnControls.append(character + ":" + "root_anim") + + if importMethod == "None": + pass + + return returnControls + + + + + + + + + + diff --git a/Core/Scripts/RigModules/ART_Torso.py b/Core/Scripts/RigModules/ART_Torso.py new file mode 100644 index 0000000..01bcc18 --- /dev/null +++ b/Core/Scripts/RigModules/ART_Torso.py @@ -0,0 +1,2394 @@ +import maya.cmds as cmds +from System.ART_RigModule import ART_RigModule +import os, time, json, weakref +from functools import partial + +import System.interfaceUtils as interfaceUtils +import System.riggingUtils as riggingUtils +import System.utils as utils + +from ThirdParty.Qt import QtGui, QtCore, QtWidgets + +# file attributes +icon = "Modules/torso.png" +hoverIcon = "Modules/hover_torso.png" +search = "biped:torso:spine" +className = "ART_Torso" +jointMover = "Core/JointMover/ART_Torso_3Spine.ma" +baseName = "torso" +rigs = ["FK::IK"] +fbxImport = ["None", "FK", "IK", "Both"] +matchData = [True, ["Match FK to IK", "Match IK to FK"]] +controlTypes = [["pelvisControls", "FK"], ["fkControls", "FK"], ["ikControls", "IK"]] + + +# begin class +class ART_Torso(ART_RigModule): + _instances = set() + + def __init__(self, rigUiInst, moduleUserName): + + self.rigUiInst = rigUiInst + self.moduleUserName = moduleUserName + self.outlinerWidgets = {} + self.__class__._instances.add(weakref.ref(self)) + + ART_RigModule.__init__(self, "ART_Torso_Module", "ART_Torso", moduleUserName) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addAttributes(self): + # call the base class method first to hook up our connections to the master module + ART_RigModule.addAttributes(self) + + # add custom attributes for this specific module + cmds.addAttr(self.networkNode, sn="Created_Bones", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".Created_Bones", "pelvis::spine_01::spine_02::spine_03::", type="string", + lock=True) + + cmds.addAttr(self.networkNode, sn="baseName", dt="string", keyable=False) + cmds.setAttr(self.networkNode + ".baseName", baseName, type="string", lock=True) + + cmds.addAttr(self.networkNode, sn="canAim", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".canAim", True, lock=True) + + cmds.addAttr(self.networkNode, sn="aimMode", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".aimMode", False, lock=True) + + # joint mover settings + + cmds.addAttr(self.networkNode, sn="includePelvis", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".includePelvis", True, lock=True) + + cmds.addAttr(self.networkNode, sn="spineJoints", keyable=False) + cmds.setAttr(self.networkNode + ".spineJoints", 3, lock=True) + + # rig creation settings + cmds.addAttr(self.networkNode, sn="buildFK", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".buildFK", True, lock=True) + + cmds.addAttr(self.networkNode, sn="buildIK", at="bool", keyable=False) + cmds.setAttr(self.networkNode + ".buildIK", True, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skeletonSettings_UI(self, name): + networkNode = self.returnNetworkNode + + # groupbox all modules get + ART_RigModule.skeletonSettings_UI(self, name, 335, 295, True) + + font = QtGui.QFont() + font.setPointSize(8) + + headerFont = QtGui.QFont() + headerFont.setPointSize(8) + headerFont.setBold(True) + + # create a VBoxLayout to add to our Groupbox and then add a QFrame for our signal/slot + self.layout = QtWidgets.QVBoxLayout(self.groupBox) + self.frame = QtWidgets.QFrame(self.groupBox) + self.layout.addWidget(self.frame) + + self.frame.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)) + self.frame.setMinimumSize(QtCore.QSize(320, 260)) + self.frame.setMaximumSize(QtCore.QSize(320, 260)) + + # add layout for custom settings + self.customSettingsLayout = QtWidgets.QVBoxLayout(self.frame) + + # current parent + self.currentParentMod = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.currentParentMod) + self.currentParentLabel = QtWidgets.QLabel("Current Parent: ") + self.currentParentLabel.setFont(font) + self.currentParentMod.addWidget(self.currentParentLabel) + + parent = cmds.getAttr(networkNode + ".parentModuleBone") + self.currentParent = QtWidgets.QLabel(parent) + self.currentParent.setFont(font) + self.currentParent.setAlignment(QtCore.Qt.AlignHCenter) + self.currentParentMod.addWidget(self.currentParent) + + # button layout for name/parent + self.buttonLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.buttonLayout) + self.changeNameBtn = QtWidgets.QPushButton("Change Name") + self.changeParentBtn = QtWidgets.QPushButton("Change Parent") + self.buttonLayout.addWidget(self.changeNameBtn) + self.buttonLayout.addWidget(self.changeParentBtn) + self.changeNameBtn.setObjectName("blueButton") + self.changeParentBtn.setObjectName("blueButton") + + # bake offsets button + self.bakeToolsLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.bakeToolsLayout) + + # Bake OFfsets + self.bakeOffsetsBtn = QtWidgets.QPushButton("Bake Offsets") + self.bakeOffsetsBtn.setFont(headerFont) + self.bakeToolsLayout.addWidget(self.bakeOffsetsBtn) + self.bakeOffsetsBtn.clicked.connect(self.bakeOffsets) + self.bakeOffsetsBtn.setToolTip("Bake the offset mover values up to the global movers to get them in sync") + + self.bakeOffsetsBtn.setObjectName("blueButton") + + # Pelvis Settings + spacerItem = QtWidgets.QSpacerItem(200, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.customSettingsLayout.addItem(spacerItem) + + self.pelvisCB = QtWidgets.QCheckBox("Include Pelvis?") + self.pelvisCB.setChecked(True) + self.customSettingsLayout.addWidget(self.pelvisCB) + self.pelvisCB.stateChanged.connect(self.toggleButtonState) + spacerItem = QtWidgets.QSpacerItem(200, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.customSettingsLayout.addItem(spacerItem) + + # Spine Bones + self.spineLayout = QtWidgets.QHBoxLayout() + self.customSettingsLayout.addLayout(self.spineLayout) + + self.numSpineBonesLabel = QtWidgets.QLabel("Number of Spine Bones: ") + self.numSpineBonesLabel.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + self.numSpineBonesLabel.setMinimumSize(QtCore.QSize(200, 20)) + self.numSpineBonesLabel.setMaximumSize(QtCore.QSize(200, 20)) + self.spineLayout.addWidget((self.numSpineBonesLabel)) + + self.numSpine = QtWidgets.QSpinBox() + self.numSpine.setMaximum(5) + self.numSpine.setMinimum(2) + self.numSpine.setMinimumSize(QtCore.QSize(100, 20)) + self.numSpine.setMaximumSize(QtCore.QSize(100, 20)) + self.numSpine.setValue(3) + self.numSpine.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.spineLayout.addWidget(self.numSpine) + + # rebuild button + spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + self.customSettingsLayout.addItem(spacerItem) + + self.applyButton = QtWidgets.QPushButton("Apply Changes") + self.customSettingsLayout.addWidget(self.applyButton) + self.applyButton.setFont(headerFont) + self.applyButton.setMinimumSize(QtCore.QSize(300, 40)) + self.applyButton.setMaximumSize(QtCore.QSize(300, 40)) + self.applyButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + self.applyButton.setEnabled(False) + + # add to the rig cretor UI's module settings layout VBoxLayout + self.rigUiInst.moduleSettingsLayout.addWidget(self.groupBox) + + # button signal/slots + self.changeNameBtn.clicked.connect(partial(self.changeModuleName, baseName, self, self.rigUiInst)) + self.changeParentBtn.clicked.connect(partial(self.changeModuleParent, self, self.rigUiInst)) + self.applyButton.clicked.connect(partial(self.applyModuleChanges, self)) + + # signal slot for groupbox checkbox + QtCore.QObject.connect(self.groupBox, QtCore.SIGNAL("toggled(bool)"), self.frame.setVisible) + self.groupBox.setChecked(False) + + # spinBox & checkbox signal/slots + self.numSpine.valueChanged.connect(self.toggleButtonState) + + # Populate the settings UI based on the network node attributes + self.updateSettingsUI() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pickerUI(self, center, animUI, networkNode, namespace): + + self.namespace = namespace + + # create qBrushes + yellowBrush = QtCore.Qt.yellow + blueBrush = QtGui.QColor(100, 220, 255) + purpleBrush = QtGui.QColor(111, 48, 161) + greenBrush = QtGui.QColor(0, 255, 30) + clearBrush = QtGui.QBrush(QtCore.Qt.black) + clearBrush.setStyle(QtCore.Qt.NoBrush) + + # create the picker border item + if networkNode.find(":") != -1: + moduleNode = networkNode.partition(":")[2] + else: + moduleNode = networkNode + + borderItem = interfaceUtils.pickerBorderItem(center.x() - 75, center.y() - 100, 150, 200, clearBrush, + moduleNode) + + # get controls + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + fkControls.reverse() + + ikControls = None + if cmds.objExists(networkNode + ".ikControls"): + ikControls = json.loads(cmds.getAttr(networkNode + ".ikControls")) + + pelvisControls = None + if cmds.objExists(networkNode + ".pelvisControls"): + pelvisControls = json.loads(cmds.getAttr(networkNode + ".pelvisControls")) + + buttonData = [] + + # get number of spine joints + spineJoints = int(cmds.getAttr(networkNode + ".spineJoints")) + + if pelvisControls != None: + pelvisButton = interfaceUtils.pickerButtonCustom(100, 20, [[0, 0], [100, 0], [90, 20], [10, 20]], [25, 175], + namespace + pelvisControls[0], blueBrush, borderItem) + bodyButton = interfaceUtils.pickerButton(110, 20, [20, 150], namespace + pelvisControls[1], yellowBrush, + borderItem) + buttonData.append([pelvisButton, namespace + pelvisControls[0], blueBrush]) + buttonData.append([bodyButton, namespace + pelvisControls[1], yellowBrush]) + + if spineJoints == 2: + spine1Button = interfaceUtils.pickerButtonCustom(100, 50, [[10, 0], [100, 0], [110, 50], [0, 50]], [20, 95], + namespace + fkControls[0], blueBrush, borderItem) + spine2Button = interfaceUtils.pickerButtonCustom(100, 60, [[10, 60], [100, 60], [110, 0], [0, 0]], [20, 30], + namespace + fkControls[1], blueBrush, borderItem) + buttonData.append([spine1Button, namespace + fkControls[0], blueBrush]) + buttonData.append([spine2Button, namespace + fkControls[1], blueBrush]) + + if spineJoints == 3: + chestAnimButton = interfaceUtils.pickerButton(120, 20, [15, 25], namespace + ikControls[0], yellowBrush, + borderItem) + midAnimButton = interfaceUtils.pickerButton(90, 20, [30, 100], namespace + ikControls[1], yellowBrush, + borderItem) + buttonData.append([chestAnimButton, namespace + ikControls[0], yellowBrush]) + buttonData.append([midAnimButton, namespace + ikControls[1], yellowBrush]) + + spine1Button = interfaceUtils.pickerButtonCustom(80, 20, [[10, 0], [100, 0], [105, 20], [5, 20]], [20, 125], + namespace + fkControls[0], blueBrush, borderItem) + spine2Button = interfaceUtils.pickerButtonCustom(80, 20, [[10, 20], [100, 20], [100, 0], [10, 0]], [20, 75], + namespace + fkControls[1], blueBrush, borderItem) + spine3Button = interfaceUtils.pickerButtonCustom(80, 20, [[10, 20], [100, 20], [105, 0], [5, 0]], [20, 50], + namespace + fkControls[2], blueBrush, borderItem) + buttonData.append([spine1Button, namespace + fkControls[0], blueBrush]) + buttonData.append([spine2Button, namespace + fkControls[1], blueBrush]) + buttonData.append([spine3Button, namespace + fkControls[2], blueBrush]) + + if spineJoints == 4: + chestAnimButton = interfaceUtils.pickerButton(120, 20, [15, 25], namespace + ikControls[0], yellowBrush, + borderItem) + midAnimButton = interfaceUtils.pickerButton(90, 15, [30, 90], namespace + ikControls[1], yellowBrush, + borderItem) + buttonData.append([chestAnimButton, namespace + ikControls[0], yellowBrush]) + buttonData.append([midAnimButton, namespace + ikControls[1], yellowBrush]) + + spine1Button = interfaceUtils.pickerButtonCustom(80, 15, [[10, 0], [100, 0], [105, 15], [5, 15]], [20, 130], + namespace + fkControls[0], blueBrush, borderItem) + spine2Button = interfaceUtils.pickerButtonCustom(80, 15, [[10, 15], [100, 15], [95, 0], [15, 0]], [20, 110], + namespace + fkControls[1], blueBrush, borderItem) + spine3Button = interfaceUtils.pickerButtonCustom(80, 15, [[15, 15], [95, 15], [100, 0], [10, 0]], [20, 70], + namespace + fkControls[2], blueBrush, borderItem) + spine4Button = interfaceUtils.pickerButtonCustom(80, 15, [[10, 15], [100, 15], [110, 0], [0, 0]], [20, 50], + namespace + fkControls[3], blueBrush, borderItem) + buttonData.append([spine1Button, namespace + fkControls[0], blueBrush]) + buttonData.append([spine2Button, namespace + fkControls[1], blueBrush]) + buttonData.append([spine3Button, namespace + fkControls[2], blueBrush]) + buttonData.append([spine4Button, namespace + fkControls[3], blueBrush]) + + if spineJoints == 5: + chestAnimButton = interfaceUtils.pickerButton(120, 20, [15, 25], namespace + ikControls[0], yellowBrush, + borderItem) + midAnimButton = interfaceUtils.pickerButton(90, 20, [30, 95], namespace + ikControls[1], yellowBrush, + borderItem) + buttonData.append([chestAnimButton, namespace + ikControls[0], yellowBrush]) + buttonData.append([midAnimButton, namespace + ikControls[1], yellowBrush]) + + spine1Button = interfaceUtils.pickerButtonCustom(80, 10, [[0, 10], [110, 10], [105, 0], [5, 0]], [20, 135], + namespace + fkControls[0], blueBrush, borderItem) + spine2Button = interfaceUtils.pickerButtonCustom(80, 10, [[5, 10], [105, 10], [100, 0], [10, 0]], [20, 120], + namespace + fkControls[1], blueBrush, borderItem) + spine3Button = interfaceUtils.pickerButtonCustom(80, 10, [[10, 10], [100, 10], [100, 0], [10, 0]], [20, 80], + namespace + fkControls[2], blueBrush, borderItem) + spine4Button = interfaceUtils.pickerButtonCustom(80, 10, [[10, 10], [100, 10], [105, 0], [5, 0]], [20, 65], + namespace + fkControls[3], blueBrush, borderItem) + spine5Button = interfaceUtils.pickerButtonCustom(80, 10, [[5, 10], [105, 10], [110, 0], [0, 0]], [20, 50], + namespace + fkControls[4], blueBrush, borderItem) + buttonData.append([spine1Button, namespace + fkControls[0], blueBrush]) + buttonData.append([spine2Button, namespace + fkControls[1], blueBrush]) + buttonData.append([spine3Button, namespace + fkControls[2], blueBrush]) + buttonData.append([spine4Button, namespace + fkControls[3], blueBrush]) + buttonData.append([spine5Button, namespace + fkControls[4], blueBrush]) + + # ======================================================================= + # settings button + # ======================================================================= + settingsBtn = interfaceUtils.pickerButton(20, 20, [125, 180], namespace + self.name + "_settings", greenBrush, + borderItem) + buttonData.append([settingsBtn, namespace + ":" + self.name + "_settings", greenBrush]) + interfaceUtils.addTextToButton("S", settingsBtn) + + # ======================================================================= + # go through button data, adding menu items + # ======================================================================= + for each in buttonData: + button = each[0] + + fkIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/jointFilter.png")))) + ikIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/ikMode.png")))) + zeroIcon1 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroAll.png")))) + zeroIcon2 = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/zeroSel.png")))) + selectIcon = QtGui.QIcon((utils.returnFriendlyPath(os.path.join(self.iconsPath, "System/select.png")))) + + switchAction = QtWidgets.QAction('Match when Switching', button.menu) + switchAction.setCheckable(True) + switchAction.setChecked(True) + + button.menu.addAction(selectIcon, "Select All Torso Controls", partial(self.selectRigControls, "all")) + button.menu.addAction(selectIcon, "Select FK Torso Controls", partial(self.selectRigControls, "fk")) + button.menu.addAction(selectIcon, "Select IK Torso Controls", partial(self.selectRigControls, "ik")) + + button.menu.addSeparator() + + button.menu.addAction(fkIcon, "FK Mode", partial(self.switchMode, "FK", switchAction)) + button.menu.addAction(ikIcon, "IK Mode", partial(self.switchMode, "IK", switchAction)) + button.menu.addAction(switchAction) + + button.menu.addSeparator() + + button.menu.addAction(zeroIcon1, "Zero Out Attrs (All)", partial(self.resetRigControls, True)) + button.menu.addAction(zeroIcon2, "Zero Out Attrs (Sel)", partial(self.resetRigControls, False)) + + # ======================================================================= + # #Create scriptJob for selection. Set scriptJob number to borderItem.data(5) + # ======================================================================= + scriptJob = cmds.scriptJob(event=["SelectionChanged", partial(self.selectionScriptJob_animUI, buttonData)], + kws=True) + borderItem.setData(5, scriptJob) + animUI.selectionScriptJobs.append(scriptJob) + + return [borderItem, False, scriptJob] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def toggleButtonState(self): + + state = self.applyButton.isEnabled() + if state == False: + self.applyButton.setEnabled(True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def applyModuleChanges(self, moduleInst): + + networkNode = self.returnNetworkNode + + # get prefix/suffix + name = self.groupBox.title() + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + if len(prefix) > 0: + if prefix.find("_") == -1: + prefix = prefix + "_" + if len(suffix) > 0: + if suffix.find("_") == -1: + suffix = "_" + suffix + + # create list of the new created bones + spineJoints = [] + + if self.pelvisCB.isChecked(): + spineJoints.append(prefix + "pelvis" + suffix) + + # get current spine value + currentNum = int(cmds.getAttr(networkNode + ".spineJoints")) + + # get new spine value + uiSpineNum = self.numSpine.value() + + if uiSpineNum != currentNum: + # update spine value, and call on update spine + cmds.setAttr(networkNode + ".spineJoints", lock=False) + cmds.setAttr(networkNode + ".spineJoints", uiSpineNum, lock=True) + + # look for any attached modules + attachedModules = self.checkForDependencies() + self.updateSpine(attachedModules, currentNum) + + for i in range(uiSpineNum): + spineJoints.append(prefix + "spine_0" + str(i + 1) + suffix) + + # build attrString + attrString = "" + for bone in spineJoints: + attrString += bone + "::" + + networkNode = self.returnNetworkNode + cmds.setAttr(networkNode + ".Created_Bones", lock=False) + cmds.setAttr(networkNode + ".Created_Bones", attrString, type="string", lock=True) + + # pelvis + self.includePelvis() + + # reset button + self.applyButton.setEnabled(False) + + # update outliner + self.updateOutliner() + self.updateBoneCount() + + # clear selection + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateSpine(self, attachedModules, oldNum): + + # gather information (current name, current parent, etc) + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + parent = cmds.getAttr(networkNode + ".parentModuleBone") + newNum = int(cmds.getAttr(networkNode + ".spineJoints")) + + # call on base class delete + movers = self.returnJointMovers + for moverGrp in movers: + for mover in moverGrp: + cmds.lockNode(mover, lock=False) + + # store mover positions (movers = [all global, all offset, all geo]) + basePositions = {} + + for each in movers: + for mover in each: + attrs = cmds.listAttr(mover, keyable=True) + attrValues = [] + for attr in attrs: + value = cmds.getAttr(mover + "." + attr) + attrValues.append([attr, value]) + basePositions[mover] = attrValues + + if cmds.getAttr(networkNode + ".aimMode") == True: + self.aimMode_Setup(False) + + # delete joint mover + cmds.delete(self.name + "_mover_grp") + + # build new jmPath name + jmPath = jointMover.partition(".ma")[0].rpartition("_")[0] + "_" + str(newNum) + "Spine.ma" + self.jointMover_Build(jmPath) + + # apply base positions + for key in basePositions: + + mover = key + attrList = basePositions.get(key) + + for attr in attrList: + if cmds.objExists(mover): + cmds.setAttr(mover + "." + attr[0], attr[1]) + + # parent the joint mover to the offset mover of the parent + mover = "" + if parent == "root": + mover = "root_mover" + + else: + # find the parent mover name to parent to + networkNodes = utils.returnRigModules() + mover = utils.findMoverNodeFromJointName(networkNodes, parent) + + # delete the old constraint and create the new one + if cmds.objExists(self.name + "_mover_grp_parentConstraint*"): + cmds.delete(self.name + "_mover_grp_parentConstraint*") + + if mover != None: + cmds.parentConstraint(mover, self.name + "_mover_grp", mo=True) + + if cmds.objExists(self.name + "_mover_grp_scaleConstraint*"): + cmds.delete(self.name + "_mover_grp_scaleConstraint*") + + if mover != None: + cmds.scaleConstraint(mover, self.name + "_mover_grp", mo=True) + + # create the connection geo between the two + childMover = utils.findOffsetMoverFromName(name) + riggingUtils.createBoneConnection(mover, childMover, name) + self.applyModuleChanges(self) + + self.aimMode_Setup(True) + + cmds.select(clear=True) + + # if there were any module dependencies, fix those now. + if len(attachedModules) > 0: + elementList = [] + + # first set parent to root mover since it will always be there + for each in attachedModules: + elementList.append([each[2], " -> parent changed from: ", each[1], " to: ", "root\n"]) + currentParent = cmds.listRelatives(each[2] + "_mover_grp", parent=True)[0] + if currentParent != "root_mover": + cmds.parentConstraint("root_mover", each[2] + "_mover_grp", mo=True) + cmds.scaleConstraint("root_mover", each[2] + "_mover_grp", mo=True) + cmds.setAttr(each[0] + ".parentModuleBone", lock=False) + cmds.setAttr(each[0] + ".parentModuleBone", "root", type="string", lock=True) + + # then, update settings UI for those dependency modules to display new parent info + modules = self.getAllModules + + if each[0] in modules: + modName = cmds.getAttr(each[0] + ".moduleName") + + for modInst in self.rigUiInst.moduleInstances: + if modInst.networkNode == each[0]: + # find the current groupBox for this module + for i in range(self.rigUiInst.moduleSettingsLayout.count()): + if type(self.rigUiInst.moduleSettingsLayout.itemAt( + i).widget()) == QtWidgets.QGroupBox: + if self.rigUiInst.moduleSettingsLayout.itemAt(i).widget().title() == modName: + self.rigUiInst.moduleSettingsLayout.itemAt(i).widget().setParent(None) + + # relaunch the skeleton settings UI with new info + modInst.skeletonSettings_UI(modName) + + # create the connection geo between the two + mover = "root_mover" + childMover = utils.findOffsetMoverFromName(each[2]) + riggingUtils.createBoneConnection(mover, childMover, each[2]) + each[3].applyModuleChanges(each[3]) + cmds.select(clear=True) + + # warn user about changes + winParent = interfaceUtils.getMainWindow() + win = interfaceUtils.DialogMessage("Attention!", + "The following modules have had their parent changed due\ + to the change in this module's structure:", + elementList, 5, winParent) + win.show() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def addJointMoverToOutliner(self): + + index = self.rigUiInst.treeWidget.topLevelItemCount() + self.outlinerWidgets = {} + + # Add the module to the tree widget in the outliner tab of the rig creator UI + self.outlinerWidgets[self.name + "_treeModule"] = QtWidgets.QTreeWidgetItem(self.rigUiInst.treeWidget) + self.rigUiInst.treeWidget.topLevelItem(index).setText(0, self.name) + foreground = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + self.outlinerWidgets[self.name + "_treeModule"].setForeground(0, foreground) + + # add the pelvis + self.outlinerWidgets[self.name + "_pelvis"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_pelvis"].setText(0, self.name + "_pelvis") + self.createGlobalMoverButton(self.name + "_pelvis", self.outlinerWidgets[self.name + "_pelvis"], self.rigUiInst) + self.createOffsetMoverButton(self.name + "_pelvis", self.outlinerWidgets[self.name + "_pelvis"], self.rigUiInst) + self.createMeshMoverButton(self.name + "_pelvis", self.outlinerWidgets[self.name + "_pelvis"], self.rigUiInst) + + # add spine01 + self.outlinerWidgets[self.name + "_spine_01"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_treeModule"]) + self.outlinerWidgets[self.name + "_spine_01"].setText(0, self.name + "_spine_01") + self.createGlobalMoverButton(self.name + "_spine_01", self.outlinerWidgets[self.name + "_spine_01"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_spine_01", self.outlinerWidgets[self.name + "_spine_01"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_spine_01", self.outlinerWidgets[self.name + "_spine_01"], + self.rigUiInst) + + # add spine02 + self.outlinerWidgets[self.name + "_spine_02"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_spine_01"]) + self.outlinerWidgets[self.name + "_spine_02"].setText(0, self.name + "_spine_02") + self.createGlobalMoverButton(self.name + "_spine_02", self.outlinerWidgets[self.name + "_spine_02"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_spine_02", self.outlinerWidgets[self.name + "_spine_02"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_spine_02", self.outlinerWidgets[self.name + "_spine_02"], + self.rigUiInst) + + # add spine03 + self.outlinerWidgets[self.name + "_spine_03"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_spine_02"]) + self.outlinerWidgets[self.name + "_spine_03"].setText(0, self.name + "_spine_03") + self.createGlobalMoverButton(self.name + "_spine_03", self.outlinerWidgets[self.name + "_spine_03"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_spine_03", self.outlinerWidgets[self.name + "_spine_03"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_spine_03", self.outlinerWidgets[self.name + "_spine_03"], + self.rigUiInst) + + # add spine04 + self.outlinerWidgets[self.name + "_spine_04"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_spine_03"]) + self.outlinerWidgets[self.name + "_spine_04"].setText(0, self.name + "_spine_04") + self.createGlobalMoverButton(self.name + "_spine_04", self.outlinerWidgets[self.name + "_spine_04"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_spine_04", self.outlinerWidgets[self.name + "_spine_04"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_spine_04", self.outlinerWidgets[self.name + "_spine_04"], + self.rigUiInst) + + # add spine05 + self.outlinerWidgets[self.name + "_spine_05"] = QtWidgets.QTreeWidgetItem( + self.outlinerWidgets[self.name + "_spine_04"]) + self.outlinerWidgets[self.name + "_spine_05"].setText(0, self.name + "_spine_05") + self.createGlobalMoverButton(self.name + "_spine_05", self.outlinerWidgets[self.name + "_spine_05"], + self.rigUiInst) + self.createOffsetMoverButton(self.name + "_spine_05", self.outlinerWidgets[self.name + "_spine_05"], + self.rigUiInst) + self.createMeshMoverButton(self.name + "_spine_05", self.outlinerWidgets[self.name + "_spine_05"], + self.rigUiInst) + + # create selection script job for module + self.createScriptJob() + + # update based on spinBox values + self.updateOutliner() + self.updateBoneCount() + self.rigUiInst.treeWidget.expandAll() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateOutliner(self): + + # whenever changes are made to the module settings, update the outliner to show the new or removed movers + + # PELVIS + + if not self.pelvisCB.isChecked(): + self.outlinerWidgets[self.originalName + "_pelvis"].setHidden(True) + else: + self.outlinerWidgets[self.originalName + "_pelvis"].setHidden(False) + + # SPINE + numSpine = self.numSpine.value() + if numSpine == 2: + self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(True) + self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(True) + self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(True) + if numSpine == 3: + self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(False) + self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(True) + self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(True) + if numSpine == 4: + self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(False) + self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(False) + self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(True) + if numSpine == 5: + self.outlinerWidgets[self.originalName + "_spine_03"].setHidden(False) + self.outlinerWidgets[self.originalName + "_spine_04"].setHidden(False) + self.outlinerWidgets[self.originalName + "_spine_05"].setHidden(False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def includePelvis(self, *args): + state = self.pelvisCB.isChecked() + + if state == False: + + # hide clavicle mover controls + cmds.setAttr(self.name + "_pelvis_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_pelvis_mover_grp.v", 0, lock=True) + + # parent upperarm to mover_grp + try: + cmds.parent(self.name + "_spine_01_mover_grp", self.name + "_mover_grp") + except Exception, e: + print e + + if state == True: + + # show clavicle mover controls + cmds.setAttr(self.name + "_pelvis_mover_grp.v", lock=False) + cmds.setAttr(self.name + "_pelvis_mover_grp.v", 1, lock=True) + + # parent upperarm to mover_grp + try: + cmds.parent(self.name + "_spine_01_mover_grp", self.name + "_pelvis_mover") + except Exception, e: + print e + + networkNode = self.returnNetworkNode + cmds.setAttr(networkNode + ".includePelvis", lock=False) + cmds.setAttr(networkNode + ".includePelvis", state, lock=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def updateSettingsUI(self): + + # this function will update the settings UI when the UI is launched based on the network node settings in the scene + networkNode = self.returnNetworkNode + + includePelvis = cmds.getAttr(networkNode + ".includePelvis") + numSpine = cmds.getAttr(networkNode + ".spineJoints") + + # update UI elements + self.numSpine.setValue(numSpine) + self.pelvisCB.setChecked(includePelvis) + + # apply changes + self.applyButton.setEnabled(False) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def createContextMenu(self, point): + + networkNode = self.returnNetworkNode + + # icons + icon_reset = QtGui.QIcon(os.path.join(self.iconsPath, "System/reset.png")) + icon_delete = QtGui.QIcon(os.path.join(self.iconsPath, "System/delete.png")) + + # create the context menu + if networkNode != "ART_Root_Module": + self.contextMenu = QtWidgets.QMenu() + self.contextMenu.addAction(icon_reset, "Reset Settings", self.resetSettings) + + self.contextMenu.addSeparator() + + self.contextMenu.addAction(icon_delete, "Delete Module", self.deleteModule) + self.contextMenu.exec_(self.groupBox.mapToGlobal(point)) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def resetSettings(self): + + self.pelvisCB.setChecked(True) + self.numSpine.setValue(3) + + # relaunch the UI + self.applyModuleChanges(self) + self.updateSettingsUI() + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def aimMode_Setup(self, state): + + # get attributes needed + name = self.groupBox.title() + networkNode = self.returnNetworkNode + numSpine = cmds.getAttr(networkNode + ".spineJoints") + + # setup aim vector details per side + aimVector = [1, 0, 0] + aimUp = [0, 1, 0] + + # if passed in state is True: + if state: + # setup aim constraints + + # pelvis + cmds.aimConstraint(name + "_spine_01_lra", name + "_pelvis_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + if numSpine == 2: + cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + if numSpine == 3: + cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + cmds.aimConstraint(name + "_spine_03_lra", name + "_spine_02_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + if numSpine == 4: + cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + cmds.aimConstraint(name + "_spine_03_lra", name + "_spine_02_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + cmds.aimConstraint(name + "_spine_04_lra", name + "_spine_03_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + if numSpine == 5: + cmds.aimConstraint(name + "_spine_02_lra", name + "_spine_01_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + cmds.aimConstraint(name + "_spine_03_lra", name + "_spine_02_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + cmds.aimConstraint(name + "_spine_04_lra", name + "_spine_03_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + cmds.aimConstraint(name + "_spine_05_lra", name + "_spine_04_mover_offset", aimVector=aimVector, + upVector=aimUp, wut="vector", wu=[0, 1, 0], mo=True) + + # if passed in state is False: + if not state: + cmds.select(name + "_mover_grp", hi=True) + aimConstraints = cmds.ls(sl=True, exactType="aimConstraint") + + for constraint in aimConstraints: + cmds.lockNode(constraint, lock=False) + cmds.delete(constraint) + + self.bakeOffsets() + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def pinModule(self, state): + + networkNode = self.returnNetworkNode + includeClav = cmds.getAttr(networkNode + ".includePelvis") + + if state: + if includeClav: + topLevelMover = self.name + "_pelvis_mover_grp" + else: + topLevelMover = self.name + "_spine_01_mover_grp" + + loc = cmds.spaceLocator()[0] + cmds.setAttr(loc + ".v", False, lock=True) + constraint = cmds.parentConstraint(topLevelMover, loc)[0] + cmds.delete(constraint) + const = cmds.parentConstraint(loc, topLevelMover)[0] + + if not cmds.objExists(networkNode + ".pinConstraint"): + cmds.addAttr(networkNode, ln="pinConstraint", keyable=True, at="message") + + cmds.connectAttr(const + ".message", networkNode + ".pinConstraint") + + if not state: + connections = cmds.listConnections(networkNode + ".pinConstraint") + if len(connections) > 0: + constraint = connections[0] + cmds.delete(constraint) + + cmds.select(clear=True) + + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def skinProxyGeo(self): + + # get the network node + networkNode = self.returnNetworkNode + name = cmds.getAttr(networkNode + ".moduleName") + baseName = cmds.getAttr(networkNode + ".baseName") + prefix = name.partition(baseName)[0] + suffix = name.partition(baseName)[2] + + # get this module's proxy geo meshes + cmds.select(name + "_mover_grp", hi=True) + proxyGeoMeshes = [] + selection = cmds.ls(sl=True) + for each in selection: + if each.find("proxy_geo") != -1: + parent = cmds.listRelatives(each, parent=True)[0] + if cmds.nodeType(each) == "transform": + proxyGeoMeshes.append(each) + + # skin the proxy geo meshes + for mesh in proxyGeoMeshes: + dupeMesh = cmds.duplicate(mesh, name="skin_" + mesh)[0] + cmds.setAttr(dupeMesh + ".overrideEnabled", lock=False) + cmds.setAttr(dupeMesh + ".overrideDisplayType", 0) + + # create skinned geo group + if not cmds.objExists("skinned_proxy_geo"): + cmds.group(empty=True, name="skinned_proxy_geo") + + cmds.parent(dupeMesh, "skinned_proxy_geo") + + boneName = mesh.partition(name + "_")[2] + boneName = boneName.partition("_proxy_geo")[0] + joint = prefix + boneName + suffix + + if not cmds.objExists(joint): + cmds.delete(dupeMesh) + + else: + cmds.select([dupeMesh, joint]) + cmds.skinCluster(tsb=True, maximumInfluences=1, obeyMaxInfluences=True, bindMethod=0, skinMethod=0, + normalizeWeights=True) + cmds.select(clear=True) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildRigCustom(self, textEdit, uiInst): + + # get the network node and find out which rigs to build + networkNode = self.returnNetworkNode + buildFK = True + buildIK = True + + # have it build all rigs by default, unless there is an attr stating otherwise (backwards- compatability) + numRigs = 0 + if cmds.objExists(networkNode + ".buildFK"): + buildFK = cmds.getAttr(networkNode + ".buildFK") + if buildFK: + numRigs += 1 + if cmds.objExists(networkNode + ".buildIK"): + buildIK_V1 = cmds.getAttr(networkNode + ".buildIK") + if buildIK_V1: + numRigs += 1 + + builtRigs = [] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # create groups and settings + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # create the spine group + spineJoints = self.returnCreatedJoints + self.spineGroup = cmds.group(empty=True, name=self.name + "_group") + constraint = cmds.parentConstraint(spineJoints[0], self.spineGroup)[0] + cmds.delete(constraint) + + joints = [] + for jnt in spineJoints: + if jnt.find("pelvis") == -1: + joints.append(jnt) + + # create the spine settings group + self.spineSettings = cmds.group(empty=True, name=self.name + "_settings") + cmds.parent(self.spineSettings, self.spineGroup) + for attr in (cmds.listAttr(self.spineSettings, keyable=True)): + cmds.setAttr(self.spineSettings + "." + attr, lock=True, keyable=False) + + # create the ctrl group (what will get the constraint to the parent) + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + self.spineCtrlGrp = cmds.group(empty=True, name=self.name + "_spine_ctrl_grp") + + constraint = cmds.parentConstraint("driver_" + parentBone, self.spineCtrlGrp)[0] + cmds.delete(constraint) + + cmds.parent(self.spineCtrlGrp, self.spineGroup) + cmds.makeIdentity(self.spineCtrlGrp, t=1, r=1, s=1, apply=True) + + includePelvis = cmds.getAttr(networkNode + ".includePelvis") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # build the rigs + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + if includePelvis: + self.buildHips(textEdit, uiInst, builtRigs, networkNode) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # FK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # if build FK was true, build the FK rig now + if buildFK: + fkInfo = self.buildFkSpine(textEdit, uiInst, builtRigs, networkNode) + builtRigs.append(["FK", fkInfo]) # [1] = nodes to hide + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # IK # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # if build IK was true, build the IK rig now + if buildIK: + ikInfo = self.buildIKSpine(textEdit, uiInst, builtRigs, networkNode) + if len(joints) > 2: + builtRigs.append(["IK", ikInfo]) # [1] = nodes to hide + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Hook up FK/IK Switching # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + # add mode attribute to settings + if len(builtRigs) > 1: + cmds.addAttr(self.spineSettings, ln="mode", min=0, max=numRigs - 1, dv=0, keyable=True) + + # mode + if len(builtRigs) > 1: + attrData = [] + rampData = [] + + """ CONSTRAINTS """ + # get the constraint connections on the driver joints for the arms + connections = [] + for joint in spineJoints: + connections.extend(list(set(cmds.listConnections("driver_" + joint, type="constraint")))) + ramps = (list(set(cmds.listConnections("driver_" + joint, type="ramp")))) + for ramp in ramps: + connections.append(ramp + ".uCoord") + + for connection in connections: + driveAttrs = [] + + if cmds.nodeType(connection) in ["pointConstraint", "orientConstraint"]: + + # get those constraint target attributes for each constraint connection + targets = cmds.getAttr(connection + ".target", mi=True) + if len(targets) > 1: + for each in targets: + driveAttrs.append( + cmds.listConnections(connection + ".target[" + str(each) + "].targetWeight", + p=True)) + + # add this data to our master list of constraint attribute data + attrData.append(driveAttrs) + else: + if cmds.nodeType(connection) == "ramp": + rampData.append(connection) + + rampData = list(set(rampData)) + + # setup set driven keys on our moder attr and those target attributes + for i in range(numRigs): + + cmds.setAttr(self.spineSettings + ".mode", i) + + # go through attr data and zero out anything but the first element in the list + for data in attrData: + for each in data: + cmds.setAttr(each[0], 0) + + cmds.setAttr(data[i][0], 1) + + # set driven keys + for data in attrData: + for each in data: + cmds.setDrivenKeyframe(each[0], cd=self.spineSettings + ".mode", itt="linear", ott="linear") + + """ RAMPS """ + # direct connect mode to uCoord value (only works if there are 2 rigs...) <- not sure if that is the case still + for data in rampData: + # create a multiply node that takes first input of 1/numRigs and 2nd of mode direct connection + multNode = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_" + data.partition(".uCoord")[0] + "_mult") + cmds.setAttr(multNode + ".input1X", float(float(1) / float(numRigs - 1))) + cmds.connectAttr(self.spineSettings + ".mode", multNode + ".input2X") + cmds.connectAttr(multNode + ".outputX", data) + + # hook up control visibility + for i in range(len(builtRigs)): + cmds.setAttr(self.spineSettings + ".mode", i) + for rig in builtRigs: + visNodes = rig[1] + for node in visNodes: + if node != None: + cmds.setAttr(node + ".v", 0) + + if builtRigs.index(rig) == i: + visNodes = rig[1] + for node in visNodes: + if node != None: + cmds.setAttr(node + ".v", 1) + + cmds.setDrivenKeyframe(visNodes, at="visibility", cd=self.spineSettings + ".mode", itt="linear", + ott="linear") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # Parent Under Offset Ctrl # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # parent under offset_anim if it exists(it always should) + if cmds.objExists("offset_anim"): + cmds.parent(self.spineGroup, "offset_anim") + + # return data + parentBone = cmds.getAttr(networkNode + ".parentModuleBone") + try: + uiInst.rigData.append([self.spineCtrlGrp, "driver_" + parentBone, numRigs]) + except: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildHips(self, textEdit, uiInst, builtRigs, networkNode): + + # update progress + if textEdit != None: + textEdit.append(" Building Pelvis Rig..") + + # find the joints in the spine module that need rigging + allJnts = self.returnCreatedJoints + joints = [] + for jnt in allJnts: + if jnt.find("pelvis") != -1: + joints.append(jnt) + + # create the grp and position and orient it correctly + controlInfo = riggingUtils.createControlFromMover(joints[0], networkNode, True, True) + self.bodyAnim = riggingUtils.createControl("square", 50, self.name + "_body_anim", True) + + constraint = cmds.pointConstraint(controlInfo[0], self.bodyAnim)[0] + cmds.delete([constraint, controlInfo[0]]) + + cmds.parent(self.bodyAnim, controlInfo[1]) + cmds.makeIdentity(self.bodyAnim, t=1, r=1, s=1, apply=True) + + self.bodyAnimGrp = cmds.rename(controlInfo[1], self.name + "_body_anim_grp") + self.bodyAnimSpace = cmds.rename(controlInfo[2], self.name + "_body_anim_space_switcher") + self.bodyAnimFollow = cmds.rename(controlInfo[3], self.name + "_body_anim_space_switcher_follow") + riggingUtils.colorControl(self.bodyAnim, 17) + + # Pelvis + hipControlInfo = riggingUtils.createControlFromMover(joints[0], networkNode, True, False) + self.hipAnim = cmds.rename(hipControlInfo[0], self.name + "_hip_anim") + self.hipAnimGrp = cmds.rename(hipControlInfo[1], self.name + "_hip_anim_grp") + riggingUtils.colorControl(self.hipAnim, 18) + + cmds.parent(self.hipAnimGrp, self.bodyAnim) + + for each in [self.bodyAnim, self.hipAnim]: + for attr in [".scaleX", ".scaleY", ".scaleZ", ".visibility"]: + cmds.setAttr(each + attr, lock=True, keyable=False) + + cmds.parent(self.bodyAnimFollow, self.spineCtrlGrp) + + # ======================================================================= + # #lastly, connect controls up to blender nodes to drive driver joints + # ======================================================================= + cmds.pointConstraint(self.hipAnim, "driver_" + joints[0], mo=True) + cmds.orientConstraint(self.hipAnim, "driver_" + joints[0]) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joints[0] + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(self.hipAnim + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + joints[0], "scale", False, 2, 0, "output") + else: + riggingUtils.createConstraint(self.hipAnim, "driver_" + joints[0], "scale", False, 2, 0) + + # add created control info to module + if not cmds.objExists(networkNode + ".pelvisControls"): + cmds.addAttr(networkNode, ln="pelvisControls", dt="string") + jsonString = json.dumps([self.hipAnim, self.bodyAnim]) + cmds.setAttr(networkNode + ".pelvisControls", jsonString, type="string") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildFkSpine(self, textEdit, uiInst, builtRigs, networkNode): + + # update progress + if textEdit != None: + textEdit.append(" Starting FK Spine Rig Build..") + + # build the rig + slot = len(builtRigs) + + # find the joints in the spine module that need rigging + allJnts = self.returnCreatedJoints + joints = [] + + for jnt in allJnts: + if jnt.find("pelvis") == -1: + joints.append(jnt) + + fkControls = [] + self.topNode = None + includePelvis = cmds.getAttr(networkNode + ".includePelvis") + + for joint in joints: + if joint == joints[0]: + data = riggingUtils.createControlFromMover(joint, networkNode, True, True) + + fkControl = cmds.rename(data[0], "fk_" + joint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp") + spaceSwitcher = cmds.rename(data[2], "fk_" + joint + "_anim_space_switcher") + spaceSwitchFollow = cmds.rename(data[3], "fk_" + joint + "_anim_space_switcher_follow") + self.topNode = spaceSwitchFollow + + fkControls.append([spaceSwitchFollow, fkControl, joint]) + # color the control + riggingUtils.colorControl(fkControl, 18) + + + else: + data = riggingUtils.createControlFromMover(joint, networkNode, True, False) + + fkControl = cmds.rename(data[0], "fk_" + joint + "_anim") + animGrp = cmds.rename(data[1], "fk_" + joint + "_anim_grp") + + fkControls.append([animGrp, fkControl, joint]) + + # color the control + riggingUtils.colorControl(fkControl, 18) + + # create hierarchy + fkControls.reverse() + + for i in range(len(fkControls)): + try: + cmds.parent(fkControls[i][0], fkControls[i + 1][1]) + except IndexError: + pass + + # ======================================================================= + # #lastly, connect controls up to blender nodes to drive driver joints + # ======================================================================= + for each in fkControls: + control = each[1] + joint = each[2] + + cmds.pointConstraint(control, "driver_" + joint, mo=True) + cmds.orientConstraint(control, "driver_" + joint) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(control + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output") + else: + riggingUtils.createConstraint(control, "driver_" + joint, "scale", False, 2, slot) + + # #======================================================================= + # clean up + # #======================================================================= + # parent top group into arm group + if includePelvis: + cmds.parent(self.topNode, self.bodyAnim) + else: + cmds.parent(self.topNode, self.spineCtrlGrp) + + # lock attrs + for each in fkControls: + control = each[1] + for attr in [".visibility"]: + cmds.setAttr(control + attr, lock=True, keyable=False) + + fkRigData = [] + for each in fkControls: + fkRigData.append(each[1]) + + # add created control info to module + if not cmds.objExists(networkNode + ".fkControls"): + cmds.addAttr(networkNode, ln="fkControls", dt="string") + jsonString = json.dumps(fkRigData) + cmds.setAttr(networkNode + ".fkControls", jsonString, type="string") + + # update progress + if textEdit != None: + textEdit.setTextColor(QtGui.QColor(0, 255, 18)) + textEdit.append(" SUCCESS: FK Build Complete!") + textEdit.setTextColor(QtGui.QColor(255, 255, 255)) + + return [spaceSwitchFollow] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def buildIKSpine(self, textEdit, uiInst, builtRigs, networkNode): + + slot = len(builtRigs) + + # find the joints in the spine module that need rigging + allJnts = self.returnCreatedJoints + joints = [] + + for jnt in allJnts: + if jnt.find("pelvis") == -1: + joints.append(jnt) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Start SplineIK creation + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + + if len(joints) > 2: + # duplicate the spine joints we'll need for the spline IK + + parent = None + rigJoints = [] + + for joint in joints: + spineBone = cmds.duplicate(joint, parentOnly=True, name="splineIK_" + joint)[0] + + if parent != None: + cmds.parent(spineBone, parent) + + else: + cmds.parent(spineBone, world=True) + + parent = spineBone + rigJoints.append(str(spineBone)) + + # create spine twist joints that will be children of the spline IK joints. This will allow us to control twist distribution directly + for joint in rigJoints: + twistJoint = cmds.duplicate(joint, name="twist_" + joint, parentOnly=True)[0] + cmds.parent(twistJoint, joint) + + # find the driver top and mid joints + topDriverJoint = "driver_" + joints[-1] + midDriverJoint = "driver_" + joints[len(joints) / 2] + + ########################################################################################################### + ########################################################################################################### + # create the spline IK + ########################################################################################################### + ########################################################################################################### + + ikNodes = cmds.ikHandle(sj=str(rigJoints[0]), ee=str(rigJoints[len(rigJoints) - 1]), sol="ikSplineSolver", + createCurve=True, simplifyCurve=True, parentCurve=False, + name=str(rigJoints[0]) + "_splineIK") + ikHandle = ikNodes[0] + ikCurve = ikNodes[2] + ikCurve = cmds.rename(ikCurve, self.name + "_spine_splineIK_curve") + cmds.setAttr(ikCurve + ".inheritsTransform", 0) + cmds.setAttr(ikHandle + ".v", 0) + cmds.setAttr(ikCurve + ".v", 0) + + # create the three joints to skin the curve to + botJoint = cmds.duplicate(rigJoints[0], name=self.name + "_splineIK_bot_jnt", parentOnly=True)[0] + topJoint = \ + cmds.duplicate(rigJoints[len(rigJoints) - 1], name=self.name + "_splineIK_top_jnt", parentOnly=True)[0] + midJoint = cmds.duplicate(topJoint, name=self.name + "_splineIK_mid_jnt", parentOnly=True)[0] + + cmds.parent([botJoint, topJoint, midJoint], world=True) + + constraint = cmds.pointConstraint([botJoint, topJoint], midJoint)[0] + cmds.delete(constraint) + + # any joint that is not the bottom or top joint needs to be point constrained to be evenly spread + drivenConsts = [] + if len(joints) == 3: + drivenConst1 = cmds.pointConstraint([midJoint, rigJoints[1]], "twist_" + rigJoints[1], mo=True)[0] + cmds.setAttr(drivenConst1 + "." + rigJoints[1] + "W1", 0) + drivenConsts.append(drivenConst1) + + if len(joints) == 4: + drivenConst1 = \ + cmds.pointConstraint([botJoint, midJoint, rigJoints[1]], "twist_" + rigJoints[1], mo=True)[0] + drivenConst2 = \ + cmds.pointConstraint([topJoint, midJoint, rigJoints[2]], "twist_" + rigJoints[2], mo=True)[0] + + cmds.setAttr(drivenConst1 + "." + rigJoints[1] + "W2", 0) + cmds.setAttr(drivenConst2 + "." + rigJoints[2] + "W2", 0) + drivenConsts.append(drivenConst1) + drivenConsts.append(drivenConst2) + + if len(joints) == 5: + drivenConst1 = \ + cmds.pointConstraint([botJoint, midJoint, rigJoints[1]], "twist_" + rigJoints[1], mo=True)[0] + drivenConst2 = cmds.pointConstraint([midJoint, rigJoints[2]], "twist_" + rigJoints[2], mo=True)[0] + drivenConst3 = \ + cmds.pointConstraint([midJoint, topJoint, rigJoints[3]], "twist_" + rigJoints[3], mo=True)[0] + + cmds.setAttr(drivenConst1 + "." + rigJoints[1] + "W2", 0) + cmds.setAttr(drivenConst2 + "." + rigJoints[2] + "W1", 0) + cmds.setAttr(drivenConst3 + "." + rigJoints[3] + "W2", 0) + + drivenConsts.append(drivenConst1) + drivenConsts.append(drivenConst2) + drivenConsts.append(drivenConst3) + + # skin the joints to the curve + cmds.select([botJoint, topJoint, midJoint]) + skin = cmds.skinCluster([botJoint, topJoint, midJoint], ikCurve, toSelectedBones=True)[0] + + # skin weight the curve + curveShape = cmds.listRelatives(ikCurve, shapes=True)[0] + numSpans = cmds.getAttr(curveShape + ".spans") + degree = cmds.getAttr(curveShape + ".degree") + numCVs = numSpans + degree + + # this should always be the case, but just to be safe + if numCVs == 4: + cmds.skinPercent(skin, ikCurve + ".cv[0]", transformValue=[(botJoint, 1.0)]) + cmds.skinPercent(skin, ikCurve + ".cv[1]", transformValue=[(botJoint, 0.5), (midJoint, 0.5)]) + cmds.skinPercent(skin, ikCurve + ".cv[2]", transformValue=[(midJoint, 0.5), (topJoint, 0.5)]) + cmds.skinPercent(skin, ikCurve + ".cv[3]", transformValue=[(topJoint, 1.0)]) + + ########################################################################################################### + ########################################################################################################### + # create the spline IK controls + ########################################################################################################### + ########################################################################################################### + + ikControls = [] + + ############################################### + # TOP CTRL + ############################################### + + data = riggingUtils.createControlFromMover(joints[-1], networkNode, True, True) + + topCtrl = cmds.rename(data[0], self.name + "_chest_ik_anim") + animGrp = cmds.rename(data[1], self.name + "_chest_ik_anim_grp") + driverGrp = cmds.duplicate(animGrp, parentOnly=True, name=self.name + "_chest_ik_anim_driver_grp")[0] + spaceSwitcher = cmds.rename(data[2], self.name + "_chest_ik_anim_space_switcher") + spaceSwitchFollow = cmds.rename(data[3], self.name + "_chest_ik_anim_space_switcher_follow") + + self.topNode = spaceSwitchFollow + + ikControls.append([spaceSwitchFollow, topCtrl, joints[-1]]) + + cmds.parent(driverGrp, animGrp) + cmds.parent(topCtrl, driverGrp) + cmds.parent(topJoint, topCtrl) + + # color the control + riggingUtils.colorControl(topCtrl, 17) + + ############################################### + # MID CTRL + ############################################### + + data = riggingUtils.createControlFromMover(joints[len(joints) / 2], networkNode, True, False) + + midCtrl = cmds.rename(data[0], self.name + "_mid_ik_anim") + midGrp = cmds.rename(data[1], self.name + "_mid_ik_anim_grp") + midDriver = cmds.duplicate(midGrp, parentOnly=True, name=self.name + "_mid_ik_anim_driver_grp")[0] + midDriverTrans = cmds.duplicate(midGrp, parentOnly=True, name=self.name + "_mid_ik_anim_trans_driver_grp")[ + 0] + + cmds.parent(midCtrl, midDriver) + cmds.parent(midDriver, midDriverTrans) + cmds.parent(midDriverTrans, midGrp) + cmds.parent(midJoint, midCtrl) + ikControls.append([midGrp, midCtrl, joints[len(joints) / 2]]) + + # color the control + riggingUtils.colorControl(midCtrl, 18) + + ############################################### + # BOT CTRL + ############################################### + includePelvis = cmds.getAttr(networkNode + ".includePelvis") + + if includePelvis: + cmds.parent(botJoint, self.hipAnim) + + else: + cmds.parent(botJoint, self.spineCtrlGrp) + + ########################################################################################################### + ########################################################################################################### + # ADDING STRETCH + ########################################################################################################### + ########################################################################################################### + + # add the attr to the top ctrl + cmds.addAttr(topCtrl, longName='stretch', defaultValue=0, minValue=0, maxValue=1, keyable=True) + cmds.addAttr(topCtrl, longName='squash', defaultValue=0, minValue=0, maxValue=1, keyable=True) + + # create the curveInfo node#find + cmds.select(ikCurve) + curveInfoNode = cmds.arclen(cmds.ls(sl=True), ch=True, name=self.name + "_splineIK_curveInfo") + originalLength = cmds.getAttr(curveInfoNode + ".arcLength") + + # create the multiply/divide node that will get the scale factor + divideNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_splineIK_scaleFactor") + divideNode_Inverse = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_splineIK_inverse") + cmds.setAttr(divideNode + ".operation", 2) + cmds.setAttr(divideNode + ".input2X", originalLength) + cmds.setAttr(divideNode_Inverse + ".operation", 2) + cmds.setAttr(divideNode_Inverse + ".input1X", originalLength) + + # create the blendcolors node + blenderNode = cmds.shadingNode("blendColors", asUtility=True, name=self.name + "_splineIK_blender") + cmds.setAttr(blenderNode + ".color2R", 1) + + blenderNode_Inverse = cmds.shadingNode("blendColors", asUtility=True, + name=self.name + "_splineIK_blender_inverse") + cmds.setAttr(blenderNode_Inverse + ".color2R", 1) + + # connect attrs + cmds.connectAttr(curveInfoNode + ".arcLength", divideNode + ".input1X") + cmds.connectAttr(curveInfoNode + ".arcLength", divideNode_Inverse + ".input2X") + cmds.connectAttr(divideNode + ".outputX", blenderNode + ".color1R") + cmds.connectAttr(divideNode_Inverse + ".outputX", blenderNode_Inverse + ".color1R") + + cmds.connectAttr(topCtrl + ".stretch", blenderNode + ".blender") + cmds.connectAttr(topCtrl + ".squash", blenderNode_Inverse + ".blender") + + # find ctrl upAxis + upAxis = self.getUpAxis(topCtrl) + if upAxis == "X": + axisB = "Y" + axisC = "Z" + if upAxis == "Y": + axisB = "X" + axisC = "Z" + if upAxis == "Z": + axisB = "X" + axisC = "Y" + + # apply squash and stretch to joints + for i in range(len(rigJoints)): + children = cmds.listRelatives(rigJoints[i], children=True) + for child in children: + if child.find("twist") != -1: + twistJoint = child + + cmds.connectAttr(blenderNode_Inverse + ".outputR", twistJoint + ".scale" + axisB) + cmds.connectAttr(blenderNode_Inverse + ".outputR", twistJoint + ".scale" + axisC) + + cmds.connectAttr(blenderNode + ".outputR", rigJoints[0] + ".scale" + upAxis) + + # setup drivenConst to only be active when stretch is on + for const in drivenConsts: + targets = cmds.getAttr(const + ".target", mi=True) + for each in targets: + attr = cmds.listConnections(const + ".target[" + str(each) + "].targetWeight", p=True) + + cmds.setAttr(topCtrl + ".stretch", 1) + cmds.setDrivenKeyframe(attr[0], cd=topCtrl + ".stretch") + + cmds.setAttr(topCtrl + ".stretch", 0) + if len(joints) == 3: + if const == drivenConst1: + if each == targets[0]: + cmds.setAttr(attr[0], 0) + if each == targets[1]: + cmds.setAttr(attr[0], 1) + + if len(joints) == 4: + if each == targets[2]: + cmds.setAttr(attr[0], 1) + else: + cmds.setAttr(attr[0], 0) + + if len(joints) == 5: + if const == drivenConst1: + if each == targets[2]: + cmds.setAttr(attr[0], 1) + else: + cmds.setAttr(attr[0], 0) + + if const == drivenConst2: + if each == targets[1]: + cmds.setAttr(attr[0], 1) + else: + cmds.setAttr(attr[0], 0) + + if const == drivenConst3: + if each == targets[2]: + cmds.setAttr(attr[0], 1) + else: + cmds.setAttr(attr[0], 0) + + cmds.setDrivenKeyframe(attr[0], cd=topCtrl + ".stretch") + + ########################################################################################################### + ########################################################################################################### + # ADDING TWiST + ########################################################################################################### + ########################################################################################################### + + # add twist amount attrs and setup + cmds.select(topCtrl) + cmds.addAttr(longName='twist_amount', defaultValue=1, minValue=0, keyable=True) + + # find number of spine joints and divide 1 by numSpineJoints + num = len(joints) + val = 1.0 / float(num) + twistamount = val + + locGrp = cmds.group(empty=True, name=self.name + "_spineIK_twist_grp") + if includePelvis: + cmds.parent(locGrp, self.bodyAnim) + + else: + cmds.parent(locGrp, self.spineCtrlGrp) + + for i in range(int(num - 1)): + + # create a locator that will be orient constrained between the body and chest + locator = cmds.spaceLocator(name=joints[i] + "_twistLoc")[0] + group = cmds.group(empty=True, name=joints[i] + "_twistLocGrp") + constraint = cmds.parentConstraint(joints[i], locator)[0] + cmds.delete(constraint) + constraint = cmds.parentConstraint(joints[i], group)[0] + cmds.delete(constraint) + cmds.parent(locator, group) + cmds.parent(group, locGrp) + cmds.setAttr(locator + ".v", 0, lock=True) + + # duplicate the locator and parent it under the group. This will be the locator that takes the rotation x twist amount and gives us the final value + + orientLoc = cmds.duplicate(locator, name=joints[i] + "_orientLoc")[0] + cmds.parent(orientLoc, locator) + cmds.makeIdentity(orientLoc, t=1, r=1, s=1, apply=True) + + # set weights on constraint + firstValue = 1 - twistamount + secondValue = 1 - firstValue + + # create constraints between body/chest + if includePelvis: + constraint = cmds.orientConstraint([self.bodyAnim, topCtrl], locator)[0] + cmds.setAttr(constraint + "." + self.bodyAnim + "W0", firstValue) + cmds.setAttr(constraint + "." + topCtrl + "W1", secondValue) + + else: + # find module's parent bone + constraint = cmds.orientConstraint([rigJoints[i], topCtrl], locator)[0] + cmds.setAttr(constraint + "." + rigJoints[i] + "W0", firstValue) + cmds.setAttr(constraint + "." + topCtrl + "W1", secondValue) + + # factor in twist amount + twistMultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=joints[i] + "_twist_amount") + + # expose the twistAmount on the control as an attr + cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2X") + cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2Y") + cmds.connectAttr(topCtrl + ".twist_amount", twistMultNode + ".input2Z") + cmds.connectAttr(locator + ".rotate", twistMultNode + ".input1") + + cmds.connectAttr(twistMultNode + ".output", orientLoc + ".rotate") + + # constrain the spine joint to the orientLoc + if upAxis == "X": + skipped = ["y", "z"] + if upAxis == "Y": + skipped = ["x", "z"] + if upAxis == "Z": + skipped = ["x", "y"] + + cmds.orientConstraint([locator, rigJoints[i]], orientLoc, mo=True) + cmds.orientConstraint(orientLoc, "twist_splineIK_" + joints[i]) + twistamount = twistamount + val + + # ======================================================================= + # #connect controls up to blender nodes to drive driver joints + # ======================================================================= + for joint in joints: + + rigJnt = "twist_splineIK_" + joint + + if joint == joints[len(joints) - 1]: + cmds.pointConstraint(rigJnt, "driver_" + joint, mo=True) + cmds.orientConstraint(topJoint, "driver_" + joint) + + else: + cmds.pointConstraint(rigJnt, "driver_" + joint, mo=True) + cmds.orientConstraint(rigJnt, "driver_" + joint) + + # plug master control scale into a new mult node that takes joint.scale into input 1, and master.scale into input 2, and plugs that into driver joint + if cmds.objExists("master_anim"): + globalScaleMult = cmds.shadingNode("multiplyDivide", asUtility=True, name=joint + "_globalScale") + cmds.connectAttr("master_anim.scale", globalScaleMult + ".input1") + cmds.connectAttr(rigJnt + ".scale", globalScaleMult + ".input2") + riggingUtils.createConstraint(globalScaleMult, "driver_" + joint, "scale", False, 2, slot, "output") + else: + riggingUtils.createConstraint(rigJnt, "driver_" + joint, "scale", False, 2, slot) + + # ======================================================================= + # #clean things up + # ======================================================================= + + # parent the components to the body anim or parent module bone + + if includePelvis: + cmds.parent(midGrp, self.bodyAnim) + else: + cmds.parent(midGrp, self.spineCtrlGrp) + + # ensure after parenting the midGrp that everything is still nice and zeroed out. + cmds.parent(midCtrl, world=True) + cmds.parent(midJoint, world=True) + + for attr in [".rx", ".ry", ".rz"]: + cmds.setAttr(midGrp + attr, 0) + + cmds.parent(midCtrl, midDriver) + cmds.makeIdentity(midCtrl, t=1, r=1, s=0, apply=True) + cmds.parent(midJoint, midCtrl) + + # parent the chest ik space switcher follow node to the body anim or parent module bone + if includePelvis: + cmds.parent(spaceSwitchFollow, self.bodyAnim) + else: + cmds.parent(spaceSwitchFollow, self.spineCtrlGrp) + + # ensure after parenting the space switcher follow for the ik chest, that everything is still nice and zeroed out. + cmds.parent(topCtrl, world=True) + cmds.parent(topJoint, world=True) + for attr in [".rx", ".ry", ".rz"]: + if cmds.getAttr(spaceSwitchFollow + attr) < 45: + if cmds.getAttr(spaceSwitchFollow + attr) > 0: + cmds.setAttr(spaceSwitchFollow + attr, 0) + + if cmds.getAttr(spaceSwitchFollow + attr) >= 80: + if cmds.getAttr(spaceSwitchFollow + attr) < 90: + cmds.setAttr(spaceSwitchFollow + attr, 90) + + if cmds.getAttr(spaceSwitchFollow + attr) > 90: + if cmds.getAttr(spaceSwitchFollow + attr) < 100: + cmds.setAttr(spaceSwitchFollow + attr, 90) + + if cmds.getAttr(spaceSwitchFollow + attr) <= -80: + if cmds.getAttr(spaceSwitchFollow + attr) > -90: + cmds.setAttr(spaceSwitchFollow + attr, -90) + + if cmds.getAttr(spaceSwitchFollow + attr) > -90: + if cmds.getAttr(spaceSwitchFollow + attr) < -100: + cmds.setAttr(spaceSwitchFollow + attr, -90) + + cmds.parent(topCtrl, driverGrp) + cmds.makeIdentity(topCtrl, t=1, r=1, s=0, apply=True) + cmds.parent(topJoint, topCtrl) + + # ======================================================================= + # #ensure top spine joint stays pinned to top ctrl + # ======================================================================= + + children = cmds.listRelatives(rigJoints[len(rigJoints) - 1], children=True) + for child in children: + if child.find("twist") != -1: + twistJoint = child + + topSpineBone = twistJoint.partition("twist_")[2] + topSpineJointConstraint = cmds.pointConstraint([topJoint, topSpineBone], twistJoint)[0] + + # connect attr on top spine joint constraint + targets = cmds.pointConstraint(topSpineJointConstraint, q=True, weightAliasList=True) + + cmds.connectAttr(topCtrl + ".stretch", topSpineJointConstraint + "." + targets[0]) + + conditionNode = cmds.shadingNode("condition", asUtility=True, name=self.name + "_twist_stretch_toggle") + cmds.connectAttr(topCtrl + ".stretch", conditionNode + ".firstTerm") + cmds.setAttr(conditionNode + ".secondTerm", 1) + cmds.setAttr(conditionNode + ".colorIfTrueR", 0) + + minusNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=self.name + "_twist_stretch_minus") + cmds.setAttr(minusNode + ".operation", 2) + cmds.connectAttr(conditionNode + ".secondTerm", minusNode + ".input1D[0]") + cmds.connectAttr(topCtrl + ".stretch", minusNode + ".input1D[1]") + cmds.connectAttr(minusNode + ".output1D", topSpineJointConstraint + "." + targets[1]) + + # ======================================================================= + # #create stretch meter attr + # ======================================================================= + cmds.addAttr(topCtrl, longName='stretchFactor', keyable=True) + cmds.connectAttr(divideNode + ".outputX", topCtrl + ".stretchFactor") + cmds.setAttr(topCtrl + ".stretchFactor", lock=True) + + cmds.addAttr(midCtrl, longName='stretchFactor', keyable=True) + cmds.connectAttr(topCtrl + ".stretchFactor", midCtrl + ".stretchFactor") + cmds.setAttr(midCtrl + ".stretchFactor", lock=True) + + # ======================================================================= + # #lock and hide attrs that should not be keyable + # ======================================================================= + + for control in [topCtrl, midCtrl]: + for attr in [".sx", ".sy", ".sz", ".v"]: + cmds.setAttr(control + attr, keyable=False, lock=True) + + # ======================================================================= + # #organize scene + # ======================================================================= + IKgrp = cmds.group(empty=True, name=self.name + "_ik_grp") + cmds.parent(IKgrp, self.spineCtrlGrp) + + cmds.parent(ikCurve, IKgrp) + cmds.parent(ikHandle, IKgrp) + cmds.parent(rigJoints[0], IKgrp) + + for jnt in rigJoints: + cmds.setAttr(jnt + ".v", 0, lock=True) + + for jnt in [botJoint, midJoint, topJoint]: + cmds.setAttr(jnt + ".v", 0, lock=True) + + # ======================================================================= + # #create matching nodes + # ======================================================================= + chest_match_node = cmds.duplicate(topCtrl, po=True, name=topCtrl + "_MATCH") + cmds.parent(chest_match_node, topDriverJoint) + + mid_match_node = cmds.duplicate(midCtrl, po=True, name=midCtrl + "_MATCH") + cmds.parent(mid_match_node, midDriverJoint) + + # ======================================================================= + # #setup auto spine + # ======================================================================= + self.setupAutoSpine(textEdit, uiInst, builtRigs, networkNode, midDriver, midDriverTrans, topCtrl, botJoint) + + # add created control info to module + if not cmds.objExists(networkNode + ".ikControls"): + cmds.addAttr(networkNode, ln="ikControls", dt="string") + jsonString = json.dumps([topCtrl, midCtrl]) + cmds.setAttr(networkNode + ".ikControls", jsonString, type="string") + + return [spaceSwitchFollow, midGrp] + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def setupAutoSpine(self, textEdit, uiInst, builtRigs, networkNode, midDriver, midDriverTrans, topCtrl, botJnt): + + cmds.addAttr(topCtrl, longName='autoSpine', defaultValue=0, minValue=0, maxValue=1, keyable=True) + cmds.addAttr(topCtrl, longName='rotationInfluence', defaultValue=.25, minValue=0, maxValue=1, keyable=True) + + topCtrlMultRY = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_autoSpine_top_driver_mult_ry") + topCtrlMultRZ = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_autoSpine_top_driver_mult_rz") + topCtrlMultSwitchRY = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_autoSpine_top_mult_switch_ry") + topCtrlMultSwitchRZ = cmds.shadingNode("multiplyDivide", asUtility=True, + name=self.name + "_autoSpine_top_mult_switch_rz") + + # ======================================================================= + # create a node that will track all world space translations and rotations on the chest IK anim + # ======================================================================= + chestMasterTrackNode = cmds.spaceLocator(name=self.name + "_chest_ik_track_parent")[0] + constraint = cmds.parentConstraint(topCtrl, chestMasterTrackNode)[0] + cmds.delete(constraint) + + chestTrackNode = cmds.spaceLocator(name=self.name + "_chest_ik_tracker")[0] + constraint = cmds.parentConstraint(topCtrl, chestTrackNode)[0] + cmds.delete(constraint) + + cmds.parent(chestTrackNode, chestMasterTrackNode) + cmds.parentConstraint(topCtrl, chestTrackNode) + + if cmds.getAttr(networkNode + ".includePelvis"): + cmds.parent(chestMasterTrackNode, self.bodyAnim) + else: + cmds.parent(chestMasterTrackNode, self.spineCtrlGrp) + + # hide locator + cmds.setAttr(chestMasterTrackNode + ".v", 0) + + botJntLoc = cmds.group(empty=True, name=self.name + "_botJnt_tracker") + constraint = cmds.parentConstraint(botJnt, botJntLoc)[0] + cmds.delete(constraint) + cmds.parent(botJntLoc, botJnt) + cmds.makeIdentity(botJntLoc, t=1, r=1, s=1, apply=True) + cmds.parentConstraint(botJnt, botJntLoc)[0] + + # ======================================================================= + # Rotate Y + # ======================================================================= + cmds.connectAttr(chestTrackNode + ".ry", topCtrlMultRY + ".input1X") + cmds.connectAttr(topCtrl + ".rotationInfluence", topCtrlMultRY + ".input2X") + + cmds.connectAttr(topCtrlMultRY + ".outputX", topCtrlMultSwitchRY + ".input1X") + cmds.connectAttr(topCtrl + ".autoSpine", topCtrlMultSwitchRY + ".input2X") + cmds.connectAttr(topCtrlMultSwitchRY + ".outputX", midDriver + ".tz") + + # ======================================================================= + # Rotate Z + # ======================================================================= + multInverse = cmds.shadingNode("multiplyDivide", asUtility=True, name=self.name + "_autoSpine_mult_rz_inverse") + cmds.connectAttr(topCtrl + ".rotationInfluence", multInverse + ".input1X") + cmds.setAttr(multInverse + ".input2X", -1) + + cmds.connectAttr(chestTrackNode + ".rz", topCtrlMultRZ + ".input1X") + cmds.connectAttr(multInverse + ".outputX", topCtrlMultRZ + ".input2X") + + cmds.connectAttr(topCtrlMultRZ + ".outputX", topCtrlMultSwitchRZ + ".input1X") + cmds.connectAttr(topCtrl + ".autoSpine", topCtrlMultSwitchRZ + ".input2X") + cmds.connectAttr(topCtrlMultSwitchRZ + ".outputX", midDriver + ".ty") + + # ======================================================================= + # Translate X + # ======================================================================= + + # Chest Control Translate X + Hip Control Translate X / 2 * autpSpine + autoSpineTXNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=midDriverTrans + "_TX_Avg") + cmds.setAttr(autoSpineTXNode + ".operation", 3) + autoSpineTX_MultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=midDriverTrans + "_TX_Mult") + + cmds.connectAttr(topCtrl + ".translateX", autoSpineTXNode + ".input1D[0]") + cmds.connectAttr(botJntLoc + ".translateX", autoSpineTXNode + ".input1D[1]") + cmds.connectAttr(autoSpineTXNode + ".output1D", autoSpineTX_MultNode + ".input1X") + cmds.connectAttr(topCtrl + ".autoSpine", autoSpineTX_MultNode + ".input2X") + cmds.connectAttr(autoSpineTX_MultNode + ".outputX", midDriverTrans + ".translateX") + + # ======================================================================= + # Translate Y + # ======================================================================= + autoSpineTYNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=midDriverTrans + "_TY_Avg") + cmds.setAttr(autoSpineTYNode + ".operation", 3) + autoSpineTY_MultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=midDriverTrans + "_TY_Mult") + + cmds.connectAttr(chestTrackNode + ".translateY", autoSpineTYNode + ".input1D[0]") + cmds.connectAttr(botJntLoc + ".translateY", autoSpineTYNode + ".input1D[1]") + cmds.connectAttr(autoSpineTYNode + ".output1D", autoSpineTY_MultNode + ".input1X") + cmds.connectAttr(topCtrl + ".autoSpine", autoSpineTY_MultNode + ".input2X") + cmds.connectAttr(autoSpineTY_MultNode + ".outputX", midDriverTrans + ".translateY") + + # ======================================================================= + # Translate Z + # ======================================================================= + autoSpineTZNode = cmds.shadingNode("plusMinusAverage", asUtility=True, name=midDriverTrans + "_TZ_Avg") + cmds.setAttr(autoSpineTZNode + ".operation", 3) + autoSpineTZ_MultNode = cmds.shadingNode("multiplyDivide", asUtility=True, name=midDriverTrans + "_TZ_Mult") + + cmds.connectAttr(chestTrackNode + ".translateZ", autoSpineTZNode + ".input1D[0]") + cmds.connectAttr(botJntLoc + ".translateZ", autoSpineTZNode + ".input1D[1]") + cmds.connectAttr(autoSpineTZNode + ".output1D", autoSpineTZ_MultNode + ".input1X") + cmds.connectAttr(topCtrl + ".autoSpine", autoSpineTZ_MultNode + ".input2X") + cmds.connectAttr(autoSpineTZ_MultNode + ".outputX", midDriverTrans + ".translateZ") + + cmds.setAttr(topCtrl + ".autoSpine", 1) + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def switchMode(self, mode, checkBox, range=False): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + # are we matching? + if not range: + match = checkBox.isChecked() + else: + match = True + + # if being called from match over frame range + if range: + if mode == matchData[1][0]: + mode = "FK" + if mode == matchData[1][1]: + mode = "IK" + + # switch to FK mode + if mode == "FK": + # get current mode + currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode") + if currentMode == 0.0: + cmds.warning("Already in FK mode.") + return + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if match: + # get fk controls + controls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + controls.reverse() + # create a duplicate chain + topCtrl = controls[0] + topGrp = cmds.listRelatives(namespace + ":" + topCtrl, parent=True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world=True) + + # match the fk controls to the corresponding joint + + for control in controls: + joint = control.partition("fk_")[2].partition("_anim")[0] + joint = namespace + ":" + joint + + constraint = cmds.parentConstraint(joint, control)[0] + + translate = cmds.getAttr(control + ".translate")[0] + rotate = cmds.getAttr(control + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], + type='double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3') + + cmds.setKeyframe(namespace + ":" + control) + + # delete dupes + cmds.delete(newControls[0]) + + # switch modes + if not range: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 0.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + # switch to IK mode + if mode == "IK": + + # get current mode + currentMode = cmds.getAttr(namespace + ":" + self.name + "_settings.mode") + if currentMode == 1.0: + cmds.warning("Already in IK mode.") + return + + if not match: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + if match: + + # get IK controls + controls = json.loads(cmds.getAttr(networkNode + ".ikControls")) + + # Chest + # create a duplicate chest anim + control = controls[0] + topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world=True) + + # match the chest anim to the last spine joint + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + joint = fkControls[0].partition("_anim")[0].partition("fk_")[2] + joint = namespace + ":" + joint + constraint = cmds.parentConstraint(joint, control)[0] + cmds.delete(constraint) + + # this will now give use good values + translate = cmds.getAttr(control + ".translate")[0] + rotate = cmds.getAttr(control + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], + type='double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3') + + cmds.setKeyframe(namespace + ":" + control) + + # delete dupes + cmds.delete(newControls[0]) + + # set auto spine off + cmds.setAttr(namespace + ":" + control + ".autoSpine", 0) + cmds.setKeyframe(namespace + ":" + control + ".autoSpine") + + # Mid Anim + # create a duplicate mid spine anim + control = controls[1] + topGrp = cmds.listRelatives(namespace + ":" + control, parent=True)[0] + newControls = cmds.duplicate(topGrp) + cmds.parent(newControls[0], world=True) + + # match the mid spibne anim to the mid spine joint + allJnts = self.returnCreatedJoints + joints = [] + for jnt in allJnts: + if jnt.find("pelvis") == -1: + joints.append(jnt) + + joint = "driver_" + joints[len(joints) / 2] + joint = namespace + ":" + joint + constraint = cmds.parentConstraint(joint, control)[0] + cmds.delete(constraint) + + # this will now give use good values + translate = cmds.getAttr(control + ".translate")[0] + rotate = cmds.getAttr(control + ".rotate")[0] + + cmds.setAttr(namespace + ":" + control + ".translate", translate[0], translate[1], translate[2], + type='double3') + cmds.setAttr(namespace + ":" + control + ".rotate", rotate[0], rotate[1], rotate[2], type='double3') + + cmds.setKeyframe(namespace + ":" + control) + + # delete dupes + cmds.delete(newControls[0]) + + # switch modes + if not range: + cmds.setAttr(namespace + ":" + self.name + "_settings.mode", 1.0) + cmds.setKeyframe(namespace + ":" + self.name + "_settings.mode") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def resetRigControls(self, resetAll): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + nonZeroAttrs = ["scale", "globalScale", "scaleX", "scaleY", "scaleZ", "twist_amount", "rotationInfluence", + "autoSpine"] + + if resetAll: + + # list any attributes on the network node that contain "controls" + controls = cmds.listAttr(networkNode, st="*Controls") + # get that data on that attr + for control in controls: + data = json.loads(cmds.getAttr(networkNode + "." + control)) + + # reset the attr on each control + + try: + for each in data: + attrs = cmds.listAttr(namespace + ":" + each, keyable=True) + for attr in attrs: + if attr not in nonZeroAttrs: + try: + cmds.setAttr(namespace + ":" + each + "." + attr, 0) + except: + pass + else: + try: + cmds.setAttr(namespace + ":" + each + "." + attr, 1) + except: + pass + except: + cmds.warning("skipped " + str(control) + ". No valid controls found to reset.") + + if not resetAll: + selection = cmds.ls(sl=True) + for each in selection: + attrs = cmds.listAttr(each, keyable=True) + + for attr in attrs: + if attr not in nonZeroAttrs: + + try: + cmds.setAttr(each + "." + attr, 0) + except: + pass + else: + try: + cmds.setAttr(each + "." + attr, 1) + except: + pass + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def getUpAxis(self, obj): + + cmds.xform(obj, ws=True, relative=True, t=[0, 0, 10]) + translate = cmds.getAttr(obj + ".translate")[0] + newTuple = (abs(translate[0]), abs(translate[1]), abs(translate[2])) + cmds.xform(obj, ws=True, relative=True, t=[0, 0, -10]) + + highestVal = max(newTuple) + axis = newTuple.index(highestVal) + upAxis = None + + if axis == 0: + upAxis = "X" + + if axis == 1: + upAxis = "Y" + + if axis == 2: + upAxis = "Z" + + return upAxis + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def importFBX(self, importMethod, character): + + returnControls = [] + + # get basic info of node + networkNode = self.returnRigNetworkNode + moduleName = cmds.getAttr(networkNode + ".moduleName") + baseModuleName = cmds.getAttr(networkNode + ".baseName") + + # find prefix/suffix of module name + prefixSuffix = moduleName.split(baseModuleName) + prefix = None + suffix = None + + if prefixSuffix[0] != '': + prefix = prefixSuffix[0] + if prefixSuffix[1] != '': + suffix = prefixSuffix[1] + + # get controls + pelvisControls = json.loads(cmds.getAttr(networkNode + ".pelvisControls")) + fkControls = json.loads(cmds.getAttr(networkNode + ".fkControls")) + ikControls = json.loads(cmds.getAttr(networkNode + ".ikControls")) + + # get joints + joints = cmds.getAttr(networkNode + ".Created_Bones") + splitJoints = joints.split("::") + createdJoints = [] + + for bone in splitJoints: + if bone != "": + createdJoints.append(bone) + + # IMPORT (FK OR IK) + for joint in createdJoints: + if joint.find("pelvis") != -1: + cmds.parentConstraint(joint, character + ":" + pelvisControls[1]) + returnControls.append(character + ":" + pelvisControls[1]) + + # IMPORT FK + if importMethod == "FK" or importMethod == "Both": + cmds.setAttr(character + ":" + moduleName + "_settings.mode", 0) + + for joint in createdJoints: + if cmds.objExists(character + ":" + "fk_" + joint + "_anim"): + cmds.parentConstraint(joint, character + ":" + "fk_" + joint + "_anim") + returnControls.append(character + ":" + "fk_" + joint + "_anim") + + # IMPORT IK + if importMethod == "IK" or importMethod == "Both": + cmds.setAttr(character + ":" + moduleName + "_settings.mode", 1) + + topJoint = createdJoints[-1] + midJoint = createdJoints[(len(createdJoints)) / 2] + + cmds.parentConstraint(topJoint, character + ":" + ikControls[0]) + returnControls.append(character + ":" + ikControls[0]) + + cmds.parentConstraint(midJoint, character + ":" + ikControls[1]) + returnControls.append(character + ":" + ikControls[1]) + + # IMPORT NONE + if importMethod == "None": + pass + + return returnControls + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def resetRigControls(self, resetAll): + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + namespace = cmds.getAttr(characterNode + ".namespace") + + if resetAll: + + # list any attributes on the network node that contain "controls" + controls = cmds.listAttr(networkNode, st="*Controls") + # get that data on that attr + for control in controls: + data = json.loads(cmds.getAttr(networkNode + "." + control)) + + # reset the attr on each control + zeroAttrs = ["translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ"] + nonZeroAttrs = ["scaleX", "scaleY", "scaleZ"] + + try: + for each in data: + attrs = cmds.listAttr(namespace + ":" + each, keyable=True) + for attr in attrs: + if attr in zeroAttrs: + cmds.setAttr(namespace + ":" + each + "." + attr, 0) + if attr in nonZeroAttrs: + cmds.setAttr(namespace + ":" + each + "." + attr, 1) + else: + pass + except: + cmds.warning("skipped " + str(control) + ". No valid controls found to reset.") + + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + def selectRigControls(self, mode): + + controls = self.getControls() + if controls == None: + return + ikControls = ["chest_ik_anim", "mid_ik_anim"] + + # get namespace + networkNode = self.returnRigNetworkNode + characterNode = cmds.listConnections(networkNode + ".parent")[0] + + try: + namespace = cmds.getAttr(characterNode + ".namespace") + except: + namespace = "" + + if mode == "all": + for control in controls: + cmds.select(namespace + ":" + control, add=True) + + if mode == "fk": + for control in controls: + if control.find("fk_") == 0: + cmds.select(namespace + ":" + control, add=True) + + if mode == "ik": + for control in controls: + for ikControl in ikControls: + if control.find(ikControl) != -1: + cmds.select(namespace + ":" + control, add=True) diff --git a/Core/Scripts/RigModules/__init__.py b/Core/Scripts/RigModules/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Core/Scripts/RigModules/__init__.py |