├── CustomProceduralRiggingTool └── CustomProceduralRigTool │ ├── skinLib │ ├── __init__.py │ └── skinLib.py │ ├── rigLib │ ├── __init__.py │ ├── base │ │ ├── __init__.py │ │ ├── controlShape │ │ │ ├── __init__.py │ │ │ ├── squareControl.py │ │ │ ├── ArrowCurve.py │ │ │ ├── unitSliderControl.py │ │ │ ├── FootControl.py │ │ │ ├── cubeOnBase.py │ │ │ ├── CubeCurve.py │ │ │ ├── Diamond.py │ │ │ ├── SliderControl.py │ │ │ ├── SpikeCrossControl.py │ │ │ ├── MoveControl.py │ │ │ ├── CrossControl.py │ │ │ ├── FistCurve.py │ │ │ ├── singleRotateControl.py │ │ │ ├── CrownCurve.py │ │ │ └── RotationControl.py │ │ ├── module.py │ │ └── control.py │ ├── utils │ │ ├── __init__.py │ │ ├── createNode.py │ │ ├── name.py │ │ ├── transform.py │ │ ├── IK_FK_Switch.py │ │ ├── dynamicParent.py │ │ └── joint.py │ └── rig │ │ ├── __init__.py │ │ ├── Slave_Joints.py │ │ ├── FK_Tail.py │ │ ├── Blend_RollChain.py │ │ ├── IK_AnimalLeg.py │ │ ├── IK_FK_Spine.py │ │ ├── IK_FK_Head_Neck.py │ │ └── IK_FK_HumanArm.py │ ├── __init__.py │ ├── Splitter_UI.py │ └── Edit_UI.py ├── .idea ├── vcs.xml ├── misc.xml ├── modules.xml └── CustomProceduralRigTool.iml └── README.md /CustomProceduralRiggingTool/CustomProceduralRigTool/skinLib/__init__.py: -------------------------------------------------------------------------------- 1 | import skinLib -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/__init__.py: -------------------------------------------------------------------------------- 1 | import base 2 | import rig 3 | import utils -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/__init__.py: -------------------------------------------------------------------------------- 1 | import control 2 | import module 3 | import controlShape -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/__init__.py: -------------------------------------------------------------------------------- 1 | import rigLib 2 | import skinLib 3 | import Edit_UI 4 | import Main_UI 5 | import Splitter_UI -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/__init__.py: -------------------------------------------------------------------------------- 1 | import createNode 2 | import dynamicParent 3 | import IK_FK_Switch 4 | import joint 5 | import name 6 | import transform -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/__init__.py: -------------------------------------------------------------------------------- 1 | import Blend_RollChain 2 | import FK_Tail 3 | import IK_AnimalLeg 4 | import IK_FK_Head_Neck 5 | import IK_FK_HumanArm 6 | import IK_FK_Spine 7 | import Slave_Joints -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/__init__.py: -------------------------------------------------------------------------------- 1 | import ArrowCurve 2 | import CrossControl 3 | import CrownCurve 4 | import CubeCurve 5 | import cubeOnBase 6 | import Diamond 7 | import FistCurve 8 | import FootControl 9 | import MoveControl 10 | import RotationControl 11 | import singleRotateControl 12 | import SliderControl 13 | import SpikeCrossControl 14 | import unitSliderControl 15 | import squareControl 16 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/squareControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | def createShape(prefix='', 4 | scale=1.0): 5 | curve = cmds.curve(n=prefix, d=1, p=[(0, -0.5, 0.5), (0, -0.5, -0.5), (0, 0.5, -0.5), (0, 0.5, 0.5), (0, -0.5, 0.5)], 6 | k=[0, 1, 2, 3, 4]) 7 | cmds.setAttr(curve + '.s', scale, scale, scale) 8 | cmds.select(cl=1) 9 | 10 | return curve 11 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/createNode.py: -------------------------------------------------------------------------------- 1 | """ 2 | createNode utils @ utils 3 | """ 4 | import maya.cmds as cmds 5 | def createNode(nodeStr='', 6 | prefix='', 7 | name=''): 8 | 9 | if nodeStr == 'condition': 10 | Node = cmds.createNode(nodeStr, n=prefix+name+'_CD') 11 | elif nodeStr == 'blendColors': 12 | Node = cmds.createNode(nodeStr, n=prefix+name+'_BLC') 13 | return Node -------------------------------------------------------------------------------- /.idea/CustomProceduralRigTool.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/ArrowCurve.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | def createShape(prefix='', scale=1.0): 3 | 4 | List = [] 5 | List.append(cmds.curve(n=prefix, p=[(-1.0, 0.0, 0.0), (-1.0, 0.0, 2.0), (1.0, 0.0, 2.0), (1.0, 0.0, 0.0), (2.0, 0.0, 0.0), (0.0, 0.0, -2.0), (-2.0, 0.0, 0.0), (-1.0, 0.0, 0.0)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7])) 6 | for x in range(len(List)-1): 7 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 8 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 9 | cmds.parent(shapeNode, List[0], add=True, s=True) 10 | cmds.delete(List[x+1]) 11 | 12 | sel = List[0] 13 | 14 | cmds.setAttr(sel + '.s', scale, scale, scale) 15 | 16 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 17 | 18 | return sel 19 | 20 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/name.py: -------------------------------------------------------------------------------- 1 | """ 2 | name @utils 3 | 4 | Utilities to work with names and strings 5 | """ 6 | 7 | 8 | def removeSuffix(name): 9 | 10 | """ 11 | Remove suffix from given name string 12 | :param name: given name string to process 13 | :return: str, name without suffix 14 | """ 15 | 16 | edits = name.split('_') 17 | 18 | if len(edits) < 2: 19 | 20 | return name 21 | 22 | suffix = '_' + edits[-1] 23 | nameNoSuffix = name[:-len(suffix)] 24 | 25 | return nameNoSuffix 26 | 27 | 28 | def removePrefix(name): 29 | """ 30 | remove prefix 31 | :param name: str, name with no suffix 32 | :return: name with out prefix 33 | """ 34 | edit = name.split('_') 35 | 36 | if len(edit) < 2: 37 | return name 38 | 39 | nameNoPrefix = edit[-1] 40 | return nameNoPrefix 41 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/unitSliderControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix=''): 5 | """ 6 | create a unit slider for blend operation 7 | :param prefix: str, prefix of the control 8 | :param scale: float, scale of the control 9 | :return: str, ctrlBox of the unitSliderControl 10 | """ 11 | Ctrl = cmds.circle(radius=0.2, nr=(1, 0, 0), n=prefix + '_Ctrl')[0] 12 | cmds.transformLimits(Ctrl, tx=(0, 0), ty=(0, 1), tz=(0, 0), etx=(1, 1), ety=(1, 1), etz=(1, 1)) 13 | 14 | CtrlBox = cmds.curve(d=1, p=[(0, 0, 0), (0, 1, 0)], k=[0, 1], n=prefix + '_CtrlBox') 15 | parentCrvShape = cmds.listRelatives(CtrlBox, s=1) 16 | cmds.setAttr(parentCrvShape[0] + '.template', 1) 17 | 18 | cmds.parent(Ctrl, CtrlBox) 19 | cmds.makeIdentity(CtrlBox, apply=1, t=1, r=1, s=1, n=0) 20 | cmds.select(cl=1) 21 | 22 | return CtrlBox 23 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/transform.py: -------------------------------------------------------------------------------- 1 | """ 2 | transform @ utils 3 | 4 | Functions to manipulate and create transforms 5 | """ 6 | 7 | import maya.cmds as cmds 8 | from . import name 9 | import sys 10 | """ 11 | Dir = 'C:/Users/tHeBeStXu/Documents/maya/scripts/KOMODO/code/python' 12 | if not Dir in sys.path: 13 | 14 | sys.path.append(Dir) 15 | """ 16 | 17 | 18 | def makeOffsetGrp (object, prefix=''): 19 | 20 | """ 21 | make offset group for given object 22 | :param object:transform object to get offset group 23 | :param prefix:str, prefix to name new objects 24 | :return:str, name of new offset group 25 | """ 26 | 27 | if not prefix: 28 | 29 | prefix = name.removeSuffix(object) 30 | 31 | offsetGrp = cmds.group(n=prefix + 'Offset_grp', em=1) 32 | 33 | objectParents = cmds.listRelatives(object, p=1) 34 | 35 | if objectParents: 36 | 37 | cmds.parent(offsetGrp, objectParents[0]) 38 | 39 | # match object transform 40 | 41 | cmds.delete(cmds.parentConstraint(object, offsetGrp)) 42 | cmds.delete(cmds.scaleConstraint(object, offsetGrp)) 43 | 44 | # parent object under offset group 45 | 46 | cmds.parent(object, offsetGrp) 47 | 48 | return offsetGrp 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CustomProceduralRigTool 2 | Custom Procedural Rig Tool for Game(Unreal) 3 | This is a procedural modular rigging tool for game, especially for Unreal Engine. 4 | Before using the script, you need to make true that your maya setup is OK for UE4. 5 | Because this is a modular rigging tool, you can use it to rig any type of creatures. For example, you can use it to rig a monster with 4 6 | arms, 2 spines and multi legs. 7 | 8 | # How to install: 9 | 1. Download the project file and unzip it somewhere in the computer, make ture to remember the directory of the unzip file location 10 | 2. Open Maya 2017+ and open script Editor 11 | 3. New a Python tab, and enter following script 12 | 13 | Dir = 'X:\WHERE\YOU\PUT\THE\FILE' 14 | import sys 15 | 16 | if Dir not in sys.path: 17 | sys.path.append(r'X:\WHERE\YOU\PUT\THE\FILE') 18 | 19 | import CustomProceduralRigTool 20 | from CustomProceduralRigTool import Main_UI as Main_UI 21 | reload(Main_UI) 22 | 23 | UI = Main_UI.RiggingMainUI(dock=1) 24 | 25 | # How to use: 26 | Please go to: https://www.bilibili.com/video/av45419722/. If you have any question, please e-mail me. 27 | 28 | # Bugs: 29 | If you find any type of bugs, please e-mail me at: 328665042@qq.com. 30 | 31 | If you like, please STAR this repository. Thank you very much. 32 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/FootControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | def createShape(prefix='', scale=1.0): 4 | List = [] 5 | List.append(cmds.curve(n=prefix,p=[(0.4249371493353358, 4.798237340988468e-17, 0.05965626747485875), (0.02479363526881334, 6.785732323110913e-17, -0.3369861890540169), (-0.4476029328500644, 4.798237340988471e-17, 0.059656267474858304), (-0.16523211069250432, 1.966335461618786e-32, 0.8432678923660822), (-0.61616597431764, -4.7982373409884694e-17, 1.635912638052866), (-0.5208473195637784, -6.785732323110915e-17, 2.405743087588424), (0.606808540733522, -4.798237340988472e-17, 1.7619653609862764), (0.46646824825008704, -3.644630067904792e-32, 1.2868969494440572), (0.4249371493353358, 4.798237340988468e-17, 0.05965626747485875), (0.02479363526881334, 6.785732323110913e-17, -0.3369861890540169), (-0.4476029328500644, 4.798237340988471e-17, 0.059656267474858304)],per = True, d=3, k=[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) 6 | for x in range(len(List)-1): 7 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 8 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 9 | cmds.parent(shapeNode, List[0], add=True, s=True) 10 | cmds.delete(List[x+1]) 11 | cmds.select(List[0]) 12 | sel = List[0] 13 | cmds.setAttr(sel + '.s', scale, scale, scale) 14 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 15 | return sel -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/Splitter_UI.py: -------------------------------------------------------------------------------- 1 | from PySide2 import QtWidgets, QtCore, QtGui 2 | 3 | 4 | class Splitter(QtWidgets.QWidget): 5 | def __init__(self, text=None): 6 | """ 7 | Splitter class for create splitter widget 8 | :param text: text between splitter lines 9 | """ 10 | super(Splitter, self).__init__() 11 | 12 | self.setMinimumHeight(2) 13 | self.mainLayout = QtWidgets.QHBoxLayout() 14 | self.setLayout(self.mainLayout) 15 | self.mainLayout.setContentsMargins(0, 0, 0, 0) 16 | self.mainLayout.setSpacing(0) 17 | self.mainLayout.setAlignment(QtCore.Qt.AlignVCenter) 18 | 19 | firstLine = QtWidgets.QFrame() 20 | firstLine.setFrameStyle(QtWidgets.QFrame.HLine) 21 | self.mainLayout.addWidget(firstLine) 22 | 23 | if not text: 24 | return 25 | 26 | font = QtGui.QFont() 27 | font.setBold(True) 28 | 29 | textWidth = QtGui.QFontMetrics(font) 30 | width = textWidth.width(text) + 10 31 | 32 | label = QtWidgets.QLabel() 33 | label.setText(text) 34 | label.setFont(font) 35 | label.setMaximumWidth(width) 36 | label.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter) 37 | 38 | self.mainLayout.addWidget(label) 39 | 40 | secondLine = QtWidgets.QFrame() 41 | secondLine.setFrameStyle(QtWidgets.QFrame.HLine) 42 | self.mainLayout.addWidget(secondLine) 43 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/cubeOnBase.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p=[(-0.5692978297614414, 1.1385956595228828, -0.5692978297614414), (-0.5692978297614414, 1.1385956595228828, 0.5692978297614414), (0.5692978297614414, 1.1385956595228828, 0.5692978297614414), (0.5692978297614414, 1.1385956595228828, -0.5692978297614414), (-0.5692978297614414, 1.1385956595228828, -0.5692978297614414), (-0.5692978297614414, 0.0, -0.5692978297614414), (0.5692978297614414, 0.0, -0.5692978297614414), (0.5692978297614414, 1.1385956595228828, -0.5692978297614414), (0.5692978297614414, 1.1385956595228828, 0.5692978297614414), (0.5692978297614414, 0.0, 0.5692978297614414), (0.5692978297614414, 0.0, -0.5692978297614414), (-0.5692978297614414, 0.0, -0.5692978297614414), (-0.5692978297614414, 0.0, 0.5692978297614414), (0.5692978297614414, 0.0, 0.5692978297614414), (0.5692978297614414, 1.1385956595228828, 0.5692978297614414), (-0.5692978297614414, 1.1385956595228828, 0.5692978297614414), (-0.5692978297614414, 0.0, 0.5692978297614414)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])) 7 | for x in range(len(List)-1): 8 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 9 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 10 | cmds.parent(shapeNode, List[0], add=True, s=True) 11 | cmds.delete(List[x+1]) 12 | sel = List[0] 13 | cmds.setAttr(sel + '.s', scale, scale, scale) 14 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 15 | return sel 16 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/CubeCurve.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | def createShape(prefix='', scale=1.0): 4 | 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p=[(-0.5692978297614414, 0.5692978297614414, -0.5692978297614414), (-0.5692978297614414, 0.5692978297614414, 0.5692978297614414), (0.5692978297614414, 0.5692978297614414, 0.5692978297614414), (0.5692978297614414, 0.5692978297614414, -0.5692978297614414), (-0.5692978297614414, 0.5692978297614414, -0.5692978297614414), (-0.5692978297614414, -0.5692978297614414, -0.5692978297614414), (0.5692978297614414, -0.5692978297614414, -0.5692978297614414), (0.5692978297614414, 0.5692978297614414, -0.5692978297614414), (0.5692978297614414, 0.5692978297614414, 0.5692978297614414), (0.5692978297614414, -0.5692978297614414, 0.5692978297614414), (0.5692978297614414, -0.5692978297614414, -0.5692978297614414), (-0.5692978297614414, -0.5692978297614414, -0.5692978297614414), (-0.5692978297614414, -0.5692978297614414, 0.5692978297614414), (0.5692978297614414, -0.5692978297614414, 0.5692978297614414), (0.5692978297614414, 0.5692978297614414, 0.5692978297614414), (-0.5692978297614414, 0.5692978297614414, 0.5692978297614414), (-0.5692978297614414, -0.5692978297614414, 0.5692978297614414)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])) 7 | for x in range(len(List)-1): 8 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 9 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 10 | cmds.parent(shapeNode, List[0], add=True, s=True) 11 | cmds.delete(List[x+1]) 12 | cmds.select(List[0]) 13 | 14 | sel = List[0] 15 | 16 | cmds.setAttr(sel + '.s', scale, scale, scale) 17 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 18 | return sel 19 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/IK_FK_Switch.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def IK_FK_Switch(prefix, 5 | switchCtrl, 6 | pvCtrl, 7 | ikCtrl, 8 | skinJoints, 9 | fkCtrlList): 10 | """ 11 | IK_FK seamless switch by scriptJob and scriptNode 12 | :param prefix: str, prefix of the scriptNode 13 | :param switchCtrl: str, switchCtrl Name, usually IK_FK_Blend_Ctrl.C 14 | :param pvCtrl: str, pole vector Ctrl name. 15 | :param ikCtrl: str, IK Ctrl name 16 | :param skinJoints: list(str), list of the skin joints[shoulder, elbow, wrist] 17 | :param fkCtrlList: list(str), list of the FK Ctrl[FK_shoulder, FK_elbow, FK_wrist] 18 | :return: None 19 | """ 20 | codeStr = ''' 21 | import maya.cmds as cmds 22 | 23 | def switch(): 24 | switchCtrl = '{0}' 25 | pvCtrl = '{1}' 26 | ikCtrl = '{2}' 27 | skinJoints = {3} 28 | fkCtrlList = {4} 29 | 30 | objAttr = switchCtrl + '.Mode' 31 | objTy = switchCtrl + '.ty' 32 | # FK 2 IK 33 | if cmds.getAttr(objAttr) == 0: 34 | cmds.matchTransform(pvCtrl, skinJoints[1], pos=1, rot=0) 35 | cmds.matchTransform(ikCtrl, skinJoints[-1], pos=1, rot=1) 36 | cmds.setAttr(objTy, 1) 37 | # IK 2 FK 38 | elif cmds.getAttr(objAttr) == 1: 39 | for i in xrange(len(skinJoints)): 40 | cmds.matchTransform(fkCtrlList[i], skinJoints[i], pos=1, rot=1) 41 | cmds.setAttr(objTy, 0) 42 | 43 | cmds.scriptJob(attributeChange=['{5}' + '.Mode', switch]) 44 | '''.format(switchCtrl, 45 | pvCtrl, 46 | ikCtrl, 47 | skinJoints, 48 | fkCtrlList, 49 | switchCtrl) 50 | nodeName = cmds.scriptNode(st=2, bs=codeStr.replace("'''", "''"), n=prefix + 'Arm_IKFK_Switch_Node_#', stp='python') 51 | cmds.scriptNode(nodeName, executeBefore=1) 52 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/dynamicParent.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | import copy 3 | 4 | 5 | def dynamicParent(): 6 | sel = cmds.ls(sl=1) 7 | 8 | locatorList = [] 9 | for i in xrange(len(sel)-1): 10 | locator = cmds.spaceLocator(n=sel[i] + '_Loc') 11 | cmds.delete(cmds.parentConstraint(sel[i], locator, mo=0)) 12 | cmds.parent(locator, sel[i]) 13 | locatorList.append(locator) 14 | 15 | DPGroup = cmds.group(n=sel[-1] + '_DPGrp', empty=1) 16 | cmds.delete(cmds.parentConstraint(sel[-1], DPGroup, mo=0)) 17 | 18 | pcGroup = cmds.group(n=sel[-1] + '_pcDPGrp', empty=1) 19 | cmds.delete(cmds.parentConstraint(sel[-1], pcGroup, mo=0)) 20 | 21 | cmds.parent(pcGroup, DPGroup) 22 | cmds.parent(sel[-1], pcGroup) 23 | 24 | newList = [] 25 | for i in locatorList: 26 | newList.append(i[0]) 27 | 28 | newList.insert(0, DPGroup) 29 | 30 | cmds.select(cl=1) 31 | 32 | for i in xrange(len(newList)): 33 | cmds.parentConstraint(newList[i], pcGroup, mo=0) 34 | 35 | parentConstraint = cmds.listRelatives(pcGroup, s=0, c=1, p=0, type='parentConstraint')[0] 36 | 37 | enumStr = ':'.join(newList) 38 | # add Attr 39 | cmds.addAttr(sel[-1], ln='Parent', at='enum', en=enumStr, k=1) 40 | 41 | for i in xrange(len(newList)): 42 | cmds.setAttr(parentConstraint + '.' + newList[i] + 'W' + str(i), 0) 43 | 44 | codeStr = '''import maya.cmds as cmds 45 | 46 | def dynamicParentSwitch(): 47 | constraintObj = '{0}' 48 | parentConstraint = '{1}' 49 | newList = {2} 50 | 51 | index = cmds.getAttr(constraintObj + '.Parent') 52 | 53 | wst = cmds.xform(constraintObj, q=1, ws=1, t=1) 54 | 55 | wsr = cmds.xform(constraintObj, q=1, ws=1, ro=1) 56 | 57 | cmds.setAttr(parentConstraint + '.' + newList[index] + 'W' + str(index), 1) 58 | 59 | for i in xrange(len(newList)): 60 | if i == index: 61 | continue 62 | else: 63 | cmds.setAttr(parentConstraint + '.' + newList[i] + 'W' + str(i), 0) 64 | 65 | cmds.xform(constraintObj, ws=1, t=wst) 66 | 67 | cmds.xform(constraintObj, ws=1, ro=wsr) 68 | 69 | cmds.scriptJob(attributeChange=['{3}' + '.Parent', dynamicParentSwitch]) 70 | '''.format(sel[-1], 71 | parentConstraint, 72 | newList, 73 | sel[-1]) 74 | nodeName = cmds.scriptNode(st=2, bs=codeStr.replace("'''", "''"), n='DynamicParent_#', stp='python') 75 | cmds.scriptNode(nodeName, executeBefore=1) 76 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/Diamond.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p =[(0.0, -0.2016202582919906, 0.10123448014461145), (0.0, 1.425671083410407e-07, 0.30285488100370994), (0.20162040085909805, 1.425671083410407e-07, 0.1012344801446119), (0.0, -0.2016202582919906, 0.10123448014461145), (-0.20162040085909827, 1.425671083410407e-07, 0.1012344801446119), (0.0, 1.425671083410407e-07, 0.30285488100370994), (0.0, 0.2016202582919897, 0.1012344801446119), (-0.20162040085909827, 1.425671083410407e-07, 0.1012344801446119), (0.0, 0.2016202582919897, 0.1012344801446119), (0.20162040085909805, 1.425671083410407e-07, 0.1012344801446119), (0.0, 1.425671083410407e-07, 0.30285488100370994), (0.0, 0.2016202582919897, 0.1012344801446119), (0.0, 0.2016202582919897, -0.10134995950254133), (0.20162040085909805, -1.4256710922921911e-07, -0.101234480144611), (0.0, -0.00011562192503866697, -0.3028548810037095), (0.0, -0.2016202582919906, -0.10111900078668068), (0.20162040085909805, -1.4256710922921911e-07, -0.101234480144611), (0.20162040085909805, 1.425671083410407e-07, 0.1012344801446119), (0.0, -0.2016202582919906, 0.10123448014461145), (0.0, -0.2016202582919906, -0.10111900078668068), (-0.20162040085909827, -1.4256710922921911e-07, -0.101234480144611), (-0.20162040085909827, 1.425671083410407e-07, 0.1012344801446119), (-0.20162040085909827, -1.4256710922921911e-07, -0.101234480144611), (0.0, 0.2016202582919897, -0.10134995950254133), (0.20162040085909805, -1.4256710922921911e-07, -0.101234480144611), (0.0, -0.2016202582919906, -0.10111900078668068), (-0.20162040085909827, -1.4256710922921911e-07, -0.101234480144611), (0.0, -0.00011562192503866697, -0.3028548810037095), (0.0, -0.2016202582919906, -0.10111900078668068), (0.20162040085909805, -1.4256710922921911e-07, -0.101234480144611), (0.0, -0.00011562192503866697, -0.3028548810037095), (0.0, 0.2016202582919897, -0.10134995950254133), (-0.20162040085909827, -1.4256710922921911e-07, -0.101234480144611), (0.0, -0.00011562192503866697, -0.3028548810037095)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33])) 7 | for x in range(len(List)-1): 8 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 9 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 10 | cmds.parent(shapeNode, List[0], add=True, s=True) 11 | cmds.delete(List[x+1]) 12 | 13 | sel = List[0] 14 | cmds.setAttr(sel + '.s', scale, scale, scale) 15 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 16 | return sel 17 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/SliderControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | curve6 = [] 6 | curve6.append(cmds.curve(n=prefix, p =[(2.0, 0.0, 0.0), (2.0, 1.0, 0.0), (-2.0, 1.0, 0.0), (-2.0, 0.0, 0.0), (2.0, 0.0, 0.0)],per = False, d=1, k=[0, 1, 2, 3, 4])) 7 | sel1 = curve6[0] 8 | cmds.setAttr(sel1 + '.s', scale, scale, scale) 9 | cmds.makeIdentity(sel1, apply=1, t=1, r=1, s=1, n=0) 10 | curve7 = [] 11 | curve7.append(cmds.curve(n=prefix, p =[(0.3506450885056627, -1.0, 0.0), (0.3506450885056627, 0.0, 0.0), (0.17532254425283136, 0.0, 0.0), (0.0, 1.0, 0.0), (-0.17532254425283136, 0.0, 0.0), (-0.3506450885056627, 0.0, 0.0), (-0.3506450885056627, -1.0, 0.0), (0.3506450885056627, -1.0, 0.0)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7])) 12 | sel2 = curve7[0] 13 | cmds.setAttr(sel2 + '.s', scale, scale, scale) 14 | cmds.makeIdentity(sel2, apply=1, t=1, r=1, s=1, n=0) 15 | cmds.parent(curve7[0], curve6[0]) 16 | nurbsCircle1 = [] 17 | nurbsCircle1.append(cmds.curve(n=prefix +'_ctl3', p=[(0.14113072238066665, -1.1228095718974698, 0.0), (-2.2770716313871086e-17, -1.0643513126198854, 0.0), (-0.14113072238066648, -1.1228095718974695, 0.0), (-0.1995889816582507, -1.2639402942781361, 0.0), (-0.14113072238066654, -1.4050710166588025, 0.0), (-6.014005537581757e-17, -1.463529275936387, 0.0), (0.14113072238066643, -1.4050710166588027, 0.0), (0.1995889816582507, -1.2639402942781361, 0.0), (0.14113072238066665, -1.1228095718974698, 0.0), (-2.2770716313871086e-17, -1.0643513126198854, 0.0), (-0.14113072238066648, -1.1228095718974695, 0.0)],per = True, d=3, k=[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) 18 | nurbsCircle1.append(cmds.curve( p =[(0.03521960613292665, -1.4991507021320607, 0.0), (7.867936329852694e-17, -1.5282734270062825, 0.0), (-0.035219606132926545, -1.4991507021320603, 0.0), (-0.19958898165825073, -2.7041487422718746, 0.0), (-0.14113072238066654, -2.845279464652541, 0.0), (-6.014005537581757e-17, -2.9037377239301256, 0.0), (0.14113072238066643, -2.845279464652541, 0.0), (0.19958898165825073, -2.7041487422718746, 0.0), (0.03521960613292665, -1.4991507021320607, 0.0), (7.867936329852694e-17, -1.5282734270062825, 0.0), (-0.035219606132926545, -1.4991507021320603, 0.0)],per = True, d=3, k=[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) 19 | for x in range(len(nurbsCircle1)-1): 20 | cmds.makeIdentity(nurbsCircle1[x+1], apply=True, t=1, r=1, s=1, n=0) 21 | shapeNode = cmds.listRelatives(nurbsCircle1[x+1], shapes=True) 22 | cmds.parent(shapeNode, nurbsCircle1[0], add=True, s=True) 23 | cmds.delete(nurbsCircle1[x+1]) 24 | cmds.parent(nurbsCircle1[0], curve7[0]) 25 | 26 | sel3 = nurbsCircle1[0] 27 | cmds.setAttr(sel3 + '.s', scale, scale, scale) 28 | cmds.makeIdentity(sel3, apply=1, t=1, r=1, s=1, n=0) 29 | 30 | fp = cmds.listRelatives(nurbsCircle1[0], f=True)[0] 31 | path = fp.split("|")[1] 32 | 33 | 34 | return path -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/SpikeCrossControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | 6 | List = [] 7 | List.append(cmds.curve(n=prefix, p=[(0.5698271508338371, 4.091121663662989e-09, -2.132883735050939e-05), (0.4208952391731131, 0.1488873944517639, -1.5755096100633637e-05), (0.2720931419242101, 4.073556049855043e-05, -1.0184545420344193e-05), (0.4209398007112384, -0.1487613617926744, -1.5755096101521815e-05), (0.5698271508338371, 4.091121663662989e-09, -2.132883735050939e-05), (0.42091194939155674, 6.301549556786412e-05, -0.1488401347819135), (0.2720931419242101, 4.073556049855043e-05, -1.0184545420344193e-05), (0.42092309049279564, 6.301716352297149e-05, 0.14880862458971134), (0.5698271508338371, 4.091121663662989e-09, -2.132883735050939e-05), (0.4208952391731131, 0.1488873944517639, -1.5755096100633637e-05), (0.2720931419242101, 4.073556049855043e-05, -1.0184545420344193e-05), (-0.2720931291529265, -0.0001260413294232876, 1.0184545417679658e-05), (-0.4209971894939688, -6.30282570215357e-05, 0.14884013797247952), (-0.5698271380625544, -8.530986004595675e-05, 2.1328837348733032e-05), (-0.4210083305952077, -6.302992497664306e-05, -0.1488086213991462), (-0.2720931291529265, -0.0001260413294232876, 1.0184545417679658e-05), (-0.42085456057731463, 0.14876116408473417, 1.5751905531047328e-05), (-0.5698271380625544, -8.530986004595675e-05, 2.1328837348733032e-05), (-0.4209804792755252, -0.14888740721321847, 1.575828666666723e-05), (-0.2720931291529265, -0.0001260413294232876, 1.0184545417679658e-05), (-0.2720931291529265, -0.0001260413294232876, 1.0184545417679658e-05), (0.0, -1.3322676295501878e-15, 0.0), (-1.1141101238898443e-05, -1.6679564396326896e-09, 0.2721144031802565), (0.00014271626145045957, 0.14882419235483146, 0.42093877648166433), (0.0, -1.3322676295501878e-15, 0.569763162551884), (1.671021844362741e-05, -0.14882437895619827, 0.42093878286606934), (-1.1141101238898443e-05, -1.6679564396326896e-09, 0.2721144031802565), (-0.14882987953462568, -2.2281592690021057e-05, 0.4209443534141677), (0.0, -1.3322676295501878e-15, 0.569763162551884), (0.14890412937122033, -6.29878057401001e-05, 0.42093320912223664), (-1.1141101238898443e-05, -1.6679564396326896e-09, 0.2721144031802565), (-3.151178319171777e-05, -4.717688018018862e-09, -0.2721144015837451), (-5.935678879254169e-05, 0.14882437257149927, -0.4209387812697942), (-4.265288443061621e-05, -6.385641793116292e-09, -0.5697631609553717), (-1.4801564748090357e-05, -0.1488243836738845, -0.42093878126955797), (-3.151178319171777e-05, -4.717688018018862e-09, -0.2721144015837451), (-0.1488613913178174, -2.2286310378039076e-05, -0.4209332107214614), (-4.265288443061621e-05, -6.385641793116292e-09, -0.5697631609553717), (0.1488726175880286, -6.299252342767403e-05, -0.42094435501339156), (-3.151178319171777e-05, -4.717688018018862e-09, -0.2721144015837451)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39])) 8 | for x in range(len(List)-1): 9 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 10 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 11 | cmds.parent(shapeNode, List[0], add=True, s=True) 12 | cmds.delete(List[x+1]) 13 | sel = List[0] 14 | cmds.setAttr(sel + '.s', scale, scale, scale) 15 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 16 | return sel -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/Slave_Joints.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def build(inputJoints=None): 5 | """ 6 | create Slave joints for given joints list. 7 | if inputJoints = None, create slave joints for all joints in the scene without end joint in the joint chain 8 | :param inputJoints: str list, target joints list for create Slave joints 9 | :return: None 10 | """ 11 | 12 | if inputJoints: 13 | targetJoints = inputJoints 14 | else: 15 | targetJoints = [] 16 | 17 | # list all selected inputJoints without end inputJoints 18 | allJoints = cmds.ls(type='joint') 19 | for joint in allJoints: 20 | if cmds.attributeQuery('slaveJoint', node=joint, exists=1): 21 | targetJoints.append(joint) 22 | 23 | cmds.select(cl=1) 24 | 25 | # 1. generate slave joint for each target joint 26 | 27 | if targetJoints: 28 | for joint in targetJoints: 29 | slaveJoint = cmds.joint(n='Slave_' + joint) 30 | cmds.select(cl=1) 31 | 32 | cmds.delete(cmds.parentConstraint(joint, slaveJoint, mo=0)) 33 | cmds.makeIdentity(slaveJoint, apply=1, t=1, r=1, s=1) 34 | 35 | if not cmds.attributeQuery('slaveJoint', node=slaveJoint, exists=1): 36 | cmds.addAttr(slaveJoint, ln='slaveJoint', at='message') 37 | 38 | cmds.connectAttr(joint + '.slaveJoint', slaveJoint + '.slaveJoint', f=1) 39 | 40 | cmds.select(cl=1) 41 | 42 | # 2. parenting 43 | 44 | if targetJoints: 45 | for joint in targetJoints: 46 | slaveJoint = cmds.listConnections(joint + '.slaveJoint', destination=1, source=0, type='joint')[0] 47 | 48 | if cmds.attributeQuery('slaveParent', node=joint, exists=1): 49 | parent = cmds.getAttr(joint + '.slaveParent') 50 | 51 | if cmds.attributeQuery('slaveJoint', node=parent, exists=1): 52 | parentSlave = cmds.listConnections(parent + '.slaveJoint', source=0, destination=1, type='joint')[0] 53 | 54 | if parentSlave: 55 | cmds.parent(slaveJoint, parentSlave) 56 | 57 | else: 58 | parent = cmds.listRelatives(joint, c=0, p=1, s=0, type='joint', path=1) 59 | if parent: 60 | if cmds.attributeQuery('slaveJoint', node=parent[0], exists=1): 61 | parentSlave = cmds.listConnections(parent[0] + '.slaveJoint', 62 | source=0, destination=1, type='joint') 63 | 64 | if parentSlave: 65 | cmds.parent(slaveJoint, parentSlave[0]) 66 | 67 | cmds.select(cl=1) 68 | 69 | # 3. Constraint slave joint 70 | 71 | if targetJoints: 72 | for joint in targetJoints: 73 | slaveJoint = cmds.listConnections(joint + '.slaveJoint', destination=1, source=0, type='joint')[0] 74 | 75 | if cmds.attributeQuery('slavePointConst', node=joint, exists=1): 76 | pointConst = cmds.getAttr(joint + '.slavePointConst') 77 | 78 | if pointConst: 79 | cmds.pointConstraint(pointConst, slaveJoint, mo=0) 80 | else: 81 | cmds.pointConstraint(joint, slaveJoint, mo=0) 82 | 83 | cmds.orientConstraint(joint, slaveJoint, mo=0) 84 | cmds.scaleConstraint(joint, slaveJoint, mo=0) 85 | 86 | cmds.select(cl=1) 87 | 88 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/MoveControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p =[(-0.3839938634902286, 4.2573685351256776e-17, -0.6952810456190021), (-0.4493179344379141, 4.038083501531363e-17, -0.6594690819169796), (-0.5699654669930883, 3.490031924607386e-17, -0.5699654671105632), (-0.6594690818169142, 2.7512788518703874e-17, -0.4493179345727984), (-0.6952810454988885, 2.3512842804192566e-17, -0.38399386370932614)],per = False, d=3, k=[0, 0, 0, 1, 2, 2, 2])) 7 | List.append(cmds.curve( p =[(-1.1519815904477793, 0.0, -0.38399386348259285), (-1.1519815904477793, 0.0, -0.7679877269651857), (-1.9199693174129653, 0.0, 0.0), (-1.1519815904477793, 0.0, 0.7679877269651857), (-1.1519815904477793, 0.0, 0.38399386348259285), (-0.6952810455459, 0.0, 0.38399386348259285)],per = False, d=1, k=[0, 1, 2, 3, 4, 5])) 8 | List.append(cmds.curve( p =[(-0.6952810454988887, -2.351284280419254e-17, 0.38399386370932576), (-0.6594690818169144, -2.7512788518703853e-17, 0.44931793457279806), (-0.5699654670431211, -3.490031924194421e-17, 0.5699654670431209), (-0.4493179345727985, -4.03808350091864e-17, 0.6594690818169142), (-0.38399386370932614, -4.2573685343901955e-17, 0.6952810454988885)],per = False, d=3, k=[0, 0, 0, 1, 2, 2, 2])) 9 | List.append(cmds.curve( p =[(0.38399386370932587, -4.257368534390195e-17, 0.6952810454988885), (0.44931793457279817, -4.03808350091864e-17, 0.6594690818169143), (0.5699654670431207, -3.4900319241944226e-17, 0.569965467043121), (0.659469081816914, -2.7512788518703884e-17, 0.4493179345727986), (0.6952810454988883, -2.3512842804192578e-17, 0.38399386370932637)],per = False, d=3, k=[0, 0, 0, 1, 2, 2, 2])) 10 | List.append(cmds.curve( p =[(0.6952810454988887, 2.351284280419254e-17, -0.3839938637093257), (0.6594690818169145, 2.751278851870385e-17, -0.44931793457279795), (0.5699654670431213, 3.4900319241944195e-17, -0.5699654670431206), (0.44931793457279867, 4.0380835009186384e-17, -0.659469081816914), (0.38399386370932637, 4.2573685343901936e-17, -0.6952810454988883)],per = False, d=3, k=[0, 0, 0, 1, 2, 2, 2])) 11 | List.append(cmds.curve( p =[(-0.38399386348259307, 0.0, 0.6952810455458994), (-0.38399386348259307, 0.0, 1.1519815904477788), (-0.7679877269651861, 0.0, 1.1519815904477788), (0.0, 0.0, 1.919969317412964), (0.7679877269651861, 0.0, 1.1519815904477788), (0.38399386348259307, 0.0, 1.1519815904477788), (0.38399386348259307, 0.0, 0.6952810463138872)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6])) 12 | List.append(cmds.curve( p =[(0.6952810463138878, 0.0, 0.38399386348259285), (1.1519815904477793, 0.0, 0.38399386348259285), (1.1519815904477793, 0.0, 0.7679877269651857), (1.9199693174129653, 0.0, 0.0), (1.1519815904477793, 0.0, -0.7679877269651857), (1.1519815904477793, 0.0, -0.38399386348259285), (0.6952810463138878, 0.0, -0.38399386348259285)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6])) 13 | List.append(cmds.curve( p =[(0.38399386348259307, 0.0, -0.6952810463138872), (0.38399386348259307, 0.0, -1.1519815904477788), (0.7679877269651861, 0.0, -1.1519815904477788), (0.0, 0.0, -1.919969317412964), (-0.7679877269651861, 0.0, -1.1519815904477788), (-0.38399386348259307, 0.0, -1.1519815904477788), (-0.38399386348259307, 0.0, -0.6952810463138872)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6])) 14 | List.append(cmds.curve( p =[(-0.6952810463138878, 0.0, -0.38399386348259285), (-1.1519815904477793, 0.0, -0.38399386348259285)],per = False, d=1, k=[0, 1])) 15 | for x in range(len(List)-1): 16 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 17 | shapeNode = cmds.listRelatives(List[x+1], shapes=True) 18 | cmds.parent(shapeNode, List[0], add=True, s=True) 19 | cmds.delete(List[x+1]) 20 | sel = List[0] 21 | cmds.setAttr(sel + '.s', scale, scale, scale) 22 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 23 | 24 | return sel -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/utils/joint.py: -------------------------------------------------------------------------------- 1 | """ 2 | joint utils @ utils 3 | """ 4 | 5 | import maya.cmds as cmds 6 | from . import name 7 | 8 | 9 | def listHierarchy(topJoint, 10 | withEndJoints=True): 11 | 12 | """ 13 | list joint hierarchy starting with top joint 14 | :param topJoint: str, joint to get listed with its joint hierarchy 15 | :param withEndJoints: bool, list hierarchy including end joints 16 | :return: list(str), listed joints starting with top joint 17 | """ 18 | 19 | listedJoints = cmds.listRelatives(topJoint, 20 | type='joint', 21 | ad=1) 22 | listedJoints.append(topJoint) 23 | listedJoints.reverse() 24 | 25 | completeJoints = listedJoints[:] 26 | 27 | if not withEndJoints: 28 | 29 | completeJoints = [j for j in listedJoints if cmds.listRelatives(j, c=1, type='joint')] 30 | 31 | return completeJoints 32 | 33 | 34 | 35 | def createRevJnts(revLocator, 36 | orientCtrl, 37 | suffix): 38 | """ 39 | create revJnts for IK 40 | :param revLocator: list(str), ['CBank_LOC','EBank_LOC','heel_LOC'...] 41 | :param orientCtrl: 42 | :return: list(str),revJntChain 43 | """ 44 | 45 | # create joints for each LOC with correct name and orientation 46 | revJoints=[] 47 | for loc in revLocator: 48 | revJnt = cmds.joint(n=name.removeSuffix(loc) + suffix) 49 | cmds.delete(cmds.orientConstraint(orientCtrl, loc, mo=0)) 50 | cmds.delete(cmds.pointConstraint(loc, revJnt, mo=0)) 51 | revJoints.append(revJnt) 52 | 53 | return revJoints 54 | 55 | 56 | def createFKjnts(CurveCVs, 57 | orientObj, 58 | prefix): 59 | """ 60 | create FK Joints by Specified curveCVs 61 | :param CurveCVs: list(str), CurveCVs in builder Curve 62 | :param orientJnt: str, orient Object 63 | :param prefix: str, prefix of FK joints 64 | :return: list(str), list of FKjoints chain 65 | """ 66 | fkJoints = [] 67 | fkClusters = [] 68 | 69 | for i in range(len(CurveCVs)): 70 | cls = cmds.cluster(CurveCVs[i], n=prefix + 'Cluster%d' % (i+1))[1] 71 | cmds.hide(cls) 72 | fkJnt = cmds.joint(n=prefix + '_FK%d' % i) 73 | cmds.delete(cmds.orientConstraint(orientObj, fkJnt, mo=0)) 74 | cmds.delete(cmds.pointConstraint(cls, fkJnt, mo=0)) 75 | fkJoints.append(fkJnt) 76 | fkClusters.append(cls) 77 | 78 | for i in range((len(fkJoints)-1)): 79 | cmds.parent(fkJoints[i+1], fkJoints[i]) 80 | 81 | return {'fkJoints': fkJoints, 'fkClusters': fkClusters} 82 | 83 | 84 | def dupSpecifiedJnts(startDupJnt, 85 | endDupJnt, 86 | suffix): 87 | dupDirtyJnt = cmds.duplicate(startDupJnt, n=startDupJnt + suffix) 88 | dupFullPath = cmds.listRelatives(dupDirtyJnt[0], f=1, ad=1) 89 | # remove endJnt Children 90 | for jnt in dupFullPath: 91 | if endDupJnt in jnt: 92 | if (len(endDupJnt) + jnt.index(endDupJnt)) < len(jnt): 93 | cmds.removeJoint(jnt) 94 | 95 | 96 | # rename cleanJnt 97 | dupCleanJnt = cmds.listRelatives(dupDirtyJnt[0], ad=1, f=1) 98 | for Jnt in dupCleanJnt: 99 | cmds.select(Jnt, add=1) 100 | for sel in cmds.ls(sl=1): 101 | cmds.rename(sel, sel.split('|')[-1] + suffix) 102 | 103 | dupCleanJnt = cmds.listRelatives(dupDirtyJnt[0], ad=1, f=1) 104 | dupCleanJnt = appendAndReverse(addtargetEndJnt=dupDirtyJnt[0], reverseList=dupCleanJnt) 105 | 106 | # clean returnList 107 | finalJnts = listHierarchy(topJoint=dupCleanJnt[0]) 108 | 109 | return finalJnts 110 | 111 | 112 | def appendAndReverse(addtargetEndJnt='',reverseList=''): 113 | reverseList.append(addtargetEndJnt) 114 | reverseList.reverse() 115 | return reverseList -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/CrossControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p=[(11.65040520317079, 0.0, -1.0753491255960874), (11.260327870011457, 0.0, -1.0753491255960874), (10.919827839642535, 0.0, -0.8669835460599025), (10.731345094628578, 0.0, -0.5561779839591772), (8.827645335077547, 0.0, -0.7404428130644156), (1.7165524628499949, 0.0, -0.7404428130644156), (0.7006951136854465, 0.0, -0.7404428130644156), (0.7006951136854465, 0.0, -1.7563012592434397), (0.7006951136854465, 3.552713678800501e-15, -8.867401810671094), (0.7006951136854465, 3.552713678800501e-15, -9.883260256850125), (1.1144722701987622, 3.552713678800501e-15, -10.134188373311648), (1.391870513759761, 3.552713678800501e-15, -10.587497938965694), (1.391870513759761, 3.552713678800501e-15, -11.106800167630926), (1.391870513759761, 3.552713678800501e-15, -11.897477970132908), (0.7509301031230269, 3.552713678800501e-15, -12.538418380769645), (-0.03974769937895495, 3.552713678800501e-15, -12.538418380769645), (-0.8304255018809439, 3.552713678800501e-15, -12.538418380769645), (-1.471365912517678, 3.552713678800501e-15, -11.897477970132908), (-1.471365912517678, 3.552713678800501e-15, -11.106800167630926), (-1.471365912517678, 3.552713678800501e-15, -10.587547305110977), (-1.1939775421857295, 3.552713678800501e-15, -10.134237739456932), (-0.78023987858864, 3.552713678800501e-15, -9.883260256850125), (-0.78023987858864, 3.552713678800501e-15, -8.867401810671094), (-0.78023987858864, 0.0, -1.7563012592434397), (-0.78023987858864, 0.0, -0.7404428130644156), (-1.7960928396952713, 0.0, -0.7404428130644156), (-8.907154995122445, 0.0, -0.7404428130644156), (-11.001958686483563, 0.0, -0.4807034302220181), (-11.164895964918708, 0.0, -0.7493320062227404), (-11.459189405705198, 0.0, -0.9294219265576693), (-11.796332402209199, 0.0, -0.9294219265576693), (-12.309648927343797, 0.0, -0.9294219265576693), (-12.72575432876686, 0.0, -0.5133165251346163), (-12.72575432876686, 0.0, -1.7763568394002505e-14), (-12.72575432876686, 0.0, 0.5133165251345808), (-12.309648927343797, 0.0, 0.9294219265576551), (-11.796332402209199, 0.0, 0.9294219265576551), (-11.459221454737152, 0.0, 0.9294219265576551), (-11.164928013950659, 0.0, 0.7493320062227262), (-11.00199073551551, 0.0, 0.4807354792539478), (-8.907198876195322, 0.0, 0.7404921792096708), (-1.7960983247676712, 0.0, 0.7404921792096708), (-0.78023987858864, 0.0, 0.7404921792096708), (-0.78023987858864, 0.0, 1.7563451403163022), (-0.78023987858864, -3.552713678800501e-15, 8.86740729574348), (-0.78023987858864, -3.552713678800501e-15, 9.883260256850118), (-1.194026908331006, -3.552713678800501e-15, 10.134188373311627), (-1.471415278662958, -3.552713678800501e-15, 10.587497938965694), (-1.471415278662958, -3.552713678800501e-15, 11.106800167630926), (-1.471415278662958, -3.552713678800501e-15, 11.8974779701329), (-0.830474868026224, -3.552713678800501e-15, 12.538418380769645), (-0.03979706552423856, -3.552713678800501e-15, 12.538418380769645), (0.7508807369777433, -3.552713678800501e-15, 12.538418380769645), (1.3918211476144808, -3.552713678800501e-15, 11.8974779701329), (1.3918211476144808, -3.552713678800501e-15, 11.106800167630926), (1.3918211476144808, -3.552713678800501e-15, 10.587547305110963), (1.114422904053475, -3.552713678800501e-15, 10.134237739456903), (0.7006951136854465, -3.552713678800501e-15, 9.883260256850118), (0.7006951136854465, -3.552713678800501e-15, 8.86740729574348), (0.7006951136854465, 0.0, 1.7563451403163022), (0.7006951136854465, 0.0, 0.7404921792096708), (1.7165524628499949, 0.0, 0.7404921792096708), (8.827645335077547, 0.0, 0.7404921792096708), (10.731345094628578, 0.0, 0.556215064963471), (10.919864920646871, 0.0, 0.866983546059874), (11.260364951015786, 0.0, 1.075349125596059), (11.65040520317079, 0.0, 1.075349125596059), (12.244316817137067, 0.0, 1.075349125596059), (12.72575432876686, 0.0, 0.5939116139662737), (12.72575432876686, 0.0, -1.7763568394002505e-14), (12.72575432876686, 0.0, -0.593911613966295), (12.244316817137067, 0.0, -1.0753491255960874), (11.65040520317079, 0.0, -1.0753491255960874)],per = False, d=3, k=[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24])) 7 | for x in range(len(List)-1): 8 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 9 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 10 | cmds.parent(shapeNode, List[0], add=True, s=True) 11 | cmds.delete(List[x+1]) 12 | 13 | #print List[0] 14 | sel = List[0] 15 | 16 | cmds.setAttr(sel + '.s', scale, scale, scale) 17 | 18 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 19 | 20 | return sel 21 | 22 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/FK_Tail.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | from ..base import control 4 | from ..base import module 5 | reload(control) 6 | reload(module) 7 | 8 | 9 | def build(tailJoints, 10 | FK_Parent='', 11 | rigScale=1.0, 12 | prefix='C_', 13 | baseRig=None 14 | ): 15 | """ 16 | Build the FK_Tail rig. 17 | :param tailJoints: list(str), tailJoints to the end. i.e.[tail_1, tail_2, tail_3, ... tail_x, tail_end] 18 | :param rigScale: float, rig scale of the FK_Tail rig module, 1.0 is used. 19 | :param FK_Parent: str, the joint which tailJoint[0] connects to. 20 | :param prefix: str, prefix of the tail rig. 21 | :param baseRig: str, base atttach of the rig, Base Class instance is used. 22 | :return: None 23 | """ 24 | rigPartName = 'Tail' 25 | 26 | cmds.select(cl=1) 27 | rigModule = module.Module(prefix=prefix, 28 | rigPartName=rigPartName, 29 | baseObject=baseRig) 30 | 31 | ########## 32 | # FK Rig # 33 | ########## 34 | validTailJoints = [] 35 | for i in tailJoints: 36 | if cmds.listRelatives(i, s=0, p=0, children=1): 37 | validTailJoints.append(i) 38 | 39 | FK_tailCtrl_List = [] 40 | FK_tailCtrlGrp_List = [] 41 | 42 | # FK Ctrl 43 | for i in xrange(len(validTailJoints)): 44 | FK_tailCtrl = control.Control(prefix=prefix + 'FK_', 45 | rigPartName=rigPartName + '_' + str(i), 46 | scale=rigScale * (len(validTailJoints) - i), 47 | translateTo=validTailJoints[i], 48 | rotateTo=validTailJoints[i], 49 | shape='circle') 50 | 51 | cmds.pointConstraint(FK_tailCtrl.C, validTailJoints[i], mo=0) 52 | cmds.orientConstraint(FK_tailCtrl.C, validTailJoints[i], mo=0) 53 | 54 | FK_tailCtrl_List.append(FK_tailCtrl.C) 55 | FK_tailCtrlGrp_List.append(FK_tailCtrl.Off) 56 | 57 | cmds.select(cl=1) 58 | 59 | # Parenting 60 | for i in xrange(len(FK_tailCtrlGrp_List)-1): 61 | cmds.parent(FK_tailCtrlGrp_List[i+1], FK_tailCtrl_List[i]) 62 | 63 | cmds.select(cl=1) 64 | 65 | # add and set ctrl visibility 66 | cmds.addAttr(FK_tailCtrl_List[0], ln='Tail_Ctrl_Visibility', at='bool', dv=0, k=1) 67 | 68 | target_Ctrl_List = [] 69 | for i in FK_tailCtrl_List[1::2]: 70 | target_Ctrl_List.append(i) 71 | 72 | ctrlShape_Input_List = [] 73 | for i in xrange(len(target_Ctrl_List)): 74 | CtrlShape = cmds.listRelatives(target_Ctrl_List[i], s=1, children=0, parent=0) 75 | ctrlShape_Input = cmds.listConnections(CtrlShape[0] + '.create', source=1, destination=0, plugs=0)[0] 76 | ctrlShape_Input_List.append(ctrlShape_Input) 77 | 78 | cmds.setAttr(FK_tailCtrl_List[0] + '.Tail_Ctrl_Visibility', 0) 79 | for i in xrange(len(ctrlShape_Input_List)): 80 | cmds.setAttr(ctrlShape_Input_List[i] + '.sweep', 0) 81 | cmds.setDrivenKeyframe(ctrlShape_Input_List[i] + '.sweep', cd=FK_tailCtrl_List[0] + '.Tail_Ctrl_Visibility') 82 | 83 | cmds.setAttr(FK_tailCtrl_List[0] + '.Tail_Ctrl_Visibility', 1) 84 | for i in xrange(len(ctrlShape_Input_List)): 85 | cmds.setAttr(ctrlShape_Input_List[i] + '.sweep', 360) 86 | cmds.setDrivenKeyframe(ctrlShape_Input_List[i] + '.sweep', cd=FK_tailCtrl_List[0] + '.Tail_Ctrl_Visibility') 87 | 88 | # Clean the hierarchy 89 | if FK_Parent: 90 | FK_Loc = cmds.spaceLocator(n=prefix + 'Tail_Loc') 91 | FK_LocShape = cmds.listRelatives(FK_Loc, s=1) 92 | cmds.setAttr(FK_LocShape[0] + '.localScaleX', 0) 93 | cmds.setAttr(FK_LocShape[0] + '.localScaleY', 0) 94 | cmds.setAttr(FK_LocShape[0] + '.localScaleZ', 0) 95 | cmds.parentConstraint(FK_Parent, FK_Loc, mo=0) 96 | cmds.parent(FK_tailCtrlGrp_List[0], FK_Loc) 97 | cmds.parent(FK_Loc, rigModule.topGrp) 98 | else: 99 | cmds.parent(FK_tailCtrlGrp_List[0], rigModule.topGrp) 100 | cmds.warning('Warning: FK_Parent is None!') 101 | 102 | cmds.select(cl=1) 103 | 104 | # add attr 105 | for joint in tailJoints[:-1]: 106 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 107 | cmds.addAttr(joint, longName='slaveJoint', at='message') 108 | 109 | if not cmds.attributeQuery('rigModule', node=joint, exists=1): 110 | cmds.addAttr(joint, longName='rigModule', at='message') 111 | 112 | # connect attr 113 | for joint in tailJoints[:-1]: 114 | if cmds.attributeQuery('rigModule', node=joint, exists=1): 115 | cmds.connectAttr(rigModule.topGrp + '.' + prefix + 'Tail_Jnt', 116 | joint + '.rigModule', f=1) 117 | 118 | cmds.select(cl=1) 119 | 120 | return rigModule 121 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/FistCurve.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='',scale=1.0): 5 | curveList = [] 6 | curveList.append(cmds.curve(n=prefix, p=[(-0.28323181266160297, 0.000406980572728477, 0.28089025488631625), (-0.27202045445878775, 0.00040578537807589576, 0.30675169764711463), (-0.16198898578534848, 0.0002959027012675586, 0.31719778364300344), (-0.14166430519302461, 0.0002638997858650516, 0.2901035131433195), (-0.12271829303889557, 0.00025713970399843245, 0.3220531749715917), (0.02713533575627433, 9.83968965067028e-05, 0.3137370793648865), (0.03176093037293855, 8.173089445495663e-05, 0.28430702611824754), (0.056749199967236874, 6.637965130906753e-05, 0.3104901640897325), (0.16751595847437994, -5.696587005177278e-05, 0.28944615284404496), (0.18015194072999668, -8.424532602469004e-05, 0.2542955321992887), (0.20724620736689808, -0.00010414314516615786, 0.27462023339664776), (0.3207623415211349, -0.0002438152315058506, 0.22016395029045432), (0.3173775484988463, -0.0002498677796364257, 0.1964544644419327), (0.28905840272616196, -0.0002755696144985942, 0.05991811674892045), (0.1866776380041197, -0.00020372807142798877, -0.025179080819704547), (0.12323791549698926, -0.00013060042904178282, -0.006968376721144698), (0.12676057536309723, -0.00012707216426488532, 0.010836715894581128), (0.16986765604860782, -0.000134037789155661, 0.10439587509111237), (0.18015194072999668, -8.424532602469004e-05, 0.2542955321992887), (0.16986765604860782, -0.000134037789155661, 0.10439587509111237), (0.12676057536309723, -0.00012707216426488532, 0.010836715894581128), (0.09568409271402309, -0.00010228833205516707, -0.007611767142518655), (0.0024926391521100932, 5.380838882240724e-06, 0.019750245463990623), (0.002033083006045003, 1.3795116727499668e-05, 0.039431556239976184), (0.038684305719927634, 2.2993503176693686e-05, 0.15647041899168113), (0.03176093037293855, 8.173089445495663e-05, 0.28430702611824754), (0.038684305719927634, 2.2993503176693686e-05, 0.15647041899168113), (0.002033083006045003, 1.3795116727499668e-05, 0.039431556239976184), (-0.015266488251546056, 2.4422900443799023e-05, 0.021304768413563324), (-0.11010438270999656, 0.00012822436953141558, 0.03484390701821305), (-0.11656024068162453, 0.0001443883808714963, 0.058323610573386975), (-0.11519749470202205, 0.00018746375152134398, 0.16863086383624448), (-0.1374982667224255, 0.00025564806165856435, 0.280354770672666), (-0.11519749470202205, 0.00018746375152134398, 0.16863086383624448), (-0.11656024068162453, 0.0001443883808714963, 0.058323610573386975), (-0.13559816406496666, 0.00015283131830712282, 0.03031021090031183), (-0.21780007626780026, 0.0002293533314217111, 0.008698728860205285), (-0.24755180732258217, 0.00026389485997291295, 0.017850037368154714), (-0.27228026568783414, 0.0003425157405972934, 0.14920929852189213), (-0.28323181266160297, 0.000406980572728477, 0.28089025488631625), (-0.27228026568783414, 0.0003425157405972934, 0.14920929852189213), (-0.25789819488421134, 0.00029678983827530203, 0.0728107553244185), (-0.2892042307992774, 0.00031225299994463995, 0.030661869279283938), (-0.3242010513873258, 0.0002727632132523139, -0.1572297122659686), (-0.2025287015210206, 8.579428754484919e-05, -0.307986548798482), (-0.1452231476832722, 2.2940662007031598e-05, -0.31649446688505767), (-0.2025287015210206, 8.579428754484919e-05, -0.307986548798482), (-0.3242010513873258, 0.0002727632132523139, -0.1572297122659686), (-0.2892042307992774, 0.00031225299994463995, 0.030661869279283938), (-0.25789819488421134, 0.00029678983827530203, 0.0728107553244185), (-0.12425690024762795, 0.0001832709423938983, 0.13494285322372146), (-0.09665712185005507, 0.00015411741762272335, 0.13361811256749678), (-0.0613147282718725, 8.523990354458721e-05, 0.053705998183338766), (-0.0924751609208636, 7.754748923050059e-05, -0.04548181549397079), (-0.2134422541094789, 0.00018357679398428584, -0.09359813071624934), (-0.21421553832849324, 0.0001637219642284249, -0.14481549519248105), (-0.2134422541094789, 0.00018357679398428584, -0.09359813071624934), (-0.0924751609208636, 7.754748923050059e-05, -0.04548181549397079), (-0.06916367857107959, 8.330227391306622e-05, 0.02872174239299352), (-0.015266488251546056, 2.4422900443799023e-05, 0.021304768413563324), (0.002033083006045003, 1.3795116727499668e-05, 0.039431556239976184), (0.0024926391521100932, 5.380838882240724e-06, 0.019750245463990623), (0.09568409271402309, -0.00010228833205516707, -0.007611767142518655), (0.12676057536309723, -0.00012707216426488532, 0.010836715894581128), (0.12323791549698926, -0.00013060042904178282, -0.006968376721144698), (0.1866776380041197, -0.00020372807142798877, -0.025179080819704547), (0.28905840272616196, -0.0002755696144985942, 0.05991811674892045), (0.30292048871058846, -0.0002629886896473588, 0.1267520038623421), (0.32760176686820724, -0.0003350288693079184, 0.01158801252367836), (0.295951744917137, -0.00040178378217803346, -0.23530154489086097), (0.20931602178536124, -0.00034612058024263703, -0.3200310907901296), (0.14436772522551244, -0.0002793849230598999, -0.32154765392622486)],per = False, d=1, k=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71])) 7 | for x in range(len(curveList)-1): 8 | cmds.makeIdentity(curveList[x+1], apply=True, t=1, r=1, s=1, n=0) 9 | shapeNode = cmds.curveListRelatives(curveList[x+1], shapes=True) 10 | cmds.parent(shapeNode, curveList[0], add=True, s=True) 11 | cmds.delete(curveList[x+1]) 12 | sel = curveList[0] 13 | cmds.setAttr(sel + '.s', scale, scale, scale) 14 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 15 | return sel -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/module.py: -------------------------------------------------------------------------------- 1 | """ 2 | module for making top rig structure and rig module 3 | """ 4 | 5 | import maya.cmds as cmds 6 | import control 7 | reload(control) 8 | 9 | sceneObjectType = 'rig' 10 | 11 | 12 | class Base(): 13 | """ 14 | class for building top rig structure 15 | """ 16 | 17 | @classmethod 18 | def addAttr(cls, group): 19 | if group: 20 | if not cmds.attributeQuery('MasterCtrl', node=group, exists=1): 21 | cmds.addAttr(group, ln='MasterCtrl', at='message') 22 | 23 | if not cmds.attributeQuery('MoveCtrl', node=group, exists=1): 24 | cmds.addAttr(group, ln='MoveCtrl', at='message') 25 | 26 | if not cmds.attributeQuery('rigModule', node=group, exists=1): 27 | cmds.addAttr(group, ln='rigModule', at='message') 28 | 29 | def __init__(self, 30 | characterName='new', 31 | scale=1.0, 32 | mainCtrlAttachObj='' 33 | ): 34 | """ 35 | :param characterName: str, character name 36 | :param scale: float, general scale of the rig 37 | :return None 38 | """ 39 | 40 | self.topGrp = cmds.group(n=characterName, em=1) 41 | 42 | characterNameAttr = 'characterName' 43 | sceneObjectTypeAttr = 'sceneObjectType' 44 | 45 | for attr in [characterNameAttr, sceneObjectTypeAttr]: 46 | 47 | cmds.addAttr(self.topGrp, ln=attr, dt='string') 48 | 49 | cmds.setAttr(self.topGrp + '.' + characterNameAttr, 50 | characterName, type='string', l=1) 51 | cmds.setAttr(self.topGrp + '.' + sceneObjectTypeAttr, 52 | sceneObjectType, type='string', l=1) 53 | 54 | # make global control 55 | 56 | self.Master_Ctrl = control.Control(prefix='C_', 57 | rigPartName='Master', 58 | shape='crownCurve', 59 | scale=scale * 10.0, 60 | parent=self.topGrp, 61 | axis='z', 62 | lockChannels=['v']) 63 | 64 | if not cmds.attributeQuery('MasterCtrl', node=self.Master_Ctrl.C, exists=1): 65 | cmds.addAttr(self.Master_Ctrl.C, ln='MasterCtrl', at='message') 66 | 67 | self.Move_Ctrl = control.Control(prefix='C_', 68 | rigPartName='Move', 69 | shape='moveControl', 70 | scale=scale * 15.0, 71 | parent=self.Master_Ctrl.C, 72 | axis='z', 73 | lockChannels=['s', 'v']) 74 | 75 | if not cmds.attributeQuery('MoveCtrl', node=self.Move_Ctrl.C, exists=1): 76 | cmds.addAttr(self.Move_Ctrl.C, ln='MoveCtrl', at='message') 77 | 78 | # add Attr 79 | if not cmds.attributeQuery('slaveJoint', node=self.Move_Ctrl.C, exists=1): 80 | cmds.addAttr(self.Move_Ctrl.C, ln='slaveJoint', at='message') 81 | 82 | if not cmds.attributeQuery('rootJoint', node=self.Move_Ctrl.C, exists=1): 83 | cmds.addAttr(self.Move_Ctrl.C, ln='rootJoint', at='message') 84 | 85 | for axis in ['y', 'z']: 86 | 87 | cmds.connectAttr(self.Master_Ctrl.C + '.sx', self.Master_Ctrl.C + '.s' + axis) 88 | cmds.setAttr(self.Master_Ctrl.C + '.s' + axis, k=0) 89 | 90 | cmds.aliasAttr('Global_Scale', self.Master_Ctrl.C + '.sx') 91 | 92 | # create a grp for objects are not influenced by rig moving 93 | self.dontTouchGrp = cmds.group(n='Dont_Touch_Grp', em=1, p=self.topGrp) 94 | # lock the inherits Transform attr 95 | cmds.setAttr(self.dontTouchGrp + '.it', 0, l=1) 96 | 97 | cmds.select(cl=1) 98 | 99 | # create setting group for further operation 100 | self.settingGrp = cmds.group(n=characterName + '_SettingGrp', em=1, p=self.dontTouchGrp) 101 | 102 | # add attrs to setting group 103 | Base.addAttr(group=self.settingGrp) 104 | 105 | # connect attr 106 | cmds.connectAttr(self.settingGrp + '.MasterCtrl', 107 | self.Master_Ctrl.C + '.MasterCtrl', f=1) 108 | 109 | cmds.connectAttr(self.settingGrp + '.MoveCtrl', 110 | self.Move_Ctrl.C + '.MoveCtrl', f=1) 111 | 112 | 113 | class Module(): 114 | 115 | """class for building module rig structure""" 116 | 117 | @classmethod 118 | def addAttr(cls, group): 119 | # query and add attribute 120 | if group: 121 | if not cmds.attributeQuery('slaveJoint', node=group, exists=1): 122 | cmds.addAttr(group, longName='slaveJoint', at='message') 123 | 124 | if not cmds.attributeQuery('settingGrp', node=group, exists=1): 125 | cmds.addAttr(group, longName='settingGrp', at='message') 126 | 127 | def __init__(self, 128 | prefix='L_', 129 | rigPartName='', 130 | baseObject=None 131 | ): 132 | 133 | """ 134 | :param prefix:str, prefix to name new objects 135 | :param baseObject:instance of base.module.Base() class 136 | :return None 137 | """ 138 | self.topGrp = cmds.group(n=prefix + rigPartName + '_Module_Grp', em=1) 139 | 140 | self.dontTouchGrp = cmds.group(n=prefix + rigPartName + '_Dont_Touch_Grp', 141 | em=1, p=self.topGrp) 142 | 143 | cmds.hide(self.dontTouchGrp) 144 | 145 | cmds.setAttr(self.dontTouchGrp + '.it', 0, l=1) 146 | 147 | Module.addAttr(group=self.topGrp) 148 | 149 | if not cmds.attributeQuery(prefix + rigPartName + '_Jnt', node=self.topGrp, exists=1): 150 | cmds.addAttr(self.topGrp, longName=prefix + rigPartName + '_Jnt', at='message') 151 | 152 | # parent module 153 | 154 | if baseObject: 155 | 156 | cmds.parent(self.topGrp, baseObject.Master_Ctrl.C) 157 | 158 | cmds.select(cl=1) 159 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/singleRotateControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n =prefix,p =[(-7.105427357601002e-15, -0.3358735290035888, 0.7361468691490706), (-0.030221345939771993, -0.43042515285533867, 0.6908148502394227), (-0.072472769789524, -0.5107046042608161, 0.6274377144647979), (-0.12400997464880703, -0.5684975545498503, 0.5501319071758723), (-0.12400997464880703, -0.5684975545498503, 0.5501319071758723), (-0.12400997464880703, -0.5684975545498503, 0.5501319071758723), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.08197748359885537, -0.540253001036092, 0.5946770761304137), (-0.04551343522386375, -0.48527382262420815, 0.6467685738089758), (-0.015501246831107096, -0.4192182992656619, 0.6896431286557706), (-0.015501246831107096, -0.4192182992656619, 0.6896431286557706), (-0.015501246831107096, -0.4192182992656619, 0.6896431286557706), (-0.015501246831107096, -0.7077292503941806, 0.43808875481816606), (-0.015501246831107096, -0.80800092168273, -0.016811817720621902), (-0.015501246831107096, -0.6943482219457593, -0.34108941639861884), (-0.015501246831107096, -0.5527220271320061, -0.5148315398676033), (-0.015501246831107096, -0.3348935247151239, -0.6771644412642893), (-0.015501246831107096, -0.1758560186022855, -0.7361468691392242), (-0.015501246831107096, -7.844604263429887e-05, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 7 | List.append(cmds.curve( p =[(3.552713678800501e-15, -0.3358735290035959, 0.7361468691490706), (0.03022134593976844, -0.43042515285534577, 0.6908148502394227), (0.07247276978952044, -0.5107046042608232, 0.6274377144647979), (0.12400997464880348, -0.5684975545498574, 0.5501319071758723), (0.12400997464880348, -0.5684975545498574, 0.5501319071758723), (0.12400997464880348, -0.5684975545498574, 0.5501319071758723), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.08197748359885182, -0.5402530010360991, 0.5946770761304137), (0.0455134352238602, -0.48527382262421526, 0.6467685738089758), (0.015501246831103543, -0.419218299265669, 0.6896431286557706), (0.015501246831103543, -0.419218299265669, 0.6896431286557706), (0.015501246831103543, -0.419218299265669, 0.6896431286557706), (0.015501246831103543, -0.7077292503941877, 0.43808875481816606), (0.015501246831103543, -0.8080009216827371, -0.016811817720621902), (0.015501246831103543, -0.6943482219457664, -0.34108941639861884), (0.015501246831103543, -0.5527220271320132, -0.5148315398676033), (0.015501246831103543, -0.334893524715131, -0.6771644412642893), (0.015501246831103543, -0.1758560186022926, -0.7361468691392242), (0.015501246831103543, -7.844604263433487e-05, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 8 | List.append(cmds.curve( p =[(0.0, 0.33587352900359235, 0.7361468691490706), (-0.030221345939764888, 0.4304251528553422, 0.6908148502394227), (-0.07247276978951689, 0.5107046042608197, 0.6274377144647979), (-0.12400997464879993, 0.5684975545498538, 0.5501319071758723), (-0.12400997464879993, 0.5684975545498538, 0.5501319071758723), (-0.12400997464879993, 0.5684975545498538, 0.5501319071758723), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.08197748359884827, 0.5402530010360955, 0.5946770761304137), (-0.045513435223856646, 0.4852738226242117, 0.6467685738089758), (-0.01550124683109999, 0.41921829926566545, 0.6896431286557706), (-0.01550124683109999, 0.41921829926566545, 0.6896431286557706), (-0.01550124683109999, 0.41921829926566545, 0.6896431286557706), (-0.01550124683109999, 0.7077292503941841, 0.43808875481816606), (-0.01550124683109999, 0.8080009216827335, -0.016811817720621902), (-0.01550124683109999, 0.6943482219457628, -0.34108941639861884), (-0.01550124683109999, 0.5527220271320097, -0.5148315398676033), (-0.01550124683109999, 0.33489352471512746, -0.6771644412642893), (-0.01550124683109999, 0.17585601860228905, -0.7361468691392242), (-0.01550124683109999, 7.844604263078215e-05, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 9 | List.append(cmds.curve( p =[(3.552713678800501e-15, 0.33587352900359235, 0.7361468691490706), (0.03022134593976844, 0.4304251528553422, 0.6908148502394227), (0.07247276978952044, 0.5107046042608197, 0.6274377144647979), (0.12400997464880348, 0.5684975545498538, 0.5501319071758723), (0.12400997464880348, 0.5684975545498538, 0.5501319071758723), (0.12400997464880348, 0.5684975545498538, 0.5501319071758723), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.08197748359885182, 0.5402530010360955, 0.5946770761304137), (0.0455134352238602, 0.4852738226242117, 0.6467685738089758), (0.015501246831103543, 0.41921829926566545, 0.6896431286557706), (0.015501246831103543, 0.41921829926566545, 0.6896431286557706), (0.015501246831103543, 0.41921829926566545, 0.6896431286557706), (0.015501246831103543, 0.7077292503941841, 0.43808875481816606), (0.015501246831103543, 0.8080009216827335, -0.016811817720621902), (0.015501246831103543, 0.6943482219457628, -0.34108941639861884), (0.015501246831103543, 0.5527220271320097, -0.5148315398676033), (0.015501246831103543, 0.33489352471512746, -0.6771644412642893), (0.015501246831103543, 0.17585601860228905, -0.7361468691392242), (0.015501246831103543, 7.844604263078215e-05, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 10 | for x in range(len(List)-1): 11 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 12 | shapeNode = cmds.listRelatives(List[x+1], shapes=True) 13 | cmds.parent(shapeNode, List[0], add=True, s=True) 14 | cmds.delete(List[x+1]) 15 | sel = List[0] 16 | cmds.setAttr(sel + '.s', scale, scale, scale) 17 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 18 | return sel -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/CrownCurve.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='new', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p=[(10.235979856897208, 0.5387466956416631, -5.064001608160172), (10.151485877817008, 0.5387466956416631, -5.062031610699659), (9.56002041972143, -0.5387466956416631, -5.048241451174565), (9.47552644064123, -0.5387466956416631, -5.046271453714052), (8.581458580479284, -0.5387466956416631, -6.782167046977893), (7.226633650695048, -0.5387466956416631, -8.241302021399537), (5.569970571620038, -0.5387466956416631, -9.259395857943009), (5.575918387952802, -0.5387466956416631, -9.334794752747538), (5.617553637591014, 0.5387466956416667, -9.862593802347586), (5.623501453923778, 0.5387466956416667, -9.937992697152108), (5.0018396866720405, 0.5387466956416667, -10.290595824653057), (4.344093509091591, 0.5387466956416667, -10.585980197725444), (3.656702513277194, 0.5387466956416667, -10.818273589216776), (3.6060751545400915, 0.5387466956416667, -10.765222345604261), (3.251679086872498, -0.5387466956416631, -10.393858865656984), (3.201051728135395, -0.5387466956416631, -10.34080762204447), (2.1905747659419728, -0.5387466956416631, -10.658773119819454), (1.115474936823345, -0.5387466956416631, -10.830869090935291), (-7.092061794722326e-06, -0.5387466956416631, -10.830869090935291), (-0.9057626700346137, -0.5387466956416631, -10.830869090935291), (-1.7847953592262602, -0.5387466956416631, -10.717013131144075), (-2.6244812896710616, -0.5387466956416631, -10.504322198408392), (-2.671915676524174, -0.5387466956416631, -10.559882430786612), (-3.0039606536334578, 0.5387466956416667, -10.948809057905049), (-3.05139504048657, 0.5387466956416667, -11.004369290283268), (-3.7515233792550635, 0.5387466956416667, -10.810585794248926), (-4.424716067389001, 0.5387466956416667, -10.552803532725871), (-5.063966147851277, 0.5387466956416667, -10.23594439658832), (-5.062219942102283, 0.5387466956416667, -10.160900101326686), (-5.049996344699226, -0.5387466956416631, -9.635583280441136), (-5.048250138950232, -0.5387466956416631, -9.560538985179509), (-6.768344618571698, -0.5387466956416631, -8.633166802905958), (-8.202614824398106, -0.5387466956416631, -7.245987887288454), (-9.19059576663028, -0.5387466956416631, -5.564601880853754), (-9.273642979575483, -0.5387466956416631, -5.571158032402327), (-9.854980944515814, 0.5387466956416631, -5.617051683301884), (-9.938028157461018, 0.5387466956416631, -5.623607834850457), (-10.290560364344165, 0.5387466956416631, -5.001875146980954), (-10.58594473741656, 0.5387466956416631, -4.344128969400483), (-10.818238128907884, 0.5387466956416631, -3.6568088942038735), (-10.754304619323518, 0.5387466956416631, -3.5957862528671605), (-10.306764298159566, -0.5387466956416631, -3.168622271417508), (-10.242830788575203, -0.5387466956416631, -3.107599630080795), (-10.508995867120388, -0.5387466956416631, -2.1760005789872743), (-10.654581711308394, -0.5387466956416631, -1.1934237878302874), (-10.654581711308394, -0.5387466956416631, -0.17636539230646164), (-10.654581711308394, -0.5387466956416631, 0.7370779806342078), (-10.539193866173035, -0.5387466956416631, 1.6235857029403284), (-10.32297108667168, -0.5387466956416631, 2.469654488985743), (-10.39867730108004, -0.5387466956416631, 2.534286165670114), (-10.92862761556602, 0.5387466956416631, 2.9867137193697637), (-11.004333829974383, 0.5387466956416631, 3.0513453960541277), (-10.810621254557828, 0.5387466956416631, 3.7514879189461716), (-10.55276807241698, 0.5387466956416631, 4.424680607080102), (-10.235979856897215, 0.5387466956416631, 5.063930687542385), (-10.130684280632012, 0.5387466956416631, 5.061475282707608), (-9.393605770078961, -0.5387466956416667, 5.044287227875511), (-9.288310193813759, -0.5387466956416667, 5.041831823040734), (-8.391901953264908, -0.5387466956416667, 6.633886219314075), (-7.1000970844439895, -0.5387466956416667, 7.973335559162624), (-5.543446260568659, -0.5387466956416667, 8.923629285104123), (-5.552341193102345, -0.5387466956416667, 9.03633520381678), (-5.614606521390096, 0.5387466956416596, 9.825286778439466), (-5.623501453923781, 0.5387466956416596, 9.937992697152122), (-5.001839686672065, 0.5387466956416596, 10.290581640529492), (-4.344164429709375, 0.5387466956416596, 10.585980197725451), (-3.6568443545127725, 0.5387466956416596, 10.818202668598989), (-3.5769207695409566, 0.5387466956416596, 10.734477776527367), (-3.017448481543612, -0.5387466956416667, 10.148395996710402), (-2.937524896571796, -0.5387466956416667, 10.06467110463878), (-2.0040677252923462, -0.5387466956416667, 10.331999281315642), (-1.0193491314782452, -0.5387466956416667, 10.47813830632236), (-7.092061794722326e-06, -0.5387466956416667, 10.47813830632236), (0.8160055361665552, -0.5387466956416667, 10.47813830632236), (1.609493776186552, -0.5387466956416667, 10.383317440344502), (2.372925858389463, -0.5387466956416667, 10.209618663266713), (2.4483089932143027, -0.5387466956416667, 10.297923405434528), (2.9759977215381763, 0.5387466956416596, 10.916064548115461), (3.051380856363016, 0.5387466956416596, 11.004369290283268), (3.7515233792550386, 0.5387466956416596, 10.810571610125375), (4.424716067388983, 0.5387466956416596, 10.552803532725864), (5.063895227233479, 0.5387466956416596, 10.23594439658832), (5.061247550646554, 0.5387466956416596, 10.122168375255118), (5.042713576244813, -0.5387466956416667, 9.325725985978384), (5.040065899657895, -0.5387466956416667, 9.211949964645182), (6.647495885866908, -0.5387466956416667, 8.347200687875347), (8.005370402215865, -0.5387466956416667, 7.080728663727033), (8.983918902282715, -0.5387466956416667, 5.548190849898429), (9.089929981625572, -0.5387466956416667, 5.556554671116768), (9.832017078118147, 0.5387466956416631, 5.615102172396551), (9.93802815746101, 0.5387466956416631, 5.623465993614889), (10.290546180220593, 0.5387466956416631, 5.001804226363166), (10.586015658034347, 0.5387466956416631, 4.3440580487826885), (10.81823812890787, 0.5387466956416631, 3.656737973586086), (10.74537028684061, 0.5387466956416631, 3.587187607242317), (10.235288834198405, -0.5387466956416631, 3.1003287832403963), (10.162420992131137, -0.5387466956416631, 3.030778416896627), (10.481563772161335, -0.5387466956416631, 2.018500071011484), (10.654581711308394, -0.5387466956416631, 0.9413860963477667), (10.654581711308394, -0.5387466956416631, -0.17636539230646164), (10.654581711308394, -0.5387466956416631, -0.9846902255669683), (10.561491308404454, -0.5387466956416631, -1.7709020102022812), (10.390983959126983, -0.5387466956416631, -2.5277668431983464), (10.459133263276838, -0.5387466956416631, -2.5859432322041194), (10.936184525824528, 0.5387466956416631, -2.993183191171905), (11.004333829974383, 0.5387466956416631, -3.051359580177678), (10.810621254557814, 0.5387466956416631, -3.751558839563952), (10.552768072416965, 0.5387466956416631, -4.4247515276978895), (10.235979856897208, 0.5387466956416631, -5.064001608160172)], 7 | per=False, 8 | d=3,k=[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36])) 9 | for x in range(len(List)-1): 10 | cmds.makeIdentity(List[x+1], apply=True, t=1, r=1, s=1, n=0) 11 | shapeNode = cmds.ListRelatives(List[x+1], shapes=True) 12 | cmds.parent(shapeNode, List[0], add=True, s=True) 13 | cmds.delete(List[x+1]) 14 | 15 | sel = List[0] 16 | cmds.setAttr(sel + '.s', scale, scale, scale) 17 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 18 | return sel 19 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/Blend_RollChain.py: -------------------------------------------------------------------------------- 1 | from maya import cmds 2 | 3 | 4 | def build(rollStart, 5 | rollEnd, 6 | numRollJoints=1, 7 | rollWithSameDir=True 8 | ): 9 | """ 10 | create a single bone roll joints chain with desired roll joints, blend rotation between rollStart and rollEnd joints 11 | :param rollStart: str, create roll joints from rollStart joint 12 | :param rollEnd: str, create roll joints ends at rollEnd joint 13 | :param roll_Parent: str, parent ik_roll_joints to roll_Parent joint. 14 | If rollWithSameDir is True, roll_Parent is the joint above rollStart joint by 1 step 15 | example: upper arm: Clavical; hip: body_pivot or c_spine_0 16 | If rollWithSameDir is False, roll_Parent is the rollStart joint 17 | example: lower arm: Elbow 18 | :param IK_Parent: str, parent ik handle to the IK_Parent joints 19 | If rollWithSameDir is True, IK_Parent is the joint above rollStart joint by 1 step 20 | example: upper arm: Clavical; hip: body_pivot or c_spine_0 21 | If rollWithSameDir is False, IK_Parent is the rollStart joint 22 | example: lower arm: Wrist 23 | :param numRollJoints: int, number of roll joints between rollStart joint and rollEnd joint 24 | :param rollWithSameDir: bool, whether the roll joints are the same generation direction 25 | with the original joints chain direction 26 | :return: None 27 | """ 28 | if numRollJoints < 1: 29 | raise RuntimeError('Param: numRollJoints must larger than 1, please input correct int number again!') 30 | return 31 | 32 | if rollWithSameDir: 33 | roll_Parent = cmds.listRelatives(rollStart, p=1, c=0, s=0, type='joint')[0] 34 | IK_Parent = cmds.listRelatives(rollStart, p=1, c=0, s=0, type='joint')[0] 35 | else: 36 | roll_Parent = rollStart 37 | IK_Parent = rollStart 38 | 39 | rollJointList = [] 40 | 41 | # create the start and end roll joints 42 | rollStart_Jnt = cmds.joint(n=rollStart + '_Roll_Start') 43 | cmds.select(cl=1) 44 | rollEnd_Jnt = cmds.joint(n=rollStart + '_Roll_End') 45 | cmds.select(cl=1) 46 | 47 | # transform the joint 48 | pc1 = cmds.parentConstraint(rollStart, rollStart_Jnt, mo=0) 49 | cmds.delete(pc1) 50 | pc2 = cmds.parentConstraint(rollEnd, rollEnd_Jnt, mo=0) 51 | cmds.delete(pc2) 52 | 53 | # freeze transformation 54 | cmds.makeIdentity(rollStart_Jnt, apply=1, t=1, r=1, s=1) 55 | cmds.makeIdentity(rollEnd_Jnt, apply=1, t=1, r=1, s=1) 56 | 57 | # parent and get the .tx attribute 58 | cmds.parent(rollEnd_Jnt, rollStart_Jnt) 59 | totalLength = cmds.getAttr(rollEnd_Jnt + '.tx') 60 | 61 | eachLeagth = totalLength / (numRollJoints + 1) 62 | 63 | # create IK Handle 64 | ikHandle = cmds.ikHandle(n=rollStart + '_Roll_IK', sj=rollStart_Jnt, ee=rollEnd_Jnt, s='sticky', sol='ikSCsolver') 65 | cmds.parent(ikHandle[0], IK_Parent) 66 | cmds.pointConstraint(rollEnd, ikHandle[0], mo=0) 67 | 68 | rollJointList.append(rollStart_Jnt) 69 | 70 | if rollWithSameDir: 71 | rollDir = rollStart 72 | rollOrient = rollStart 73 | # create middle roll joints and transform it 74 | for i in range(0, numRollJoints): 75 | middleRoll_Jnt = cmds.duplicate(rollEnd_Jnt, n=rollStart + '_Roll_' + str(i + 1)) 76 | cmds.setAttr(middleRoll_Jnt[0] + '.tx', eachLeagth * (int(i) + 1)) 77 | cmds.parent(middleRoll_Jnt, rollDir) 78 | 79 | oc = cmds.orientConstraint(rollOrient, rollStart_Jnt, middleRoll_Jnt, mo=0) 80 | cmds.setAttr(oc[0] + '.' + rollStart_Jnt + 'W1', (len(range(0, numRollJoints)) - int(i))) 81 | cmds.setAttr(oc[0] + '.' + rollOrient + 'W0', (int(i) + 1)) 82 | 83 | rollJointList.append(middleRoll_Jnt[0]) 84 | 85 | else: 86 | rollDir = rollEnd 87 | rollOrient = rollEnd 88 | # create middle roll joints and transform it 89 | for i in range(0, numRollJoints): 90 | middleRoll_Jnt = cmds.duplicate(rollEnd_Jnt, n=rollStart + '_Roll_' + str(i + 1)) 91 | cmds.setAttr(middleRoll_Jnt[0] + '.tx', eachLeagth * (int(i) + 1)) 92 | cmds.parent(middleRoll_Jnt, rollDir) 93 | 94 | oc = cmds.orientConstraint(rollOrient, rollStart, middleRoll_Jnt, mo=0) 95 | cmds.setAttr(oc[0] + '.' + rollStart + 'W1', (len(range(0, numRollJoints)) - int(i))) 96 | cmds.setAttr(oc[0] + '.' + rollOrient + 'W0', (int(i) + 1)) 97 | 98 | rollJointList.append(middleRoll_Jnt[0]) 99 | 100 | # parent 101 | cmds.parent(rollStart_Jnt, roll_Parent) 102 | 103 | ############# 104 | # attribute # 105 | ############# 106 | if rollWithSameDir: 107 | # slave pointConstraint attr 108 | if not cmds.attributeQuery('slavePointConst', node=rollStart, exists=1): 109 | cmds.addAttr(rollStart, ln='slavePointConst', dt='string') 110 | 111 | cmds.setAttr(rollStart + '.slavePointConst', cmds.ls(rollEnd, long=1)[0], type='string', lock=1) 112 | 113 | if not cmds.attributeQuery('slaveParent', node=rollStart, exists=1): 114 | cmds.addAttr(rollStart, ln='slaveParent', dt='string') 115 | 116 | cmds.setAttr(rollStart + '.slaveParent', cmds.ls(rollJointList[-1], long=1)[0], type='string', lock=1) 117 | 118 | # slave parent attr 119 | for i in xrange(len(rollJointList) - 1): 120 | if not cmds.attributeQuery('slaveParent', node=rollJointList[i + 1], exists=1): 121 | cmds.addAttr(rollJointList[i + 1], ln='slaveParent', dt='string') 122 | cmds.setAttr(rollJointList[i + 1] + '.slaveParent', cmds.ls(rollJointList[i], long=1)[0], type='string', 123 | lock=1) 124 | else: 125 | # add and set attr 126 | if not cmds.attributeQuery('slaveParent', node=rollStart, exists=1): 127 | cmds.addAttr(rollStart, ln='slaveParent', dt='string') 128 | cmds.setAttr(rollStart + '.slaveParent', cmds.ls(rollStart_Jnt, long=1)[0], type='string', lock=1) 129 | 130 | for i in xrange(len(rollJointList) - 1): 131 | if not cmds.attributeQuery('slaveParent', node=rollJointList[i], exists=1): 132 | cmds.addAttr(rollJointList[i], ln='slaveParent', dt='string') 133 | cmds.setAttr(rollJointList[i] + '.slaveParent', cmds.ls(rollJointList[i+1], long=1)[0], type='string', 134 | lock=1) 135 | 136 | # add attr 137 | for joint in rollJointList: 138 | if not cmds.attributeQuery('rigModule', node=joint, exists=1): 139 | cmds.addAttr(joint, ln='rigModule', at='message') 140 | 141 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 142 | cmds.addAttr(joint, ln='slaveJoint', at='message') 143 | 144 | if not cmds.attributeQuery('rollJoint', node=joint, exists=1): 145 | cmds.addAttr(joint, ln='rollJoint', at='bool') 146 | cmds.setAttr(joint + '.rollJoint', 1, lock=1) 147 | 148 | rigModule = cmds.listConnections(rollStart + '.rigModule', source=1, destination=0, shapes=0)[0] 149 | 150 | if not cmds.attributeQuery('rollJoint', node=rigModule, exists=1): 151 | cmds.addAttr(rigModule, ln='rollJoint', at='message') 152 | 153 | for joint in rollJointList: 154 | cmds.connectAttr(rigModule + '.rollJoint', joint + '.rigModule', f=1) 155 | 156 | cmds.select(cl=1) 157 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/Edit_UI.py: -------------------------------------------------------------------------------- 1 | from PySide2 import QtWidgets 2 | import maya.cmds as cmds 3 | import logging 4 | import inspect 5 | from functools import partial 6 | import Splitter_UI 7 | 8 | 9 | class EditWidget(QtWidgets.QDialog): 10 | def __init__(self, instance, uiName, functionName): 11 | 12 | logging.basicConfig() 13 | logger = logging.getLogger('%s' % uiName) 14 | logger.setLevel(logging.INFO) 15 | 16 | try: 17 | cmds.deleteUI('%s' % uiName) 18 | except: 19 | logger.info('No %s exists!' % uiName) 20 | 21 | super(EditWidget, self).__init__(parent=instance) 22 | self.setObjectName('%s' % uiName) 23 | self.setWindowTitle('%s' % uiName) 24 | self.setModal(False) 25 | 26 | self.instance = instance 27 | self.functionName = functionName 28 | 29 | # Turn on track selection order for selecting vertices and lines 1 by 1 30 | self.TSO_Type = cmds.selectPref(q=1, tso=1) 31 | cmds.selectPref(tso=1) 32 | 33 | self.buildUI() 34 | self.populate() 35 | self.show() 36 | self.refreshListWidget() 37 | 38 | def buildUI(self): 39 | """ 40 | Build the Edit UI 41 | :return: None 42 | """ 43 | # Main layout 44 | self.mainLayout = QtWidgets.QGridLayout() 45 | self.setLayout(self.mainLayout) 46 | 47 | # parameters part 48 | self.paramSplitterWidget = Splitter_UI.Splitter('Parameters') 49 | 50 | self.formWidget = QtWidgets.QFrame() 51 | self.formWidget.setFrameStyle(QtWidgets.QFrame.StyledPanel) 52 | self.formWidget.setFrameShadow(QtWidgets.QFrame.Plain) 53 | self.formLayout = QtWidgets.QFormLayout() 54 | self.formWidget.setLayout(self.formLayout) 55 | 56 | # Selection part 57 | self.selSplitterWidget = Splitter_UI.Splitter('Check & Select') 58 | 59 | selectionWidget = QtWidgets.QFrame() 60 | selectionWidget.setFrameStyle(QtWidgets.QFrame.StyledPanel) 61 | selectionWidget.setFrameShadow(QtWidgets.QFrame.Plain) 62 | 63 | selectionLayout = QtWidgets.QVBoxLayout() 64 | selectionWidget.setLayout(selectionLayout) 65 | 66 | # filter part 67 | filterWidget = QtWidgets.QWidget() 68 | filterLayout = QtWidgets.QHBoxLayout() 69 | filterWidget.setLayout(filterLayout) 70 | filterLabel = QtWidgets.QLabel('Filter: ') 71 | self.jointCheck = QtWidgets.QCheckBox('joint') 72 | self.locatorCheck = QtWidgets.QCheckBox('locator') 73 | 74 | filterLayout.addWidget(filterLabel) 75 | filterLayout.addWidget(self.jointCheck) 76 | filterLayout.addWidget(self.locatorCheck) 77 | 78 | self.jointCheck.stateChanged.connect(self.refreshListWidget) 79 | self.locatorCheck.stateChanged.connect(self.refreshListWidget) 80 | 81 | # arrangement 82 | self.mainLayout.addWidget(self.paramSplitterWidget, 0, 0, 1, 1) 83 | self.mainLayout.addWidget(self.formWidget, 1, 0, 1, 1) 84 | self.mainLayout.addWidget(self.selSplitterWidget, 0, 1, 1, 1) 85 | self.mainLayout.addWidget(selectionWidget, 1, 1, 1, 1) 86 | 87 | self.listWidget = QtWidgets.QListWidget() 88 | self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) 89 | 90 | self.rowItem = {} 91 | self.tupe = inspect.getargspec(func=self.functionName) 92 | for i in self.tupe[0]: 93 | layout = QtWidgets.QHBoxLayout() 94 | 95 | self.rowItem[i] = QtWidgets.QLineEdit() 96 | button = QtWidgets.QPushButton('<<<') 97 | 98 | layout.addWidget(self.rowItem[i]) 99 | layout.addWidget(button) 100 | 101 | button.clicked.connect(partial(self.setEditLine, self.rowItem[i])) 102 | 103 | self.formLayout.addRow(i, layout) 104 | 105 | selectionLayout.addWidget(filterWidget) 106 | selectionLayout.addWidget(self.listWidget) 107 | 108 | # selectionWidget.setMaximumHeight(self.formWidget.height()) 109 | 110 | self.createGeneralButton(self.mainLayout) 111 | 112 | def setEditLine(self, editLine): 113 | """ 114 | set specified editLine text 115 | :param editLine: specified editLine 116 | :return: None 117 | """ 118 | # listWidget selected items 119 | listItems = self.listWidget.selectedItems() 120 | itemStr = [] 121 | for i in listItems: 122 | itemStr.append(self.listWidget.item(self.listWidget.row(i)).text()) 123 | 124 | # vertices or lines 125 | selList = cmds.ls(os=1) 126 | 127 | finalList = itemStr + selList 128 | 129 | if finalList: 130 | if len(finalList) < 2: 131 | editLine.setText(finalList[0]) 132 | else: 133 | editLine.setText(str(finalList)) 134 | 135 | def saveData(self): 136 | """ 137 | Save the args info to the specified rig widget's rigArgs dictionary 138 | :return: None 139 | """ 140 | tupe = inspect.getargspec(self.functionName) 141 | for i in tupe[0]: 142 | self.instance.rigArgs[i] = self.rowItem[i].text() 143 | 144 | def setData(self): 145 | """ 146 | Save the rigArgs info and close the rigArgs dialog 147 | :return: None 148 | """ 149 | self.saveData() 150 | 151 | self.close() 152 | 153 | cmds.selectPref(tso=self.TSO_Type) 154 | 155 | def cancel(self): 156 | """ 157 | Cancel button action -> close the rigArgs dialog 158 | :return: None 159 | """ 160 | self.close() 161 | cmds.selectPref(tso=self.TSO_Type) 162 | 163 | def populate(self): 164 | """ 165 | Refresh and populate the rigArgs info for each arg 166 | :return: None 167 | """ 168 | for arg in self.instance.rigArgs.keys(): 169 | if arg in self.rowItem.keys(): 170 | self.rowItem[arg].setText(str(self.instance.rigArgs[arg])) 171 | else: 172 | raise RuntimeWarning('No specified properties!') 173 | 174 | def createGeneralButton(self, layout): 175 | """ 176 | Create the Cancel and OK button for each widget 177 | :param layout: the edit window main widget 178 | :return: None 179 | """ 180 | btnWidget = QtWidgets.QWidget() 181 | btnLayout = QtWidgets.QHBoxLayout(btnWidget) 182 | layout.addWidget(btnWidget, 2, 0, 1, 2) 183 | 184 | cancel_Btn = QtWidgets.QPushButton('Cancel') 185 | OK_Btn = QtWidgets.QPushButton('OK') 186 | 187 | btnLayout.addWidget(cancel_Btn) 188 | btnLayout.addWidget(OK_Btn) 189 | 190 | OK_Btn.clicked.connect(self.setData) 191 | cancel_Btn.clicked.connect(self.cancel) 192 | 193 | def refreshListWidget(self): 194 | """ 195 | refresh listWidget with specified checked 196 | :return: None 197 | """ 198 | 199 | self.listWidget.clear() 200 | 201 | joints = [] 202 | locators = [] 203 | if self.jointCheck.isChecked(): 204 | joints = cmds.ls(type='joint') 205 | 206 | locaterShapes = [] 207 | if self.locatorCheck.isChecked(): 208 | locaterShapes = cmds.ls(type='locator') 209 | 210 | for loc in locaterShapes: 211 | locators.append(cmds.listRelatives(loc, p=1)[0]) 212 | 213 | returnList = joints + locators 214 | 215 | if returnList: 216 | if len(returnList) > 1: 217 | self.listWidget.addItems(returnList) 218 | else: 219 | self.listWidget.addItem(returnList[0]) -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/control.py: -------------------------------------------------------------------------------- 1 | """ 2 | module for making rig control 3 | """ 4 | 5 | import maya.cmds as cmds 6 | import controlShape 7 | reload(controlShape) 8 | 9 | 10 | class Control(): 11 | 12 | """ 13 | class for building rig control 14 | """ 15 | 16 | def __init__(self, 17 | prefix='L_', 18 | rigPartName='', 19 | scale=1.0, 20 | translateTo='', 21 | rotateTo='', 22 | parent='', 23 | shape='circle', 24 | axis='x', 25 | lockChannels=['s', 'v']): 26 | """ 27 | create rig control and rig offset group 28 | :param prefix: str, prefix to name new objects 29 | :param rigPartName: str, rig part name 30 | :param scale: float, scale value for size of control shapes 31 | :param translateTo: str, reference object for control position 32 | :param rotateTo: str,reference object for control orientation 33 | :param parent:str, object to be parent of new control 34 | :param shape: str, control shape type 35 | :param lockChannels: list(str), list of channels on control to be locked and non-keyable 36 | """ 37 | 38 | circleNormal = [1, 0, 0] 39 | ctrlObject = None 40 | 41 | if shape in ['circle', 'circleX']: 42 | 43 | circleNormal = [1, 0, 0] 44 | 45 | elif shape == 'circleY': 46 | 47 | circleNormal = [0, 1, 0] 48 | 49 | elif shape == 'circleZ': 50 | 51 | circleNormal = [0, 0, 1] 52 | 53 | elif shape == 'sphere': 54 | ctrlObject = cmds.circle(n=prefix + rigPartName + '_Ctrl', ch=False, normal=[1, 0, 0], radius=scale)[0] 55 | addShape = cmds.circle(n=prefix + rigPartName + '_Ctrl2', ch=False, normal=[0, 0, 1], radius=scale)[0] 56 | cmds.parent(cmds.listRelatives(addShape, s=1), ctrlObject, r=1, s=1) 57 | cmds.delete(addShape) 58 | 59 | elif shape == 'crossControl': 60 | ctrlObject = controlShape.CrossControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 61 | 62 | elif shape == 'arrowCurve': 63 | ctrlObject = controlShape.ArrowCurve.createShape(prefix=prefix + rigPartName + '_Ctrl') 64 | 65 | elif shape == 'crownCurve': 66 | ctrlObject = controlShape.CrownCurve.createShape(prefix=prefix + rigPartName + '_Ctrl') 67 | 68 | elif shape == 'cubeCurve': 69 | ctrlObject = controlShape.CubeCurve.createShape(prefix=prefix + rigPartName + '_Ctrl') 70 | 71 | elif shape == 'cubeOnBase': 72 | ctrlObject = controlShape.cubeOnBase.createShape(prefix=prefix + rigPartName + '_Ctrl') 73 | 74 | elif shape == 'diamond': 75 | ctrlObject = controlShape.Diamond.createShape(prefix=prefix + rigPartName + '_Ctrl') 76 | 77 | elif shape == 'fistCurve': 78 | ctrlObject = controlShape.FistCurve.createShape(prefix=prefix + rigPartName + '_Ctrl') 79 | 80 | elif shape == 'footControl': 81 | ctrlObject = controlShape.FootControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 82 | 83 | elif shape == 'moveControl': 84 | ctrlObject = controlShape.MoveControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 85 | 86 | elif shape == 'rotationControl': 87 | ctrlObject = controlShape.RotationControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 88 | 89 | elif shape == 'singleRotateControl': 90 | ctrlObject = controlShape.singleRotateControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 91 | 92 | elif shape == 'spikeCrossControl': 93 | ctrlObject = controlShape.SpikeCrossControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 94 | 95 | elif shape == 'unitSliderControl': 96 | ctrlBox = controlShape.unitSliderControl.createShape(prefix=prefix + rigPartName) 97 | ctrlObject = cmds.listRelatives(ctrlBox, children=1, parent=0, s=0) 98 | ctrlObject = ctrlObject[1] 99 | 100 | elif shape == 'squareControl': 101 | ctrlObject = controlShape.squareControl.createShape(prefix=prefix + rigPartName + '_Ctrl') 102 | 103 | if not ctrlObject: 104 | ctrlObject = cmds.circle(n=prefix + rigPartName + '_Ctrl', ch=1, 105 | normal=circleNormal, radius=1.0)[0] 106 | 107 | # rotate the ctrlObject 108 | if shape in ['circle', 'circleX', 'circleY', 'circleZ']: 109 | pass 110 | else: 111 | self.rotate_Ctrl(ctrlObject=ctrlObject, shape=shape, axis=axis) 112 | 113 | # ctrl offset group 114 | ctrlOffset = cmds.group(n=prefix + rigPartName + '_CtrlGrp', em=1) 115 | if shape in ['unitSliderControl']: 116 | cmds.parent(ctrlBox, ctrlOffset) 117 | else: 118 | cmds.parent(ctrlObject, ctrlOffset) 119 | 120 | # scale the control grp 121 | cmds.setAttr(ctrlOffset + '.s', scale, scale, scale) 122 | 123 | # color control 124 | ctrlShapes = cmds.listRelatives(ctrlObject, s=1) 125 | 126 | [cmds.setAttr(s + '.ove', 1) for s in ctrlShapes] 127 | 128 | if prefix.startswith('L_'): 129 | [cmds.setAttr(s + '.ovc', 6) for s in ctrlShapes] 130 | 131 | elif prefix.startswith('R_'): 132 | [cmds.setAttr(s + '.ovc', 13) for s in ctrlShapes] 133 | 134 | else: 135 | [cmds.setAttr(s + '.ovc', 22) for s in ctrlShapes] 136 | 137 | # translate control 138 | 139 | if cmds.objExists(translateTo): 140 | cmds.delete(cmds.pointConstraint(translateTo, ctrlOffset, mo=0)) 141 | 142 | # rotate control 143 | 144 | if cmds.objExists(rotateTo): 145 | cmds.delete(cmds.orientConstraint(rotateTo, ctrlOffset, mo=0)) 146 | 147 | # parent control 148 | 149 | if cmds.objExists(parent): 150 | cmds.parent(ctrlOffset, parent) 151 | 152 | # lock control channels 153 | 154 | singleAttributeLockList = [] 155 | for lockChannel in lockChannels: 156 | 157 | if lockChannel in ['t', 'r', 's']: 158 | 159 | for axis in ['x', 'y', 'z']: 160 | 161 | at = lockChannel + axis 162 | singleAttributeLockList.append(at) 163 | 164 | else: 165 | singleAttributeLockList.append(lockChannel) 166 | 167 | for at in singleAttributeLockList: 168 | cmds.setAttr(ctrlObject + '.' + at, l=1, k=0) 169 | 170 | # add public members 171 | 172 | self.C = ctrlObject 173 | self.Off = ctrlOffset 174 | 175 | def rotate_Ctrl(self, ctrlObject, shape, axis='x'): 176 | """ 177 | not support for sliderControl and unitSliderControl 178 | :param ctrlObject: INSTANCE.C 179 | :param shape: control shape 180 | :param axis: forward axis 181 | :return: None 182 | """ 183 | ctrlShape = cmds.listRelatives(ctrlObject, s=1, type='nurbsCurve') 184 | 185 | cls = cmds.cluster(ctrlShape)[1] 186 | 187 | if axis == 'x' and shape in ['crossControl', 'crownCurve', 'fistCurve', 188 | 'footControl', 'moveControl', 'spikeCrossControl']: 189 | cmds.setAttr(cls + '.rz', 90) 190 | 191 | elif axis == 'x' and shape in ['rotationControl', 'singleRotateControl']: 192 | cmds.setAttr(cls + '.ry', 90) 193 | 194 | elif axis == 'z' and shape in ['arrowCurve', 'crossControl', 'crownCurve', 'cubeOnBase', 'fistCurve', 195 | 'footControl', 'moveControl', 'spikeCrossControl']: 196 | cmds.setAttr(cls + '.rx', 90) 197 | 198 | elif axis == 'y' and shape in ['rotationControl', 'singleRotateControl']: 199 | cmds.setAttr(cls + '.rx', 90) 200 | 201 | elif axis == 'y' and shape in ['squareControl']: 202 | cmds.setAttr(cls + '.rz', 90) 203 | 204 | elif axis == 'z' and shape in ['squareControl']: 205 | cmds.setAttr(cls + '.ry', 90) 206 | 207 | elif axis == 'x' and shape in ['cubeOnBase']: 208 | cmds.move(0, 0, 0, [cls + '.scalePivot', cls + '.rotatePivot'], rpr=1) 209 | cmds.setAttr(cls + '.rz', -90) 210 | elif axis == 'x' and shape in ['arrowCurve']: 211 | cmds.move(0, 0, 0, [cls + '.scalePivot', cls + '.rotatePivot'], rpr=1) 212 | cmds.setAttr(cls + '.ry', -90) 213 | cmds.setAttr(cls + '.rx', -90) 214 | else: 215 | pass 216 | 217 | # delete the cluster 218 | cmds.delete(ctrlShape, ch=1) 219 | 220 | cmds.select(cl=1) 221 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/IK_AnimalLeg.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | from ..base import module 4 | from ..base import control 5 | 6 | from ..utils import name 7 | 8 | reload(module) 9 | reload(control) 10 | reload(name) 11 | 12 | 13 | def build(legJoints, 14 | revJntlocList, 15 | ankleRollLoc, 16 | spineJnt='', 17 | prefix='L_', 18 | rigScale=1.0, 19 | baseRig=None): 20 | """ 21 | IK animal leg rig, for 22 | :param legJoints: list(str), leg joints.[hip, knee, ankle, ball, toe, toeEnd] 23 | :param revJntlocList: list(str), rev_joint locator list.[CBank, EBank, Heel, Pivot] 24 | :param ankleRollLoc: str, ankleRoll locator. 25 | :param spineJnt: str, start joint of the spine(i.e. spine_0) 26 | :param prefix: str, 'L_' OR 'L_Front'... 27 | :param rigScale: float, rig scale of the module. 28 | :param baseRig: instance, base attach of the rig. Base Class instance is used. 29 | :return: None. 30 | """ 31 | rigPartName = 'AnimLeg' 32 | 33 | if spineJnt: 34 | try: 35 | cmds.objectType(spineJnt) == 'joint' 36 | except: 37 | cmds.error('%s is not a joint type!' %spineJnt) 38 | else: 39 | parentJnt = cmds.listRelatives(legJoints[0], s=0, children=0, parent=1, type='joint') 40 | if parentJnt: 41 | spineJnt = parentJnt 42 | else: 43 | pass 44 | 45 | cmds.select(cl=1) 46 | 47 | rigModule = module.Module(prefix=prefix, 48 | rigPartName=rigPartName, 49 | baseObject=baseRig) 50 | 51 | hintFirstLength = cmds.getAttr(legJoints[2] + '.tx') 52 | hintSecondLength = cmds.getAttr(legJoints[1] + '.tx') + cmds.getAttr(legJoints[3] + '.tx') 53 | 54 | cmds.select(cl=1) 55 | 56 | # create IK_HintLeg 57 | hintJnt_List = [] 58 | for i in xrange(3): 59 | hintJnt = cmds.joint(n=prefix + rigPartName + 'Hint_Jnt' + str(i)) 60 | cmds.setAttr(hintJnt + '.drawStyle', 2) 61 | cmds.select(cl=1) 62 | hintJnt_List.append(hintJnt) 63 | 64 | for i in xrange(len(hintJnt_List)-1): 65 | cmds.parent(hintJnt_List[i+1], hintJnt_List[i]) 66 | 67 | cmds.setAttr(hintJnt_List[1] + '.tx', hintFirstLength) 68 | cmds.setAttr(hintJnt_List[2] + '.tx', hintSecondLength) 69 | 70 | cmds.select(cl=1) 71 | 72 | cmds.setAttr(hintJnt_List[0] + '.rotateX', -90) 73 | cmds.setAttr(hintJnt_List[0] + '.rotateZ', 90) 74 | 75 | cmds.setAttr(hintJnt_List[1] + '.rotateZ', 90) 76 | 77 | cmds.makeIdentity(hintJnt_List[0], apply=1, t=1, r=1, s=1, n=0, pn=1) 78 | 79 | # hint leg ik 80 | IK_Hint_Part_List = cmds.ikHandle(n=prefix + rigPartName + 'hintLeg_IK', sj=hintJnt_List[0], 81 | ee=hintJnt_List[-1], sol='ikRPsolver') 82 | 83 | pc1 = cmds.pointConstraint(legJoints[0], hintJnt_List[0], mo=0) 84 | cmds.delete(pc1) 85 | pc2 = cmds.pointConstraint(legJoints[3], IK_Hint_Part_List[0], mo=0) 86 | cmds.delete(pc2) 87 | 88 | # create footCtrl and rev joints 89 | Foot_IK_Ctrl = control.Control(prefix=prefix, 90 | rigPartName=rigPartName, 91 | scale=rigScale*5, 92 | translateTo=legJoints[-2], 93 | rotateTo=legJoints[-2], 94 | shape='footControl', 95 | axis='y', 96 | lockChannels=['v']) 97 | cmds.select(cl=1) 98 | # flatten Ctrl and mirror the Ctrl action by plan YZ 99 | cmds.setAttr(Foot_IK_Ctrl.Off + '.rotateX', 90) 100 | cmds.setAttr(Foot_IK_Ctrl.Off + '.rotateY', 0) 101 | cmds.setAttr(Foot_IK_Ctrl.Off + '.rotateZ', cmds.getAttr(Foot_IK_Ctrl.Off + '.rotateZ') + 90) 102 | 103 | if prefix.startswith('R_'): 104 | cmds.setAttr(Foot_IK_Ctrl.Off + '.scaleZ', cmds.getAttr(Foot_IK_Ctrl.Off + '.scaleZ') * (-1)) 105 | 106 | cmds.select(cl=1) 107 | 108 | revJntList = [] 109 | for i in xrange(len(revJntlocList)): 110 | revJnt = cmds.joint(n=(name.removeSuffix(revJntlocList[i]) + '_Rev')) 111 | cmds.setAttr(revJnt + '.drawStyle', 2) 112 | cmds.select(cl=1) 113 | cmds.delete(cmds.pointConstraint(revJntlocList[i], revJnt, mo=0)) 114 | cmds.delete(cmds.orientConstraint(Foot_IK_Ctrl.C, revJnt, mo=0)) 115 | revJntList.append(revJnt) 116 | 117 | cmds.select(cl=1) 118 | 119 | for i in revJntlocList: 120 | cmds.delete(i) 121 | 122 | cmds.select(cl=1) 123 | 124 | legJoints_Rev = [] 125 | for i in legJoints: 126 | legJoints_Rev.append(i) 127 | legJoints_Rev.reverse() 128 | 129 | cmds.select(cl=1) 130 | 131 | for i in xrange(len(legJoints_Rev[:3])): 132 | revJnt = cmds.joint(n=legJoints_Rev[i] + '_Rev') 133 | cmds.setAttr(revJnt + '.drawStyle', 2) 134 | cmds.select(cl=1) 135 | cmds.delete(cmds.pointConstraint(legJoints_Rev[i], revJnt, mo=0)) 136 | cmds.delete(cmds.orientConstraint(Foot_IK_Ctrl.C, revJnt, mo=0)) 137 | 138 | revJntList.append(revJnt) 139 | 140 | cmds.select(cl=1) 141 | 142 | # parenting 143 | for i in xrange(len(revJntList)-1): 144 | cmds.parent(revJntList[i+1], revJntList[i]) 145 | cmds.select(cl=1) 146 | 147 | cmds.select(cl=1) 148 | 149 | cmds.makeIdentity(revJntList[0], apply=1, t=1, r=1, s=1, n=0, pn=1) 150 | 151 | # create BallRoll_Ctrl and RevJntRoll_Ctrl 152 | 153 | ballRoll_Ctrl = control.Control(prefix=prefix, 154 | rigPartName='BallRoll', 155 | scale=rigScale*3, 156 | translateTo=legJoints[-3], 157 | rotateTo=hintJnt_List[-1], 158 | shape='sphere', 159 | lockChannels=['t', 's', 'v']) 160 | cmds.orientConstraint(hintJnt_List[-1], ballRoll_Ctrl.Off, mo=0) 161 | 162 | cmds.select(cl=1) 163 | 164 | revJntRoll_Ctrl = control.Control(prefix=prefix, 165 | rigPartName='AnkleRoll', 166 | scale=rigScale * 7, 167 | translateTo=ankleRollLoc, 168 | rotateTo=Foot_IK_Ctrl.C, 169 | shape='rotationControl', 170 | axis='y', 171 | lockChannels=['t', 's', 'v']) 172 | cmds.delete(ankleRollLoc) 173 | cmds.select(cl=1) 174 | 175 | # revJntRoll_Ctrl connects attrs to revJntList 176 | cmds.addAttr(revJntRoll_Ctrl.C, ln='Ball2Toe', k=1, at="float", min=0, max=1, dv=0) 177 | 178 | # rotate Z 179 | 180 | condition1 = cmds.createNode('condition', n=prefix + 'Foot_CD#') 181 | cmds.setAttr(condition1 + '.colorIfFalseR', 0) 182 | 183 | cmds.setAttr(condition1 + '.operation', 2) 184 | 185 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateZ', condition1 + '.firstTerm', f=1) 186 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateZ', condition1 + '.colorIfTrueR', f=1) 187 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateZ', condition1 + '.colorIfFalseG', f=1) 188 | 189 | cmds.connectAttr(condition1 + '.outColorR', revJntList[0] + '.rotateZ', f=1) 190 | cmds.connectAttr(condition1 + '.outColorG', revJntList[1] + '.rotateZ', f=1) 191 | 192 | # rotate Y 193 | 194 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateY', revJntList[3] + '.rotateY', f=1) 195 | 196 | # rotate X 197 | condition2 = cmds.createNode('condition', n=prefix + 'Foot_CD#') 198 | cmds.setAttr(condition2 + '.colorIfFalseR', 0) 199 | cmds.setAttr(condition2 + '.operation', 2) 200 | 201 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateX', condition2 + '.firstTerm', f=1) 202 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateX', condition2 + '.colorIfTrueR', f=1) 203 | cmds.connectAttr(revJntRoll_Ctrl.C + '.rotateX', condition2 + '.colorIfFalseG', f=1) 204 | 205 | cmds.connectAttr(condition2 + '.outColorG', revJntList[2] + '.rotateX', f=1) 206 | 207 | blendColors = cmds.createNode('blendColors', n=prefix + 'Foot_BLC#') 208 | cmds.connectAttr(revJntRoll_Ctrl.C + '.Ball2Toe', blendColors + '.blender', f=1) 209 | cmds.connectAttr(condition2 + '.outColorR', blendColors + '.color1R', f=1) 210 | cmds.connectAttr(condition2 + '.outColorR', blendColors + '.color2G', f=1) 211 | 212 | cmds.connectAttr(blendColors + '.outputR', revJntList[4] + '.rotateX', f=1) 213 | cmds.connectAttr(blendColors + '.outputG', revJntList[5] + '.rotateX', f=1) 214 | 215 | cmds.select(cl=1) 216 | 217 | # Create IK for legJoints 218 | IK_Hip_Part_List = cmds.ikHandle(n=prefix + rigPartName + 'Hip_IK', sj=legJoints[0], ee=legJoints[2], sol='ikRPsolver') 219 | IK_Ball_List = cmds.ikHandle(n=prefix + rigPartName + 'Ball_IK', sj=legJoints[2], ee=legJoints[3], sol='ikSCsolver') 220 | IK_Toe_List = cmds.ikHandle(n=prefix + rigPartName + 'Toe_IK', sj=legJoints[3], ee=legJoints[4], sol='ikSCsolver') 221 | IK_ToeEnd_List = cmds.ikHandle(n=prefix + rigPartName + 'ToeEnd_IK', sj=legJoints[-2], ee=legJoints[-1], sol='ikSCsolver') 222 | cmds.select(cl=1) 223 | 224 | # pole vector Ctrl 225 | PV_Ctrl = control.Control(prefix=prefix, 226 | rigPartName='Leg_PV', 227 | scale=rigScale * 18, 228 | translateTo=legJoints[1], 229 | shape='diamond', 230 | lockChannels=['r', 's', 'v']) 231 | cmds.select(cl=1) 232 | cmds.poleVectorConstraint(PV_Ctrl.C, IK_Hint_Part_List[0]) 233 | cmds.setAttr(IK_Hint_Part_List[0] + '.twist', 180) 234 | cmds.poleVectorConstraint(PV_Ctrl.C, IK_Hip_Part_List[0]) 235 | 236 | cmds.select(cl=1) 237 | 238 | # final parenting 239 | if spineJnt: 240 | cmds.parent(hintJnt_List[0], spineJnt) 241 | else: 242 | cmds.warning('No spine joint, IK system may not work as expected!') 243 | cmds.parent(hintJnt_List[0], rigModule.topGrp) 244 | 245 | cmds.parent(IK_Hip_Part_List[0], ballRoll_Ctrl.C) 246 | cmds.parent(IK_Ball_List[0], ballRoll_Ctrl.C) 247 | 248 | cmds.parent(ballRoll_Ctrl.Off, revJntList[-1]) 249 | cmds.parent(IK_Hint_Part_List[0], revJntList[-1]) 250 | 251 | cmds.parent(IK_Toe_List[0], revJntList[-2]) 252 | cmds.parent(IK_ToeEnd_List[0], revJntList[-3]) 253 | 254 | cmds.parent(revJntList[0], Foot_IK_Ctrl.C) 255 | cmds.parent(revJntRoll_Ctrl.Off, Foot_IK_Ctrl.C) 256 | 257 | cmds.parent(PV_Ctrl.Off, rigModule.topGrp) 258 | cmds.parent(Foot_IK_Ctrl.Off, rigModule.topGrp) 259 | 260 | # add Attr 261 | for joint in legJoints: 262 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 263 | cmds.addAttr(joint, longName='slaveJoint', at='message') 264 | 265 | if not cmds.attributeQuery('rigModule', node=joint, exists=1): 266 | cmds.addAttr(joint, longName='rigModule', at='message') 267 | 268 | # connect Attr 269 | for joint in legJoints: 270 | if cmds.attributeQuery('rigModule', node=joint, exists=1): 271 | cmds.connectAttr(rigModule.topGrp + '.' + prefix + rigPartName + '_Jnt', 272 | joint + '.rigModule', f=1) 273 | 274 | cmds.select(cl=1) 275 | 276 | return rigModule 277 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/IK_FK_Spine.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | from ..base import module 3 | from ..base import control 4 | reload(module) 5 | reload(control) 6 | 7 | 8 | def build(spineJoints, 9 | prefix='C_', 10 | rigScale=1.0, 11 | numFK_Jnt=3, 12 | spineBackUpAxis='y', 13 | mainSpineAttach=None, 14 | baseRig=None): 15 | """ 16 | Build IK_FK_Spine rig. 17 | This IK_FK_Spine build module is used for spine joint chain which is placed in the 0 x-Axis position. 18 | :param spineJoints: list(str), original spine joints, from the C_Spine_0 to C_Spine_x, you need to make true that 19 | the spine joints are at same directions, i.e. x-axis is main axis, and z-axis is point to the 20 | -x axis of world space. 21 | :param prefix: str, prefix of the spine, usually, 'C_' is used. 22 | :param rigScale: float, rig scale of the IK_FK_Spine rig module. 23 | :param numFK_Jnt: int, number of FK spine joints, greater than 3. 24 | :param mainSpineAttach: str, main Spine Attach part name, if the spine is not the mainSpine, must set a attachJoint 25 | name to it. Usually the last valid joint of attached part. 26 | :param baseRig: str, base atttach of the rig. Base Class instance is used. 27 | :return: dictionary, rigModule, chest_ctrl (used for upper body parts rig, IK_FK_Arm .etc)and pelvis_ctrl (used for FK_Tail rig) 28 | """ 29 | # param check 30 | if numFK_Jnt < 3: 31 | raise RuntimeError('Param: numFK_Jnt must larger than 3!') 32 | return 33 | 34 | # local rigPartName 35 | rigPartName = 'Spine' 36 | 37 | rigModule = module.Module(prefix=prefix, 38 | rigPartName=rigPartName, 39 | baseObject=baseRig) 40 | 41 | if spineBackUpAxis in ['y', 'Y']: 42 | worldUpVector = (0, 1, 0) 43 | elif spineBackUpAxis in ['z', 'Z']: 44 | worldUpVector = (0, 0, 1) 45 | 46 | # fk skeleton chain 47 | # create FK crv 48 | ik_part_list = [] 49 | ik_part_list = cmds.ikHandle(sj=spineJoints[0], ee=spineJoints[-1], parentCurve=1, sol='ikSplineSolver', numSpans=4, 50 | simplifyCurve=0) 51 | 52 | cmds.delete(ik_part_list[0]) 53 | 54 | FK_Crv = ik_part_list[-1] 55 | 56 | fkJntList = [] 57 | eachADD = 1.0 / (len(range(numFK_Jnt)) - 1) 58 | 59 | for i in range(numFK_Jnt): 60 | fkJnt = cmds.joint(n='FK_' + prefix + rigPartName + '_' + str(i)) 61 | pc = cmds.parentConstraint(spineJoints[0], fkJnt, mo=0) 62 | cmds.delete(pc) 63 | 64 | motionPath = cmds.pathAnimation(FK_Crv, fkJnt, n=fkJnt + '_motionPath', fractionMode=1, follow=1, 65 | followAxis='x', upAxis='y', worldUpType='Vector', 66 | worldUpVector=worldUpVector, inverseUp=0, inverseFront=0, bank=0) 67 | 68 | # cmds.disconnectAttr(motionPath + '_uValue.output', motionPath + '.uValue') 69 | cmds.cutKey(motionPath + '.u', time=()) 70 | 71 | cmds.setAttr(motionPath + '.uValue', eachADD * float(i)) 72 | 73 | for attr in ['t', 'r']: 74 | for axis in ['x', 'y', 'z']: 75 | cmds.delete(fkJnt + '.%s%s' % (attr, axis), icn=1) 76 | 77 | cmds.delete(motionPath) 78 | 79 | cmds.select(cl=1) 80 | 81 | fkJntList.append(fkJnt) 82 | 83 | # delete the motionPath 84 | cmds.delete(FK_Crv) 85 | 86 | # move the last fk joint to the end of the spineJoints 87 | pc3 = cmds.pointConstraint(spineJoints[-1], fkJntList[-1], mo=0) 88 | cmds.delete(pc3) 89 | 90 | # aimConstraint all the fk_joints, the last joints must be same direction as the last joints of original joints list 91 | fkJntList_rev = [] 92 | 93 | for i in fkJntList: 94 | fkJntList_rev.append(i) 95 | fkJntList_rev.reverse() 96 | 97 | for i in xrange(len(fkJntList_rev)-1): 98 | ac = cmds.aimConstraint(fkJntList_rev[i], fkJntList_rev[i+1], mo=0, weight=1, aimVector=(1, 0, 0), 99 | upVector=(0, 1, 0), worldUpType='vector', worldUpVector=worldUpVector) 100 | cmds.delete(ac) 101 | 102 | # orientConstraint the last joint 103 | oc = cmds.orientConstraint(spineJoints[-1], fkJntList_rev[0], mo=0) 104 | cmds.delete(oc) 105 | 106 | # parent 107 | for i in xrange(len(fkJntList_rev)-1): 108 | cmds.parent(fkJntList_rev[i], fkJntList_rev[i+1]) 109 | 110 | # set fk joints drawStyle to None and display to template 111 | 112 | for i in fkJntList: 113 | cmds.setAttr(i + '.drawStyle', 2) 114 | 115 | # freeze transformation 116 | cmds.makeIdentity(fkJntList[0], apply=1) 117 | 118 | 119 | ########## 120 | # FK rig # 121 | ########## 122 | FK_CtrlGrp_List = [] 123 | FK_Ctrl_List = [] 124 | 125 | for i in xrange(len(fkJntList)-2): 126 | FK_C_Spine_Ctrl = control.Control(prefix=prefix + 'FK_', 127 | rigPartName=rigPartName + '_' + str(i), 128 | scale=rigScale, 129 | translateTo=fkJntList[i+1], 130 | rotateTo=fkJntList[i+1], 131 | shape='circle', 132 | lockChannels=['t', 's', 'v']) 133 | 134 | cmds.orientConstraint(FK_C_Spine_Ctrl.C, fkJntList[i+1], mo=0) 135 | 136 | FK_CtrlGrp_List.append(FK_C_Spine_Ctrl.Off) 137 | FK_Ctrl_List.append(FK_C_Spine_Ctrl.C) 138 | 139 | cmds.select(cl=1) 140 | 141 | # parent the CtrlGrps to the proper places 142 | for i in xrange(len(FK_Ctrl_List)-1): 143 | cmds.parent(FK_CtrlGrp_List[i+1], FK_Ctrl_List[i]) 144 | 145 | cmds.parent(FK_CtrlGrp_List[0], fkJntList[0]) 146 | 147 | ############# 148 | # Body Ctrl # 149 | ############# 150 | 151 | if not mainSpineAttach: 152 | # create a square control shape for body ctrl 153 | body_Ctrl = control.Control(prefix=prefix, 154 | rigPartName='Body', 155 | scale=rigScale * 15, 156 | shape='squareControl', 157 | translateTo=spineJoints[0], 158 | axis='z') 159 | else: 160 | body_Loc = cmds.spaceLocator(n=prefix + rigPartName + '_Loc') 161 | body_LocShape = cmds.listRelatives(body_Loc, s=1) 162 | cmds.setAttr(body_LocShape[0] + '.localScaleX', 0) 163 | cmds.setAttr(body_LocShape[0] + '.localScaleY', 0) 164 | cmds.setAttr(body_LocShape[0] + '.localScaleZ', 0) 165 | cmds.parentConstraint(mainSpineAttach, body_Loc, mo=0) 166 | 167 | C_Pelvis_Ctrl = control.Control(prefix=prefix, 168 | rigPartName='Pelvis', 169 | scale=rigScale*2, 170 | translateTo=spineJoints[0], 171 | rotateTo=spineJoints[0], 172 | axis='x', 173 | shape='moveControl') 174 | 175 | C_Chest_Ctrl = control.Control(prefix=prefix, 176 | rigPartName='Chest', 177 | scale=rigScale*3, 178 | translateTo=spineJoints[-1], 179 | rotateTo=spineJoints[-1], 180 | axis='x', 181 | shape='moveControl') 182 | 183 | # create 2 joints for controlling ikHandle curve 184 | pelvis_Jnt = cmds.joint(n=prefix + 'Pelvis') 185 | cmds.select(cl=1) 186 | cmds.setAttr(pelvis_Jnt + '.v', 0) 187 | chest_Jnt = cmds.joint(n=prefix + 'Chest') 188 | cmds.select(cl=1) 189 | cmds.setAttr(chest_Jnt + '.v', 0) 190 | 191 | pc1 = cmds.parentConstraint(fkJntList[0], pelvis_Jnt, mo=0) 192 | cmds.delete(pc1) 193 | cmds.makeIdentity(pelvis_Jnt, apply=1) 194 | 195 | pc2 = cmds.parentConstraint(fkJntList[-1], chest_Jnt, mo=0) 196 | cmds.delete(pc2) 197 | cmds.makeIdentity(chest_Jnt, apply=1) 198 | 199 | ########## 200 | # IK rig # 201 | ########## 202 | 203 | IK_Part_List = cmds.ikHandle(n=prefix + rigPartName + '_IK', 204 | sj=spineJoints[0], 205 | ee=spineJoints[-1], 206 | parentCurve=0, 207 | numSpans=4, 208 | sol='ikSplineSolver') 209 | 210 | # bind ik curve with 2 joints 211 | cmds.select(cl=1) 212 | cmds.select(IK_Part_List[-1]) 213 | cmds.select(chest_Jnt, add=1) 214 | cmds.select(pelvis_Jnt, add=1) 215 | cmds.skinCluster(chest_Jnt, pelvis_Jnt, IK_Part_List[-1], tsb=1) 216 | 217 | # setup IK Twist 218 | cmds.setAttr(IK_Part_List[0] + '.dTwistControlEnable', 1) 219 | cmds.setAttr(IK_Part_List[0] + '.dWorldUpType', 4) 220 | cmds.connectAttr(C_Pelvis_Ctrl.C + '.worldMatrix[0]', IK_Part_List[0] + '.dWorldUpMatrix') 221 | cmds.connectAttr(C_Chest_Ctrl.C + '.worldMatrix[0]', IK_Part_List[0] + '.dWorldUpMatrixEnd') 222 | 223 | # add attr 224 | for joint in spineJoints: 225 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 226 | cmds.addAttr(joint, ln='slaveJoint', at='message') 227 | 228 | if not cmds.attributeQuery('rigModule', node=joint, exists=1): 229 | cmds.addAttr(joint, ln='rigModule', at='message') 230 | 231 | # connect attr 232 | for joint in spineJoints: 233 | if cmds.attributeQuery('rigModule', node=joint, exists=1): 234 | cmds.connectAttr(rigModule.topGrp + '.' + prefix + rigPartName + "_Jnt", 235 | joint + '.rigModule', f=1) 236 | 237 | # clean up the hierarchy 238 | cmds.parent(pelvis_Jnt, C_Pelvis_Ctrl.C) 239 | cmds.parent(chest_Jnt, C_Chest_Ctrl.C) 240 | 241 | # parent fk_jnt to body_Ctrl 242 | if not mainSpineAttach: 243 | cmds.parent(fkJntList[0], body_Ctrl.C) 244 | 245 | # parent pelvis_CtrlGrp to body_Ctrl 246 | cmds.parent(C_Pelvis_Ctrl.Off, body_Ctrl.C) 247 | else: 248 | cmds.parent(fkJntList[0], body_Loc) 249 | cmds.parent(C_Pelvis_Ctrl.Off, body_Loc) 250 | 251 | 252 | # parent chest_CtrlGrp to fkJntList[-1] 253 | cmds.parent(C_Chest_Ctrl.Off, fkJntList[-1]) 254 | 255 | cmds.parent(IK_Part_List[-1], IK_Part_List[0], rigModule.dontTouchGrp) 256 | 257 | # parent body_CtrlGrp to rigmodule.topGrp 258 | if not mainSpineAttach: 259 | cmds.parent(body_Ctrl.Off, rigModule.topGrp) 260 | else: 261 | cmds.parent(body_Loc, rigModule.topGrp) 262 | 263 | cmds.select(cl=1) 264 | 265 | # rootJoint 266 | rootJnt = '' 267 | if not mainSpineAttach: 268 | rootJnt = cmds.listRelatives(spineJoints[0], p=1, c=0, s=0, type='joint') 269 | 270 | if rootJnt: 271 | 272 | if not cmds.attributeQuery('slaveJoint', node=rootJnt[0], exists=1): 273 | cmds.addAttr(rootJnt[0], ln='slaveJoint', at='message') 274 | 275 | if not cmds.attributeQuery('rootJoint', node=rootJnt[0], exists=1): 276 | cmds.addAttr(rootJnt[0], ln='rootJoint', at='message') 277 | 278 | 279 | # return 280 | return {'chest_Ctrl': C_Chest_Ctrl.C, 281 | 'pelvis_Ctrl': C_Pelvis_Ctrl.C, 282 | 'rootJnt': rootJnt[0], 283 | 'rigModule': rigModule} 284 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/base/controlShape/RotationControl.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def createShape(prefix='', scale=1.0): 5 | List = [] 6 | List.append(cmds.curve(n=prefix, p=[(0.33587352900359235, 3.552713678800501e-15, 0.7361468691490706), (0.4304251528553422, 0.03022134593976844, 0.6908148502394227), (0.5107046042608197, 0.07247276978952044, 0.6274377144647979), (0.5684975545498538, 0.12400997464880348, 0.5501319071758723), (0.5684975545498538, 0.12400997464880348, 0.5501319071758723), (0.5684975545498538, 0.12400997464880348, 0.5501319071758723), (0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (0.5402530010360955, 0.08197748359885182, 0.5946770761304137), (0.4852738226242117, 0.0455134352238602, 0.6467685738089757), (0.41921829926566545, 0.015501246831103543, 0.6896431286557706), (0.41921829926566545, 0.015501246831103543, 0.6896431286557706), (0.41921829926566545, 0.015501246831103543, 0.6896431286557706), (0.7077292503941841, 0.015501246831103543, 0.43808875481816606), (0.8080009216827335, 0.015501246831103543, -0.016811817720621902), (0.6943482219457628, 0.015501246831103543, -0.34108941639861884), (0.5527220271320097, 0.015501246831103543, -0.5148315398676033), (0.33489352471512746, 0.015501246831103543, -0.6771644412642893), (0.17585601860228905, 0.015501246831103543, -0.7201406688717121), (0.015501247071298963, 0.015501246831103543, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 7 | List.append(cmds.curve(p=[(0.33587352900359235, -3.552713678800501e-15, 0.7361468691490706), (0.4304251528553422, -0.03022134593976844, 0.6908148502394227), (0.5107046042608197, -0.07247276978952044, 0.6274377144647979), (0.5684975545498538, -0.12400997464880348, 0.5501319071758723), (0.5684975545498538, -0.12400997464880348, 0.5501319071758723), (0.5684975545498538, -0.12400997464880348, 0.5501319071758723), (0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (0.5402530010360955, -0.08197748359885182, 0.5946770761304137), (0.4852738226242117, -0.0455134352238602, 0.6467685738089757), (0.41921829926566545, -0.015501246831103543, 0.6896431286557706), (0.41921829926566545, -0.015501246831103543, 0.6896431286557706), (0.41921829926566545, -0.015501246831103543, 0.6896431286557706), (0.7077292503941841, -0.015501246831103543, 0.43808875481816606), (0.8080009216827335, -0.015501246831103543, -0.016811817720621902), (0.6943482219457628, -0.015501246831103543, -0.34108941639861884), (0.5527220271320097, -0.015501246831103543, -0.5148315398676033), (0.33489352471512746, -0.015501246831103543, -0.6771644412642893), (0.17585601860228905, -0.015501246831103543, -0.7201406688717121), (0.015501247071298963, -0.015501246831103543, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 8 | List.append(cmds.curve(p=[(-0.33587352900359235, 3.552713678800501e-15, 0.7361468691490706), (-0.4304251528553422, 0.03022134593976844, 0.6908148502394227), (-0.5107046042608197, 0.07247276978952044, 0.6274377144647979), (-0.5684975545498538, 0.12400997464880348, 0.5501319071758723), (-0.5684975545498538, 0.12400997464880348, 0.5501319071758723), (-0.5684975545498538, 0.12400997464880348, 0.5501319071758723), (-0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (-0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (-0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (-0.5819931861859438, 0.12400997464880348, 0.5346306603447717), (-0.5402530010360955, 0.08197748359885182, 0.5946770761304137), (-0.4852738226242117, 0.0455134352238602, 0.6467685738089757), (-0.41921829926566545, 0.015501246831103543, 0.6896431286557706), (-0.41921829926566545, 0.015501246831103543, 0.6896431286557706), (-0.41921829926566545, 0.015501246831103543, 0.6896431286557706), (-0.7077292503941841, 0.015501246831103543, 0.43808875481816606), (-0.8080009216827335, 0.015501246831103543, -0.016811817720621902), (-0.6943482219457628, 0.015501246831103543, -0.34108941639861884), (-0.5527220271320097, 0.015501246831103543, -0.5148315398676033), (-0.33489352471512746, 0.015501246831103543, -0.6771644412642893), (-0.17585601860228905, 0.015501246831103543, -0.7201406688717121), (-0.015501247071298963, 0.015501246831103543, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 9 | List.append(cmds.curve(p=[(-0.33587352900359235, -3.552713678800501e-15, 0.7361468691490706), (-0.4304251528553422, -0.03022134593976844, 0.6908148502394227), (-0.5107046042608197, -0.07247276978952044, 0.6274377144647979), (-0.5684975545498538, -0.12400997464880348, 0.5501319071758723), (-0.5684975545498538, -0.12400997464880348, 0.5501319071758723), (-0.5684975545498538, -0.12400997464880348, 0.5501319071758723), (-0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (-0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (-0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (-0.5819931861859438, -0.12400997464880348, 0.5346306603447717), (-0.5402530010360955, -0.08197748359885182, 0.5946770761304137), (-0.4852738226242117, -0.0455134352238602, 0.6467685738089757), (-0.41921829926566545, -0.015501246831103543, 0.6896431286557706), (-0.41921829926566545, -0.015501246831103543, 0.6896431286557706), (-0.41921829926566545, -0.015501246831103543, 0.6896431286557706), (-0.7077292503941841, -0.015501246831103543, 0.43808875481816606), (-0.8080009216827335, -0.015501246831103543, -0.016811817720621902), (-0.6943482219457628, -0.015501246831103543, -0.34108941639861884), (-0.5527220271320097, -0.015501246831103543, -0.5148315398676033), (-0.33489352471512746, -0.015501246831103543, -0.6771644412642893), (-0.17585601860228905, -0.015501246831103543, -0.7201406688717121), (-0.015501247071298963, -0.015501246831103543, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 10 | List.append(cmds.curve(p=[(-7.105427357601002e-15, -0.3358735290035888, 0.7361468691490706), (-0.030221345939771993, -0.43042515285533867, 0.6908148502394227), (-0.072472769789524, -0.5107046042608161, 0.6274377144647979), (-0.12400997464880703, -0.5684975545498503, 0.5501319071758723), (-0.12400997464880703, -0.5684975545498503, 0.5501319071758723), (-0.12400997464880703, -0.5684975545498503, 0.5501319071758723), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.12400997464880703, -0.5819931861859402, 0.5346306603447717), (-0.08197748359885537, -0.540253001036092, 0.5946770761304137), (-0.04551343522386375, -0.48527382262420815, 0.6467685738089757), (-0.015501246831107096, -0.4192182992656619, 0.6896431286557706), (-0.015501246831107096, -0.4192182992656619, 0.6896431286557706), (-0.015501246831107096, -0.4192182992656619, 0.6896431286557706), (-0.015501246831107096, -0.7077292503941806, 0.43808875481816606), (-0.015501246831107096, -0.80800092168273, -0.016811817720621902), (-0.015501246831107096, -0.6943482219457593, -0.34108941639861884), (-0.015501246831107096, -0.5527220271320061, -0.5148315398676033), (-0.015501246831107096, -0.3348935247151239, -0.6771644412642893), (-0.015501246831107096, -0.1758560186022855, -0.7201406688717121), (-0.015501246831107096, -0.01550124707129541, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 11 | List.append(cmds.curve(p=[(3.552713678800501e-15, -0.3358735290035959, 0.7361468691490706), (0.03022134593976844, -0.43042515285534577, 0.6908148502394227), (0.07247276978952044, -0.5107046042608232, 0.6274377144647979), (0.12400997464880348, -0.5684975545498574, 0.5501319071758723), (0.12400997464880348, -0.5684975545498574, 0.5501319071758723), (0.12400997464880348, -0.5684975545498574, 0.5501319071758723), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.12400997464880348, -0.5819931861859473, 0.5346306603447717), (0.08197748359885182, -0.5402530010360991, 0.5946770761304137), (0.0455134352238602, -0.48527382262421526, 0.6467685738089757), (0.015501246831103543, -0.419218299265669, 0.6896431286557706), (0.015501246831103543, -0.419218299265669, 0.6896431286557706), (0.015501246831103543, -0.419218299265669, 0.6896431286557706), (0.015501246831103543, -0.7077292503941877, 0.43808875481816606), (0.015501246831103543, -0.8080009216827371, -0.016811817720621902), (0.015501246831103543, -0.6943482219457664, -0.34108941639861884), (0.015501246831103543, -0.5527220271320132, -0.5148315398676033), (0.015501246831103543, -0.334893524715131, -0.6771644412642893), (0.015501246831103543, -0.1758560186022926, -0.7201406688717121), (0.015501246831103543, -0.015501247071302515, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 12 | List.append(cmds.curve(p=[(0.0, 0.33587352900359235, 0.7361468691490706), (-0.030221345939764888, 0.4304251528553422, 0.6908148502394227), (-0.07247276978951689, 0.5107046042608197, 0.6274377144647979), (-0.12400997464879993, 0.5684975545498538, 0.5501319071758723), (-0.12400997464879993, 0.5684975545498538, 0.5501319071758723), (-0.12400997464879993, 0.5684975545498538, 0.5501319071758723), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.12400997464879993, 0.5819931861859438, 0.5346306603447717), (-0.08197748359884827, 0.5402530010360955, 0.5946770761304137), (-0.045513435223856646, 0.4852738226242117, 0.6467685738089757), (-0.01550124683109999, 0.41921829926566545, 0.6896431286557706), (-0.01550124683109999, 0.41921829926566545, 0.6896431286557706), (-0.01550124683109999, 0.41921829926566545, 0.6896431286557706), (-0.01550124683109999, 0.7077292503941841, 0.43808875481816606), (-0.01550124683109999, 0.8080009216827335, -0.016811817720621902), (-0.01550124683109999, 0.6943482219457628, -0.34108941639861884), (-0.01550124683109999, 0.5527220271320097, -0.5148315398676033), (-0.01550124683109999, 0.33489352471512746, -0.6771644412642893), (-0.01550124683109999, 0.17585601860228905, -0.7201406688717121), (-0.01550124683109999, 0.015501247071298963, -0.7361468691392242)],per = False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 13 | List.append(cmds.curve(p=[(3.552713678800501e-15, 0.33587352900359235, 0.7361468691490706), (0.03022134593976844, 0.4304251528553422, 0.6908148502394227), (0.07247276978952044, 0.5107046042608197, 0.6274377144647979), (0.12400997464880348, 0.5684975545498538, 0.5501319071758723), (0.12400997464880348, 0.5684975545498538, 0.5501319071758723), (0.12400997464880348, 0.5684975545498538, 0.5501319071758723), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.12400997464880348, 0.5819931861859438, 0.5346306603447717), (0.08197748359885182, 0.5402530010360955, 0.5946770761304137), (0.0455134352238602, 0.4852738226242117, 0.6467685738089757), (0.015501246831103543, 0.41921829926566545, 0.6896431286557706), (0.015501246831103543, 0.41921829926566545, 0.6896431286557706), (0.015501246831103543, 0.41921829926566545, 0.6896431286557706), (0.015501246831103543, 0.7077292503941841, 0.43808875481816606), (0.015501246831103543, 0.8080009216827335, -0.016811817720621902), (0.015501246831103543, 0.6943482219457628, -0.34108941639861884), (0.015501246831103543, 0.5527220271320097, -0.5148315398676033), (0.015501246831103543, 0.33489352471512746, -0.6771644412642893), (0.015501246831103543, 0.17585601860228905, -0.7201406688717121), (0.015501246831103543, 0.015501247071298963, -0.7361468691392242)], per=False, d=3, k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19])) 14 | 15 | for x in range(len(List)-1): 16 | cmds.makeIdentity(List[x+1],apply=True,t=1,r=1,s=1,n=0) 17 | shapeNode = cmds.listRelatives(List[x+1], shapes=True) 18 | cmds.parent(shapeNode, List[0], add=True, s=True) 19 | cmds.delete(List[x+1]) 20 | sel = List[0] 21 | cmds.setAttr(sel + '.s', scale, scale, scale) 22 | cmds.makeIdentity(sel, apply=1, t=1, r=1, s=1, n=0) 23 | return sel -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/IK_FK_Head_Neck.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | from ..base import module 3 | from ..base import control 4 | reload(module) 5 | reload(control) 6 | 7 | 8 | def build(neckJoints, 9 | Neck_Parent='', 10 | rigScale=1.0, 11 | prefix='C_', 12 | blendCtrl_Pos='', 13 | baseRig=None 14 | ): 15 | """ 16 | Build the IK_FK_Neck rig. 17 | :param neckJoints: list(str), neck joints and head joint list, [neck_0, neck_1, ... neck_#, head, head_end] 18 | :param Neck_Parent: str, Neck parent joint, it's usually the last valid joint of the spine joints(i.e. Spine_#) 19 | :param rigScale: float, rig scale of the control 20 | :param prefix: str, 'C_', 'L_' or 'R_' 21 | :param blendCtrl_Pos: str, space locator 22 | :param baseRig: str, base atttach of the rig, Base Class instance is used. 23 | :return: None 24 | """ 25 | if Neck_Parent: 26 | try: 27 | cmds.objectType(Neck_Parent) == 'joint' 28 | pass 29 | except: 30 | cmds.error('%s is not a joint, please check again' % Neck_Parent) 31 | 32 | else: 33 | parentJnt = cmds.listRelatives(neckJoints[0], s=0, c=0, parent=1, type='joint') 34 | if parentJnt: 35 | Neck_Parent = parentJnt 36 | else: 37 | cmds.warning('No parent jnt of %s, IK may not work as expected!' % neckJoints[0]) 38 | 39 | cmds.select(cl=1) 40 | 41 | rigPartName = 'Head' 42 | 43 | rigModule = module.Module(prefix=prefix, 44 | rigPartName=rigPartName, 45 | baseObject=baseRig) 46 | 47 | cmds.select(cl=1) 48 | 49 | # duplicate the specified joints 50 | # create fk joints list 51 | fk_Joints_List = [] 52 | fkHeadJnts_Dirty_Start = cmds.duplicate(neckJoints[0], n='FK_' + neckJoints[0], renameChildren=1) 53 | fk_Joints_List.append(fkHeadJnts_Dirty_Start[0]) 54 | fkHeadJnts_Dirty_Children = cmds.listRelatives(fkHeadJnts_Dirty_Start, s=0, parent=0, children=1, type='joint') 55 | 56 | for i in range(len(fkHeadJnts_Dirty_Children)): 57 | rename_Jnt = cmds.rename(fkHeadJnts_Dirty_Children[i], 'FK_' + neckJoints[i+1]) 58 | fk_Joints_List.append(rename_Jnt) 59 | 60 | cmds.setAttr(fk_Joints_List[0] + '.v', 0) 61 | cmds.select(cl=1) 62 | 63 | # create ik joints list 64 | ik_Joints_List = [] 65 | ikHeadJnts_Dirty_Start = cmds.duplicate(neckJoints[0], n='IK_' + neckJoints[0], renameChildren=1) 66 | ik_Joints_List.append(ikHeadJnts_Dirty_Start[0]) 67 | ikHeadJnts_Dirty_Children = cmds.listRelatives(ikHeadJnts_Dirty_Start, s=0, parent=0, children=1, type='joint') 68 | 69 | for i in range(len(ikHeadJnts_Dirty_Children)): 70 | rename_Jnt = cmds.rename(ikHeadJnts_Dirty_Children[i], 'IK_' + neckJoints[i+1]) 71 | ik_Joints_List.append(rename_Jnt) 72 | 73 | cmds.setAttr(ik_Joints_List[0] + '.v', 0) 74 | cmds.select(cl=1) 75 | 76 | ########## 77 | # FK Rig # 78 | ########## 79 | 80 | FK_Neck_CtrlGrp_List = [] 81 | FK_Neck_Ctrl_List = [] 82 | 83 | for i in xrange(len(fk_Joints_List)-2): 84 | FK_Neck_Ctrl = control.Control(prefix=prefix + 'FK_', 85 | rigPartName='Neck_' + str(i), 86 | scale=rigScale, 87 | translateTo=fk_Joints_List[i], 88 | rotateTo=fk_Joints_List[i], 89 | shape='arrowCurve', 90 | axis='x', 91 | lockChannels=['t', 's', 'v'] 92 | ) 93 | cmds.orientConstraint(FK_Neck_Ctrl.C, fk_Joints_List[i], mo=0) 94 | 95 | FK_Neck_CtrlGrp_List.append(FK_Neck_Ctrl.Off) 96 | FK_Neck_Ctrl_List.append(FK_Neck_Ctrl.C) 97 | 98 | cmds.select(cl=1) 99 | 100 | # parent the CtrlGrps to the proper places 101 | for i in xrange(len(FK_Neck_Ctrl_List)-1): 102 | cmds.parent(FK_Neck_CtrlGrp_List[i+1], FK_Neck_Ctrl_List[i]) 103 | 104 | FK_Head_Ctrl = control.Control(prefix=prefix + 'FK_', 105 | rigPartName=rigPartName, 106 | scale=rigScale, 107 | translateTo=fk_Joints_List[-2], 108 | rotateTo=fk_Joints_List[-2], 109 | shape='cubeOnBase', 110 | axis='x', 111 | lockChannels=['t', 's', 'v']) 112 | 113 | # Local LOC 114 | fk_headLocal = cmds.spaceLocator(n='FK_' + prefix + rigPartName + '_Local') 115 | fk_headLocal_Shape = cmds.listRelatives(fk_headLocal, s=1) 116 | cmds.setAttr(fk_headLocal_Shape[0] + '.localScaleX', 0) 117 | cmds.setAttr(fk_headLocal_Shape[0] + '.localScaleY', 0) 118 | cmds.setAttr(fk_headLocal_Shape[0] + '.localScaleZ', 0) 119 | cmds.setAttr(fk_headLocal_Shape[0] + '.template', 1) 120 | 121 | # World LOC 122 | fk_headWorld = cmds.spaceLocator(n='FK_' + prefix + rigPartName + '_World') 123 | fk_headWorld_Shape = cmds.listRelatives(fk_headWorld, s=1) 124 | cmds.setAttr(fk_headWorld_Shape[0] + '.localScaleX', 0) 125 | cmds.setAttr(fk_headWorld_Shape[0] + '.localScaleY', 0) 126 | cmds.setAttr(fk_headWorld_Shape[0] + '.localScaleZ', 0) 127 | cmds.setAttr(fk_headWorld_Shape[0] + '.template', 1) 128 | 129 | cmds.delete(cmds.parentConstraint(fk_Joints_List[-2], fk_headLocal, mo=0)) 130 | cmds.delete(cmds.parentConstraint(fk_Joints_List[-2], fk_headWorld, mo=0)) 131 | 132 | FK_Head_OrientConstraint = cmds.orientConstraint(fk_headLocal, fk_headWorld, FK_Head_Ctrl.Off, mo=0) 133 | cmds.pointConstraint(fk_headLocal, FK_Head_Ctrl.Off, mo=0) 134 | 135 | # create attr and setDrivenKey 136 | cmds.addAttr(FK_Head_Ctrl.C, ln='Local2World', at="float", min=0, max=1, dv=0, k=1) 137 | cmds.setAttr(FK_Head_Ctrl.C + '.Local2World', 0) 138 | cmds.setAttr(FK_Head_OrientConstraint[0] + '.' + fk_headLocal[0] + 'W0', 1) 139 | cmds.setAttr(FK_Head_OrientConstraint[0] + '.' + fk_headWorld[0] + 'W1', 0) 140 | 141 | cmds.setDrivenKeyframe(FK_Head_OrientConstraint[0] + '.' + fk_headLocal[0] + 'W0', 142 | cd=FK_Head_Ctrl.C + '.Local2World') 143 | cmds.setDrivenKeyframe(FK_Head_OrientConstraint[0] + '.' + fk_headWorld[0] + 'W1', 144 | cd=FK_Head_Ctrl.C + '.Local2World') 145 | 146 | cmds.setAttr(FK_Head_Ctrl.C + '.Local2World', 1) 147 | cmds.setAttr(FK_Head_OrientConstraint[0] + '.' + fk_headLocal[0] + 'W0', 0) 148 | cmds.setAttr(FK_Head_OrientConstraint[0] + '.' + fk_headWorld[0] + 'W1', 1) 149 | 150 | cmds.setDrivenKeyframe(FK_Head_OrientConstraint[0] + '.' + fk_headLocal[0] + 'W0', 151 | cd=FK_Head_Ctrl.C + '.Local2World') 152 | cmds.setDrivenKeyframe(FK_Head_OrientConstraint[0] + '.' + fk_headWorld[0] + 'W1', 153 | cd=FK_Head_Ctrl.C + '.Local2World') 154 | 155 | # point and orient constriant the fk head joint 156 | cmds.pointConstraint(FK_Head_Ctrl.C, fk_Joints_List[-2], mo=0) 157 | cmds.orientConstraint(FK_Head_Ctrl.C, fk_Joints_List[-2], mo=1) 158 | 159 | ########## 160 | # IK Rig # 161 | ########## 162 | IK_Head_Ctrl = control.Control(prefix=prefix + 'IK_', 163 | rigPartName=rigPartName, 164 | scale=rigScale, 165 | translateTo=ik_Joints_List[-2], 166 | rotateTo=ik_Joints_List[-2], 167 | shape='moveControl', 168 | axis='x') 169 | 170 | IK_Start_Jnt = cmds.joint(n='IK_' + prefix + rigPartName + '_StartJnt') 171 | cmds.select(cl=1) 172 | IK_End_Jnt = cmds.joint(n='IK_' + prefix + rigPartName + '_EndJnt') 173 | cmds.select(cl=1) 174 | cmds.delete(cmds.parentConstraint(neckJoints[0], IK_Start_Jnt, mo=0)) 175 | cmds.delete(cmds.parentConstraint(neckJoints[-2], IK_End_Jnt, mo=0)) 176 | 177 | cmds.makeIdentity(IK_Start_Jnt, apply=1, t=1, r=1, s=1, n=0, pn=1) 178 | cmds.makeIdentity(IK_End_Jnt, apply=1, t=1, r=1, s=1, n=0, pn=1) 179 | 180 | cmds.select(cl=1) 181 | cmds.parent(IK_End_Jnt, IK_Head_Ctrl.C) 182 | 183 | if Neck_Parent: 184 | cmds.parent(IK_Start_Jnt, Neck_Parent) 185 | else: 186 | cmds.parent(IK_Start_Jnt, rigModule.topGrp) 187 | 188 | cmds.setAttr(IK_Start_Jnt + '.v', 0) 189 | cmds.setAttr(IK_End_Jnt + '.v', 0) 190 | 191 | # ik handle 192 | IK_Part_List = cmds.ikHandle(n=prefix + rigPartName + '_IK', 193 | sj=ik_Joints_List[0], 194 | ee=ik_Joints_List[-2], 195 | sol='ikSplineSolver', 196 | pcv=0, 197 | numSpans=4) 198 | 199 | cmds.select(cl=1) 200 | cmds.select(IK_Part_List[-1]) 201 | cmds.select(IK_Start_Jnt, add=1) 202 | cmds.select(IK_End_Jnt, add=1) 203 | cmds.skinCluster(IK_Start_Jnt, IK_End_Jnt, IK_Part_List[-1], tsb=1) 204 | cmds.select(cl=1) 205 | 206 | # setup IK Twist 207 | cmds.setAttr(IK_Part_List[0] + '.dTwistControlEnable', 1) 208 | cmds.setAttr(IK_Part_List[0] + '.dWorldUpType', 4) 209 | cmds.connectAttr(IK_Start_Jnt + '.worldMatrix[0]', IK_Part_List[0] + '.dWorldUpMatrix') 210 | cmds.connectAttr(IK_End_Jnt + '.worldMatrix[0]', IK_Part_List[0] + '.dWorldUpMatrixEnd') 211 | 212 | # create ik_head_local and ik_head_world 213 | ik_headLocal = cmds.spaceLocator(n='IK_' + prefix + rigPartName + '_Local') 214 | ik_headLocal_Shape = cmds.listRelatives(ik_headLocal, s=1) 215 | cmds.setAttr(ik_headLocal_Shape[0] + '.localScaleX', 0) 216 | cmds.setAttr(ik_headLocal_Shape[0] + '.localScaleY', 0) 217 | cmds.setAttr(ik_headLocal_Shape[0] + '.localScaleZ', 0) 218 | cmds.setAttr(ik_headLocal_Shape[0] + '.template', 1) 219 | 220 | ik_headWorld = cmds.spaceLocator(n='IK_' + prefix + rigPartName + '_World') 221 | ik_headWorld_Shape = cmds.listRelatives(ik_headWorld, s=1) 222 | cmds.setAttr(ik_headWorld_Shape[0] + '.localScaleX', 0) 223 | cmds.setAttr(ik_headWorld_Shape[0] + '.localScaleY', 0) 224 | cmds.setAttr(ik_headWorld_Shape[0] + '.localScaleZ', 0) 225 | cmds.setAttr(ik_headWorld_Shape[0] + '.template', 1) 226 | 227 | cmds.delete(cmds.parentConstraint(ik_Joints_List[-2], ik_headLocal, mo=0)) 228 | cmds.delete(cmds.parentConstraint(ik_Joints_List[-2], ik_headWorld, mo=0)) 229 | 230 | IK_Head_OrientConstraint = cmds.orientConstraint(ik_headLocal, ik_headWorld, IK_Head_Ctrl.Off, mo=0) 231 | 232 | # create attr and setDrivenKey 233 | cmds.addAttr(IK_Head_Ctrl.C, ln='Local2World', at="float", min=0, max=1, dv=0, k=1) 234 | 235 | cmds.setAttr(IK_Head_Ctrl.C + '.Local2World', 0) 236 | cmds.setAttr(IK_Head_OrientConstraint[0] + '.' + ik_headLocal[0] + 'W0', 1) 237 | cmds.setAttr(IK_Head_OrientConstraint[0] + '.' + ik_headWorld[0] + 'W1', 0) 238 | 239 | cmds.setDrivenKeyframe(IK_Head_OrientConstraint[0] + '.' + ik_headLocal[0] + 'W0', 240 | cd=IK_Head_Ctrl.C + '.Local2World') 241 | cmds.setDrivenKeyframe(IK_Head_OrientConstraint[0] + '.' + ik_headWorld[0] + 'W1', 242 | cd=IK_Head_Ctrl.C + '.Local2World') 243 | 244 | cmds.setAttr(IK_Head_Ctrl.C + '.Local2World', 1) 245 | cmds.setAttr(IK_Head_OrientConstraint[0] + '.' + ik_headLocal[0] + 'W0', 0) 246 | cmds.setAttr(IK_Head_OrientConstraint[0] + '.' + ik_headWorld[0] + 'W1', 1) 247 | 248 | cmds.setDrivenKeyframe(IK_Head_OrientConstraint[0] + '.' + ik_headLocal[0] + 'W0', 249 | cd=IK_Head_Ctrl.C + '.Local2World') 250 | cmds.setDrivenKeyframe(IK_Head_OrientConstraint[0] + '.' + ik_headWorld[0] + 'W1', 251 | cd=IK_Head_Ctrl.C + '.Local2World') 252 | 253 | # IK FK BLEND 254 | IK_FK_BlendCtrl = control.Control(prefix=prefix, 255 | rigPartName=rigPartName + '_Blend', 256 | scale=rigScale*5, 257 | translateTo=blendCtrl_Pos, 258 | rotateTo=blendCtrl_Pos, 259 | shape='unitSliderControl', 260 | lockChannels=['tx', 'tz', 'r', 's', 'v']) 261 | 262 | for i in range(len(fk_Joints_List)): 263 | # blend node 264 | blend = cmds.createNode('blendColors') 265 | # ik 266 | cmds.connectAttr(ik_Joints_List[i] + '.r', blend + '.color1', f=1) 267 | # fk 268 | cmds.connectAttr(fk_Joints_List[i] + '.r', blend + '.color2', f=1) 269 | # output to origin neckJoints 270 | cmds.connectAttr(blend + '.output', neckJoints[i] + '.r', f=1) 271 | # IK_FK_BlendCtrl 272 | cmds.connectAttr(IK_FK_BlendCtrl.C + '.ty', blend + '.blender') 273 | 274 | # visibility blend 275 | cmds.setAttr(IK_FK_BlendCtrl.C + '.ty', 0) 276 | cmds.setAttr(FK_Neck_CtrlGrp_List[0] + '.v', 1) 277 | cmds.setAttr(FK_Head_Ctrl.Off + '.v', 1) 278 | cmds.setAttr(IK_Head_Ctrl.Off + '.v', 0) 279 | 280 | cmds.setDrivenKeyframe(FK_Neck_CtrlGrp_List[0] + '.v', cd=IK_FK_BlendCtrl.C + '.ty') 281 | cmds.setDrivenKeyframe(FK_Head_Ctrl.Off + '.v', cd=IK_FK_BlendCtrl.C + '.ty') 282 | cmds.setDrivenKeyframe(IK_Head_Ctrl.Off + '.v', cd=IK_FK_BlendCtrl.C + '.ty') 283 | 284 | cmds.setAttr(IK_FK_BlendCtrl.C + '.ty', 1) 285 | cmds.setAttr(FK_Neck_CtrlGrp_List[0] + '.v', 0) 286 | cmds.setAttr(FK_Head_Ctrl.Off + '.v', 0) 287 | cmds.setAttr(IK_Head_Ctrl.Off + '.v', 1) 288 | 289 | cmds.setDrivenKeyframe(FK_Neck_CtrlGrp_List[0] + '.v', cd=IK_FK_BlendCtrl.C + '.ty') 290 | cmds.setDrivenKeyframe(FK_Head_Ctrl.Off + '.v', cd=IK_FK_BlendCtrl.C + '.ty') 291 | cmds.setDrivenKeyframe(IK_Head_Ctrl.Off + '.v', cd=IK_FK_BlendCtrl.C + '.ty') 292 | 293 | neckLoc = cmds.spaceLocator(n=prefix + 'Neck_Loc') 294 | 295 | if Neck_Parent: 296 | cmds.parentConstraint(Neck_Parent, neckLoc, mo=0) 297 | 298 | cmds.parent(FK_Neck_CtrlGrp_List[0], neckLoc) 299 | cmds.parent(IK_Head_Ctrl.Off, neckLoc) 300 | 301 | # fk_headLocal and fk_headWorld 302 | cmds.parent(fk_headLocal, FK_Neck_Ctrl_List[-1]) 303 | cmds.parent(fk_headWorld, rigModule.topGrp) 304 | # ik_headLocal and ik_headWorld 305 | cmds.parent(ik_headLocal, neckLoc) 306 | cmds.parent(ik_headWorld, rigModule.topGrp) 307 | 308 | # ik parts 309 | cmds.parent(IK_Part_List[0], rigModule.dontTouchGrp) 310 | cmds.parent(IK_Part_List[-1], rigModule.dontTouchGrp) 311 | 312 | # blend ctrl 313 | cmds.pointConstraint(blendCtrl_Pos, IK_FK_BlendCtrl.Off, mo=0) 314 | blendCtrl_Pos_Shape = cmds.listRelatives(blendCtrl_Pos, s=1) 315 | cmds.setAttr(blendCtrl_Pos_Shape[0] + '.localScaleX', 0) 316 | cmds.setAttr(blendCtrl_Pos_Shape[0] + '.localScaleY', 0) 317 | cmds.setAttr(blendCtrl_Pos_Shape[0] + '.localScaleZ', 0) 318 | cmds.setAttr(blendCtrl_Pos_Shape[0] + '.template', 1) 319 | headBlendLoc = cmds.spaceLocator(n=prefix + rigPartName + '_Blend_Loc') 320 | headBlendLoc_Shape = cmds.listRelatives(headBlendLoc, s=1) 321 | cmds.setAttr(headBlendLoc_Shape[0] + '.localScaleX', 0) 322 | cmds.setAttr(headBlendLoc_Shape[0] + '.localScaleY', 0) 323 | cmds.setAttr(headBlendLoc_Shape[0] + '.localScaleZ', 0) 324 | cmds.setAttr(headBlendLoc_Shape[0] + '.template', 1) 325 | cmds.pointConstraint(neckJoints[-2], headBlendLoc, mo=0) 326 | cmds.parent(blendCtrl_Pos, headBlendLoc) 327 | cmds.parent(IK_FK_BlendCtrl.Off, rigModule.topGrp) 328 | cmds.parent(headBlendLoc, rigModule.topGrp) 329 | 330 | # clean rigModule 331 | cmds.parent(FK_Head_Ctrl.Off, rigModule.topGrp) 332 | cmds.parent(neckLoc, rigModule.topGrp) 333 | 334 | # add attr 335 | for joint in neckJoints[:-1]: 336 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 337 | cmds.addAttr(joint, ln='slaveJoint', at='message') 338 | 339 | if not cmds.attributeQuery('rigModule', node=joint, exists=1): 340 | cmds.addAttr(joint, ln='rigModule', at='message') 341 | 342 | # connect attr 343 | for joint in neckJoints[:-1]: 344 | if cmds.attributeQuery('rigModule', node=joint, exists=1): 345 | cmds.connectAttr(rigModule.topGrp + '.' + prefix + rigPartName + '_Jnt', 346 | joint + '.rigModule', f=1) 347 | 348 | cmds.select(cl=1) 349 | 350 | return rigModule 351 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/rigLib/rig/IK_FK_HumanArm.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | from ..base import module 4 | from ..base import control 5 | 6 | from .. utils import name 7 | from .. utils import IK_FK_Switch 8 | 9 | reload(module) 10 | reload(control) 11 | reload(name) 12 | reload(IK_FK_Switch) 13 | 14 | 15 | def build(armJoints, 16 | prefix='L_', 17 | rigScale=1.0, 18 | FK_Parent='', 19 | switchCtrlPos='', 20 | baseRig=None): 21 | """ 22 | Build the IK_FK_Arm rig. 23 | :param armJoints: list(str), armJoints list, [L_clavical, L_shoulder, L_elbow, L_wrist] 24 | :param prefix: str, prefix of the rig 25 | :param rigScale: float, rig scale of the IK_FK_Arm rig module. 26 | :param FK_Parent: str, the joint which armJoints[0] connects to. 27 | :param switchCtrlPos: str, position of the IK_FK_Blend_Ctrl position. 28 | :param baseRig: baseRig: str, base atttach of the rig. Base Class instance is used. 29 | :return: None 30 | """ 31 | 32 | rigPartName = 'Arm' 33 | 34 | rigModule = module.Module(prefix=prefix, 35 | rigPartName=rigPartName, 36 | baseObject=baseRig) 37 | 38 | # create FK joints chain 39 | fk_preParent = armJoints[0] 40 | fk_Joint_List = [] 41 | for i in xrange(len(armJoints)-1): 42 | newJnt = cmds.joint(n='FK_' + armJoints[i+1]) 43 | cmds.delete(cmds.parentConstraint(armJoints[i+1], newJnt, mo=0)) 44 | cmds.makeIdentity(newJnt, apply=1, t=1, r=1, s=1) 45 | cmds.parent(newJnt, fk_preParent) 46 | fk_Joint_List.append(newJnt) 47 | fk_preParent = newJnt 48 | cmds.select(cl=1) 49 | cmds.setAttr(fk_Joint_List[0] + '.v', 0) 50 | 51 | # create IK joints chain 52 | ik_preParent = armJoints[0] 53 | ik_Joint_List = [] 54 | for i in xrange(len(armJoints)-1): 55 | newJnt = cmds.joint(n='IK_' + armJoints[i+1]) 56 | cmds.delete(cmds.parentConstraint(armJoints[i+1], newJnt, mo=0)) 57 | cmds.makeIdentity(newJnt, apply=1, t=1, r=1, s=1) 58 | cmds.parent(newJnt, ik_preParent) 59 | ik_Joint_List.append(newJnt) 60 | ik_preParent = newJnt 61 | cmds.select(cl=1) 62 | 63 | cmds.setAttr(ik_Joint_List[0] + '.v', 0) 64 | 65 | cmds.select(cl=1) 66 | 67 | ############## 68 | # Arm FK Rig # 69 | ############## 70 | FK_Arm_Ctrl_List = [] 71 | FK_Arm_CtrlGrp_List = [] 72 | for i in xrange(len(fk_Joint_List)): 73 | FK_Arm_Ctrl = control.Control(prefix=prefix + 'FK_', 74 | rigPartName=name.removePrefix(armJoints[i+1]), 75 | scale=rigScale*3.0, 76 | translateTo=fk_Joint_List[i], 77 | rotateTo=fk_Joint_List[i], 78 | shape='cubeOnBase', 79 | axis='x', 80 | lockChannels=['t', 's', 'v']) 81 | cmds.pointConstraint(FK_Arm_Ctrl.C, fk_Joint_List[i], mo=0) 82 | cmds.orientConstraint(FK_Arm_Ctrl.C, fk_Joint_List[i], mo=0) 83 | 84 | FK_Arm_Ctrl_List.append(FK_Arm_Ctrl.C) 85 | FK_Arm_CtrlGrp_List.append(FK_Arm_Ctrl.Off) 86 | cmds.select(cl=1) 87 | 88 | # lock the .rx and ry attribute of elbowCtrl 89 | # cmds.setAttr(FK_Arm_Ctrl_List[1] + '.rx', l=1, k=0) 90 | # cmds.setAttr(FK_Arm_Ctrl_List[1] + '.ry', l=1, k=0) 91 | 92 | # parent the CtrlGrps to the proper places 93 | for i in xrange(len(FK_Arm_Ctrl_List)-1): 94 | cmds.parent(FK_Arm_CtrlGrp_List[i+1], FK_Arm_Ctrl_List[i]) 95 | 96 | # clavical Rig 97 | clavical_Ctrl = control.Control(prefix=prefix, 98 | rigPartName=name.removePrefix(armJoints[0]), 99 | scale=rigScale*3.0, 100 | translateTo=armJoints[0], 101 | rotateTo=armJoints[0], 102 | shape='rotationControl', 103 | axis='x', 104 | lockChannels=['t', 's', 'v']) 105 | 106 | cmds.orientConstraint(clavical_Ctrl.C, armJoints[0], mo=0) 107 | 108 | # Clavical local2World 109 | cmds.addAttr(clavical_Ctrl.C, ln='Local2World', at="float", min=0, max=1, dv=0, k=1) 110 | 111 | clavical_Local = cmds.spaceLocator(n=armJoints[0] + '_Local') 112 | clavical_Local_Shape = cmds.listRelatives(clavical_Local, s=1) 113 | cmds.setAttr(clavical_Local_Shape[0] + '.localScaleX', 0) 114 | cmds.setAttr(clavical_Local_Shape[0] + '.localScaleY', 0) 115 | cmds.setAttr(clavical_Local_Shape[0] + '.localScaleZ', 0) 116 | cmds.setAttr(clavical_Local_Shape[0] + '.template', 1) 117 | 118 | clavical_World = cmds.spaceLocator(n=armJoints[0] + '_World') 119 | clavical_World_Shape = cmds.listRelatives(clavical_World, s=1) 120 | cmds.setAttr(clavical_World_Shape[0] + '.localScaleX', 0) 121 | cmds.setAttr(clavical_World_Shape[0] + '.localScaleY', 0) 122 | cmds.setAttr(clavical_World_Shape[0] + '.localScaleZ', 0) 123 | cmds.setAttr(clavical_World_Shape[0] + '.template', 1) 124 | 125 | cmds.delete(cmds.parentConstraint(FK_Arm_Ctrl_List[0], clavical_Local, mo=0)) 126 | cmds.delete(cmds.parentConstraint(FK_Arm_Ctrl_List[0], clavical_World, mo=0)) 127 | 128 | cmds.pointConstraint(clavical_Local, FK_Arm_CtrlGrp_List[0], mo=0) 129 | clavical_OrientConstraint = cmds.orientConstraint(clavical_Local, clavical_World, FK_Arm_CtrlGrp_List[0], mo=0) 130 | 131 | cmds.setAttr(clavical_Ctrl.C + '.Local2World', 0) 132 | cmds.setAttr(clavical_OrientConstraint[0] + '.' + clavical_Local[0] + 'W0', 1) 133 | cmds.setAttr(clavical_OrientConstraint[0] + '.' + clavical_World[0] + 'W1', 0) 134 | 135 | cmds.setDrivenKeyframe(clavical_OrientConstraint[0] + '.' + clavical_Local[0] + 'W0', 136 | cd=clavical_Ctrl.C + '.Local2World') 137 | cmds.setDrivenKeyframe(clavical_OrientConstraint[0] + '.' + clavical_World[0] + 'W1', 138 | cd=clavical_Ctrl.C + '.Local2World') 139 | 140 | cmds.setAttr(clavical_Ctrl.C + '.Local2World', 1) 141 | cmds.setAttr(clavical_OrientConstraint[0] + '.' + clavical_Local[0] + 'W0', 0) 142 | cmds.setAttr(clavical_OrientConstraint[0] + '.' + clavical_World[0] + 'W1', 1) 143 | 144 | cmds.setDrivenKeyframe(clavical_OrientConstraint[0] + '.' + clavical_Local[0] + 'W0', 145 | cd=clavical_Ctrl.C + '.Local2World') 146 | cmds.setDrivenKeyframe(clavical_OrientConstraint[0] + '.' + clavical_World[0] + 'W1', 147 | cd=clavical_Ctrl.C + '.Local2World') 148 | 149 | cmds.parent(clavical_Local, armJoints[0]) 150 | cmds.parent(clavical_World, rigModule.topGrp) 151 | 152 | ############## 153 | # Arm IK Rig # 154 | ############## 155 | IK_Arm_Ctrl = control.Control(prefix=prefix + 'IK_', 156 | rigPartName=rigPartName, 157 | scale=rigScale*3, 158 | translateTo=ik_Joint_List[-1], 159 | rotateTo=ik_Joint_List[-1], 160 | shape='circle') 161 | 162 | cmds.orientConstraint(IK_Arm_Ctrl.C, ik_Joint_List[-1], mo=0) 163 | 164 | IK_Arm_PV_Ctrl = control.Control(prefix=prefix + 'IK_', 165 | rigPartName=rigPartName + '_PV', 166 | scale=rigScale*3, 167 | translateTo=ik_Joint_List[1], 168 | shape='diamond', 169 | lockChannels=['r', 's', 'v']) 170 | 171 | ik_Part_List = cmds.ikHandle(n=prefix + rigPartName + '_IK', sj=ik_Joint_List[0], 172 | ee=ik_Joint_List[-1], sol='ikRPsolver') 173 | 174 | cmds.parent(ik_Part_List[0], IK_Arm_Ctrl.C) 175 | cmds.setAttr(ik_Part_List[0] + '.v', 0) 176 | cmds.poleVectorConstraint(IK_Arm_PV_Ctrl.C, ik_Part_List[0]) 177 | 178 | ############### 179 | # FK Hand Rig # 180 | ############### 181 | 182 | # get finger joint list 183 | finger_Start_Joints_List = cmds.listRelatives(armJoints[-1], p=0, children=1, s=0, type='joint') 184 | 185 | finger_Joints_Dic = {} 186 | clean_Finger_Joints_Dic = {} 187 | for i in xrange(len(finger_Start_Joints_List)): 188 | finger_Joints_Dic[('Finger_' + str(i))] = cmds.listRelatives(finger_Start_Joints_List[i], 189 | p=0, allDescendents=1, s=0, type='joint') 190 | finger_Joints_Dic[('Finger_' + str(i))].append(finger_Start_Joints_List[i]) 191 | # remove the end joint 192 | finger_Joints_Dic[('Finger_' + str(i))].reverse() 193 | clean_Finger_Joints_Dic[('Finger_' + str(i))] = finger_Joints_Dic[('Finger_' + str(i))][:-1] 194 | 195 | # create FK Ctrl 196 | finger_FK_Ctrl_Dic = {} 197 | finger_FK_CtrlGrp_Dic = {} 198 | for key in clean_Finger_Joints_Dic: 199 | finger_FK_Ctrl_Dic[key] = [] 200 | finger_FK_CtrlGrp_Dic[key] = [] 201 | for i in xrange(len(clean_Finger_Joints_Dic[key])): 202 | cleanRigPartName = name.removePrefix(name.removeSuffix(clean_Finger_Joints_Dic[key][i])) 203 | FK_Finger_Ctrl = control.Control(prefix=prefix + 'FK_', 204 | rigPartName=(cleanRigPartName + '_' + str(i)), 205 | scale=rigScale, 206 | translateTo=clean_Finger_Joints_Dic[key][i], 207 | rotateTo=clean_Finger_Joints_Dic[key][i], 208 | shape='circleZ', 209 | lockChannels=['t', 's', 'v'] 210 | ) 211 | cmds.pointConstraint(FK_Finger_Ctrl.C, clean_Finger_Joints_Dic[key][i], mo=0) 212 | cmds.orientConstraint(FK_Finger_Ctrl.C, clean_Finger_Joints_Dic[key][i], mo=0) 213 | 214 | finger_FK_Ctrl_Dic[key].append(FK_Finger_Ctrl.C) 215 | finger_FK_CtrlGrp_Dic[key].append(FK_Finger_Ctrl.Off) 216 | 217 | # clean the hierarchy 218 | for key in finger_FK_CtrlGrp_Dic: 219 | for i in xrange(len(finger_FK_CtrlGrp_Dic[key])-1): 220 | cmds.parent(finger_FK_CtrlGrp_Dic[key][i+1], finger_FK_Ctrl_Dic[key][i]) 221 | 222 | # use locator as grp to control the handCtrl 223 | hand_Loc = cmds.spaceLocator(n=prefix + 'Wrist_Grp_Loc') 224 | hand_Loc_Shape = cmds.listRelatives(hand_Loc, s=1) 225 | cmds.setAttr(hand_Loc_Shape[0] + '.localScaleX', 0) 226 | cmds.setAttr(hand_Loc_Shape[0] + '.localScaleY', 0) 227 | cmds.setAttr(hand_Loc_Shape[0] + '.localScaleZ', 0) 228 | 229 | cmds.parentConstraint(armJoints[-1], hand_Loc, mo=0) 230 | 231 | for key in finger_FK_CtrlGrp_Dic: 232 | cmds.parent(finger_FK_CtrlGrp_Dic[key][0], hand_Loc) 233 | 234 | cmds.parent(hand_Loc, rigModule.topGrp) 235 | 236 | ############### 237 | # FK IK Blend # 238 | ############### 239 | 240 | IK_FK_Blend_Ctrl = control.Control(prefix=prefix, 241 | rigPartName=rigPartName + '_Blend', 242 | scale=rigScale * 3, 243 | translateTo=switchCtrlPos, 244 | shape='unitSliderControl', 245 | lockChannels=['tx', 'tz', 'r', 's', 'v']) 246 | # add enum attr for IK_FK seamless switch 247 | cmds.addAttr(IK_FK_Blend_Ctrl.C, ln='Mode', at='enum', en='IK:FK', k=1) 248 | 249 | cmds.rotate(0, 0, -90, IK_FK_Blend_Ctrl.Off, relative=1, objectSpace=1) 250 | 251 | for i in xrange(len(fk_Joint_List)): 252 | # create blendColors node 253 | blendNode = cmds.createNode('blendColors') 254 | # IK 255 | cmds.connectAttr(ik_Joint_List[i] + '.r', blendNode + '.color1', f=1) 256 | # FK 257 | cmds.connectAttr(fk_Joint_List[i] + '.r', blendNode + '.color2', f=1) 258 | # Skin 259 | cmds.connectAttr(blendNode + '.output', armJoints[i+1] + '.r', f=1) 260 | # blendNode 261 | cmds.connectAttr(IK_FK_Blend_Ctrl.C + '.ty', blendNode + '.blender') 262 | 263 | # visibility blend 264 | cmds.setAttr(IK_FK_Blend_Ctrl.C + '.ty', 0) 265 | cmds.setAttr(FK_Arm_CtrlGrp_List[0] + '.v', 1) 266 | cmds.setAttr(IK_Arm_Ctrl.Off + '.v', 0) 267 | cmds.setAttr(IK_Arm_PV_Ctrl.Off + '.v', 0) 268 | 269 | cmds.setDrivenKeyframe(FK_Arm_CtrlGrp_List[0] + '.v', cd=IK_FK_Blend_Ctrl.C + '.ty') 270 | cmds.setDrivenKeyframe(IK_Arm_Ctrl.Off + '.v', cd=IK_FK_Blend_Ctrl.C + '.ty') 271 | cmds.setDrivenKeyframe(IK_Arm_PV_Ctrl.Off + '.v', cd=IK_FK_Blend_Ctrl.C + '.ty') 272 | 273 | cmds.setAttr(IK_FK_Blend_Ctrl.C + '.ty', 1) 274 | cmds.setAttr(FK_Arm_CtrlGrp_List[0] + '.v', 0) 275 | cmds.setAttr(IK_Arm_Ctrl.Off + '.v', 1) 276 | cmds.setAttr(IK_Arm_PV_Ctrl.Off + '.v', 1) 277 | 278 | cmds.setDrivenKeyframe(FK_Arm_CtrlGrp_List[0] + '.v', cd=IK_FK_Blend_Ctrl.C + '.ty') 279 | cmds.setDrivenKeyframe(IK_Arm_Ctrl.Off + '.v', cd=IK_FK_Blend_Ctrl.C + '.ty') 280 | cmds.setDrivenKeyframe(IK_Arm_PV_Ctrl.Off + '.v', cd=IK_FK_Blend_Ctrl.C + '.ty') 281 | 282 | cmds.pointConstraint(switchCtrlPos, IK_FK_Blend_Ctrl.Off, mo=0) 283 | switchCtrlPos_Shape = cmds.listRelatives(switchCtrlPos, s=1) 284 | cmds.setAttr(switchCtrlPos_Shape[0] + '.localScaleX', 0) 285 | cmds.setAttr(switchCtrlPos_Shape[0] + '.localScaleY', 0) 286 | cmds.setAttr(switchCtrlPos_Shape[0] + '.localScaleZ', 0) 287 | cmds.setAttr(switchCtrlPos_Shape[0] + '.template', 1) 288 | switchCtrlLoc = cmds.spaceLocator(n=prefix + rigPartName + 'BlendCtrl_Loc') 289 | switchCtrlLoc_Shape = cmds.listRelatives(switchCtrlLoc, s=1) 290 | cmds.setAttr(switchCtrlLoc_Shape[0] + '.localScaleX', 0) 291 | cmds.setAttr(switchCtrlLoc_Shape[0] + '.localScaleY', 0) 292 | cmds.setAttr(switchCtrlLoc_Shape[0] + '.localScaleZ', 0) 293 | cmds.setAttr(switchCtrlLoc_Shape[0] + '.template', 1) 294 | 295 | cmds.pointConstraint(armJoints[-1], switchCtrlLoc, mo=0) 296 | cmds.parent(switchCtrlPos, switchCtrlLoc) 297 | 298 | # add attr 299 | for joint in armJoints: 300 | if not cmds.attributeQuery('rigModule', node=joint, exists=1): 301 | cmds.addAttr(joint, ln='rigModule', at='message') 302 | 303 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 304 | cmds.addAttr(joint, ln='slaveJoint', at='message') 305 | 306 | for key in clean_Finger_Joints_Dic.keys(): 307 | for joint in clean_Finger_Joints_Dic[key]: 308 | if not cmds.attributeQuery(prefix + rigPartName + '_Jnt', node=joint, exists=1): 309 | cmds.addAttr(joint, ln=prefix + rigPartName + '_Jnt', at='message') 310 | 311 | if not cmds.attributeQuery('slaveJoint', node=joint, exists=1): 312 | cmds.addAttr(joint, ln='slaveJoint', at='message') 313 | 314 | # connect attr 315 | for joint in armJoints: 316 | if cmds.attributeQuery('rigModule', node=joint, exists=1): 317 | cmds.connectAttr(rigModule.topGrp + '.' + prefix + rigPartName + '_Jnt', 318 | joint + '.rigModule', f=1) 319 | 320 | for key in clean_Finger_Joints_Dic.keys(): 321 | for joint in clean_Finger_Joints_Dic[key]: 322 | if cmds.attributeQuery('rigModule', node=joint, exists=1): 323 | cmds.connectAttr(rigModule.topGrp + '.' + prefix + rigPartName + '_Jnt', 324 | joint + '.rigModule', f=1) 325 | 326 | # final cleaning 327 | cmds.parent(FK_Arm_CtrlGrp_List[0], clavical_Ctrl.C) 328 | 329 | if FK_Parent: 330 | FK_Loc = cmds.spaceLocator(n=prefix + rigPartName + '_Loc') 331 | FK_LocShape = cmds.listRelatives(FK_Loc, s=1) 332 | cmds.setAttr(FK_LocShape[0] + '.localScaleX', 0) 333 | cmds.setAttr(FK_LocShape[0] + '.localScaleY', 0) 334 | cmds.setAttr(FK_LocShape[0] + '.localScaleZ', 0) 335 | cmds.parentConstraint(FK_Parent, FK_Loc, mo=0) 336 | cmds.parent(clavical_Ctrl.Off, FK_Loc) 337 | cmds.parent(FK_Loc, rigModule.topGrp) 338 | else: 339 | cmds.warning('FK_Parent is None') 340 | cmds.parent(clavical_Ctrl.Off, rigModule.topGrp) 341 | 342 | cmds.parent(IK_Arm_PV_Ctrl.Off, rigModule.topGrp) 343 | cmds.parent(IK_Arm_Ctrl.Off, rigModule.topGrp) 344 | cmds.parent(switchCtrlLoc, rigModule.topGrp) 345 | cmds.parent(IK_FK_Blend_Ctrl.Off, rigModule.topGrp) 346 | 347 | cmds.select(cl=1) 348 | 349 | # IK_FK_seamless Switch by scriptJob and scriptNode 350 | IK_FK_Switch.IK_FK_Switch(prefix=prefix, 351 | switchCtrl=IK_FK_Blend_Ctrl.C, 352 | pvCtrl=IK_Arm_PV_Ctrl.C, 353 | ikCtrl=IK_Arm_Ctrl.C, 354 | skinJoints=armJoints[1:], 355 | fkCtrlList=FK_Arm_Ctrl_List) 356 | 357 | cmds.select(cl=1) 358 | 359 | return rigModule 360 | -------------------------------------------------------------------------------- /CustomProceduralRiggingTool/CustomProceduralRigTool/skinLib/skinLib.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cPickle as pickle 3 | import maya.cmds as cmds 4 | import maya.OpenMaya as openmaya 5 | import maya.OpenMayaUI as openmayaui 6 | import maya.OpenMayaAnim as openmayaanim 7 | from functools import partial 8 | 9 | 10 | from PySide2 import QtGui, QtWidgets, QtCore 11 | from shiboken2 import wrapInstance 12 | 13 | 14 | def show(): 15 | """ 16 | Show Export and Import dialog UI 17 | :return: 18 | """ 19 | dialog = SkinIODialog(getMayaWindow()) 20 | dialog.show() 21 | 22 | 23 | def getMayaWindow(): 24 | """ 25 | Get the mayaMainWindow as parent 26 | :return: mayaMainWindow Ptr 27 | """ 28 | ptr = openmayaui.MQtUtil.mainWindow() 29 | return wrapInstance(long(ptr), QtWidgets.QMainWindow) 30 | 31 | 32 | def getShape(node, intermediate=False): 33 | """ 34 | Get the shape from specified node. 35 | 36 | :param node: node Name of a transform or shape node. 37 | :param intermediate: intermediate True to get the intermediate shape, False to get the visible shape 38 | :return: the name of the desired shape node 39 | """ 40 | if cmds.nodeType(node) == 'transform': 41 | shapes = cmds.listRelatives(node, shapes=1, path=1) 42 | 43 | # from transform node to get the shape node 44 | if not shapes: 45 | shapes = [] 46 | for shape in shapes: 47 | isIntermediate = cmds.getAttr('%s.intermediateObject' % shape) 48 | # Sometimes there are left over intermediate shapes that are not used to(the duplicated deformed shape) 49 | # check the connections to make sure we get the one that is used 50 | # return intermediate shape which has incoming objects 51 | if intermediate and isIntermediate and cmds.listConnections(shape, source=0, destination=1): 52 | return shape 53 | 54 | # return visible shape 55 | elif not intermediate and not isIntermediate: 56 | return shape 57 | 58 | if shapes: 59 | return shapes[0] 60 | # return the shape which just is a Shape Node 61 | elif cmds.nodeType(node) in ['mesh', 'nurbsCurve', 'nurbsSurface']: 62 | return node 63 | 64 | return None 65 | 66 | 67 | class SkinCluster(object): 68 | # global variable extension 69 | kFileExtension = '.skin' 70 | 71 | @classmethod 72 | def export(cls, filePath=None, shape=None): 73 | skin = SkinCluster(shape) 74 | skin.exportSkin(filePath) 75 | 76 | @classmethod 77 | def createAndImport(cls, filePath=None, shape=None): 78 | """ 79 | Create a skinCluster on the specified shape if one does not already exist 80 | and then import the weight data. 81 | :param filePath: filePath of the skinWeights 82 | :param shape: mesh shape which skinCluster deforms 83 | :return: 84 | """ 85 | 86 | if not shape: 87 | try: 88 | shape = cmds.ls(sl=1)[0] 89 | 90 | except: 91 | raise RuntimeError('No shape selected') 92 | 93 | if filePath == None: 94 | startDir = cmds.workspace(q=1, rootDirectory=1) 95 | filePath = cmds.fileDialog2(dialogStyle=2, fileMode=1, startingDirectory=startDir, 96 | fileFilter='Skin Files (*%s)' % SkinCluster.kFileExtension) 97 | 98 | if not filePath: 99 | return 100 | if not isinstance(filePath, basestring): 101 | filePath = filePath[0] 102 | 103 | # Read the data from the file 104 | fh = open(filePath, 'rb') 105 | data = pickle.load(fh) 106 | fh.close() 107 | 108 | # Make sure the vertex count is the same 109 | meshVertices = cmds.polyEvaluate(shape, vertex=1) 110 | 111 | importedVertices = len(data['blendWeights']) 112 | if meshVertices != importedVertices: 113 | raise RuntimeError('Vertex counts do not match. %d != %d' % (meshVertices, importedVertices)) 114 | 115 | 116 | # check if the shape already has a skinCluster 117 | if SkinCluster.getSkinCluster(shape): 118 | skinCluster = SkinCluster(shape) 119 | else: 120 | # create a new skinCluster 121 | joints = data['weights'].keys() 122 | 123 | # Make sure all the joints exist 124 | 125 | unusedImports = [] 126 | # Create a set for get which joint in the scene doesn't have weights 127 | noMatch = set([SkinCluster.removeNamespaceFromString(x) for x in cmds.ls(type='joint')]) 128 | 129 | for j in joints: 130 | if j in noMatch: 131 | noMatch.remove(j) 132 | else: 133 | unusedImports.append(j) 134 | 135 | # Remapping the joints 136 | # if there were unmapped influences ask the user to map them 137 | if unusedImports and noMatch: 138 | 139 | mappingDialog = WeightRemapDialog(getMayaWindow()) 140 | mappingDialog.setInfluences(unusedImports, noMatch) 141 | mappingDialog.exec_() 142 | 143 | for src, dst in mappingDialog.mapping.items(): 144 | # swap the mapping 145 | data['weights'][dst] = data['weights'][src] 146 | del data['weights'][src] 147 | 148 | # Create the skinCluster with post normalization so setting the weights does not 149 | # normalize all weights 150 | joints = data['weights'].keys() 151 | 152 | skinCluster = cmds.skinCluster(joints, shape, tsb=1, nw=2, n=data['name']) 153 | skinCluster = SkinCluster(shape) 154 | 155 | skinCluster.setData(data) 156 | print "Imported %s" % filePath 157 | 158 | @classmethod 159 | def getSkinCluster(cls, shape): 160 | """ 161 | Get the skinCluster node attached to the specified shape. 162 | :param shape: Shape node name 163 | :return: The attached skinCluster name or None if no skinCluster is attached 164 | """ 165 | shape = getShape(shape) 166 | history = cmds.listHistory(shape, pruneDagObjects=1, interestLevel=2) 167 | 168 | if not history: 169 | return None 170 | skins = [x for x in history if cmds.nodeType(x) == 'skinCluster'] 171 | 172 | if skins: 173 | return skins[0] 174 | return None 175 | 176 | @classmethod 177 | def removeNamespaceFromString(cls, influenceName): 178 | """ 179 | Remove namespaces from a string 180 | CHANGES NAMESPACE: joint1 | NAMESAPCE:joint2 -> joint1 | joint2 181 | :param influenceName: string, name with a namespace 182 | :return: string ,name without a namespace 183 | """ 184 | tokens = influenceName.split('|') 185 | result = '' 186 | 187 | for i, tokens in enumerate(tokens): 188 | if i > 0: 189 | result += '|' 190 | 191 | result += tokens.split(':')[-1] 192 | 193 | return result 194 | 195 | def __init__(self, shape=None): 196 | if not shape: 197 | try: 198 | shape = cmds.ls(sl=1)[0] 199 | 200 | except: 201 | raise RuntimeError('No shape selected') 202 | 203 | self.shape = getShape(shape) 204 | if not self.shape: 205 | raise RuntimeError('No shape connected to %s' % shape) 206 | 207 | # Get the skinCluster node attached to the shape 208 | self.node = SkinCluster.getSkinCluster(self.shape) 209 | if not self.node: 210 | raise ValueError('No skinCluster attached to %s' % self.shape) 211 | 212 | # Get the skinCluster MObject 213 | selectionList = openmaya.MSelectionList() 214 | selectionList.add(self.node) 215 | self.mobj = openmaya.MObject() 216 | selectionList.getDependNode(0, self.mobj) 217 | self.fn = openmayaanim.MFnSkinCluster(self.mobj) 218 | self.data = {'weights': {}, 219 | 'blendWeights': [], 220 | 'name': self.node} 221 | 222 | def gatherData(self): 223 | """ 224 | get and store the skinningMethod and normalizeWeights attributes in data dictionary 225 | :return: None 226 | """ 227 | dagPath, components = self.__getGeometryComponents() 228 | self.gatherInfluenceWeights(dagPath, components) 229 | self.gatherBlendWeights(dagPath, components) 230 | 231 | for attr in ['skinningMethod', 'normalizeWeights']: 232 | self.data[attr] = cmds.getAttr('%s.%s' % (self.node, attr)) 233 | 234 | def __getGeometryComponents(self): 235 | """ 236 | get the dagPath of influence object(joint) and Geometry components(vertex) 237 | :return: dagPath, componnets 238 | """ 239 | # get dagPath and member components of skined shape 240 | # the deformerSet pretty controls which vertex is deformed by the skinCluster 241 | # the deformerSet will allows us to pull out that components(vertex) mobject that we need 242 | fnSet = openmaya.MFnSet(self.fn.deformerSet()) 243 | members = openmaya.MSelectionList() 244 | # the MSelectionList contains the vertex information in the deformerSet above 245 | fnSet.getMembers(members, False) 246 | 247 | dagPath = openmaya.MDagPath() 248 | components = openmaya.MObject() 249 | 250 | # dagPath: dagPath of influence objects(joint) 251 | # components: mesh components(vertex) 252 | members.getDagPath(0, dagPath, components) 253 | 254 | return dagPath, components 255 | 256 | def gatherInfluenceWeights(self, dagPath, components): 257 | """ 258 | get and store the weights of each influence object for same ordered components(vertex) in data['weights'] dictionary 259 | :param dagPath: 260 | :param components: mesh components(vertex) 261 | :return: None 262 | """ 263 | # Gathers all the influence weights 264 | weights = self.__getCurrentWeights(dagPath, components) 265 | 266 | influencePaths = openmaya.MDagPathArray() 267 | # influencePaths is the fullPath of the object(joint) 268 | numInfluences = self.fn.influenceObjects(influencePaths) 269 | # weight size = number of components(vertex) * number of influenceObjects(joints) 270 | numComponentsPerInfluence = weights.length() / numInfluences 271 | 272 | for ii in range(influencePaths.length()): 273 | influenceName = influencePaths[ii].partialPathName() 274 | # we want to store the weights by influence without the namespace so it is easier 275 | # to import if the namespace is different 276 | influenceNameWithoutNamespace = SkinCluster.removeNamespaceFromString(influenceName) 277 | # store the weight of each influence object(joint) for same ordered components(vertex) 278 | self.data['weights'][influenceNameWithoutNamespace] = [weights[jj * numInfluences + ii] for jj in range(numComponentsPerInfluence)] 279 | 280 | def gatherBlendWeights(self, dagPath, components): 281 | """ 282 | Gather the BlendWeights 283 | :param dagPath: dagPath of influence objects(joint) 284 | :param components: mesh components(vertex) 285 | :return: None 286 | """ 287 | weights = openmaya.MDoubleArray() 288 | self.fn.getBlendWeights(dagPath, components, weights) 289 | self.data['blendWeights'] = [weights[i] for i in range(weights.length())] 290 | 291 | def __getCurrentWeights(self, dagPath, components): 292 | """ 293 | Get the current weights array. Be careful about the weight array, it is a giant single array. 294 | The order of the weights array is dependent on the indices of the joint 295 | :param dagPath: path to object deformed by the skinCluster 296 | :param components: Components to return weight for, every single vertex in the mesh 297 | :return: Weights 298 | """ 299 | weights = openmaya.MDoubleArray() 300 | util = openmaya.MScriptUtil() 301 | 302 | util.createFromInt(0) 303 | 304 | pUInt = util.asUintPtr() 305 | # Gets the skinCluster weights for ALL influenceObjects(joints) for the specified components of the object whose dagPath is specified. 306 | # More details see: https://download.autodesk.com/us/maya/2011help/API/class_m_fn_skin_cluster.html#82e83fc5ab653aa15c5431710b3ac86a 307 | self.fn.getWeights(dagPath, components, weights, pUInt) 308 | # weights is a giant single Double Array 309 | # size = number of components(vertex) * number of influenceObjects(joints) 310 | return weights 311 | 312 | def exportSkin(self, filePath=None): 313 | """ 314 | Export the skinCluster data to disk 315 | :param filePath: File Path 316 | :return: 317 | """ 318 | if filePath == None: 319 | startDir = cmds.workspace(q=1, rootDirectory=1) 320 | filePath = cmds.fileDialog2(dialogStyle=2, fileMode=0, startingDirectory=startDir, 321 | fileFilter='Skin Files(*%s)' % SkinCluster.kFileExtension) 322 | 323 | if not filePath: 324 | return 325 | 326 | filePath = filePath[0] 327 | 328 | if not filePath.endswith(SkinCluster.kFileExtension): 329 | filePath += SkinCluster.kFileExtension 330 | 331 | self.gatherData() 332 | 333 | fh = open(filePath, 'wb') 334 | pickle.dump(self.data, fh, pickle.HIGHEST_PROTOCOL) 335 | 336 | fh.close() 337 | print "Exported skinCluster (%d influences, %d vertices) %s" % (len(self.data['weights'].keys()), len(self.data['blendWeights']), filePath) 338 | 339 | def setData(self, data): 340 | """ 341 | Sets the data and stores it in the Maya skinCluster node. 342 | :return: 343 | """ 344 | self.data = data 345 | dagPath, components = self.__getGeometryComponents() 346 | self.setInfluenceWeights(dagPath, components) 347 | self.setBlendWeights(dagPath, components) 348 | 349 | for attr in ['skinningMethod', 'normalizeWeights']: 350 | cmds.setAttr('%s.%s' % (self.node, attr), self.data[attr]) 351 | 352 | def setInfluenceWeights(self, dagPath, components): 353 | """ 354 | 355 | :param dagPath: 356 | :param components: 357 | :return: 358 | """ 359 | # get the existing weights and fill in the new weights 360 | weights = self.__getCurrentWeights(dagPath, components) 361 | influencePaths = openmaya.MDagPathArray() 362 | numInfluences = self.fn.influenceObjects(influencePaths) 363 | numComponentsPerInfluence = weights.length() / numInfluences 364 | 365 | # Keep track of which imported influences aren't used 366 | unusedImports = [] 367 | # Keep track of which existing influences don't get anything imported 368 | noMatch = [influencePaths[ii].partialPathName() for ii in xrange(influencePaths.length())] 369 | 370 | for importedInfluence, importedWeights in self.data['weights'].items(): 371 | for inf_count in xrange(influencePaths.length()): 372 | # partialPathName used to return exclusive partial path name of the object 373 | influenceName = influencePaths[inf_count].partialPathName() 374 | influenceWithoutNamespace = SkinCluster.removeNamespaceFromString(influenceName) 375 | 376 | if influenceWithoutNamespace == importedInfluence: 377 | # Store the imported weights into the MDoubeArray 378 | for jj in xrange(numComponentsPerInfluence): 379 | weights.set(importedWeights[jj], jj * numInfluences + inf_count) 380 | 381 | noMatch.remove(influenceName) 382 | break 383 | else: 384 | unusedImports.append(importedInfluence) 385 | 386 | if unusedImports and noMatch: 387 | mappingDialog = WeightRemapDialog(getMayaWindow()) 388 | mappingDialog.setInfluences(unusedImports, noMatch) 389 | mappingDialog.exec_() 390 | for src, dst in mappingDialog.mapping.items(): 391 | for ii in range(influencePaths.length()): 392 | if influencePaths[ii].partialPathName() == dst: 393 | for jj in range(numComponentsPerInfluence): 394 | weights.set(self.data['weights'][src][jj], jj*numInfluences+ii) 395 | break 396 | 397 | influenceIndics = openmaya.MIntArray(numInfluences) 398 | for ii in range(numInfluences): 399 | influenceIndics.set(ii, ii) 400 | self.fn.setWeights(dagPath, components, influenceIndics, weights, False) 401 | 402 | def setBlendWeights(self, dagPath, components): 403 | """ 404 | Set BlendWeights 405 | :param dagPath: 406 | :param components: 407 | :return: 408 | """ 409 | blendWeights = openmaya.MDoubleArray(len(self.data['blendWeights'])) 410 | for i, w in enumerate(self.data['blendWeights']): 411 | blendWeights.set(w, i) 412 | 413 | self.fn.setBlendWeights(dagPath, components, blendWeights) 414 | 415 | 416 | class WeightRemapDialog(QtWidgets.QDialog): 417 | def __init__(self, parent=None): 418 | super(WeightRemapDialog, self).__init__(parent) 419 | 420 | self.setWindowTitle('Remap Weights') 421 | self.setObjectName('remapWeightUI') 422 | 423 | self.setModal(True) 424 | self.resize(600, 400) 425 | self.mapping = {} 426 | 427 | self.mainVbox = QtWidgets.QVBoxLayout() 428 | 429 | self.setLayout(self.mainVbox) 430 | 431 | label = QtWidgets.QLabel('The following influences have no corresponding influence from the import file. ' 432 | 'You can either remap the influences or skip them') 433 | 434 | label.setWordWrap(True) 435 | 436 | self.mainVbox.addWidget(label) 437 | 438 | self.HBox = QtWidgets.QHBoxLayout() 439 | self.mainVbox.addLayout(self.HBox) 440 | 441 | 442 | self.VBox = QtWidgets.QVBoxLayout() 443 | self.HBox.addLayout(self.VBox) 444 | 445 | self.VBox.addWidget(QtWidgets.QLabel('Unmapped influences')) 446 | 447 | self.existingInfluences = QtWidgets.QListWidget() 448 | self.VBox.addWidget(self.existingInfluences) 449 | 450 | vbox = QtWidgets.QVBoxLayout() 451 | self.HBox.addLayout(vbox) 452 | vbox.addWidget(QtWidgets.QLabel('Available imported influence')) 453 | self.scrollArea = QtWidgets.QScrollArea() 454 | self.widget = QtWidgets.QScrollArea() 455 | self.importedInfluenceLayout = QtWidgets.QVBoxLayout(self.widget) 456 | vbox.addWidget(self.widget) 457 | 458 | hbox = QtWidgets.QHBoxLayout() 459 | self.mainVbox.addLayout(hbox) 460 | hbox.addStretch() 461 | self.btn = QtWidgets.QPushButton('OK') 462 | self.btn.released.connect(self.accept) 463 | hbox.addWidget(self.btn) 464 | 465 | def setInfluences(self, importedInfluences, existingInfluences): 466 | infs = list(existingInfluences) 467 | infs.sort() 468 | self.existingInfluences.addItems(infs) 469 | 470 | width = 200 471 | for inf in importedInfluences: 472 | row = QtWidgets.QHBoxLayout() 473 | self.importedInfluenceLayout.addLayout(row) 474 | 475 | label = QtWidgets.QLabel(inf) 476 | row.addWidget(label) 477 | 478 | toggleBtn = QtWidgets.QPushButton('->') 479 | toggleBtn.setMaximumWidth(30) 480 | row.addWidget(toggleBtn) 481 | 482 | label = QtWidgets.QLabel('') 483 | label.setMaximumWidth(width) 484 | label.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) 485 | row.addWidget(label) 486 | 487 | toggleBtn.released.connect(partial(self.setInfluencesMapping, src=inf, label=label)) 488 | 489 | self.importedInfluenceLayout.addStretch() 490 | 491 | 492 | def setInfluencesMapping(self, src, label): 493 | selectedInfluence = self.existingInfluences.selectedItems() 494 | 495 | if not selectedInfluence: 496 | return 497 | 498 | dst = selectedInfluence[0].text() 499 | 500 | label.setText(dst) 501 | 502 | self.mapping[src] = dst 503 | 504 | index = self.existingInfluences.indexFromItem(selectedInfluence[0]) 505 | 506 | item = self.existingInfluences.takeItem(index.row()) 507 | 508 | del item 509 | 510 | 511 | class SkinIODialog(QtWidgets.QDialog): 512 | 513 | def __init__(self, parent=None): 514 | super(SkinIODialog, self).__init__(parent) 515 | 516 | self.setWindowTitle('Skin IO') 517 | self.setObjectName('skinioWidget') 518 | self.setModal(False) 519 | self.setFixedSize(200, 80) 520 | 521 | self.vbox = QtWidgets.QVBoxLayout() 522 | self.setLayout(self.vbox) 523 | 524 | self.exportBtn = QtWidgets.QPushButton("Export") 525 | self.vbox.addWidget(self.exportBtn) 526 | self.exportBtn.clicked.connect(SkinCluster.export) 527 | 528 | self.importBtn = QtWidgets.QPushButton("Import") 529 | self.vbox.addWidget(self.importBtn) 530 | self.importBtn.clicked.connect(SkinCluster.createAndImport) 531 | --------------------------------------------------------------------------------