# importing libraries: import maya.cmds as cmds from Library import dpUtils as utils import dpBaseClass as Base import dpLayoutClass as Layout # global variables to this module: CLASS_NAME = "Spine" TITLE = "m011_spine" DESCRIPTION = "m012_spineDesc" ICON = "/Icons/dp_spine.png" class Spine(Base.StartClass, Layout.LayoutClass): def __init__(self, *args, **kwargs): # Add the needed parameter to the kwargs dict to be able to maintain the parameter order kwargs["CLASS_NAME"] = CLASS_NAME kwargs["TITLE"] = TITLE kwargs["DESCRIPTION"] = DESCRIPTION kwargs["ICON"] = ICON Base.StartClass.__init__(self, *args, **kwargs) # Declare variable self.integratedActionsDic = {} self.cvJointLoc = None self.shapeSizeCH = None # List of returned data: self.aHipsAList = [] self.aChestAList = [] self.aVolVariationAttrList = [] self.aActVolVariationAttrList = [] self.aMScaleVolVariationAttrList = [] self.aIkFkBlendAttrList = [] self.aInnerCtrls = [] self.aOuterCtrls = [] self.aRbnJointList = [] self.aClusterGrp = [] def createModuleLayout(self, *args): Base.StartClass.createModuleLayout(self) Layout.LayoutClass.basicModuleLayout(self) # Custom MODULE LAYOUT: # verify if we are creating or re-loading this module instance: firstTime = cmds.getAttr(self.moduleGrp+'.nJoints') if firstTime == 1: try: cmds.intField(self.nJointsIF, edit=True, value=3, minValue=3) except: pass self.changeJointNumber(3) def reCreateEditSelectedModuleLayout(self, bSelect=False, *args): Layout.LayoutClass.reCreateEditSelectedModuleLayout(self, bSelect) # style layout: self.styleLayout = cmds.rowLayout(numberOfColumns=4, columnWidth4=(100, 50, 50, 70), columnAlign=[(1, 'right'), (2, 'left'), (3, 'right')], adjustableColumn=4, columnAttach=[(1, 'both', 2), (2, 'left', 2), (3, 'left', 2), (3, 'both', 10)], parent="selectedColumn") cmds.text(label=self.langDic[self.langName]['m041_style'], visible=True, parent=self.styleLayout) self.styleMenu = cmds.optionMenu("styleMenu", label='', changeCommand=self.changeStyle, parent=self.styleLayout) styleMenuItemList = [self.langDic[self.langName]['m042_default'], self.langDic[self.langName]['m026_biped']] for item in styleMenuItemList: cmds.menuItem(label=item, parent=self.styleMenu) # read from guide attribute the current value to style: currentStyle = cmds.getAttr(self.moduleGrp+".style") cmds.optionMenu(self.styleMenu, edit=True, select=int(currentStyle+1)) def changeStyle(self, style, *args): """ Change the style to be applyed custom actions to be more animator friendly. We will optimise: control world orientation """ # for Default style: if style == self.langDic[self.langName]['m042_default']: cmds.setAttr(self.moduleGrp+".style", 0) # for Biped style: if style == self.langDic[self.langName]['m026_biped']: cmds.setAttr(self.moduleGrp+".style", 1) def createGuide(self, *args): Base.StartClass.createGuide(self) # Custom GUIDE: cmds.setAttr(self.moduleGrp+".moduleNamespace", self.moduleGrp[:self.moduleGrp.rfind(":")], type='string') cmds.addAttr(self.moduleGrp, longName="nJoints", attributeType='long') cmds.addAttr(self.moduleGrp, longName="style", attributeType='enum', enumName=self.langDic[self.langName]['m042_default']+':'+self.langDic[self.langName]['m026_biped']) cmds.setAttr(self.moduleGrp+".nJoints", 1) self.cvJointLoc, shapeSizeCH = self.ctrls.cvJointLoc(ctrlName=self.guideName+"_JointLoc1", r=0.5, d=1, guide=True) self.connectShapeSize(shapeSizeCH) self.cvEndJoint, shapeSizeCH = self.ctrls.cvLocator(ctrlName=self.guideName+"_JointEnd", r=0.1, d=1, guide=True) self.connectShapeSize(shapeSizeCH) cmds.parent(self.cvEndJoint, self.cvJointLoc) cmds.setAttr(self.cvEndJoint+".tz", 1.3) cmds.transformLimits(self.cvEndJoint, tz=(0.01, 1), etz=(True, False)) self.ctrls.setLockHide([self.cvEndJoint], ['tx', 'ty', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz']) cmds.parent(self.cvJointLoc, self.moduleGrp) # Edit GUIDE: cmds.setAttr(self.moduleGrp+".rx", -90) cmds.setAttr(self.moduleGrp+".ry", -90) cmds.setAttr(self.moduleGrp+"_RadiusCtrl.tx", 4) def changeJointNumber(self, enteredNJoints, *args): """ Edit the number of joints in the guide. """ utils.useDefaultRenderLayer() # get the number of joints entered by user: if enteredNJoints == 0: try: self.enteredNJoints = cmds.intField(self.nJointsIF, query=True, value=True) except: return else: self.enteredNJoints = enteredNJoints # get the number of joints existing: self.currentNJoints = cmds.getAttr(self.moduleGrp+".nJoints") # start analisys the difference between values: if self.enteredNJoints != self.currentNJoints: self.cvEndJoint = self.guideName+"_JointEnd" if self.currentNJoints > 1: # delete current point constraints: for n in range(2, self.currentNJoints): cmds.delete(self.guideName+"_ParentConstraint"+str(n)) # verify if the nJoints is greather or less than the current if self.enteredNJoints > self.currentNJoints: # add the new cvLocators: for n in range(self.currentNJoints+1, self.enteredNJoints+1): # create another N cvLocator: self.cvLocator, shapeSizeCH = self.ctrls.cvLocator(ctrlName=self.guideName+"_JointLoc"+str(n), r=0.3, d=1, guide=True) self.connectShapeSize(shapeSizeCH) # set its nJoint value as n: cmds.setAttr(self.cvLocator+".nJoint", n) # parent its group to the first cvJointLocator: self.cvLocGrp = cmds.group(self.cvLocator, name=self.cvLocator+"_Grp") cmds.parent(self.cvLocGrp, self.guideName+"_JointLoc"+str(n-1), relative=True) cmds.setAttr(self.cvLocGrp+".translateZ", 2) if n > 2: cmds.parent(self.cvLocGrp, self.guideName+"_JointLoc1", absolute=True) elif self.enteredNJoints<self.currentNJoints: # re-parent cvEndJoint: self.cvLocator = self.guideName+"_JointLoc" + str(self.enteredNJoints) cmds.parent(self.cvEndJoint, world=True) # delete difference of nJoints: for n in range(self.enteredNJoints, self.currentNJoints): # re-parent the children guides: childrenGuideBellowList = utils.getGuideChildrenList(self.guideName+"_JointLoc"+str(n+1)+"_Grp") if childrenGuideBellowList: for childGuide in childrenGuideBellowList: cmds.parent(childGuide, self.cvLocator) cmds.delete(self.guideName+"_JointLoc"+str(n+1)+"_Grp") # re-parent cvEndJoint: cmds.parent(self.cvEndJoint, self.cvLocator) cmds.setAttr(self.cvEndJoint+".tz", 1.3) cmds.setAttr(self.cvEndJoint+".visibility", 0) # re-create parentConstraints: if self.enteredNJoints > 1: for n in range(2, self.enteredNJoints): self.parentConst = cmds.parentConstraint(self.guideName+"_JointLoc1", self.cvEndJoint, self.guideName+"_JointLoc"+str(n)+"_Grp", name=self.guideName+"_ParentConstraint"+str(n), maintainOffset=True)[0] nParentValue = (n-1) / float(self.enteredNJoints-1) cmds.setAttr(self.parentConst+".Guide_JointLoc1W0", 1-nParentValue) cmds.setAttr(self.parentConst+".Guide_JointEndW1", nParentValue) self.ctrls.setLockHide([self.guideName+"_JointLoc"+ str(n)], ['rx', 'ry', 'rz', 'sx', 'sy', 'sz']) # actualise the nJoints in the moduleGrp: cmds.setAttr(self.moduleGrp+".nJoints", self.enteredNJoints) self.currentNJoints = self.enteredNJoints # re-build the preview mirror: Layout.LayoutClass.createPreviewMirror(self) cmds.select(self.moduleGrp) def rigModule(self, *args): Base.StartClass.rigModule(self) # verify if the guide exists: if cmds.objExists(self.moduleGrp): try: hideJoints = cmds.checkBox('hideJointsCB', query=True, value=True) except: hideJoints = 1 self.currentStyle = cmds.getAttr(self.moduleGrp+".style") # start as no having mirror: sideList = [""] # analisys the mirror module: self.mirrorAxis = cmds.getAttr(self.moduleGrp+".mirrorAxis") if self.mirrorAxis != 'off': # get rigs names: self.mirrorNames = cmds.getAttr(self.moduleGrp+".mirrorName") # get first and last letters to use as side initials (prefix): sideList = [self.mirrorNames[0]+'_', self.mirrorNames[len(self.mirrorNames)-1]+'_'] for s, side in enumerate(sideList): duplicated = cmds.duplicate(self.moduleGrp, name=side+self.userGuideName+'_Guide_Base')[0] allGuideList = cmds.listRelatives(duplicated, allDescendents=True) for item in allGuideList: cmds.rename(item, side+self.userGuideName+"_"+item) self.mirrorGrp = cmds.group(name="Guide_Base_Grp", empty=True) cmds.parent(side+self.userGuideName+'_Guide_Base', self.mirrorGrp, absolute=True) # re-rename grp: cmds.rename(self.mirrorGrp, side+self.userGuideName+'_'+self.mirrorGrp) # do a group mirror with negative scaling: if s == 1: for axis in self.mirrorAxis: cmds.setAttr(side+self.userGuideName+'_'+self.mirrorGrp+'.scale' + axis, -1) # joint labelling: jointLabelAdd = 1 else: # if not mirror: duplicated = cmds.duplicate(self.moduleGrp, name=self.userGuideName+'_Guide_Base')[0] allGuideList = cmds.listRelatives(duplicated, allDescendents=True) for item in allGuideList: cmds.rename(item, self.userGuideName+"_"+item) self.mirrorGrp = cmds.group(self.userGuideName+'_Guide_Base', name="Guide_Base_Grp", relative=True) # re-rename grp: cmds.rename(self.mirrorGrp, self.userGuideName+'_'+self.mirrorGrp) # joint labelling: jointLabelAdd = 0 # store the number of this guide by module type dpAR_count = utils.findModuleLastNumber(CLASS_NAME, "dpAR_type") + 1 # run for all sides for s, side in enumerate(sideList): self.base = side+self.userGuideName+'_Guide_Base' # get the number of joints to be created: self.nJoints = cmds.getAttr(self.base+".nJoints") # create controls: self.hipsACtrl = self.ctrls.cvControl("id_041_SpineHipsA", ctrlName=side+self.userGuideName+"_"+self.langDic[self.langName]['c027_hips']+"A_Ctrl", r=self.ctrlRadius, d=self.curveDegree) self.chestACtrl = self.ctrls.cvControl("id_044_SpineChestA", ctrlName=side+self.userGuideName+"_"+self.langDic[self.langName]['c028_chest']+"A_Ctrl", r=self.ctrlRadius, d=self.curveDegree) # optimize controls CV shapes: tempHipsACluster = cmds.cluster(self.hipsACtrl)[1] cmds.setAttr(tempHipsACluster+".scaleY", 0.25) cmds.delete(self.hipsACtrl, constructionHistory=True) tempChestACluster = cmds.cluster(self.chestACtrl)[1] cmds.setAttr(tempChestACluster+".scaleY", 0.4) cmds.delete(self.chestACtrl, constructionHistory=True) # create start and end Fk controls: self.hipsFkCtrl = self.ctrls.cvControl("id_067_SpineFk", ctrlName=side+self.userGuideName+"_"+self.langDic[self.langName]['c027_hips']+"A_Fk_Ctrl", r=self.ctrlRadius, d=self.curveDegree, dir="+Z") self.chestFkCtrl = self.ctrls.cvControl("id_067_SpineFk", ctrlName=side+self.userGuideName+"_"+self.langDic[self.langName]['c028_chest']+"A_Fk_Ctrl", r=self.ctrlRadius, d=self.curveDegree, dir="+Z") self.hipsBCtrl = self.ctrls.cvControl("id_042_SpineHipsB", side+self.userGuideName+"_"+self.langDic[self.langName]['c027_hips']+"B_Ctrl", r=self.ctrlRadius, d=self.curveDegree, dir="+X") self.chestBCtrl = self.ctrls.cvControl("id_045_SpineChestB", side+self.userGuideName+"_"+self.langDic[self.langName]['c028_chest']+"B_Ctrl", r=self.ctrlRadius, d=self.curveDegree, dir="+X") cmds.addAttr(self.hipsACtrl, longName=side+self.userGuideName+'_'+self.langDic[self.langName]['c031_volumeVariation'], attributeType="float", defaultValue=1, keyable=True) cmds.addAttr(self.hipsACtrl, longName=side+self.userGuideName+'_active_'+self.langDic[self.langName]['c031_volumeVariation'], attributeType="float", defaultValue=1, keyable=True) cmds.addAttr(self.hipsACtrl, longName=side+self.userGuideName+'_masterScale_'+self.langDic[self.langName]['c031_volumeVariation'], attributeType="float", defaultValue=1, keyable=True) cmds.addAttr(self.hipsACtrl, longName=side+self.userGuideName+'Fk_ikFkBlend', attributeType="float", min=0, max=1, defaultValue=1, keyable=True) self.aHipsAList.append(self.hipsACtrl) self.aChestAList.append(self.chestACtrl) self.aVolVariationAttrList.append(side+self.userGuideName+'_'+self.langDic[self.langName]['c031_volumeVariation']) self.aActVolVariationAttrList.append(side+self.userGuideName+'_active_'+self.langDic[self.langName]['c031_volumeVariation']) self.aMScaleVolVariationAttrList.append(side+self.userGuideName+'_masterScale_'+self.langDic[self.langName]['c031_volumeVariation']) self.aIkFkBlendAttrList.append(side+self.userGuideName+'Fk_ikFkBlend') # Setup axis order if self.rigType == Base.RigType.quadruped: cmds.setAttr(self.hipsACtrl + ".rotateOrder", 1) cmds.setAttr(self.hipsBCtrl + ".rotateOrder", 1) cmds.setAttr(self.chestACtrl + ".rotateOrder", 1) cmds.setAttr(self.chestBCtrl + ".rotateOrder", 1) cmds.setAttr(self.hipsFkCtrl + ".rotateOrder", 1) cmds.setAttr(self.chestFkCtrl + ".rotateOrder", 1) cmds.rotate(90, 0, 0, self.hipsACtrl, self.hipsBCtrl, self.chestACtrl, self.chestBCtrl, self.hipsFkCtrl, self.chestFkCtrl) cmds.makeIdentity(self.hipsACtrl, self.hipsBCtrl, self.chestACtrl, self.chestBCtrl, self.hipsFkCtrl, self.chestFkCtrl, apply=True, rotate=True) else: cmds.setAttr(self.hipsACtrl + ".rotateOrder", 3) cmds.setAttr(self.hipsBCtrl + ".rotateOrder", 3) cmds.setAttr(self.chestACtrl + ".rotateOrder", 3) cmds.setAttr(self.chestBCtrl + ".rotateOrder", 3) cmds.setAttr(self.hipsFkCtrl + ".rotateOrder", 3) cmds.setAttr(self.chestFkCtrl + ".rotateOrder", 3) # Keep a list of ctrls we want to colorize a certain way self.aInnerCtrls.append([self.hipsBCtrl, self.chestBCtrl]) self.aOuterCtrls.append([self.hipsACtrl, self.chestACtrl, self.hipsFkCtrl, self.chestFkCtrl]) # organize hierarchy: cmds.parent(self.hipsBCtrl, self.hipsACtrl) cmds.parent(self.chestBCtrl, self.chestACtrl) cmds.parent(self.hipsFkCtrl, self.hipsACtrl) cmds.parent(self.chestFkCtrl, self.chestACtrl) if self.currentStyle == 0: #default cmds.rotate(-90, 0, 0, self.hipsACtrl, self.chestACtrl) cmds.makeIdentity(self.hipsACtrl, self.chestACtrl, apply=True, rotate=True) # position of controls: bottomLocGuide = side+self.userGuideName+"_Guide_JointLoc1" topLocGuide = side+self.userGuideName+"_Guide_JointLoc"+str(self.nJoints) # snap controls to guideLocators: cmds.delete(cmds.parentConstraint(bottomLocGuide, self.hipsACtrl, maintainOffset=False)) cmds.delete(cmds.parentConstraint(topLocGuide, self.chestACtrl, maintainOffset=False)) # change axis orientation for biped stype if self.currentStyle == 1: #biped cmds.rotate(0, 0, 0, self.hipsACtrl, self.chestACtrl) cmds.makeIdentity(self.hipsACtrl, self.chestACtrl, apply=True, rotate=True) cmds.parent(self.chestACtrl, self.hipsACtrl) # zeroOut transformations: self.hipsACtrlZero, self.chestAZero, self.chestBGrp, self.hipsFkCtrlZero, self.chestFkCtrlZero = utils.zeroOut([self.hipsACtrl, self.chestACtrl, self.chestBCtrl, self.hipsFkCtrl, self.chestFkCtrl]) self.chestBGrp = cmds.rename(self.chestBGrp, self.chestBGrp.replace("Zero", "Grp")) self.chestBZero = utils.zeroOut([self.chestBGrp])[0] self.ctrls.setLockHide([self.hipsACtrl, self.hipsBCtrl, self.chestACtrl, self.chestBCtrl, self.hipsFkCtrl, self.chestFkCtrl], ['v'], l=False) # modify the pivots of chest controls: upPivotPos = cmds.xform(side+self.userGuideName+"_Guide_JointLoc"+str(self.nJoints-1), query=True, worldSpace=True, translation=True) cmds.move(upPivotPos[0], upPivotPos[1], upPivotPos[2], self.chestACtrl+".scalePivot", self.chestACtrl+".rotatePivot") # add originedFrom attributes to hipsA, hipsB and chestB: utils.originedFrom(objName=self.hipsACtrl, attrString=self.base) utils.originedFrom(objName=self.hipsBCtrl, attrString=bottomLocGuide) utils.originedFrom(objName=self.hipsFkCtrl, attrString=bottomLocGuide) utils.originedFrom(objName=self.chestBCtrl, attrString=topLocGuide) utils.originedFrom(objName=self.chestFkCtrl, attrString=topLocGuide) # create a simple spine ribbon: returnedRibbonList = self.ctrls.createSimpleRibbon(name=side+self.userGuideName, totalJoints=(self.nJoints-1), jointLabelNumber=(s+jointLabelAdd), jointLabelName=self.userGuideName) rbnNurbsPlane = returnedRibbonList[0] rbnNurbsPlaneShape = returnedRibbonList[1] rbnJointGrpList = returnedRibbonList[2] self.aRbnJointList = returnedRibbonList[3] # position of ribbon nurbs plane: cmds.setAttr(rbnNurbsPlane+".tz", -4) cmds.move(0, 0, 0, rbnNurbsPlane+".scalePivot", rbnNurbsPlane+".rotatePivot") cmds.rotate(90, 90, 0, rbnNurbsPlane) cmds.makeIdentity(rbnNurbsPlane, apply=True, translate=True, rotate=True) downLocPos = cmds.xform(side+self.userGuideName+"_Guide_JointLoc1", query=True, worldSpace=True, translation=True) upLocPos = cmds.xform(side+self.userGuideName+"_Guide_JointLoc"+str(self.nJoints), query=True, worldSpace=True, translation=True) cmds.move(downLocPos[0], downLocPos[1], downLocPos[2], rbnNurbsPlane) # create up and down clusters: downCluster = cmds.cluster(rbnNurbsPlane+".cv[0:3][0:1]", name=side+self.userGuideName+'_Down_Cls')[1] upCluster = cmds.cluster(rbnNurbsPlane+".cv[0:3]["+str(self.nJoints)+":"+str(self.nJoints+1)+"]", name=side+self.userGuideName+'_Up_Cls')[1] # get positions of joints from ribbon nurbs plane: startRbnJointPos = cmds.xform(side+self.userGuideName+"_00_Jnt", query=True, worldSpace=True, translation=True) endRbnJointPos = cmds.xform(side+self.userGuideName+"_%02d_Jnt"%(self.nJoints-1), query=True, worldSpace=True, translation=True) # move pivots of clusters to start and end positions: cmds.move(startRbnJointPos[0], startRbnJointPos[1], startRbnJointPos[2], downCluster+".scalePivot", downCluster+".rotatePivot") cmds.move(endRbnJointPos[0], endRbnJointPos[1], endRbnJointPos[2], upCluster+".scalePivot", upCluster+".rotatePivot") # snap clusters to guideLocators: tempDel = cmds.parentConstraint(bottomLocGuide, downCluster, maintainOffset=False) cmds.delete(tempDel) tempDel = cmds.parentConstraint(topLocGuide, upCluster, maintainOffset=False) cmds.delete(tempDel) # rotate clusters to compensate guide: upClusterRot = cmds.xform(upCluster, query=True, worldSpace=True, rotation=True) downClusterRot = cmds.xform(downCluster, query=True, worldSpace=True, rotation=True) cmds.xform(upCluster, worldSpace=True, rotation=(upClusterRot[0]+90, upClusterRot[1], upClusterRot[2])) cmds.xform(downCluster, worldSpace=True, rotation=(downClusterRot[0]+90, downClusterRot[1], downClusterRot[2])) # scaleY of the clusters in order to avoid great extremity deforms: rbnHeight = self.ctrls.distanceBet(side+self.userGuideName+"_Guide_JointLoc"+str(self.nJoints), side+self.userGuideName+"_Guide_JointLoc1", keep=False)[0] cmds.setAttr(upCluster+".sy", rbnHeight / 10) cmds.setAttr(downCluster+".sy", rbnHeight / 10) # parent clusters in controls (up and down): cmds.parentConstraint(self.hipsBCtrl, downCluster, maintainOffset=True, name=downCluster+"_ParentConstraint") cmds.parentConstraint(self.chestBCtrl, upCluster, maintainOffset=True, name=upCluster+"_ParentConstraint") # organize a group of clusters: clustersGrp = cmds.group(name=side+self.userGuideName+"_Rbn_Clusters_Grp", empty=True) self.aClusterGrp.append(clustersGrp) if hideJoints: cmds.setAttr(clustersGrp+".visibility", 0) cmds.parent(downCluster, upCluster, clustersGrp, relative=True) # make ribbon joints groups scalable: for r, rbnJntGrp in enumerate(rbnJointGrpList): if ((r > 0) and (r < (len(rbnJointGrpList) - 1))): scaleGrp = cmds.group(rbnJntGrp, name=rbnJntGrp.replace("_Grp", "_Scale_Grp")) self.ctrls.directConnect(scaleGrp, rbnJntGrp, ['sx', 'sz']) cmds.scaleConstraint(clustersGrp, scaleGrp, maintainOffset=True, name=rbnJntGrp+"_ScaleConstraint") else: cmds.scaleConstraint(clustersGrp, rbnJntGrp, maintainOffset=True, name=rbnJntGrp+"_ScaleConstraint") # calculate the distance to volumeVariation: arcLenShape = cmds.createNode('arcLengthDimension', name=side+self.userGuideName+"_Rbn_ArcLenShape") arcLenFather = cmds.listRelatives(arcLenShape, parent=True)[0] arcLen = cmds.rename(arcLenFather, side+self.userGuideName+"_Rbn_ArcLen") arcLenShape = cmds.listRelatives(arcLen, children=True, shapes=True)[0] cmds.setAttr(arcLen+'.visibility', 0) # connect nurbsPlaneShape to arcLength node: cmds.connectAttr(rbnNurbsPlaneShape+'.worldSpace[0]', arcLenShape+'.nurbsGeometry') cmds.setAttr(arcLenShape+'.vParamValue', 1) # avoid undesired squash if rotateZ the nurbsPlane: cmds.setAttr(arcLenShape+'.uParamValue', 0.5) arcLenValue = cmds.getAttr(arcLenShape+'.arcLengthInV') # create a multiplyDivide to output the squashStretch values: rbnMD = cmds.createNode('multiplyDivide', name=side+self.userGuideName+"_Rbn_MD") cmds.connectAttr(arcLenShape+'.arcLengthInV', rbnMD+'.input2X') cmds.setAttr(rbnMD+'.input1X', arcLenValue) cmds.setAttr(rbnMD+'.operation', 2) # create a blendColor, a condition and a multiplyDivide in order to get the correct result value of volumeVariation: rbnBlendColors = cmds.createNode('blendColors', name=side+self.userGuideName+"_Rbn_BlendColor") cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'_'+self.langDic[self.langName]['c031_volumeVariation'], rbnBlendColors+'.blender') rbnCond = cmds.createNode('condition', name=side+self.userGuideName+'_Rbn_Cond') cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'_active_'+self.langDic[self.langName]['c031_volumeVariation'], rbnCond+'.firstTerm') cmds.connectAttr(rbnBlendColors+'.outputR', rbnCond+'.colorIfTrueR') cmds.connectAttr(rbnMD+'.outputX', rbnBlendColors+'.color1R') rbnVVMD = cmds.createNode('multiplyDivide', name=side+self.userGuideName+"_Rbn_VV_MD") cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'_masterScale_'+self.langDic[self.langName]['c031_volumeVariation'], rbnVVMD+'.input2X') cmds.connectAttr(rbnVVMD+'.outputX', rbnCond+'.colorIfFalseR') cmds.setAttr(rbnVVMD+'.operation', 2) cmds.setAttr(rbnBlendColors+'.color2R', 1) cmds.setAttr(rbnCond+".secondTerm", 1) # middle ribbon setup: for n in range(1, self.nJoints - 1): if self.currentStyle == 0: #default self.middleCtrl = self.ctrls.cvControl("id_043_SpineMiddle", side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n)+"_Ctrl", r=self.ctrlRadius, d=self.curveDegree) self.middleFkCtrl = self.ctrls.cvControl("id_067_SpineFk", side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n)+"_Fk_Ctrl", r=self.ctrlRadius, d=self.curveDegree) cmds.setAttr(self.middleCtrl+".rotateOrder", 4) cmds.setAttr(self.middleFkCtrl+".rotateOrder", 4) cmds.rotate(0, 0, 90, self.middleCtrl, self.middleFkCtrl) cmds.makeIdentity(self.middleCtrl, self.middleFkCtrl, apply=True, rotate=True) else: #biped self.middleCtrl = self.ctrls.cvControl("id_043_SpineMiddle", side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n)+"_Ctrl", r=self.ctrlRadius, d=self.curveDegree, dir="+X") self.middleFkCtrl = self.ctrls.cvControl("id_067_SpineFk", side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n)+"_Fk_Ctrl", r=self.ctrlRadius, d=self.curveDegree, dir="+X") cmds.setAttr(self.middleCtrl+".rotateOrder", 3) cmds.setAttr(self.middleFkCtrl+".rotateOrder", 3) self.aInnerCtrls[s].append(self.middleCtrl) self.aOuterCtrls[s].append(self.middleFkCtrl) self.ctrls.setLockHide([self.middleCtrl, self.middleFkCtrl], ['sx', 'sy', 'sz']) cmds.setAttr(self.middleCtrl+'.visibility', keyable=False) cmds.setAttr(self.middleFkCtrl+'.visibility', keyable=False) cmds.parent(self.middleCtrl, self.hipsACtrl) middleLocGuide = side+self.userGuideName+"_Guide_JointLoc"+str(n + 1) cmds.delete(cmds.parentConstraint(middleLocGuide, self.middleCtrl, maintainOffset=False)) cmds.delete(cmds.parentConstraint(middleLocGuide, self.middleFkCtrl, maintainOffset=False)) if self.currentStyle == 1: #biped cmds.rotate(0, 0, 0, self.middleCtrl, self.middleFkCtrl) if self.rigType == Base.RigType.quadruped: cmds.rotate(90, 0, 0, self.middleCtrl, self.middleFkCtrl) cmds.makeIdentity(self.middleCtrl, self.middleFkCtrl, apply=True, rotate=True) self.middleCtrlGrp = utils.zeroOut([self.middleCtrl])[0] self.middleCtrlGrp = cmds.rename(self.middleCtrlGrp, self.middleCtrlGrp.replace("Zero", "Grp")) self.middleCtrlZero = utils.zeroOut([self.middleCtrlGrp])[0] self.middleFkCtrlZero = utils.zeroOut([self.middleFkCtrl])[0] middleCluster = cmds.cluster(rbnNurbsPlane+".cv[0:3]["+str(n+1)+"]", name=side+self.userGuideName+'_Middle_Cls')[1] middleLocPos = cmds.xform(side+self.userGuideName+"_Guide_JointLoc"+str(n), query=True, worldSpace=True, translation=True) tempDel = cmds.parentConstraint(middleLocGuide, middleCluster, maintainOffset=False) cmds.delete(tempDel) middleClusterRot = cmds.xform(middleCluster, query=True, worldSpace=True, rotation=True) cmds.xform(middleCluster, worldSpace=True, rotation=(middleClusterRot[0]+90, middleClusterRot[1], middleClusterRot[2])) cmds.parentConstraint(self.middleCtrl, middleCluster, maintainOffset=True, name=middleCluster+"_ParentConstraint") # parenting constraints like guide locators: self.parentConst = cmds.parentConstraint(self.hipsBCtrl, self.chestBCtrl, self.middleCtrlZero, name=self.middleCtrl+"_ParentConstraint", maintainOffset=True)[0] nParentValue = (n) / float(self.nJoints-1) cmds.setAttr(self.parentConst+"."+self.hipsBCtrl+"W0", 1-nParentValue) cmds.setAttr(self.parentConst+"."+self.chestBCtrl+"W1", nParentValue) cmds.parent(middleCluster, clustersGrp, relative=True) # add originedFrom attribute to this middle ctrl: utils.originedFrom(objName=self.middleCtrl, attrString=middleLocGuide) utils.originedFrom(objName=self.middleFkCtrl, attrString=middleLocGuide) # apply volumeVariation to joints in the middle ribbon setup: cmds.connectAttr(rbnCond+'.outColorR', self.aRbnJointList[n]+'.scaleX') cmds.connectAttr(rbnCond+'.outColorR', self.aRbnJointList[n]+'.scaleZ') # create intensity attribute to drive joint with more force in horizontal: cmds.addAttr(self.middleCtrl, longName=self.langDic[self.langName]['c049_intensity'], attributeType="float", min=0, max=1, defaultValue=0, keyable=True) cmds.addAttr(self.middleFkCtrl, longName=self.langDic[self.langName]['c049_intensity'], attributeType="float", min=0, max=1, defaultValue=0, keyable=True) jointFather = cmds.listRelatives(self.aRbnJointList[n], allParents=True)[0] intRevNode = cmds.createNode("reverse", name=side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n)+"_"+self.langDic[self.langName]['c049_intensity']+"_Rev") middleIntBC = cmds.createNode("blendColors", name=side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n)+"_"+self.langDic[self.langName]['c049_intensity']+"_BC") middleIntPC = cmds.parentConstraint(self.middleCtrl, jointFather, self.aRbnJointList[n], maintainOffset=True, name=self.aRbnJointList[n]+"_"+self.langDic[self.langName]['c049_intensity']+"_ParentConstraint")[0] cmds.connectAttr(self.middleFkCtrl+"."+self.langDic[self.langName]['c049_intensity'], middleIntBC+".color1R", force=True) cmds.connectAttr(self.middleCtrl+"."+self.langDic[self.langName]['c049_intensity'], middleIntBC+".color2R", force=True) cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'Fk_ikFkBlend', middleIntBC+".blender", force=True) cmds.connectAttr(middleIntBC+".outputR", middleIntPC+"."+self.middleCtrl+"W0", force=True) cmds.connectAttr(self.middleCtrl+"."+self.langDic[self.langName]['c049_intensity'], intRevNode+".inputX", force=True) cmds.connectAttr(intRevNode+".outputX", middleIntPC+"."+jointFather+"W1", force=True) # fk middle control hierarchy: if n == 1: #first middle cmds.parent(self.middleFkCtrlZero, self.hipsFkCtrl) else: cmds.parent(self.middleFkCtrlZero, side+self.userGuideName+"_"+self.langDic[self.langName]['c029_middle']+str(n-1)+"_Fk_Ctrl") # build fk setup: self.middleCtrlGrpPC = cmds.parentConstraint(self.middleCtrlZero, self.middleFkCtrl, self.middleCtrlGrp, maintainOffset=True, name=self.middleCtrlGrp+"_IkFkBlend_ParentConstraint")[0] if n == 1: self.revNode = cmds.createNode('reverse', name=side+self.userGuideName+"_IkFkBlend_Rev") cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'Fk_ikFkBlend', self.revNode+".inputX", force=True) # connecting ikFkBlend using the reverse node: cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'Fk_ikFkBlend', self.middleCtrlGrpPC+"."+self.middleFkCtrl+"W1", force=True) cmds.connectAttr(self.revNode+'.outputX', self.middleCtrlGrpPC+"."+self.middleCtrlZero+"W0", force=True) # ikFkBlend visibility: cmds.connectAttr(self.revNode+'.outputX', self.middleCtrlZero+".visibility", force=True) # finishing ikFkBlend: chestACtrlShape = cmds.listRelatives(self.chestACtrl, children=True, type="shape")[0] chestBCtrlShape = cmds.listRelatives(self.chestBCtrl, children=True, type="shape")[0] cmds.parent(self.chestFkCtrlZero, self.middleFkCtrl) self.chestCtrlGrpPC = cmds.parentConstraint(self.chestBZero, self.chestFkCtrl, self.chestBGrp, maintainOffset=True, name=self.chestBGrp+"_IkFkBlend_ParentConstraint")[0] cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'Fk_ikFkBlend', self.chestCtrlGrpPC+"."+self.chestFkCtrl+"W1", force=True) cmds.connectAttr(self.revNode+'.outputX', self.chestCtrlGrpPC+"."+self.chestBZero+"W0", force=True) cmds.connectAttr(self.revNode+'.outputX', chestACtrlShape+".visibility", force=True) cmds.connectAttr(self.revNode+'.outputX', chestBCtrlShape+".visibility", force=True) cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'Fk_ikFkBlend', self.hipsFkCtrlZero+".visibility", force=True) cmds.connectAttr(self.hipsACtrl+'.'+side+self.userGuideName+'Fk_ikFkBlend', self.chestFkCtrlZero+".visibility", force=True) # update spine volume variation setup currentVV = cmds.getAttr(rbnMD+'.outputX') cmds.setAttr(rbnVVMD+'.input1X', currentVV) # organize groups: self.rbnRigGrp = cmds.group(name=side+self.userGuideName+"_Grp", empty=True) self.rbnControlGrp = cmds.group(name=side+self.userGuideName+"_Control_Grp", empty=True) cmds.parent(self.hipsACtrlZero, self.rbnControlGrp, relative=True) cmds.parent(clustersGrp, side+self.userGuideName+"_Rbn_RibbonJoint_Grp", self.rbnControlGrp, arcLen, self.rbnRigGrp, relative=True) if hideJoints: cmds.setAttr(side+self.userGuideName+"_Rbn_RibbonJoint_Grp.visibility", 0) # add hook attributes to be read when rigging integrated modules: utils.addHook(objName=self.rbnControlGrp, hookType='ctrlHook') utils.addHook(objName=clustersGrp, hookType='scalableHook') utils.addHook(objName=self.rbnRigGrp, hookType='staticHook') cmds.addAttr(self.rbnRigGrp, longName="dpAR_name", dataType="string") cmds.addAttr(self.rbnRigGrp, longName="dpAR_type", dataType="string") cmds.setAttr(self.rbnRigGrp+".dpAR_name", self.userGuideName, type="string") cmds.setAttr(self.rbnRigGrp+".dpAR_type", CLASS_NAME, type="string") # add module type counter value cmds.addAttr(self.rbnRigGrp, longName='dpAR_count', attributeType='long', keyable=False) cmds.setAttr(self.rbnRigGrp+'.dpAR_count', dpAR_count) # lockHide scale of up and down controls: self.ctrls.setLockHide([self.hipsACtrl, self.hipsBCtrl, self.chestACtrl, self.chestBCtrl, self.hipsFkCtrl, self.chestFkCtrl], ['sx', 'sy', 'sz']) # delete duplicated group for side (mirror): cmds.delete(side+self.userGuideName+'_'+self.mirrorGrp) # finalize this rig: self.integratingInfo() cmds.select(clear=True) # delete UI (moduleLayout), GUIDE and moduleInstance namespace: self.deleteModule() def integratingInfo(self, *args): Base.StartClass.integratingInfo(self) """ This method will create a dictionary with informations about integrations system between modules. """ self.integratedActionsDic = { "module": { "hipsAList": self.aHipsAList, "chestAList": self.aChestAList, "volumeVariationAttrList": self.aVolVariationAttrList, "ActiveVolumeVariationAttrList": self.aActVolVariationAttrList, "MasterScaleVolumeVariationAttrList": self.aMScaleVolVariationAttrList, "IkFkBlendAttrList": self.aIkFkBlendAttrList, "InnerCtrls": self.aInnerCtrls, "OuterCtrls": self.aOuterCtrls, "jointList": self.aRbnJointList, "scalableGrp": self.aClusterGrp, } }