def addWires(self): # adding wires self.w1 = pm.wire(self.upCrv, w=self.upBlink)[0] self.w2 = pm.wire(self.lowCrv, w=self.lowBlink)[0] self.w3 = pm.wire(self.upTarget, w=self.upCrv_ctl)[0] self.w4 = pm.wire(self.lowTarget, w=self.lowCrv_ctl)[0] # adding blendshapes self.bs_upBlink = pm.blendShape(self.upTarget, self.midTarget, self.upBlink, n=self.getName("blendShapeUpBlink")) self.bs_lowBlink = pm.blendShape(self.lowTarget, self.midTargetLower, self.lowBlink, n=self.getName("blendShapeLowBlink")) self.bs_mid = pm.blendShape(self.lowTarget, self.upTarget, self.midTarget, n=self.getName("blendShapeMidBlink")) self.bs_midLower = pm.blendShape(self.lowTarget, self.upTarget, self.midTargetLower, n=self.getName("blendShapeMidLowerBlink")) # setting blendshape reverse connections rev_node = pm.createNode("reverse") pm.connectAttr(self.bs_upBlink[0].attr(self.midTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", self.bs_upBlink[0].attr(self.upTarget.name())) rev_node = pm.createNode("reverse") rev_nodeLower = pm.createNode("reverse") pm.connectAttr(self.bs_lowBlink[0].attr(self.midTargetLower.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", self.bs_lowBlink[0].attr(self.lowTarget.name())) rev_node = pm.createNode("reverse") pm.connectAttr(self.bs_mid[0].attr(self.upTarget.name()), rev_node + ".inputX") pm.connectAttr(self.bs_midLower[0].attr(self.upTarget.name()), rev_nodeLower + ".inputX") pm.connectAttr(rev_node + ".outputX", self.bs_mid[0].attr(self.lowTarget.name())) pm.connectAttr(rev_nodeLower + ".outputX", self.bs_midLower[0].attr(self.lowTarget.name())) # setting default values self.bs_mid[0].attr(self.upTarget.name()).set(self.blinkH) self.bs_midLower[0].attr(self.upTarget.name()).set(self.blinkH)
def guideMyEyes(self): filePath = r"E:\sgScripts\project\dave\guide\dave_eyelidCTLCurves.ma" cmds.file(filePath, i=1, dns=1) pm.wire("l_up_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="l_low_up_CURV", n="l_top_WIR") pm.wire("l_down_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="l_low_down_CURV", n="l_bot_WIR") pm.wire("r_up_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="r_low_up_CURV", n="r_top_WIR") pm.wire("r_down_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="r_low_down_CURV", n="r_bot_WIR")
def guideMyEyes(self): cmds.file(EYELIDCTLCURVE, i=1, dns=1) pm.wire("l_up_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="l_low_up_CURV", n="l_top_WIR") pm.wire("l_down_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="l_low_down_CURV", n="l_bot_WIR") pm.wire("r_up_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="r_low_up_CURV", n="r_top_WIR") pm.wire("r_down_CURV", gw=True, en=1.000000, ce=0.000000, li=0.000000, wire="r_low_down_CURV", n="r_bot_WIR")
def alignVertexLoopWithCurve(): ''' select loop of verts curve is created to sculpt verts ''' verts = pm.ls(os=True, fl=True) sv = mesh.SortedVertices(verts) # use first and last verts to create 1-span curve firstVert = sv.verts[0] lastVert = sv.verts[-1] firstPos = firstVert.getPosition() lastPos = lastVert.getPosition() crv = pm.curve(ep=(firstPos, lastPos), d=3) endParam = crv.getParamAtPoint(lastPos) * 0.99 # place verts along curve totalVerts = len(sv.verts) params = [endParam/(totalVerts-1)*vertId for vertId in range(totalVerts)] print params for vert, param in zip(sv.verts, params): print vert, param pos = crv.getPointAtParam(param) vert.setPosition(pos) # make wire deformer to sculpt verts wire = pm.wire(sv.verts, w=crv)
def createDrivers(self): # surfaceRbn_BS = surfaceRbn.duplicate()[0] # surfaceRbn_BS.rename(name + '_BS') # surfaceRbn_BS.translateX.set(segments * 0.5 ) # blendshapeNode = pm.blendShape(surfaceRbn_BS,surfaceRbn,name=surfaceRbn.name() + '_blendShape')[0] # blendshapeNode.attr(surfaceRbn_BS.name()).set(1) startLocator = pm.spaceLocator(name=self.name + '_start_loc') startLocatorGrp = pm.group(startLocator, name=startLocator.name() + '_grp') startLocatorGrp.translate.set(self.start) midLocator = pm.spaceLocator(name=self.name + '_mid_loc') midLocatorGrp = pm.group(midLocator, name=midLocator.name() + '_grp') endLocator = pm.spaceLocator(name=self.name + '_end_loc') endLocatorGrp = pm.group(endLocator, name=endLocator.name() + '_grp') endLocatorGrp.translate.set(self.end) self.rbnLocs.append(startLocator) self.rbnLocs.append(midLocator) self.rbnLocs.append(endLocator) # pm.pointConstraint(startLocator, endLocator, midLocatorGrp) self.rbnLocGrp = pm.group([startLocatorGrp, midLocatorGrp, endLocatorGrp], n=self.name + '_drv_loc_grp') # # curveDrv = pm.curve(d=2, p=[self.start, (0, 0, 0), self.end], k=[0, 0, 1, 1]) curveDrv.rename(self.name + '_wire_crv') self.wireCrv = curveDrv wireSrf = pm.duplicate(self.rbnSrf, name=self.name + '_wire_srf')[0] wireDef = pm.wire(wireSrf, w=curveDrv, en=1, gw=False, ce=0, li=0, dds=[(0, 20)], n=self.name + '_wire')
def alignVertexLoopWithCurve(): ''' select loop of verts curve is created to sculpt verts ''' verts = pm.ls(os=True, fl=True) sv = mesh.SortedVertices(verts) # use first and last verts to create 1-span curve firstVert = sv.verts[0] lastVert = sv.verts[-1] firstPos = firstVert.getPosition() lastPos = lastVert.getPosition() crv = pm.curve(ep=(firstPos, lastPos), d=3) endParam = crv.getParamAtPoint(lastPos) * 0.99 # place verts along curve totalVerts = len(sv.verts) params = [ endParam / (totalVerts - 1) * vertId for vertId in range(totalVerts) ] print params for vert, param in zip(sv.verts, params): print vert, param pos = crv.getPointAtParam(param) vert.setPosition(pos) # make wire deformer to sculpt verts wire = pm.wire(sv.verts, w=crv)
def create(self, curveType, spans, selOnly): sel = pm.selected() cmds.CreateCurveFromPoly() curve = pm.selected() pm.rebuildCurve(curve, spans=spans) # set UI curve self.uiObj.setCurrentCurve(curve[0].shortName()) if curveType == 1: pm.nurbsCurveToBezier() pm.delete(curve, ch=True) # Deform if selOnly: sel = pm.polyListComponentConversion(sel, fe=True, tv=True) self.wire = pm.wire(sel, w=curve) else: #Object self.wire = pm.wire(sel[0].node(), w=curve)
def build_wire_deform(self, *args): """ builds a curve with 3 cv's controled by clusters Args: None Returns (None) """ crv_name = self.flexiPlaneNameField.getText() + '_flexiPlane_wire_CRV' surf_wirebShp_name = self.flexiPlaneNameField.getText() + '_flexiPlane_wire_bShp_SURF' surf_bShp_tweekNode_name = self.flexiPlaneNameField.getText() + '_flexiPlane_bShp_SURF_tweak02' wireNode_name = self.flexiPlaneNameField.getText() + '_flexiPlane_bShp_wireNode_SURF' surf_bShpGRP_name = self.flexiPlaneNameField.getText() + '_flexiPlane_bShp_GRP' wire_deformer = mel.eval("wire -gw false -en 1.000000 -ce 0.000000 -li 0.000000 -w " + crv_name + " " + surf_wirebShp_name +";")[0] wireSurf_inputList = pm.listConnections( surf_wirebShp_name + 'Shape' ) pm.rename( wireSurf_inputList[-1] , surf_bShp_tweekNode_name ) pm.rename( wireSurf_inputList[-3] , wireNode_name ) pm.wire( wireNode_name, edit=True, dds = (0, 20.000000) ) pm.parent( crv_name, surf_bShpGRP_name ) pm.parent( crv_name + 'BaseWire', surf_bShpGRP_name ) pm.select( cl = True )
def create_clusters(self): self.ik_drv_crv = pm.rebuildCurve(self.ik_crv, ch=1, rpo=0, rt=0, end=1, kr=2, kcp=0, kep=1, kt=0, s=2, d=3, tol=0.01, name=self.ik_crv.name().replace( 'crv', 'drv_crv'))[0] self.ik_drv_crv.attr('v').set(0) pm.delete(self.ik_drv_crv, ch=1) wire_def = pm.wire(self.ik_crv, w=self.ik_drv_crv, en=1, gw=False, ce=0, li=0, dds=[(0, 20)], n=self.ik_crv.name() + '_wire') wire_transform = pm.listConnections( (wire_def[0].name() + '.baseWire[0]'))[0] # pm.parent(self.ik_drv_crv, self.rigGrp) # pm.parent(wire_transform , self.rigGrp) for i, cv in enumerate(['.cv[0:1]', '.cv[2]', '.cv[3:4]']): cluster = pm.cluster(self.ik_drv_crv.name() + cv) name = join_name(self.ik_crv.name(), 'cls', str(i)) cluster[1].rename(name) cluster[1].attr('v').set(0) self.clusters.append(cluster[1]) pm.parent(cluster[1], self.ik_ctrl[i])
def bdBuildRbnDT(self,name,start,end,segments): surfaceRbn = pm.nurbsPlane(ax = [0,0,22], d=3, u=1, v=segments , w=1, lr = segments)[0] surfaceRbn.rename(name) flcGrp = self.bdCreateFol(surfaceRbn,segments) surfaceRbn_BS = surfaceRbn.duplicate()[0] surfaceRbn_BS.rename(name + '_BS') surfaceRbn_BS.translateX.set(segments * 0.5 ) blendshapeNode = pm.blendShape(surfaceRbn_BS,surfaceRbn,name=surfaceRbn.name() + '_blendShape')[0] blendshapeNode.attr(surfaceRbn_BS.name()).set(1) locatorsRbn = [] topLocator = pm.spaceLocator() topLocator.rename(name + '_loc_top_CON') topLocator.translateY.set(segments * 0.5) pm.makeIdentity(topLocator,apply=True,t=True,r=True,s=True) midLocator = pm.spaceLocator() midLocator.rename(name + '_loc_mid_CON') midLocatorGrp = pm.group(midLocator,name=midLocator.name() + '_grp') pm.makeIdentity(midLocator,apply=True,t=True,r=True,s=True) botLocator = pm.spaceLocator() botLocator.rename(name + '_loc_bot_CON') botLocator.translateY.set(segments * -0.5) pm.makeIdentity(botLocator,apply=True,t=True,r=True,s=True) locatorsRbn.append(topLocator) locatorsRbn.append(midLocator) locatorsRbn.append(botLocator) pm.pointConstraint(topLocator,botLocator,midLocatorGrp) conGrp = pm.group([topLocator,midLocatorGrp,botLocator],n=name.replace('srf','CON_GRP')) curveDrv = pm.curve(d=2, p=[(0, segments * 0.5, 0), (0, 0, 0), (0, segments * -0.5, 0)],k=[0,0,1,1]) curveDrv.rename(name.replace('srf', 'wire_CRV')) curveDrv.translateX.set(segments * 0.5) wireDef = pm.wire(surfaceRbn_BS,w=curveDrv,en=1,gw=False,ce=0, li=0, dds = [0,20], n=name.replace('srf','wire')) #kind of a hack wireDefBase = wireDef[0].baseWire[0].listConnections(d=False,s=True) curveCLS,clsGrp = self.bdClustersOnCurve(curveDrv,segments) for i in range(3): locatorsRbn[i].translate.connect(curveCLS[i].translate) #organize a bit moveGrp = pm.group([conGrp,surfaceRbn],name=name.replace('srf','move_GRP')) extraGrp = pm.group([flcGrp,surfaceRbn_BS,clsGrp,curveDrv,wireDefBase],name = name.replace('srf','extra_GRP')) allGrp = pm.group([moveGrp,extraGrp],name = name.replace('srf','RBN')) self.bdFlcScaleCnstr(moveGrp,flcGrp) globalCon = pm.spaceLocator() globalCon.rename(name.replace("srf",'world_CON')) pm.parent(globalCon,allGrp) pm.parent(moveGrp,globalCon) self.bdCreateJoints(flcGrp) twistDef, twistDefTransform = self.bdAddTwist(surfaceRbn_BS) pm.parent(twistDefTransform, extraGrp) topLocator.rotateY.connect(twistDef.startAngle) botLocator.rotateY.connect(twistDef.endAngle) pm.reorderDeformers(wireDef[0],twistDef,surfaceRbn_BS)
def doRig(self): cnstrGrp = pm.group(em=True, n=self.name + 'EyeLid_constrained_grp') sysGrp = pm.group(em=True, n=self.name + 'EyeLidSys_grp') crvsGrp = pm.group(em=True, n=self.name + 'Curves_grp') clsGrp = pm.group(em=True, n=self.name + 'Clusters_grp') jntGrp = pm.group(em=True, n=self.name + 'Joints_grp') locGrp = pm.group(em=True, n=self.name + 'Locators_grp') if pm.objExists('head_contrained'): constrained_grp = 'head_contrained' else: constrained_grp = pm.group(n='head_contrained', em=True) pm.parent(crvsGrp, clsGrp, jntGrp, locGrp, sysGrp) sysGrp.visibility.set(False) pm.delete(self.upCtrlCrv, self.lowCtrlCrv, ch=True) self.upEdgeLoop = selectLoopByLocators(mesh=self.mesh, loc1=self.inCorner, loc2=self.outCorner, loc3=self.upCorner) pm.select(self.upEdgeLoop) upCrv = pm.polyToCurve(form=2, degree=1, n=self.name + 'UpperCrv', ch=False)[0] self.upCrv = pm.rebuildCurve(upCrv, rt=3, rpo=True, d=3, end=1, kr=0, kcp=1, kep=0, kt=0, s=25, tol=0.01, ch=False)[0] if not atStart(loc=self.inCorner, crvName=self.upCrv): pm.reverseCurve(self.upCrv, ch=False, replaceOriginal=True) self.lowEdgeLoop = selectLoopByLocators(mesh=self.mesh, loc1=self.inCorner, loc2=self.outCorner, loc3=self.lowCorner) pm.select(self.lowEdgeLoop) lowCrv = pm.polyToCurve(form=2, degree=1, n=self.name + 'LowerCrv', ch=False)[0] self.lowCrv = pm.rebuildCurve(lowCrv, rt=3, rpo=True, d=3, end=1, kr=0, kcp=1, kep=0, kt=0, s=25, tol=0.01, ch=False)[0] if not atStart(loc=self.inCorner, crvName=self.lowCrv): pm.reverseCurve(self.lowCrv, ch=False, replaceOriginal=True) upBlink = pm.rebuildCurve(self.upCrv, s=20, rt=0, rpo=False, ch=False, n=self.name + 'upBlink')[0] lowBlink = pm.rebuildCurve(self.lowCrv, s=20, rt=0, rpo=False, ch=False, n=self.name + 'lowBlink')[0] upTarget = pm.rebuildCurve(self.upCrv, s=20, rt=0, rpo=False, ch=False, n=self.name + 'upTarget')[0] lowTarget = pm.rebuildCurve(self.lowCrv, s=20, rt=0, rpo=False, ch=False, n=self.name + 'lowTarget')[0] midTarget = pm.rebuildCurve(self.lowCrv, s=20, rt=0, rpo=False, ch=False, n=self.name + 'midTarget')[0] pm.parent(upTarget, lowTarget, midTarget, lowBlink, upBlink, self.upCtrlCrv, self.lowCtrlCrv, self.upCrv, self.lowCrv, crvsGrp) w1 = pm.wire(self.upCrv, w=upBlink)[0] w2 = pm.wire(self.lowCrv, w=lowBlink)[0] w3 = pm.wire(upTarget, w=self.upCtrlCrv)[0] w4 = pm.wire(lowTarget, w=self.lowCtrlCrv)[0] bs_upBlink = pm.blendShape(upTarget, midTarget, upBlink, n=self.name + "blendShapeUpBlink") bs_lowBlink = pm.blendShape(lowTarget, midTarget, lowBlink, n=self.name + "blendShapeLowBlink") bs_mid = pm.blendShape(lowTarget, upTarget, midTarget, n=self.name + "blendShapeLowBlink") # setting blendshape reverse connections rev_node = pm.createNode("reverse") pm.connectAttr(bs_upBlink[0].attr(midTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", bs_upBlink[0].attr(upTarget.name())) rev_node = pm.createNode("reverse") pm.connectAttr(bs_lowBlink[0].attr(midTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", bs_lowBlink[0].attr(lowTarget.name())) rev_node = pm.createNode("reverse") pm.connectAttr(bs_mid[0].attr(upTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", bs_mid[0].attr(lowTarget.name())) # setting default values bs_mid[0].attr(upTarget.name()).set(.3) cvsUp = self.upCtrlCrv.getCVs(space="world") cvsLow = self.lowCtrlCrv.getCVs(space="world") upCtrls = [] lowCtrls = [] cornerCtrls = [] for i in range(1, 4): pos = cvsUp[i] clsUp = pm.cluster(self.upCtrlCrv.cv[i], n=self.name + 'ClsUp' + str(i))[1] pm.group() rp = pm.xform(clsUp, q=True, rp=True, ws=True) grp = pm.group(em=True, n=clsUp.name() + 'off1_grp') pm.xform(grp, t=rp, ws=True) grp1 = pm.duplicate(grp, n=clsUp.name() + 'off2_grp')[0] pm.parent(grp, grp1) pm.parent(clsUp.getParent(), grp) pm.parent(grp1, clsGrp) ctrlUp = controlTools.cntrlCrv(name=self.name + 'EyeLidUp' + str(i), obj=clsUp, connType='connection', hasZeroGrp=True, cntrlSulfix='_ctrl', icone='circuloZ', size=.1, offsets=1) ctrlUp.getParent().translate >> grp.translate ctrlUp.getParent().rotate >> grp.rotate ctrlUp.getParent().scale >> grp.scale pm.xform(ctrlUp.getParent(2), ws=True, t=pos) pm.parent(ctrlUp.getParent(2), cnstrGrp) upCtrls.append(ctrlUp) pos = cvsLow[i] clsLow = pm.cluster(self.lowCtrlCrv.cv[i], n=self.name + 'ClsLow' + str(i))[1] pm.group() rp = pm.xform(clsLow, q=True, rp=True, ws=True) grp = pm.group(em=True, n=clsLow.name() + 'off1_grp') pm.xform(grp, t=rp, ws=True) grp1 = pm.duplicate(grp, n=clsLow.name() + 'off2_grp')[0] pm.parent(grp, grp1) pm.parent(clsLow.getParent(), grp) pm.parent(grp1, clsGrp) ctrlLow = controlTools.cntrlCrv(name=self.name + 'EyeLidLow' + str(i), obj=clsLow, connType='connection', hasZeroGrp=True, cntrlSulfix='_ctrl', icone='circuloZ', size=.1, offsets=1) ctrlLow.getParent().translate >> grp.translate ctrlLow.getParent().rotate >> grp.rotate ctrlLow.getParent().scale >> grp.scale pm.xform(ctrlLow.getParent(2), ws=True, t=pos) pm.parent(ctrlLow.getParent(2), cnstrGrp) lowCtrls.append(ctrlLow) for i in [0, 4]: pos = cvsUp[i] clsCorner = pm.cluster(self.upCtrlCrv.cv[i], self.lowCtrlCrv.cv[i], n=self.name + 'ClsCorner' + str(i))[1] pm.group() rp = pm.xform(clsCorner, q=True, rp=True, ws=True) grp = pm.group(em=True, n=clsCorner.name() + 'off1_grp') pm.xform(grp, t=rp, ws=True) grp1 = pm.duplicate(grp, n=clsCorner.name() + 'off2_grp')[0] pm.parent(grp, grp1) pm.parent(clsCorner.getParent(), grp) pm.parent(grp1, clsGrp) ctrlCorner = controlTools.cntrlCrv(name=self.name + 'EyeLidCorner' + str(i), obj=clsCorner, connType='connection', hasZeroGrp=True, cntrlSulfix='_ctrl', icone='circuloZ', size=.1, offsets=1) pm.xform(ctrlCorner.getParent(2), ws=True, t=pos) pm.parent(ctrlCorner.getParent(2), cnstrGrp) cornerCtrls.append(ctrlCorner) upCrvNode = pm.PyNode(self.upCrv) lowCrvNode = pm.PyNode(self.lowCrv) centerPos = pm.xform(self.eyeCenter, q=True, ws=True, t=True) cvs = upCrvNode.getCVs(space="world") aimLocs = [] for i, pos in enumerate(cvs): pm.select(cl=True) jntBase = pm.joint(p=centerPos, n=self.name + 'EyelidUp_' + str(i) + '_zero') jnt = pm.joint(p=pos, n=self.name + 'EyelidUp_' + str(i) + '_jnt') self.skinJoints.append(jnt.name()) pm.joint(jntBase, e=True, zso=True, oj='xyz', sao='yup') pm.parent(jntBase, jntGrp) loc = pm.spaceLocator(p=[0, 0, 0], n=jnt.name() + 'UpAim_loc') loc.translate.set(pos) loc.localScale.set(.01, .01, .01) pm.aimConstraint(loc, jntBase, aim=(1, 0, 0), u=(0, 1, 0), wut='vector', wu=(0, 1, 0)) pm.parent(loc, locGrp) aimLocs.append(loc) pm.select(aimLocs, self.upCrv) attachTools.hookOnCurve(tangent=False) cvs = lowCrvNode.getCVs(space="world") aimLocs = [] for i, pos in enumerate(cvs): pm.select(cl=True) jntBase = pm.joint(p=centerPos, n=self.name + 'EyelidLw_' + str(i) + '_zero') jnt = pm.joint(p=pos, n=self.name + 'EyelidLw_' + str(i) + '_jnt') self.skinJoints.append(jnt.name()) pm.joint(jntBase, e=True, zso=True, oj='xyz', sao='yup') pm.parent(jntBase, jntGrp) loc = pm.spaceLocator(p=[0, 0, 0], n=jnt.name() + 'LwAim_loc') loc.translate.set(pos) loc.localScale.set(.01, .01, .01) pm.aimConstraint(loc, jntBase, aim=(1, 0, 0), u=(0, 1, 0), wut='vector', wu=(0, 1, 0)) pm.parent(loc, locGrp) aimLocs.append(loc) pm.select(aimLocs, self.lowCrv) attachTools.hookOnCurve(tangent=False) pm.parentConstraint(upCtrls[1], cornerCtrls[0], upCtrls[0].getParent(), mo=1) pm.parentConstraint(upCtrls[1], cornerCtrls[1], upCtrls[2].getParent(), mo=1) pm.parentConstraint(lowCtrls[1], cornerCtrls[0], lowCtrls[0].getParent(), mo=1) pm.parentConstraint(lowCtrls[1], cornerCtrls[1], lowCtrls[2].getParent(), mo=1) up_ctl = upCtrls[1] pm.addAttr(up_ctl, ln="blink", at="float", dv=0, minValue=0, maxValue=1, k=True) pm.addAttr(up_ctl, ln="blinkMult", at="float", dv=1, minValue=1, maxValue=2, k=True) pm.addAttr(up_ctl, ln="blinkHeight", at="float", dv=0.3, minValue=0, maxValue=1, k=True) pm.addAttr(up_ctl, ln="fleshyEye", at="float", dv=0.5, minValue=0, maxValue=1, k=True) fleshyEye_loc = pm.spaceLocator(n=self.name + 'FleshyEye_loc') fleshyEye_loc.visibility.set(0) pm.parent(fleshyEye_loc, cnstrGrp) pm.xform(fleshyEye_loc, t=centerPos, ws=True) pm.parentConstraint(fleshyEye_loc, upCtrls[1].getParent(), mo=1) pm.parentConstraint(fleshyEye_loc, lowCtrls[1].getParent(), mo=1) fleshyEyeMulti = pm.createNode('multiplyDivide', name=self.name + 'multiFleshy') fleshyEyeMulti.output.outputX >> fleshyEye_loc.rotate.rotateX fleshyEyeMulti.output.outputY >> fleshyEye_loc.rotate.rotateY fleshyEyeMulti.output.outputZ >> fleshyEye_loc.rotate.rotateZ up_ctl.fleshyEye >> fleshyEyeMulti.input2.input2X up_ctl.fleshyEye >> fleshyEyeMulti.input2.input2Y up_ctl.fleshyEye >> fleshyEyeMulti.input2.input2Z mult_node = pm.createNode('multDoubleLinear', name=self.name + 'multBlink') up_ctl.blink >> mult_node.input1 up_ctl.blinkMult >> mult_node.input2 mult_node.output >> bs_upBlink[0].attr(midTarget.name()) mult_node.output >> bs_lowBlink[0].attr(midTarget.name()) up_ctl.blinkHeight >> bs_mid[0].attr(upTarget.name()) reverse_node = pm.createNode('reverse', name=self.name + 'blinkReverse') up_ctl.blink >> reverse_node.inputX reverse_node.outputX >> w1.scale[0] reverse_node.outputX >> w2.scale[0] reverse_node.outputX >> w3.scale[0] reverse_node.outputX >> w4.scale[0] self.guideMoveall.visibility.set(0) pm.parent(cnstrGrp, constrained_grp)
def build_phase_2(self): if self.head_controller is None: self.show_warning("Make sure you've set a head controller!") return # there's a chance that the user doesn't run the entire script at once # so for phase 2 we're just find the curves again by the special attribute they received when they were made # It's not the prettiest way, but it works self.do_not_touch_group = pm.PyNode("DO_NOT_TOUCH") self.side_prefix = str(self.ui.cb_side_prefix.currentText()) eyelid_deformer_curve_group = pm.PyNode( "%s_eyelid_deformer_curve_group" % self.side_prefix) high_res_curve_up = None high_res_curve_down = None low_res_curve_up = None low_res_curve_down = None for node in pm.ls(type="transform"): if node.hasAttr("eyelidCurve"): if "high" in node.eyelidCurve.get( ) and self.side_prefix in node.eyelidCurve.get(): if "up" in node.eyelidCurve.get(): high_res_curve_up = node else: high_res_curve_down = node if "low" in node.eyelidCurve.get( ) and self.side_prefix in node.eyelidCurve.get(): if "up" in node.eyelidCurve.get(): low_res_curve_up = node else: low_res_curve_down = node # apply wire deformer to high res curves pm.wire(high_res_curve_up, groupWithBase=False, envelope=1, crossingEffect=0, localInfluence=0, wire=low_res_curve_up.name()) pm.wire(high_res_curve_down, groupWithBase=False, envelope=1, crossingEffect=0, localInfluence=0, wire=low_res_curve_down.name()) # make a list of the main lid controllers # these are the two controllers in the middle of the upper and lower eyelid that will hold the blink attribute main_lid_controllers = [] # make a list for the constrain controllers # these are the controllers on the edge of the eye, and on top and bottom, that are needed to constrain the helper controllers # that sit between them # 0 = corner at nose, 1 = main controller on top of eye, 2 = corner at outer edge of eye, 3 = main controller at the bottom of eye constrain_controllers = [] # make a list for the constrained groups on the helper controllers # these controllers sit between the corners and the main controllers # they each have a group called constrained in their hierarchy that we're going to constrain # that way we still have a driven group that we can use for automation (like moving the lids when the eye look up, down, left or right) # and we can still grab the controller itself to make adjustments # 0 = between corner at nose and top main, 1 = between top main and corner at edge # 2 = between corner at nose and bottom main, 3 = between bottom main and corner at edge helper_constrained_groups = [] # get the position for the controls joints of the low res curve, skin the low res curves to these joints # also create the controllers and have them constrain the joints for the low res curve pm.select(None) eye_controller_group = pm.group(name="%s_eye_controller_group" % self.side_prefix) pm.select(None) eye_controller_joint_group = pm.group( name="%s_eye_controller_joint_group" % self.side_prefix) #eye_controller_joint_group.visibility.set(False) control_joints_1 = [] for index, cv_location in enumerate(low_res_curve_up.getCVs()): pm.select(None) jnt = pm.joint(name="%s_eyelid_control_joint_%02d" % (self.side_prefix, index), position=cv_location, radius=self.ui.spin_joint_size.value()) control_joints_1.append(jnt) controller = pm.circle(normal=[0, 0, 1], name="%s_eyelid_%02d_controller" % (self.side_prefix, index))[0] driven = pm.group(controller, name=controller.name().replace( "controller", "driven")) constrained = pm.group(driven, name=driven.name().replace( "driven", "constrained")) offset = pm.group(constrained, name=constrained.replace("constrained", "offset")) offset.setTranslation(cv_location) offset.setScale((self.joint_radius * 10, self.joint_radius * 10, self.joint_radius * 10)) if self.ui.chk_flip_controller_orientation.isChecked(): print "Flipping offset group 180 degrees." offset.setRotation([0, 180, 0]) pm.parentConstraint(controller, jnt, maintainOffset=True) pm.parent(offset, eye_controller_group) if index == 2: main_lid_controllers.append(controller) self.lock_and_hide_attributes(controller, ["sx", "sy", "sz"]) if index == 0 or index == 2 or index == 4: constrain_controllers.append(controller) self.lock_and_hide_attributes(controller, ["sx", "sy", "sz"]) if index == 1 or index == 3: helper_constrained_groups.append(constrained) self.lock_and_hide_attributes( controller, ["sx", "sy", "sz", "rx", "ry", "rz"]) pm.parent(jnt, eye_controller_joint_group) pm.skinCluster(control_joints_1, low_res_curve_up, toSelectedBones=True) control_joints_2 = [] for index, cv_location in enumerate(low_res_curve_down.getCVs()): if index == 1 or index == 2 or index == 3: pm.select(None) jnt = pm.joint(name="%s_eyelid_control_joint_%02d" % (self.side_prefix, index + 5), position=cv_location, radius=self.ui.spin_joint_size.value()) control_joints_2.append(jnt) controller = pm.circle(normal=[0, 0, 1], name="%s_eyelid_%02d_controller" % (self.side_prefix, index + 5))[0] driven = pm.group(controller, name=controller.name().replace( "controller", "driven")) constrained = pm.group(driven, name=driven.name().replace( "driven", "constrained")) offset = pm.group(constrained, name=constrained.replace( "constrained", "offset")) offset.setTranslation(cv_location) offset.setScale( (self.joint_radius * 10, self.joint_radius * 10, self.joint_radius * 10)) pm.parentConstraint(controller, jnt, maintainOffset=True) pm.parent(offset, eye_controller_group) if index == 2: main_lid_controllers.append(controller) constrain_controllers.append(controller) self.lock_and_hide_attributes(controller, ["sx", "sy", "sz"]) if index == 1 or index == 3: helper_constrained_groups.append(constrained) self.lock_and_hide_attributes( controller, ["sx", "sy", "sz", "rx", "ry", "rz"]) pm.parent(jnt, eye_controller_joint_group) pm.skinCluster(control_joints_2, control_joints_1[0], control_joints_1[-1], low_res_curve_down, toSelectedBones=True) #constrain the inbetween helper constrain groups to the 4 main controllers on the edges and top and top bottom of the eye pm.parentConstraint(constrain_controllers[0], constrain_controllers[1], helper_constrained_groups[0], maintainOffset=True) pm.parentConstraint(constrain_controllers[1], constrain_controllers[2], helper_constrained_groups[1], maintainOffset=True) pm.parentConstraint(constrain_controllers[0], constrain_controllers[3], helper_constrained_groups[2], maintainOffset=True) pm.parentConstraint(constrain_controllers[3], constrain_controllers[2], helper_constrained_groups[3], maintainOffset=True) # Blinking # # set up the blink height blink_height_curve = pm.duplicate(low_res_curve_up, name="%s_blink_height_curve" % self.side_prefix)[0] blink_height_blend_shape = pm.blendShape( low_res_curve_down, low_res_curve_up, blink_height_curve, name="%s_blink_height_shapes" % self.side_prefix) for index, controller in enumerate(main_lid_controllers): if index == 0: self.add_attribute(controller, "blink_height", 0, type="float") self.add_attribute(controller, "blink", 0, type="float") pm.connectAttr( "%s.blink_height" % main_lid_controllers[0].name(), "%s_blink_height_shapes.%s" % (self.side_prefix, low_res_curve_down.name())) reverse_node = pm.createNode("reverse", name="%s_eye_blink_reverse" % self.side_prefix) pm.connectAttr("%s.blink_height" % main_lid_controllers[0].name(), "%s.inputX" % reverse_node.name()) pm.connectAttr( "%s.outputX" % reverse_node.name(), "%s_blink_height_shapes.%s" % (self.side_prefix, low_res_curve_up.name())) #set up the blink high_res_blink_curve_up = pm.duplicate( high_res_curve_up, name="%s_up_eyelid_high_blink_curve" % self.side_prefix)[0] high_res_blink_curve_down = pm.duplicate( high_res_curve_down, name="%s_down_eye_high_blink_curve" % self.side_prefix)[0] main_lid_controllers[0].blink_height.set(0) up_blink_wire_deformer = pm.wire(high_res_blink_curve_up, groupWithBase=False, envelope=1, crossingEffect=0, localInfluence=0, wire=blink_height_curve.name())[0] main_lid_controllers[0].blink_height.set(1) low_blink_wire_deformer = pm.wire(high_res_blink_curve_down, groupWithBase=False, envelope=1, crossingEffect=0, localInfluence=0, wire=blink_height_curve.name())[0] main_lid_controllers[0].blink_height.set(0) up_blink_wire_deformer.setWireScale(0, 0) low_blink_wire_deformer.setWireScale(0, 0) blink_up_blend_shape = pm.blendShape(high_res_blink_curve_up, high_res_curve_up, name="%s_up_blink_shapes" % self.side_prefix) blink_down_blend_shape = pm.blendShape(high_res_blink_curve_down, high_res_curve_down, name="%s_down_blink_shapes" % self.side_prefix) pm.connectAttr( "%s.blink" % main_lid_controllers[0], "%s_up_blink_shapes.%s" % (self.side_prefix, high_res_blink_curve_up.name())) pm.connectAttr( "%s.blink" % main_lid_controllers[1], "%s_down_blink_shapes.%s" % (self.side_prefix, high_res_blink_curve_down.name())) pm.parent(eye_controller_group, self.head_controller) pm.parent(eye_controller_joint_group, self.do_not_touch_group) self.show_success_message("Phase 2 built successfully!") return "success"
def doRig(self): nurbsSurf = pm.nurbsPlane(p=(0, 0, 0), ax=(0, 1, 0), w=self.width, lr=0.1, d=3, u=self.div, v=1, ch=0, n=self.flexName + 'FlexNurbsSrf')[0] nurbsSurf.visibility.set(False) nurbsSurf.translate.set(self.width / 2, 0, 0) spacing = 1.0 / float(self.div) start = spacing / 2.0 grp1 = pm.group(n=self.flexName + 'Folicules_grp', empty=True) grp2 = pm.group(em=True, n=self.flexName + 'ribbonGlobalMove') grp3 = pm.group(em=True, n=self.flexName + 'FlexNoMove') for i in range(int(self.div)): foll = self.createFoll(self.flexName + 'Follicle' + str('%02d' % i), nurbsSurf, start + spacing * i, 0.5) jnt1 = pm.joint(p=(0, 0, 0), n=self.flexName + str('%02d' % i) + '_jnt') pm.move(0, 0, 0, jnt1, ls=True) pm.parent(foll, grp1) nurbsSurfBlend = pm.nurbsPlane(p=(0, 0, 0), ax=(0, 1, 0), w=self.width, lr=0.1, d=3, u=self.div, v=1, ch=0, n=self.flexName + 'FlexBlendNurbsSrf')[0] nurbsSurfBlend.translate.set(self.width / 2, 0, 0) pm.blendShape(nurbsSurfBlend, nurbsSurf, frontOfChain=True, tc=0, w=(0, 1)) crv = pm.curve(d=2, p=[((self.width * -0.5), 0, 0), (0, 0, 0), ((self.width * 0.5), 0, 0)], k=[0, 0, 1, 1], n=self.flexName + 'Crv') crv.translate.set(self.width / 2, 0, 0) cls1 = pm.cluster(crv + '.cv[0]', crv + '.cv[1]', rel=True, n=self.flexName + 'Cls1') pm.move((self.width * -0.5), 0, 0, cls1[1] + '.scalePivot', cls1[1] + '.rotatePivot') cls2 = pm.cluster(crv + '.cv[2]', crv + '.cv[1]', rel=True, n=self.flexName + 'Cls2') pm.move((self.width * 0.5), 0, 0, cls2[1] + '.scalePivot', cls2[1] + '.rotatePivot') cls3 = pm.cluster(crv + '.cv[1]', rel=True, n=self.flexName + 'Cls3') pm.percent(cls1[0], crv + '.cv[1]', v=0.5) pm.percent(cls2[0], crv + '.cv[1]', v=0.5) twist = pm.nonLinear(nurbsSurfBlend, type='twist', n=self.flexName + 'Twist') twist[1].rotate.set(0, 0, 90) wir = pm.wire(nurbsSurfBlend, gw=False, en=1.000000, ce=0.000000, li=0.000000, w=crv, dds=(0, 20)) wireNode = pm.PyNode(wir[0]) baseWire = [x for x in wireNode.connections() if 'BaseWire' in x.name()] cntrl1 = controlTools.cntrlCrv(name=self.flexName + 'aux1', icone='grp') cntrl2 = controlTools.cntrlCrv(name=self.flexName + 'aux2', icone='grp') cntrl3 = controlTools.cntrlCrv(name=self.flexName + 'aux3', icone='grp') pos = pm.pointOnSurface(nurbsSurfBlend, u=0.0, v=0.5) cntrl1.getParent().translate.set(pos) pos = pm.pointOnSurface(nurbsSurfBlend, u=1.0, v=0.5) cntrl2.getParent().translate.set(pos) pos = pm.pointOnSurface(nurbsSurfBlend, u=0.5, v=0.5) cntrl3.getParent().translate.set(pos) cntrl1.addAttr('twist', at='float', dv=0, k=1) cntrl2.addAttr('twist', at='float', dv=0, k=1) pm.pointConstraint(cntrl1, cntrl2, cntrl3.getParent()) cntrl1.translate >> cls1[1].translate cntrl2.translate >> cls2[1].translate cntrl3.translate >> cls3[1].translate cntrl2.twist >> twist[0].startAngle cntrl1.twist >> twist[0].endAngle pm.parent(nurbsSurf, cntrl1.getParent(), cntrl2.getParent(), cntrl3.getParent(), grp2) pm.parent(grp1, nurbsSurfBlend, cls1[1], cls2[1], cls3[1], baseWire, crv, twist[1], grp3) pm.setAttr(grp3 + '.visibility', 0) # pm.group (grp1,grp2,grp3,n=self.flexName+'Flex_grp') # implementar squash/stretch # implementar o connect to limb
avgPos.output3D >> cv2 # this method will hinge on which surface is the .inputSurface for various surface nodes # preclamped CPOS: pre-wire surf # clamped dynPosi: post-wire surf surfs = list(set(j.rangeU.inputs()[0].surface.get() for j in jnts)) for s in surfs: targs = [ o for o in s.ws.outputs(plugs=True) + s.local.outputs(plugs=True) if "dynposi" not in o.name()] src = s.create.inputs(plugs=True)[0] for t in targs: src >> t wire = pmc.wire(surfs)[0] openCurve.l >> wire.baseWire[0] closedCurve.l >> wire.deformedWire[0] bd = surfs[0].blendDriver.inputs(shapes=True)[0] bd.addAttr("stickyLipsStrength", min=0.0, max=1.0, k=True) bd.addAttr("stickyLipsParam", min=0.0, max=1.0, k=True) bd.stickyLipsParam >> wire.wireLocatorParameter[0] bd.stickyLipsStrength >> wire.wireLocatorPercentage[0] pmc.select(wire) # base 0 means these are overlapping pmc.select(closedCurve.u[.25]) pmc.select(closedCurve.u[.625]) # simplify input param to 0.0-0.5 since it loops around # but wait, f**k, the parameter is applied to the initial curve,
def doRig(self): anchorList = [] cntrlList = [] locList = [] offCtrlLoc=[] offAuxLoc = [] dummyCrv = self.ribbonDict['moveallSetup']['nameTempl']+'_dummy_crv' pm.hide(pm.polyCube(n=dummyCrv)) if pm.objExists(self.ribbonDict['moveallSetup']['nameTempl']): pm.delete(self.ribbonDict['moveallSetup']['nameTempl']) if pm.objExists(self.ribbonDict['noMoveSetup']['nameTempl']): pm.delete(self.ribbonDict['noMoveSetup']['nameTempl']) ###Estrutura que nao deve ter transformacao noMoveSpace = pm.group(empty=True, n=self.ribbonDict['noMoveSetup']['nameTempl']) if not pm.objExists('NOMOVE'): pm.group(self.ribbonDict['noMoveSetup']['nameTempl'], n='NOMOVE') else: pm.parent(self.ribbonDict['noMoveSetup']['nameTempl'], 'NOMOVE') pm.parent(self.ribbonDict['moveallSetup']['nameTempl']+'_dummy_crv', noMoveSpace) noMoveSpace.visibility.set(0) noMoveSpace.translate.set(self.size * -0.5, 0, 0) noMoveBend1 = pm.nurbsPlane(p=(self.size * -0.25, 0, 0), ax=(0, 0, 1), w=self.size * 0.5, lr=.1, d=3, u=5, v=1) noMoveBend2 = pm.nurbsPlane(p=(self.size * 0.25, 0, 0), ax=(0, 0, 1), w=self.size * 0.5, lr=.1, d=3, u=5, v=1) noMoveCrvJnt = pm.curve(bezier=True, d=3, p=[(self.size * -0.50, 0, 0), (self.size * -0.499, 0, 0), (self.size * -0.496, 0, 0), (self.size * -0.495, 0, 0), (self.size * -0.395, 0, 0), (self.size * -0.10, 0, 0), (0, 0, 0), (self.size * 0.10, 0, 0), (self.size * 0.395, 0, 0), (self.size * 0.495, 0, 0), (self.size * 0.496, 0, 0), (self.size * 0.499, 0, 0), (self.size * 0.50, 0, 0)], k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10]) noMoveCrvTweak1 = pm.curve(d=2, p=[(self.size * -0.5, 0, 0), (self.size * -0.25, 0, 0), (self.size * 0, 0, 0)], k=[0, 0, 1, 1]) noMoveCrvTweak2 = pm.curve(d=2, p=[(self.size * 0.0, 0, 0), (self.size * 0.25, 0, 0), (self.size * 0.50, 0, 0)], k=[0, 0, 1, 1]) # Deformers das superficies noMove twist1 = pm.nonLinear(noMoveBend1[0], type='twist') # twist das superficies noMove twist2 = pm.nonLinear(noMoveBend2[0], type='twist') twist1[1].rotateZ.set(90) twist2[1].rotateZ.set(90) wireTweak1 = pm.wire(noMoveBend1[0], w=noMoveCrvTweak1, dds=[(0, 50)]) wireTweak2 = pm.wire(noMoveBend2[0], w=noMoveCrvTweak2, dds=[(0, 50)]) wireDef = pm.wire(noMoveBend1[0], noMoveBend2[0], w=noMoveCrvJnt, dds=[(0, 50)]) # Wire das superficies noMove wireDef[0].rotation.set(1) # seta wire controlando rotacao baseWire = [x for x in wireDef[0].connections() if 'BaseWire' in x.name()] baseWireTweak1 = [x for x in wireTweak1[0].connections() if 'BaseWire' in x.name()] baseWireTweak2 = [x for x in wireTweak2[0].connections() if 'BaseWire' in x.name()] pm.group(baseWire, baseWireTweak1, baseWireTweak2, noMoveCrvJnt, noMoveCrvTweak1, noMoveCrvTweak2, noMoveBend1[0], noMoveBend2[0], p=noMoveSpace, n=self.name + 'Deforms') pm.parent(twist1[1], twist2[1], noMoveSpace) ###Estrutura que pode ser movida cntrlsSpace = pm.group(empty=True, n=self.ribbonDict['moveallSetup']['nameTempl']) cntrlsSpace.translate.set(self.size * -0.5, 0, 0) bendSurf1 = pm.nurbsPlane(p=(self.size * -0.25, 0, 0), ax=(0, 0, 1), w=self.size * 0.5, lr=.1, d=3, u=5, v=1) bendSurf2 = pm.nurbsPlane(p=(self.size * 0.25, 0, 0), ax=(0, 0, 1), w=self.size * 0.5, lr=.1, d=3, u=5, v=1) # blendShape transferindo as deformaacoes para a superficie move blend1 = pm.blendShape(noMoveBend1[0], bendSurf1[0]) blend2 = pm.blendShape(noMoveBend2[0], bendSurf2[0]) pm.blendShape(blend1, e=True, w=[(0, 1)]) pm.blendShape(blend2, e=True, w=[(0, 1)]) pm.parent(bendSurf1[0], bendSurf2[0], cntrlsSpace) ##Cntrls tweak1Cls = pm.cluster(noMoveCrvTweak1.name()+'.cv[1]') tweak2Cls = pm.cluster(noMoveCrvTweak2.name() + '.cv[1]') displaySetup = self.ribbonDict['ctrlTweakSetup'].copy() cntrlName = displaySetup['nameTempl'] + '1' cntrlTweak1 = controlTools.cntrlCrv(name=cntrlName, obj=tweak1Cls[1], connType='connection', align='pivot', offsets=1, **displaySetup) cntrlName = displaySetup['nameTempl'] + '2' cntrlTweak2 = controlTools.cntrlCrv(name=cntrlName, obj=tweak2Cls[1], connType='connection', align='pivot', offsets=1, **displaySetup) controlTools.addMultiply([cntrlTweak1.getParent(), cntrlTweak2.getParent()]) tweakFoll1 = self.attachObj(obj=cntrlTweak1.getParent(3), mesh=bendSurf1[0], u=0.5, v=0.5, mode=4) tweakFoll2 = self.attachObj(obj=cntrlTweak2.getParent(3), mesh=bendSurf2[0], u=0.5, v=0.5, mode=4) tweakGrp = pm.group(tweak1Cls[1], tweak2Cls[1], n=self.name+'TweakCls_grp') pm.parent(tweakGrp, noMoveSpace) pm.parent(cntrlTweak1.getParent(3), cntrlTweak2.getParent(3), cntrlsSpace) for i in range(0, 7): anchor = pm.cluster(noMoveCrvJnt.name() + '.cv[' + str(i + 3) + ']') pm.cluster(anchor[1], e=True, g=dummyCrv) clsHandle = anchor[1] anchorGrp = pm.group(em=True, n=self.name+'clusterGrp' + str(i)) anchorDrn = pm.group(em=True, n=self.name+'clusterDrn' + str(i), p=anchorGrp) pos = pm.xform(anchor[1], q=True, ws=True, rp=True) pm.xform(anchorGrp, t=pos, ws=True) pm.parent(anchor[1], anchorDrn) anchorList.append(anchor[1]) if i == 0 or i == 6: displaySetup = self.ribbonDict['cntrlSetup'].copy() cntrlName = displaySetup['nameTempl'] + str(i) cntrl = controlTools.cntrlCrv(name=cntrlName, obj=anchor[1], **displaySetup) elif i == 3: displaySetup = self.ribbonDict['midCntrlSetup'].copy() cntrlName = displaySetup['nameTempl'] + str(i) cntrl = controlTools.cntrlCrv(name=cntrlName, obj=anchor[1], **displaySetup) else: displaySetup = self.ribbonDict['cntrlTangSetup'].copy() cntrlName = displaySetup['nameTempl'] + str(i) cntrl = controlTools.cntrlCrv(name=cntrlName, obj=anchor[1], **displaySetup) offCtrlLoc.append(pm.spaceLocator(n=cntrlName+'off_loc')) offCtrlLoc[-1].localScale.set(0.2, 0.2, 0.2) pm.parent(offCtrlLoc[-1], cntrl, r=True) if i in [1, 2, 4, 5]: offCtrlLoc[-1].getShape().visibility.set(False) # Nao pode fazer conexao na criacao do controle, pois tera conexao direta pm.xform(cntrl.getParent(), t=pos, ws=True) # estrutura de buffers para conexao direta auxLocGrp = pm.group(em=True, n=self.name + 'Aux_grp') auxLoc = pm.group(em=True, p=auxLocGrp, n=self.name + str(i)+ 'Aux_loc') pm.xform(auxLocGrp, t=pos, ws=True) loc = pm.PyNode(auxLoc) if i==0 or i==3 or i==6: tmpOffAuxLoc = pm.group(em=True, n=self.name + str(i) + 'AuxOff_loc') offAuxLoc.append(tmpOffAuxLoc) pm.parent(tmpOffAuxLoc, auxLoc, r=True) offCtrlLoc[-1].translate >> offAuxLoc[-1].translate offCtrlLoc[-1].rotate >> offAuxLoc[-1].rotate if i == 1 or i == 4: pm.xform(anchorGrp, s=(-1, 1, 1), r=True) pm.xform(cntrl.getParent(), s=(-1, 1, 1), r=True) pm.xform(loc.getParent(), s=(-1, 1, 1), r=True) # Conexoes dos buffers cm os clusters e com os controles pm.parentConstraint(cntrl, loc, mo=True) loc.translate >> anchorDrn.translate loc.rotate >> anchorDrn.rotate cntrlList.append(cntrl) locList.append(loc) # workaround do flip do inicio do wire(adicao de mais pontos) startCls = pm.cluster(noMoveCrvJnt.name() + '.cv[0:2]') endCls = pm.cluster(noMoveCrvJnt.name() + '.cv[10:14]') pm.cluster(startCls[1], e=True, g=dummyCrv) pm.cluster(endCls[1], e=True, g=dummyCrv) pm.parent(startCls[1], anchorList[0]) pm.parent(endCls[1], anchorList[6]) cntrlsSpace.addAttr('midCtrlViz', at='double', dv=1, max=1, min=0, k=True, h=False) cntrlsSpace.addAttr('bezierCtrlViz', at='double', dv=1,max=1, min=0, k=True, h=False) cntrlsSpace.addAttr('bendExtraCtrlViz', at='double',max=1, min=0, dv=1, k=True, h=False) cntrlsSpace.addAttr('extraCtrlsVis', at='double', dv=0,max=1, min=0, k=True, h=False) cntrlList[0].addAttr('twist', at='double', dv=0, k=True) cntrlList[0].addAttr('stretchDist', at='double', dv=0, k=True) cntrlList[0].addAttr('autoVolumStregth', at='double', dv=0, k=True) cntrlList[3].addAttr('twist', at='double', dv=0, k=True) cntrlList[3].addAttr('autoVolume', at='double', dv=0, k=True) cntrlList[6].addAttr('twist', at='double', dv=0, k=True) cntrlList[6].addAttr('stretchDist', at='double', dv=0, k=True) cntrlList[6].addAttr('autoVolumStregth', at='double', dv=0, k=True) cntrlList[0].twist >> twist1[0].endAngle cntrlList[3].twist >> twist1[0].startAngle cntrlList[3].twist >> twist2[0].endAngle cntrlList[6].twist >> twist2[0].startAngle # cria sistema do tweak pra compensar twist da ribbon tweak1Twist1Multi = pm.createNode('multDoubleLinear', name='tweak1Twist1Multi') tweak1Twist2Multi = pm.createNode('multDoubleLinear', name='tweak1Twist1Multi') tweak1Add = pm.createNode('addDoubleLinear', name='tweak1Add') tweak2Twist1Multi = pm.createNode('multDoubleLinear', name='tweak1Twist1Multi') tweak2Twist2Multi = pm.createNode('multDoubleLinear', name='tweak1Twist1Multi') tweak2Add = pm.createNode('addDoubleLinear', name='tweak1Add') cntrlList[0].twist >> tweak1Twist1Multi.input1 tweak1Twist1Multi.input2.set(-0.5) cntrlList[3].twist >> tweak1Twist2Multi.input1 tweak1Twist2Multi.input2.set (-0.5) tweak1Twist1Multi.output >> tweak1Add.input1 tweak1Twist2Multi.output >> tweak1Add.input2 tweak1Add.output >> cntrlTweak1.getParent(2).rotate.rotateX cntrlList[6].twist >> tweak2Twist1Multi.input1 tweak2Twist1Multi.input2.set(-0.5) cntrlList[3].twist >> tweak2Twist2Multi.input1 tweak2Twist2Multi.input2.set(-0.5) tweak2Twist1Multi.output >> tweak2Add.input1 tweak2Twist2Multi.output >> tweak2Add.input2 tweak2Add.output >> cntrlTweak2.getParent(2).rotate.rotateX # hierarquia pm.parent(anchorList[1].getParent(2), anchorList[0]) pm.parent(anchorList[5].getParent(2), anchorList[6]) pm.parent(anchorList[2].getParent(2), anchorList[4].getParent(2), anchorList[3]) pm.parent(cntrlList[1].getParent(), offCtrlLoc[0]) pm.parent(cntrlList[5].getParent(), offCtrlLoc[6]) pm.parent(cntrlList[2].getParent(), cntrlList[4].getParent(), offCtrlLoc[3]) pm.parent(cntrlList[3].getParent(), cntrlList[0].getParent(), cntrlList[6].getParent(), cntrlsSpace) pm.parent(locList[1].getParent(), offAuxLoc[0]) pm.parent(locList[5].getParent(), offAuxLoc[2]) pm.parent(locList[2].getParent(), locList[4].getParent(), offAuxLoc[1]) pm.parent(locList[3].getParent(), locList[0].getParent(), locList[6].getParent(), cntrlsSpace) pm.parent(anchorList[3].getParent(2), anchorList[0].getParent(2), anchorList[6].getParent(2), noMoveSpace) for i, j in zip([1, 2, 4, 5], [0, 3, 3, 6]): crv = pm.curve(d=1, p=[(1, 0, 0), (-1, 0, 0)], k=[0, 1]) crv.inheritsTransform.set(False) crv.template.set(True) offCtrlLoc[i].worldPosition[0] >> crv.getShape().controlPoints[0] offCtrlLoc[j].worldPosition[0] >> crv.getShape().controlPoints[1] pm.parent(crv, offCtrlLoc[i], r=True) # Skin joints do ribbon skinJntsGrp = pm.group(em=True, n=self.name + 'SkinJnts') follGrp = pm.group(em=True, n=self.name + 'Foll_grp') pm.parent(tweakFoll1, tweakFoll2, follGrp) # cria ramps para controlar o perfil de squash e stretch ramp1 = pm.createNode('ramp', n=self.name+'SquashRamp1') ramp1.attr('type').set(1) ramp2 = pm.createNode('ramp', n=self.name+'SquashRamp2') ramp2.attr('type').set(1) expre1 = "float $dummy = " + ramp1.name() + ".outAlpha;float $output[];float $color[];" expre2 = "float $dummy = " + ramp2.name() + ".outAlpha;float $output[];float $color[];" extraCntrlsGrp = pm.group(em=True, r=True, p=cntrlsSpace, n=self.name + 'ExtraCntrls') # loop pra fazer os colocar o numero escolhido de joints ao longo do ribbon. # cria tmb node tree pro squash/stretch # e controles extras vIncrement = float((1.0 - (self.offsetStart + self.offsetEnd)) / ((self.numJnts - 2) / 2.0)) for i in range(1, (self.numJnts / 2) + 1): # cria estrutura pra superficie 1 pm.select(cl=True) jntName = self.ribbonDict['jntSetup']['nameTempl'] + 'A' + str(i) + self.jntSulfix jnt1 = pm.joint(p=(0, 0, 0), n=jntName) self.skinJoints.append(jnt1) displaySetup = self.ribbonDict['cntrlExtraSetup'].copy() cntrlName = displaySetup['nameTempl'] + 'A' + str(i) cntrl1 = controlTools.cntrlCrv(name=cntrlName, obj=jnt1, connType='constraint', **displaySetup) # node tree blend1A = pm.createNode('blendTwoAttr', n=self.name+'VolumeBlend1A') blend1B = pm.createNode('blendTwoAttr', n=self.name+'VolumeBlend1B') gammaCorr1 = pm.createNode('gammaCorrect', n=self.name+'VolumeGamma1') cntrlList[0].attr('autoVolumStregth') >> gammaCorr1.gammaX cntrlList[0].attr('stretchDist') >> gammaCorr1.value.valueX blend1A.input[0].set(1) gammaCorr1.outValueX >> blend1A.input[1] blend1B.input[0].set(1) blend1A.output >> blend1B.input[1] cntrlList[3].attr ('autoVolume') >> blend1B.attributesBlender blend1B.output >> cntrl1.getParent().scaleY blend1B.output >> cntrl1.getParent().scaleZ # expressao que le a rampa para setar valores da escala de cada joint quando fizer squash/stretch expre1 = expre1 + "$color = `colorAtPoint -o RGB -u " + str( self.offsetStart + (i - 1) * vIncrement) + " -v 0.5 " + ramp1.name() + " `;$output[" + str( i) + "] = $color[0];" + blend1A.name() + ".attributesBlender=$output[" + str(i) + "];" # cria estrutura pra superficie 2 pm.select(cl=True) jntName = self.ribbonDict['jntSetup']['nameTempl'] + 'B' + str(i) + self.jntSulfix jnt2 = pm.joint(p=(0, 0, 0), n=jntName) self.skinJoints.append(jnt2) displaySetup = self.ribbonDict['cntrlExtraSetup'].copy() cntrlName = displaySetup['nameTempl'] + 'B' + str(i) cntrl2 = controlTools.cntrlCrv(name=cntrlName, connType='constraint', obj=jnt2, **displaySetup) # node tree blend2A = pm.createNode('blendTwoAttr', n=self.name+'VolumeBlend2A') blend2B = pm.createNode('blendTwoAttr', n=self.name+'VolumeBlend2B') gammaCorr2 = pm.createNode('gammaCorrect', n=self.name+'VolumeGamma2') cntrlList[6].attr('autoVolumStregth') >> gammaCorr2.gammaX cntrlList[6].attr('stretchDist') >> gammaCorr2.value.valueX blend2A.input[0].set(1) gammaCorr2.outValueX >> blend2A.input[1] blend2B.input[0].set(1) blend2A.output >> blend2B.input[1] cntrlList[3].attr('autoVolume') >> blend2B.attributesBlender blend2B.output >> cntrl2.getParent().scaleY blend2B.output >> cntrl2.getParent().scaleZ # expressao que le a rampa para setar valores da escala de cada joint quando fizer squash/stretch expre2 = expre2 + "$color = `colorAtPoint -o RGB -u " + str( self.offsetStart + (i - 1) * vIncrement) + " -v 0.5 " + ramp2.name() + " `;$output[" + str( i) + "] = $color[0];" + blend2A.name() + ".attributesBlender=$output[" + str(i) + "];" # prende joints nas supeficies com follicules foll1 = self.attachObj(cntrl1.getParent(), bendSurf1[0], self.offsetStart + (i - 1) * vIncrement, 0.5, 4) foll2 = self.attachObj(cntrl2.getParent(), bendSurf2[0], self.offsetStart + (i - 1) * vIncrement, 0.5, 4) pm.parent(cntrl1.getParent(), cntrl2.getParent(), extraCntrlsGrp) pm.parent(jnt1, jnt2, skinJntsGrp) pm.parent(foll1, foll2, follGrp) pm.select (cl=True) jntName = self.ribbonDict['jntSetup']['nameTempl'] +'Elbow' + self.jntSulfix elbowJnt = pm.joint(p=(0, 0, 0), n=jntName) pm.parent(elbowJnt, skinJntsGrp) elbowAuxFoll1 = self.createFoll(bendSurf1[0], 0.999, 0.5) elbowAuxFoll2 = self.createFoll(bendSurf2[0], 0.001, 0.5) pm.parent(elbowAuxFoll1, elbowAuxFoll2, follGrp) orientConstraint = pm.PyNode(pm.orientConstraint(elbowAuxFoll1, elbowAuxFoll2, elbowJnt, mo=False)) orientConstraint.interpType.set(2) pm.pointConstraint(cntrlList[3], elbowJnt, mo=False) # seta expressoes para so serem avaliadas por demanda pm.expression(s=expre1, ae=False, n=self.name+'Expression1') pm.expression(s=expre2, ae=False, n=self.name+'Expression2') pm.parent(skinJntsGrp, cntrlsSpace) pm.parent(follGrp, noMoveSpace) # hideCntrls pm.toggle(bendSurf1[0], bendSurf2[0], g=True) bendSurf1[0].visibility.set(0) bendSurf2[0].visibility.set (0) # skinJntsGrp.visibility.set(0) cntrlsSpace.extraCtrlsVis >> extraCntrlsGrp.visibility cntrlsSpace.bezierCtrlViz >> cntrlList[0].getParent().visibility cntrlsSpace.midCtrlViz >> cntrlList[3].getParent().visibility cntrlsSpace.bezierCtrlViz >> cntrlList[4].getParent().visibility cntrlsSpace.bezierCtrlViz >> cntrlList[2].getParent().visibility cntrlsSpace.bezierCtrlViz >> cntrlList[6].getParent().visibility cntrlsSpace.bendExtraCtrlViz >> cntrlTweak1.getParent().visibility cntrlsSpace.bendExtraCtrlViz >> cntrlTweak2.getParent().visibility # povoa ribbon Dict self.ribbonDict['name'] = 'bezierRibbon' self.ribbonDict['ribbonMoveAll'] = cntrlsSpace for i in range(0, 7): self.ribbonDict['cntrl' + str(i)] = cntrlList[i]
def ar_addWireTool(curve, mesh, orientSample=None): """ @ add wire from curve and add controller on each cv. Args: curve (str): wire curve. mesh (str): geometry. orientSample (str): sub controller orient aim point. Returns: bool. """ # convert parameters into PyNode. curve = pm.PyNode(curve) mesh = pm.PyNode(mesh) curveUpperGroup = curve.getParent() if not curveUpperGroup: ar_qui.ar_displayMessage( 'error', 'Please create upperGroup on the "%s".' % curve) return False curveShape = curve.getShape() if not curveShape: ar_qui.ar_displayMessage('error', '"%s" has no shape.' % curve) return False # press tab from down line. cvs = pm.ls(curve + '.cv[*]', fl=True) cls = None if not orientSample: cls = pm.cluster(cvs, n=curve + '_Cluster') orientSample = cls[1] # create root group. rootGrp = pm.createNode('transform', n='Wire_' + curve + '_RootGrp', ss=True) controllersGrp = pm.createNode('transform', n=curve + '_Ctrl_Grp', ss=True) jointsGrp = pm.createNode('transform', n=curve + '_Joints_Grp', ss=True) pm.parent(controllersGrp, jointsGrp, rootGrp) pm.select(cl=True) # create main Controller. mainCtrl = curve.duplicate(n=curve + '_MainCtrl')[0] mainCtrl.v.unlock() mainCtrl.v.set(1) # hide default curve. curve.v.unlock() curve.v.set(0) curve.v.lock() pm.parent(mainCtrl, w=True) mainCtrlExtraGrp = pm.createNode('transform', n=curve + '_MainCtrl_ExtraGrp') mainCtrlOffsetGrp = pm.createNode('transform', n=curve + '_MainCtrl_OffsetGrp') pm.parent(mainCtrlExtraGrp, mainCtrlOffsetGrp) pm.delete(pm.parentConstraint(curveUpperGroup, mainCtrlOffsetGrp)) pm.parent(mainCtrl, mainCtrlExtraGrp) # assign pivot and freeze transform main curve. pivPos = pm.xform(mainCtrlExtraGrp, q=True, ws=True, piv=True)[:3] pm.xform(mainCtrl, ws=True, piv=pivPos) pm.makeIdentity(mainCtrl, apply=True, t=1, r=1, s=1, n=0, pn=1) mainCtrl.setAttr('v', l=True, cb=False, k=False) # visibility attributes. pm.addAttr(mainCtrl, longName='visAttrs', at='enum', en='=====', k=True) mainCtrl.visAttrs.lock() pm.addAttr(mainCtrl, ln='clusterVis', at='bool', k=True) pm.addAttr(mainCtrl, ln='jointsVis', at='bool', k=True) pm.addAttr(mainCtrl, ln='subCtrlVis', at='bool', k=True, dv=True) # wire attributes. pm.addAttr(mainCtrl, ln='wireAttrs', at='enum', en='=====', k=True) mainCtrl.wireAttrs.lock() pm.addAttr(mainCtrl, ln='envelope', at='double', min=0, max=1, dv=1, k=True) pm.addAttr(mainCtrl, ln='dropoffDistance', at='double', min=0, dv=1, k=True) # ----------------------- # create joints on each cv. joints = [] for i, cv in enumerate(cvs): pm.select(cl=True) pos = pm.xform(cv, q=True, ws=True, t=True) jnt = pm.joint(p=pos, n=curve + '_' + str(i) + '_jt') joints.append(jnt) mainCtrl.jointsVis.connect(jnt.v) # x axis orient in center and create cluster and parent. for i in range(len(joints)): if i != len(cvs) - 1: pm.delete( pm.aimConstraint(orientSample, joints[i], o=[0, 0, 0], w=True, aim=[1, 0, 0], u=[0, 0, 1], wut="object", wuo=joints[i + 1])) else: pm.delete( pm.aimConstraint(orientSample, joints[i], o=[0, 0, 0], w=True, aim=[1, 0, 0], u=[0, 0, 1], wut="object", wuo=joints[0])) pm.makeIdentity(joints[i], a=True, t=1, r=1, s=1, n=0, pn=1) cvCls = pm.cluster(cvs[i], en=1, n=joints[i][:-2] + 'Cls') pm.parent(cvCls[1], joints[i]) mainCtrl.clusterVis.connect(cvCls[1].v, f=True) if cls: pm.delete(cls) # create controllers. for i in range(len(joints)): # create sub controller. controller = pm.modeling.curve(d=1, p=[[-0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [-0.5, -0.5, 0.5], [-0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [0.5, -0.5, -0.5], [0.5, -0.5, 0.5], [0.5, 0.5, 0.5], [0.5, 0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, -0.5, -0.5], [-0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [-0.5, 0.5, -0.5]], k=[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], n=joints[i] + '_CTRL') extraGroup = pm.createNode('transform', n=joints[i] + '_CTRL_ExtraGrp', ss=True) offsetGroup = pm.createNode('transform', n=joints[i] + '_CTRL_OffsetGrp', ss=True) # lock and hide unwanted attributes. mainCtrl.subCtrlVis.connect(offsetGroup.v) # controller.r.lock() controller.setAttr('rx', l=True, cb=False, k=False) controller.setAttr('ry', l=True, cb=False, k=False) controller.setAttr('rz', l=True, cb=False, k=False) controller.setAttr('sx', l=True, cb=False, k=False) controller.setAttr('sy', l=True, cb=False, k=False) controller.setAttr('sz', l=True, cb=False, k=False) controller.setAttr('v', l=True, cb=False, k=False) pm.parent(controller, extraGroup) pm.parent(extraGroup, offsetGroup) pm.delete(pm.parentConstraint(joints[i], offsetGroup)) pm.parent(offsetGroup, mainCtrl) pm.parentConstraint(controller, joints[i]) # parent all joints in joints grp. pm.parent(joints, jointsGrp) pm.parent(mainCtrlOffsetGrp, controllersGrp) # add Wire Tool on mesh. wireDeformer = pm.wire(mesh, gw=False, en=1.0, ce=0.0, li=0.0, w=curve, n='wire_' + curve) # connect wire attributes on main controller. mainCtrl.envelope.connect(wireDeformer[0].envelope, f=True) mainCtrl.dropoffDistance.connect(wireDeformer[0].dropoffDistance[0], f=True) ar_qui.ar_displayMessage('success', 'wire tool added successfully.') return True
def rig(edge_loop="", up_vertex="", low_vertex="", name_prefix="", thickness=0.3, do_skin=True, rigid_loops=5, falloff_loops=8, head_joint=None, jaw_joint=None, parent_node=None, control_name="ctl", upper_lip_ctl=None, lower_lip_ctl=None): ###### # Var ###### FRONT_OFFSET = .02 NB_ROPE = 15 ################## # Helper functions ################## def setName(name, side="C", idx=None): namesList = [name_prefix, side, name] if idx is not None: namesList[1] = side + str(idx) name = "_".join(namesList) return name ############### # Checkers ############## # Loop if edge_loop: try: edge_loop = [pm.PyNode(e) for e in edge_loop.split(",")] except pm.MayaNodeError: pm.displayWarning( "Some of the edges listed in edge loop can not be found") return else: pm.displayWarning("Please set the edge loop first") return # Vertex if up_vertex: try: up_vertex = pm.PyNode(up_vertex) except pm.MayaNodeError: pm.displayWarning("%s can not be found" % up_vertex) return else: pm.displayWarning("Please set the upper lip central vertex") return if low_vertex: try: low_vertex = pm.PyNode(low_vertex) except pm.MayaNodeError: pm.displayWarning("%s can not be found" % low_vertex) return else: pm.displayWarning("Please set the lower lip central vertex") return # skinnign data if do_skin: if not head_joint: pm.displayWarning("Please set the Head Jnt or unCheck Compute " "Topological Autoskin") return else: try: head_joint = pm.PyNode(head_joint) except pm.MayaNodeError: pm.displayWarning( "Head Joint: %s can not be found" % head_joint ) return if not jaw_joint: pm.displayWarning("Please set the Jaw Jnt or unCheck Compute " "Topological Autoskin") return else: try: jaw_joint = pm.PyNode(jaw_joint) except pm.MayaNodeError: pm.displayWarning("Jaw Joint: %s can not be found" % jaw_joint) return # check if the rig already exist in the current scene if pm.ls(setName("root")): pm.displayWarning("The object %s already exist in the scene. Please " "choose another name prefix" % setName("root")) return ##################### # Root creation ##################### lips_root = primitive.addTransform(None, setName("root")) lipsCrv_root = primitive.addTransform(lips_root, setName("crvs")) lipsRope_root = primitive.addTransform(lips_root, setName("rope")) ##################### # Geometry ##################### geo = pm.listRelatives(edge_loop[0], parent=True)[0] ##################### # Groups ##################### try: ctlSet = pm.PyNode("rig_controllers_grp") except pm.MayaNodeError: pm.sets(n="rig_controllers_grp", em=True) ctlSet = pm.PyNode("rig_controllers_grp") try: defset = pm.PyNode("rig_deformers_grp") except pm.MayaNodeError: pm.sets(n="rig_deformers_grp", em=True) defset = pm.PyNode("rig_deformers_grp") ##################### # Curves creation ##################### # get extreme position using the outer loop extr_v = meshNavigation.getExtremeVertexFromLoop(edge_loop) upPos = extr_v[0] lowPos = extr_v[1] inPos = extr_v[2] outPos = extr_v[3] edgeList = extr_v[4] vertexList = extr_v[5] upPos = up_vertex lowPos = low_vertex # upper crv upLip_edgeRange = meshNavigation.edgeRangeInLoopFromMid(edgeList, upPos, inPos, outPos) upCrv = curve.createCuveFromEdges(upLip_edgeRange, setName("upperLip"), parent=lipsCrv_root) # store the closest vertex by curv cv index. To be use fo the auto skining upLip_closestVtxList = [] # offset upper lip Curve cvs = upCrv.getCVs(space="world") for i, cv in enumerate(cvs): closestVtx = meshNavigation.getClosestVertexFromTransform(geo, cv) upLip_closestVtxList.append(closestVtx) if i == 0: # we know the curv starts from right to left offset = [cv[0] - thickness, cv[1], cv[2] - thickness] elif i == len(cvs) - 1: offset = [cv[0] + thickness, cv[1], cv[2] - thickness] else: offset = [cv[0], cv[1] + thickness, cv[2]] upCrv.setCV(i, offset, space='world') # lower crv lowLip_edgeRange = meshNavigation.edgeRangeInLoopFromMid(edgeList, lowPos, inPos, outPos) lowCrv = curve.createCuveFromEdges(lowLip_edgeRange, setName("lowerLip"), parent=lipsCrv_root) lowLip_closestVtxList = [] # offset lower lip Curve cvs = lowCrv.getCVs(space="world") for i, cv in enumerate(cvs): closestVtx = meshNavigation.getClosestVertexFromTransform(geo, cv) lowLip_closestVtxList.append(closestVtx) if i == 0: # we know the curv starts from right to left offset = [cv[0] - thickness, cv[1], cv[2] - thickness] elif i == len(cvs) - 1: offset = [cv[0] + thickness, cv[1], cv[2] - thickness] else: # we populate the closest vertext list here to skipt the first # and latest point offset = [cv[0], cv[1] - thickness, cv[2]] lowCrv.setCV(i, offset, space='world') upCrv_ctl = curve.createCurveFromCurve(upCrv, setName("upCtl_crv"), nbPoints=7, parent=lipsCrv_root) lowCrv_ctl = curve.createCurveFromCurve(lowCrv, setName("lowCtl_crv"), nbPoints=7, parent=lipsCrv_root) upRope = curve.createCurveFromCurve(upCrv, setName("upRope_crv"), nbPoints=NB_ROPE, parent=lipsCrv_root) lowRope = curve.createCurveFromCurve(lowCrv, setName("lowRope_crv"), nbPoints=NB_ROPE, parent=lipsCrv_root) upCrv_upv = curve.createCurveFromCurve(upCrv, setName("upCrv_upv"), nbPoints=7, parent=lipsCrv_root) lowCrv_upv = curve.createCurveFromCurve(lowCrv, setName("lowCrv_upv"), nbPoints=7, parent=lipsCrv_root) upRope_upv = curve.createCurveFromCurve(upCrv, setName("upRope_upv"), nbPoints=NB_ROPE, parent=lipsCrv_root) lowRope_upv = curve.createCurveFromCurve(lowCrv, setName("lowRope_upv"), nbPoints=NB_ROPE, parent=lipsCrv_root) # offset upv curves for crv in [upCrv_upv, lowCrv_upv, upRope_upv, lowRope_upv]: cvs = crv.getCVs(space="world") for i, cv in enumerate(cvs): # we populate the closest vertext list here to skipt the first # and latest point offset = [cv[0], cv[1], cv[2] + FRONT_OFFSET] crv.setCV(i, offset, space='world') rigCrvs = [upCrv, lowCrv, upCrv_ctl, lowCrv_ctl, upRope, lowRope, upCrv_upv, lowCrv_upv, upRope_upv, lowRope_upv] for crv in rigCrvs: crv.attr("visibility").set(False) ################## # Joints ################## lvlType = "transform" # upper joints upperJoints = [] cvs = upCrv.getCVs(space="world") pm.progressWindow(title='Creating Upper Joints', progress=0, max=len(cvs)) for i, cv in enumerate(cvs): pm.progressWindow(e=True, step=1, status='\nCreating Joint for %s' % cv) oTransUpV = pm.PyNode(pm.createNode( lvlType, n=setName("upLipRopeUpv", idx=str(i).zfill(3)), p=lipsRope_root, ss=True)) oTrans = pm.PyNode( pm.createNode(lvlType, n=setName("upLipRope", idx=str(i).zfill(3)), p=lipsRope_root, ss=True)) oParam, oLength = curve.getCurveParamAtPosition(upRope, cv) uLength = curve.findLenghtFromParam(upRope, oParam) u = uLength / oLength applyop.pathCns( oTransUpV, upRope_upv, cnsType=False, u=u, tangent=False) cns = applyop.pathCns( oTrans, upRope, cnsType=False, u=u, tangent=False) cns.setAttr("worldUpType", 1) cns.setAttr("frontAxis", 0) cns.setAttr("upAxis", 1) pm.connectAttr(oTransUpV.attr("worldMatrix[0]"), cns.attr("worldUpMatrix")) # getting joint parent if head_joint and isinstance(head_joint, (str, string_types)): try: j_parent = pm.PyNode(head_joint) except pm.MayaNodeError: j_parent = False elif head_joint and isinstance(head_joint, pm.PyNode): j_parent = head_joint else: j_parent = False jnt = rigbits.addJnt(oTrans, noReplace=True, parent=j_parent) upperJoints.append(jnt) pm.sets(defset, add=jnt) pm.progressWindow(e=True, endProgress=True) # lower joints lowerJoints = [] cvs = lowCrv.getCVs(space="world") pm.progressWindow(title='Creating Lower Joints', progress=0, max=len(cvs)) for i, cv in enumerate(cvs): pm.progressWindow(e=True, step=1, status='\nCreating Joint for %s' % cv) oTransUpV = pm.PyNode(pm.createNode( lvlType, n=setName("lowLipRopeUpv", idx=str(i).zfill(3)), p=lipsRope_root, ss=True)) oTrans = pm.PyNode(pm.createNode( lvlType, n=setName("lowLipRope", idx=str(i).zfill(3)), p=lipsRope_root, ss=True)) oParam, oLength = curve.getCurveParamAtPosition(lowRope, cv) uLength = curve.findLenghtFromParam(lowRope, oParam) u = uLength / oLength applyop.pathCns(oTransUpV, lowRope_upv, cnsType=False, u=u, tangent=False) cns = applyop.pathCns(oTrans, lowRope, cnsType=False, u=u, tangent=False) cns.setAttr("worldUpType", 1) cns.setAttr("frontAxis", 0) cns.setAttr("upAxis", 1) pm.connectAttr(oTransUpV.attr("worldMatrix[0]"), cns.attr("worldUpMatrix")) # getting joint parent if jaw_joint and isinstance(jaw_joint, (str, string_types)): try: j_parent = pm.PyNode(jaw_joint) except pm.MayaNodeError: pass elif jaw_joint and isinstance(jaw_joint, pm.PyNode): j_parent = jaw_joint else: j_parent = False jnt = rigbits.addJnt(oTrans, noReplace=True, parent=j_parent) lowerJoints.append(jnt) pm.sets(defset, add=jnt) pm.progressWindow(e=True, endProgress=True) ################## # Controls ################## # Controls lists upControls = [] upVec = [] upNpo = [] lowControls = [] lowVec = [] lowNpo = [] # controls options axis_list = ["sx", "sy", "sz", "ro"] upCtlOptions = [["corner", "R", "square", 4, .05, axis_list], ["upOuter", "R", "circle", 14, .03, []], ["upInner", "R", "circle", 14, .03, []], ["upper", "C", "square", 4, .05, axis_list], ["upInner", "L", "circle", 14, .03, []], ["upOuter", "L", "circle", 14, .03, []], ["corner", "L", "square", 4, .05, axis_list]] lowCtlOptions = [["lowOuter", "R", "circle", 14, .03, []], ["lowInner", "R", "circle", 14, .03, []], ["lower", "C", "square", 4, .05, axis_list], ["lowInner", "L", "circle", 14, .03, []], ["lowOuter", "L", "circle", 14, .03, []]] params = ["tx", "ty", "tz", "rx", "ry", "rz"] # upper controls cvs = upCrv_ctl.getCVs(space="world") pm.progressWindow(title='Upper controls', progress=0, max=len(cvs)) v0 = transform.getTransformFromPos(cvs[0]) v1 = transform.getTransformFromPos(cvs[-1]) distSize = vector.getDistance(v0, v1) * 3 for i, cv in enumerate(cvs): pm.progressWindow(e=True, step=1, status='\nCreating control for%s' % cv) t = transform.getTransformFromPos(cv) # Get nearest joint for orientation of controls joints = upperJoints + lowerJoints nearest_joint = None nearest_distance = None for joint in joints: distance = vector.getDistance( transform.getTranslation(joint), cv ) if nearest_distance is None or distance < nearest_distance: nearest_distance = distance nearest_joint = joint if nearest_joint: t = transform.setMatrixPosition( transform.getTransform(nearest_joint), cv ) temp = primitive.addTransform( lips_root, setName("temp"), t ) temp.rx.set(0) t = transform.getTransform(temp) pm.delete(temp) oName = upCtlOptions[i][0] oSide = upCtlOptions[i][1] o_icon = upCtlOptions[i][2] color = upCtlOptions[i][3] wd = upCtlOptions[i][4] oPar = upCtlOptions[i][5] npo = primitive.addTransform(lips_root, setName("%s_npo" % oName, oSide), t) upNpo.append(npo) ctl = icon.create(npo, setName("%s_%s" % (oName, control_name), oSide), t, icon=o_icon, w=wd * distSize, d=wd * distSize, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, .07 * distSize), color=color) upControls.append(ctl) name_split = control_name.split("_") if len(name_split) == 2 and name_split[-1] == "ghost": pass else: pm.sets(ctlSet, add=ctl) attribute.addAttribute(ctl, "isCtl", "bool", keyable=False) attribute.setKeyableAttributes(ctl, params + oPar) upv = primitive.addTransform(ctl, setName("%s_upv" % oName, oSide), t) upv.attr("tz").set(FRONT_OFFSET) upVec.append(upv) if oSide == "R": npo.attr("sx").set(-1) pm.progressWindow(e=True, endProgress=True) # lower controls cvs = lowCrv_ctl.getCVs(space="world") pm.progressWindow(title='Lower controls', progress=0, max=len(cvs)) for i, cv in enumerate(cvs[1:-1]): pm.progressWindow(e=True, step=1, status='\nCreating control for%s' % cv) t = transform.getTransformFromPos(cv) # Get nearest joint for orientation of controls joints = upperJoints + lowerJoints nearest_joint = None nearest_distance = None for joint in joints: distance = vector.getDistance( transform.getTranslation(joint), cv ) if nearest_distance is None or distance < nearest_distance: nearest_distance = distance nearest_joint = joint if nearest_joint: t = transform.setMatrixPosition( transform.getTransform(nearest_joint), cv ) temp = primitive.addTransform( lips_root, setName("temp"), t ) temp.rx.set(0) t = transform.getTransform(temp) pm.delete(temp) oName = lowCtlOptions[i][0] oSide = lowCtlOptions[i][1] o_icon = lowCtlOptions[i][2] color = lowCtlOptions[i][3] wd = lowCtlOptions[i][4] oPar = lowCtlOptions[i][5] npo = primitive.addTransform(lips_root, setName("%s_npo" % oName, oSide), t) lowNpo.append(npo) ctl = icon.create(npo, setName("%s_%s" % (oName, control_name), oSide), t, icon=o_icon, w=wd * distSize, d=wd * distSize, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, .07 * distSize), color=color) lowControls.append(ctl) name_split = control_name.split("_") if len(name_split) == 2 and control_name.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=ctl) attribute.addAttribute(ctl, "isCtl", "bool", keyable=False) attribute.setKeyableAttributes(ctl, params + oPar) upv = primitive.addTransform(ctl, setName("%s_upv" % oName, oSide), t) upv.attr("tz").set(FRONT_OFFSET) lowVec.append(upv) if oSide == "R": npo.attr("sx").set(-1) pm.progressWindow(e=True, endProgress=True) # reparentig controls pm.parent(upNpo[1], lowNpo[0], upControls[0]) pm.parent(upNpo[2], upNpo[4], upControls[3]) pm.parent(upNpo[-2], lowNpo[-1], upControls[-1]) pm.parent(lowNpo[1], lowNpo[3], lowControls[2]) # Connecting control crvs with controls applyop.gear_curvecns_op(upCrv_ctl, upControls) applyop.gear_curvecns_op(lowCrv_ctl, [upControls[0]] + lowControls + [upControls[-1]]) applyop.gear_curvecns_op(upCrv_upv, upVec) applyop.gear_curvecns_op(lowCrv_upv, [upVec[0]] + lowVec + [upVec[-1]]) # adding wires pm.wire(upCrv, w=upCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(lowCrv, w=lowCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(upRope, w=upCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(lowRope, w=lowCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(upRope_upv, w=upCrv_upv, dropoffDistance=[0, 1000]) pm.wire(lowRope_upv, w=lowCrv_upv, dropoffDistance=[0, 1000]) # setting constrains # up cns_node = pm.parentConstraint(upControls[0], upControls[3], upControls[1].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(upControls[0].name() + "W0").set(.75) cns_node.attr(upControls[3].name() + "W1").set(.25) cns_node.interpType.set(0) # noFlip cns_node = pm.parentConstraint(upControls[0], upControls[3], upControls[2].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(upControls[0].name() + "W0").set(.25) cns_node.attr(upControls[3].name() + "W1").set(.75) cns_node.interpType.set(0) # noFlip cns_node = pm.parentConstraint(upControls[3], upControls[6], upControls[4].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(upControls[3].name() + "W0").set(.75) cns_node.attr(upControls[6].name() + "W1").set(.25) cns_node.interpType.set(0) # noFlip cns_node = pm.parentConstraint(upControls[3], upControls[6], upControls[5].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(upControls[3].name() + "W0").set(.25) cns_node.attr(upControls[6].name() + "W1").set(.75) cns_node.interpType.set(0) # noFlip # low cns_node = pm.parentConstraint(upControls[0], lowControls[2], lowControls[0].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(upControls[0].name() + "W0").set(.75) cns_node.attr(lowControls[2].name() + "W1").set(.25) cns_node.interpType.set(0) # noFlip cns_node = pm.parentConstraint(upControls[0], lowControls[2], lowControls[1].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(upControls[0].name() + "W0").set(.25) cns_node.attr(lowControls[2].name() + "W1").set(.75) cns_node.interpType.set(0) # noFlip cns_node = pm.parentConstraint(lowControls[2], upControls[6], lowControls[3].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(lowControls[2].name() + "W0").set(.75) cns_node.attr(upControls[6].name() + "W1").set(.25) cns_node.interpType.set(0) # noFlip cns_node = pm.parentConstraint(lowControls[2], upControls[6], lowControls[4].getParent(), mo=True, skipRotate=["x", "y", "z"]) cns_node.attr(lowControls[2].name() + "W0").set(.25) cns_node.attr(upControls[6].name() + "W1").set(.75) cns_node.interpType.set(0) # noFlip ########################################### # Connecting rig ########################################### if parent_node: try: if isinstance(parent_node, string_types): parent_node = pm.PyNode(parent_node) parent_node.addChild(lips_root) except pm.MayaNodeError: pm.displayWarning("The Lips rig can not be parent to: %s. Maybe " "this object doesn't exist." % parent_node) if head_joint and jaw_joint: try: if isinstance(head_joint, string_types): head_joint = pm.PyNode(head_joint) except pm.MayaNodeError: pm.displayWarning("Head Joint or Upper Lip Joint %s. Can not be " "fount in the scene" % head_joint) return try: if isinstance(jaw_joint, string_types): jaw_joint = pm.PyNode(jaw_joint) except pm.MayaNodeError: pm.displayWarning("Jaw Joint or Lower Lip Joint %s. Can not be " "fount in the scene" % jaw_joint) return ref_ctls = [head_joint, jaw_joint] if upper_lip_ctl and lower_lip_ctl: try: if isinstance(upper_lip_ctl, string_types): upper_lip_ctl = pm.PyNode(upper_lip_ctl) except pm.MayaNodeError: pm.displayWarning("Upper Lip Ctl %s. Can not be " "fount in the scene" % upper_lip_ctl) return try: if isinstance(lower_lip_ctl, string_types): lower_lip_ctl = pm.PyNode(lower_lip_ctl) except pm.MayaNodeError: pm.displayWarning("Lower Lip Ctl %s. Can not be " "fount in the scene" % lower_lip_ctl) return ref_ctls = [upper_lip_ctl, lower_lip_ctl] # in order to avoid flips lets create a reference transform # also to avoid flips, set any multi target parentConstraint to noFlip ref_cns_list = [] print (ref_ctls) for cns_ref in ref_ctls: t = transform.getTransformFromPos( cns_ref.getTranslation(space='world')) ref = pm.createNode("transform", n=cns_ref.name() + "_cns", p=cns_ref, ss=True) ref.setMatrix(t, worldSpace=True) ref_cns_list.append(ref) # right corner connection cns_node = pm.parentConstraint(ref_cns_list[0], ref_cns_list[1], upControls[0].getParent(), mo=True) cns_node.interpType.set(0) # noFlip # left corner connection cns_node = pm.parentConstraint(ref_cns_list[0], ref_cns_list[1], upControls[-1].getParent(), mo=True) cns_node.interpType.set(0) # noFlip # up control connection cns_node = pm.parentConstraint(ref_cns_list[0], upControls[3].getParent(), mo=True) # low control connection cns_node = pm.parentConstraint(ref_cns_list[1], lowControls[2].getParent(), mo=True) ########################################### # Auto Skinning ########################################### if do_skin: # eyelid vertex rows totalLoops = rigid_loops + falloff_loops vertexLoopList = meshNavigation.getConcentricVertexLoop(vertexList, totalLoops) vertexRowList = meshNavigation.getVertexRowsFromLoops(vertexLoopList) # we set the first value 100% for the first initial loop skinPercList = [1.0] # we expect to have a regular grid topology for r in range(rigid_loops): for rr in range(2): skinPercList.append(1.0) increment = 1.0 / float(falloff_loops) # we invert to smooth out from 100 to 0 inv = 1.0 - increment for r in range(falloff_loops): for rr in range(2): if inv < 0.0: inv = 0.0 skinPercList.append(inv) inv -= increment # this loop add an extra 0.0 indices to avoid errors for r in range(10): for rr in range(2): skinPercList.append(0.0) # base skin if head_joint: try: head_joint = pm.PyNode(head_joint) except pm.MayaNodeError: pm.displayWarning( "Auto skin aborted can not find %s " % head_joint) return # Check if the object has a skinCluster objName = pm.listRelatives(geo, parent=True)[0] skinCluster = skin.getSkinCluster(objName) if not skinCluster: skinCluster = pm.skinCluster(head_joint, geo, tsb=True, nw=2, n='skinClsEyelid') lipsJoints = upperJoints + lowerJoints closestVtxList = upLip_closestVtxList + lowLip_closestVtxList pm.progressWindow(title='Auto skinning process', progress=0, max=len(lipsJoints)) for i, jnt in enumerate(lipsJoints): pm.progressWindow(e=True, step=1, status='\nSkinning %s' % jnt) skinCluster.addInfluence(jnt, weight=0) v = closestVtxList[i] for row in vertexRowList: if v in row: for i, rv in enumerate(row): # find the deformer with max value for each vertex w = pm.skinPercent(skinCluster, rv, query=True, value=True) transJoint = pm.skinPercent(skinCluster, rv, query=True, t=None) max_value = max(w) max_index = w.index(max_value) perc = skinPercList[i] t_value = [(jnt, perc), (transJoint[max_index], 1.0 - perc)] pm.skinPercent(skinCluster, rv, transformValue=t_value) pm.progressWindow(e=True, endProgress=True)
def eyeRig(eyeMesh, edgeLoop, blinkH, namePrefix, offset, rigidLoops, falloffLoops, headJnt, doSkin, parent=None, ctlName="ctl", sideRange=False, customCorner=False, intCorner=None, extCorner=None, ctlGrp=None, defGrp=None): """Create eyelid and eye rig Args: eyeMesh (TYPE): Description edgeLoop (TYPE): Description blinkH (TYPE): Description namePrefix (TYPE): Description offset (TYPE): Description rigidLoops (TYPE): Description falloffLoops (TYPE): Description headJnt (TYPE): Description doSkin (TYPE): Description parent (None, optional): Description ctlName (str, optional): Description sideRange (bool, optional): Description customCorner (bool, optional): Description intCorner (None, optional): Description extCorner (None, optional): Description ctlGrp (None, optional): Description defGrp (None, optional): Description Returns: TYPE: Description """ # Checkers if edgeLoop: edgeLoopList = [pm.PyNode(e) for e in edgeLoop.split(",")] else: pm.displayWarning("Please set the edge loop first") return if eyeMesh: try: eyeMesh = pm.PyNode(eyeMesh) except pm.MayaNodeError: pm.displayWarning("The object %s can not be found in the " "scene" % (eyeMesh)) return else: pm.displayWarning("Please set the eye mesh first") if doSkin: if not headJnt: pm.displayWarning("Please set the Head Jnt or unCheck " "Compute Topological Autoskin") return # Initial Data bboxCenter = meshNavigation.bboxCenter(eyeMesh) extr_v = meshNavigation.getExtremeVertexFromLoop(edgeLoopList, sideRange) upPos = extr_v[0] lowPos = extr_v[1] inPos = extr_v[2] outPos = extr_v[3] edgeList = extr_v[4] vertexList = extr_v[5] # Detect the side L or R from the x value if inPos.getPosition(space='world')[0] < 0.0: side = "R" inPos = extr_v[3] outPos = extr_v[2] normalPos = outPos npw = normalPos.getPosition(space='world') normalVec = npw - bboxCenter else: side = "L" normalPos = outPos npw = normalPos.getPosition(space='world') normalVec = bboxCenter - npw # Manual Vertex corners if customCorner: if intCorner: try: if side == "R": inPos = pm.PyNode(extCorner) else: inPos = pm.PyNode(intCorner) except pm.MayaNodeError: pm.displayWarning("%s can not be found" % intCorner) return else: pm.displayWarning("Please set the internal eyelid corner") return if extCorner: try: normalPos = pm.PyNode(extCorner) npw = normalPos.getPosition(space='world') if side == "R": outPos = pm.PyNode(intCorner) normalVec = npw - bboxCenter else: outPos = pm.PyNode(extCorner) normalVec = bboxCenter - npw except pm.MayaNodeError: pm.displayWarning("%s can not be found" % extCorner) return else: pm.displayWarning("Please set the external eyelid corner") return # Check if we have prefix: if namePrefix: namePrefix = string.removeInvalidCharacter(namePrefix) else: pm.displayWarning("Prefix is needed") return def setName(name, ind=None): namesList = [namePrefix, side, name] if ind is not None: namesList[1] = side + str(ind) name = "_".join(namesList) return name if pm.ls(setName("root")): pm.displayWarning("The object %s already exist in the scene. Please " "choose another name prefix" % setName("root")) return # Eye root eye_root = primitive.addTransform(None, setName("root")) eyeCrv_root = primitive.addTransform(eye_root, setName("crvs")) # Eyelid Main crvs try: upEyelid = meshNavigation.edgeRangeInLoopFromMid( edgeList, upPos, inPos, outPos) upCrv = curve.createCurveFromOrderedEdges( upEyelid, inPos, setName("upperEyelid"), parent=eyeCrv_root) upCrv_ctl = curve.createCurveFromOrderedEdges( upEyelid, inPos, setName("upCrv_%s" % ctlName), parent=eyeCrv_root) pm.rebuildCurve(upCrv_ctl, s=2, rt=0, rpo=True, ch=False) lowEyelid = meshNavigation.edgeRangeInLoopFromMid( edgeList, lowPos, inPos, outPos) lowCrv = curve.createCurveFromOrderedEdges( lowEyelid, inPos, setName("lowerEyelid"), parent=eyeCrv_root) lowCrv_ctl = curve.createCurveFromOrderedEdges( lowEyelid, inPos, setName("lowCrv_%s" % ctlName), parent=eyeCrv_root) pm.rebuildCurve(lowCrv_ctl, s=2, rt=0, rpo=True, ch=False) except UnboundLocalError: if customCorner: pm.displayWarning("This error is maybe caused because the custom " "Corner vertex is not part of the edge loop") pm.displayError(traceback.format_exc()) return upBlink = curve.createCurveFromCurve( upCrv, setName("upblink_crv"), nbPoints=30, parent=eyeCrv_root) lowBlink = curve.createCurveFromCurve( lowCrv, setName("lowBlink_crv"), nbPoints=30, parent=eyeCrv_root) upTarget = curve.createCurveFromCurve( upCrv, setName("upblink_target"), nbPoints=30, parent=eyeCrv_root) lowTarget = curve.createCurveFromCurve( lowCrv, setName("lowBlink_target"), nbPoints=30, parent=eyeCrv_root) midTarget = curve.createCurveFromCurve( lowCrv, setName("midBlink_target"), nbPoints=30, parent=eyeCrv_root) rigCrvs = [upCrv, lowCrv, upCrv_ctl, lowCrv_ctl, upBlink, lowBlink, upTarget, lowTarget, midTarget] for crv in rigCrvs: crv.attr("visibility").set(False) # localBBOX localBBox = eyeMesh.getBoundingBox(invisible=True, space='world') wRadius = abs((localBBox[0][0] - localBBox[1][0])) dRadius = abs((localBBox[0][1] - localBBox[1][1]) / 1.7) # Groups if not ctlGrp: ctlGrp = "rig_controllers_grp" try: ctlSet = pm.PyNode(ctlGrp) except pm.MayaNodeError: pm.sets(n=ctlGrp, em=True) ctlSet = pm.PyNode(ctlGrp) if not defGrp: defGrp = "rig_deformers_grp" try: defset = pm.PyNode(defGrp) except pm.MayaNodeError: pm.sets(n=defGrp, em=True) defset = pm.PyNode(defGrp) # Calculate center looking at averagePosition = ((upPos.getPosition(space='world') + lowPos.getPosition(space='world') + inPos.getPosition(space='world') + outPos.getPosition(space='world')) / 4) if side == "R": negate = False offset = offset over_offset = dRadius else: negate = False over_offset = dRadius if side == "R" and sideRange or side == "R" and customCorner: axis = "z-x" # axis = "zx" else: axis = "z-x" t = transform.getTransformLookingAt( bboxCenter, averagePosition, normalVec, axis=axis, negate=negate) over_npo = primitive.addTransform( eye_root, setName("center_lookatRoot"), t) over_ctl = icon.create(over_npo, setName("over_%s" % ctlName), t, icon="square", w=wRadius, d=dRadius, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, over_offset), color=4) node.add_controller_tag(over_ctl) attribute.add_mirror_config_channels(over_ctl) attribute.setKeyableAttributes( over_ctl, params=["tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz"]) if side == "R": over_npo.attr("rx").set(over_npo.attr("rx").get() * -1) over_npo.attr("ry").set(over_npo.attr("ry").get() + 180) over_npo.attr("sz").set(-1) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=over_ctl) center_lookat = primitive.addTransform( over_ctl, setName("center_lookat"), t) # Tracking # Eye aim control t_arrow = transform.getTransformLookingAt(bboxCenter, averagePosition, upPos.getPosition(space='world'), axis="zy", negate=False) radius = abs((localBBox[0][0] - localBBox[1][0]) / 1.7) arrow_npo = primitive.addTransform(eye_root, setName("aim_npo"), t_arrow) arrow_ctl = icon.create(arrow_npo, setName("aim_%s" % ctlName), t_arrow, icon="arrow", w=1, po=datatypes.Vector(0, 0, radius), color=4) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=arrow_ctl) attribute.setKeyableAttributes(arrow_ctl, params=["rx", "ry", "rz"]) # tracking custom trigger if side == "R": tt = t_arrow else: tt = t aimTrigger_root = primitive.addTransform( center_lookat, setName("aimTrigger_root"), tt) aimTrigger_lvl = primitive.addTransform( aimTrigger_root, setName("aimTrigger_lvl"), tt) aimTrigger_lvl.attr("tz").set(1.0) aimTrigger_ref = primitive.addTransform( aimTrigger_lvl, setName("aimTrigger_ref"), tt) aimTrigger_ref.attr("tz").set(0.0) # connect trigger with arrow_ctl pm.parentConstraint(arrow_ctl, aimTrigger_ref, mo=True) # Controls lists upControls = [] trackLvl = [] # upper eyelid controls upperCtlNames = ["inCorner", "upInMid", "upMid", "upOutMid", "outCorner"] cvs = upCrv_ctl.getCVs(space="world") if side == "R" and not sideRange: # if side == "R": cvs = [cv for cv in reversed(cvs)] for i, cv in enumerate(cvs): if utils.is_odd(i): color = 14 wd = .5 icon_shape = "circle" params = ["tx", "ty", "tz"] else: color = 4 wd = .7 icon_shape = "square" params = ["tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz"] t = transform.setMatrixPosition(t, cvs[i]) npo = primitive.addTransform(center_lookat, setName("%s_npo" % upperCtlNames[i]), t) npoBase = npo if i == 2: # we add an extra level to input the tracking ofset values npo = primitive.addTransform(npo, setName("%s_trk" % upperCtlNames[i]), t) trackLvl.append(npo) ctl = icon.create(npo, setName("%s_%s" % (upperCtlNames[i], ctlName)), t, icon=icon_shape, w=wd, d=wd, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, offset), color=color) attribute.add_mirror_config_channels(ctl) node.add_controller_tag(ctl, over_ctl) upControls.append(ctl) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=ctl) attribute.setKeyableAttributes(ctl, params) if side == "R": npoBase.attr("ry").set(180) npoBase.attr("sz").set(-1) # adding parent average contrains to odd controls for i, ctl in enumerate(upControls): if utils.is_odd(i): pm.parentConstraint(upControls[i - 1], upControls[i + 1], ctl.getParent(), mo=True) # lower eyelid controls lowControls = [upControls[0]] lowerCtlNames = ["inCorner", "lowInMid", "lowMid", "lowOutMid", "outCorner"] cvs = lowCrv_ctl.getCVs(space="world") if side == "R" and not sideRange: cvs = [cv for cv in reversed(cvs)] for i, cv in enumerate(cvs): # we skip the first and last point since is already in the uper eyelid if i in [0, 4]: continue if utils.is_odd(i): color = 14 wd = .5 icon_shape = "circle" params = ["tx", "ty", "tz"] else: color = 4 wd = .7 icon_shape = "square" params = ["tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz"] t = transform.setMatrixPosition(t, cvs[i]) npo = primitive.addTransform(center_lookat, setName("%s_npo" % lowerCtlNames[i]), t) npoBase = npo if i == 2: # we add an extra level to input the tracking ofset values npo = primitive.addTransform(npo, setName("%s_trk" % lowerCtlNames[i]), t) trackLvl.append(npo) ctl = icon.create(npo, setName("%s_%s" % (lowerCtlNames[i], ctlName)), t, icon=icon_shape, w=wd, d=wd, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, offset), color=color) attribute.add_mirror_config_channels(ctl) lowControls.append(ctl) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=ctl) attribute.setKeyableAttributes(ctl, params) # mirror behaviout on R side controls if side == "R": npoBase.attr("ry").set(180) npoBase.attr("sz").set(-1) for lctl in reversed(lowControls[1:]): node.add_controller_tag(lctl, over_ctl) lowControls.append(upControls[-1]) # adding parent average contrains to odd controls for i, ctl in enumerate(lowControls): if utils.is_odd(i): pm.parentConstraint(lowControls[i - 1], lowControls[i + 1], ctl.getParent(), mo=True) # Connecting control crvs with controls applyop.gear_curvecns_op(upCrv_ctl, upControls) applyop.gear_curvecns_op(lowCrv_ctl, lowControls) # adding wires w1 = pm.wire(upCrv, w=upBlink)[0] w2 = pm.wire(lowCrv, w=lowBlink)[0] w3 = pm.wire(upTarget, w=upCrv_ctl)[0] w4 = pm.wire(lowTarget, w=lowCrv_ctl)[0] # adding blendshapes bs_upBlink = pm.blendShape(upTarget, midTarget, upBlink, n="blendShapeUpBlink") bs_lowBlink = pm.blendShape(lowTarget, midTarget, lowBlink, n="blendShapeLowBlink") bs_mid = pm.blendShape(lowTarget, upTarget, midTarget, n="blendShapeLowBlink") # setting blendshape reverse connections rev_node = pm.createNode("reverse") pm.connectAttr(bs_upBlink[0].attr(midTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", bs_upBlink[0].attr(upTarget.name())) rev_node = pm.createNode("reverse") pm.connectAttr(bs_lowBlink[0].attr(midTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", bs_lowBlink[0].attr(lowTarget.name())) rev_node = pm.createNode("reverse") pm.connectAttr(bs_mid[0].attr(upTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", bs_mid[0].attr(lowTarget.name())) # setting default values bs_mid[0].attr(upTarget.name()).set(blinkH) # joints root jnt_root = primitive.addTransformFromPos( eye_root, setName("joints"), pos=bboxCenter) # head joint if headJnt: try: headJnt = pm.PyNode(headJnt) jnt_base = headJnt except pm.MayaNodeError: pm.displayWarning( "Aborted can not find %s " % headJnt) return else: # Eye root jnt_base = jnt_root eyeTargets_root = primitive.addTransform(eye_root, setName("targets")) eyeCenter_jnt = rigbits.addJnt(arrow_ctl, jnt_base, grp=defset, jntName=setName("center_jnt")) # Upper Eyelid joints ################################################## cvs = upCrv.getCVs(space="world") upCrv_info = node.createCurveInfoNode(upCrv) # aim constrain targets and joints upperEyelid_aimTargets = [] upperEyelid_jnt = [] upperEyelid_jntRoot = [] for i, cv in enumerate(cvs): # aim targets trn = primitive.addTransformFromPos(eyeTargets_root, setName("upEyelid_aimTarget", i), pos=cv) upperEyelid_aimTargets.append(trn) # connecting positions with crv pm.connectAttr(upCrv_info + ".controlPoints[%s]" % str(i), trn.attr("translate")) # joints jntRoot = primitive.addJointFromPos(jnt_root, setName("upEyelid_jnt_base", i), pos=bboxCenter) jntRoot.attr("radius").set(.08) jntRoot.attr("visibility").set(False) upperEyelid_jntRoot.append(jntRoot) applyop.aimCns(jntRoot, trn, axis="zy", wupObject=jnt_root) jnt_ref = primitive.addJointFromPos(jntRoot, setName("upEyelid_jnt_ref", i), pos=cv) jnt_ref.attr("radius").set(.08) jnt_ref.attr("visibility").set(False) jnt = rigbits.addJnt(jnt_ref, jnt_base, grp=defset, jntName=setName("upEyelid_jnt", i)) upperEyelid_jnt.append(jnt) # Lower Eyelid joints ################################################## cvs = lowCrv.getCVs(space="world") lowCrv_info = node.createCurveInfoNode(lowCrv) # aim constrain targets and joints lowerEyelid_aimTargets = [] lowerEyelid_jnt = [] lowerEyelid_jntRoot = [] for i, cv in enumerate(cvs): if i in [0, len(cvs) - 1]: continue # aim targets trn = primitive.addTransformFromPos(eyeTargets_root, setName("lowEyelid_aimTarget", i), pos=cv) lowerEyelid_aimTargets.append(trn) # connecting positions with crv pm.connectAttr(lowCrv_info + ".controlPoints[%s]" % str(i), trn.attr("translate")) # joints jntRoot = primitive.addJointFromPos(jnt_root, setName("lowEyelid_base", i), pos=bboxCenter) jntRoot.attr("radius").set(.08) jntRoot.attr("visibility").set(False) lowerEyelid_jntRoot.append(jntRoot) applyop.aimCns(jntRoot, trn, axis="zy", wupObject=jnt_root) jnt_ref = primitive.addJointFromPos(jntRoot, setName("lowEyelid_jnt_ref", i), pos=cv) jnt_ref.attr("radius").set(.08) jnt_ref.attr("visibility").set(False) jnt = rigbits.addJnt(jnt_ref, jnt_base, grp=defset, jntName=setName("lowEyelid_jnt", i)) lowerEyelid_jnt.append(jnt) # Channels # Adding and connecting attributes for the blink up_ctl = upControls[2] blink_att = attribute.addAttribute( over_ctl, "blink", "float", 0, minValue=0, maxValue=1) blinkMult_att = attribute.addAttribute( over_ctl, "blinkMult", "float", 1, minValue=1, maxValue=2) midBlinkH_att = attribute.addAttribute( over_ctl, "blinkHeight", "float", blinkH, minValue=0, maxValue=1) mult_node = node.createMulNode(blink_att, blinkMult_att) pm.connectAttr(mult_node + ".outputX", bs_upBlink[0].attr(midTarget.name())) pm.connectAttr(mult_node + ".outputX", bs_lowBlink[0].attr(midTarget.name())) pm.connectAttr(midBlinkH_att, bs_mid[0].attr(upTarget.name())) low_ctl = lowControls[2] # Adding channels for eye tracking upVTracking_att = attribute.addAttribute(up_ctl, "vTracking", "float", .02, minValue=0, maxValue=1, keyable=False, channelBox=True) upHTracking_att = attribute.addAttribute(up_ctl, "hTracking", "float", .01, minValue=0, maxValue=1, keyable=False, channelBox=True) lowVTracking_att = attribute.addAttribute(low_ctl, "vTracking", "float", .01, minValue=0, maxValue=1, keyable=False, channelBox=True) lowHTracking_att = attribute.addAttribute(low_ctl, "hTracking", "float", .01, minValue=0, maxValue=1, keyable=False, channelBox=True) mult_node = node.createMulNode(upVTracking_att, aimTrigger_ref.attr("ty")) pm.connectAttr(mult_node + ".outputX", trackLvl[0].attr("ty")) mult_node = node.createMulNode(upHTracking_att, aimTrigger_ref.attr("tx")) pm.connectAttr(mult_node + ".outputX", trackLvl[0].attr("tx")) mult_node = node.createMulNode(lowVTracking_att, aimTrigger_ref.attr("ty")) pm.connectAttr(mult_node + ".outputX", trackLvl[1].attr("ty")) mult_node = node.createMulNode(lowHTracking_att, aimTrigger_ref.attr("tx")) pm.connectAttr(mult_node + ".outputX", trackLvl[1].attr("tx")) # Tension on blink node.createReverseNode(blink_att, w1.scale[0]) node.createReverseNode(blink_att, w3.scale[0]) node.createReverseNode(blink_att, w2.scale[0]) node.createReverseNode(blink_att, w4.scale[0]) ########################################### # Reparenting ########################################### if parent: try: if isinstance(parent, basestring): parent = pm.PyNode(parent) parent.addChild(eye_root) except pm.MayaNodeError: pm.displayWarning("The eye rig can not be parent to: %s. Maybe " "this object doesn't exist." % parent) ########################################### # Auto Skinning ########################################### if doSkin: # eyelid vertex rows totalLoops = rigidLoops + falloffLoops vertexLoopList = meshNavigation.getConcentricVertexLoop(vertexList, totalLoops) vertexRowList = meshNavigation.getVertexRowsFromLoops(vertexLoopList) # we set the first value 100% for the first initial loop skinPercList = [1.0] # we expect to have a regular grid topology for r in range(rigidLoops): for rr in range(2): skinPercList.append(1.0) increment = 1.0 / float(falloffLoops) # we invert to smooth out from 100 to 0 inv = 1.0 - increment for r in range(falloffLoops): for rr in range(2): if inv < 0.0: inv = 0.0 skinPercList.append(inv) inv -= increment # this loop add an extra 0.0 indices to avoid errors for r in range(10): for rr in range(2): skinPercList.append(0.0) # base skin geo = pm.listRelatives(edgeLoopList[0], parent=True)[0] # Check if the object has a skinCluster objName = pm.listRelatives(geo, parent=True)[0] skinCluster = skin.getSkinCluster(objName) if not skinCluster: skinCluster = pm.skinCluster(headJnt, geo, tsb=True, nw=2, n='skinClsEyelid') eyelidJoints = upperEyelid_jnt + lowerEyelid_jnt pm.progressWindow(title='Auto skinning process', progress=0, max=len(eyelidJoints)) firstBoundary = False for jnt in eyelidJoints: pm.progressWindow(e=True, step=1, status='\nSkinning %s' % jnt) skinCluster.addInfluence(jnt, weight=0) v = meshNavigation.getClosestVertexFromTransform(geo, jnt) for row in vertexRowList: if v in row: it = 0 # iterator inc = 1 # increment for i, rv in enumerate(row): try: perc = skinPercList[it] t_val = [(jnt, perc), (headJnt, 1.0 - perc)] pm.skinPercent(skinCluster, rv, transformValue=t_val) if rv.isOnBoundary(): # we need to compare with the first boundary # to check if the row have inverted direction # and offset the value if not firstBoundary: firstBoundary = True firstBoundaryValue = it else: if it < firstBoundaryValue: it -= 1 elif it > firstBoundaryValue: it += 1 inc = 2 except IndexError: continue it = it + inc pm.progressWindow(e=True, endProgress=True) # Eye Mesh skinning skinCluster = skin.getSkinCluster(eyeMesh) if not skinCluster: skinCluster = pm.skinCluster(eyeCenter_jnt, eyeMesh, tsb=True, nw=1, n='skinClsEye')
def wire(s, d): wire = pm.wire(s, w=d, dropoffDistance=[0, 1000])
def rigRbn(self): # -------------- Create the wire curve that will drive the blendshape target srf---# self.rbnWireCrv = pm.curve(d=2, p=[[self.start[0], 0, self.rbnWidth * 5.0], [0, 0, self.rbnWidth * 5.0], [self.end[0], 0, self.rbnWidth * 5.0]], k=[0, 0, 1, 1], name=self.rbnName + '_wire_crv') self.rbnWireCrv.hide() pm.parent(self.rbnWireCrv, self.rbnNoTransformGrp) # -------------- Create the surface that will be the target blendshape ------------# self.rbnBsSrf = pm.duplicate(self.rbnSrf, name=self.rbnName + '_srf_bs')[0] self.rbnBsSrf.hide() pm.parent(self.rbnBsSrf, self.rbnNoTransformGrp) pm.xform(self.rbnBsSrf, r=1, t=[0, 0, self.rbnWidth * 5.0]) blendshapeNode = pm.blendShape(self.rbnBsSrf, self.rbnSrf, name=self.rbnName + '_blendShape')[0] blendshapeNode.attr(self.rbnBsSrf.name()).set(1) # -------------- Create the locators that will drive the ribbon -------------------# topLocator = pm.spaceLocator(name=self.rbnName + '_loc_01', p=[self.start[0], 0, 0]) pm.makeIdentity(topLocator, apply=True, t=True, r=True, s=True) topLocator.setPivots(topLocator.c.get()) midLocator = pm.spaceLocator(name=self.rbnName + '_loc_02', p=[0, 0, 0]) midLocatorGrp = pm.group(midLocator, name=midLocator.name() + '_grp') botLocator = pm.spaceLocator(name=self.rbnName + '_loc_03', p=[self.end[0], 0, 0]) pm.makeIdentity(botLocator, apply=True, t=True, r=True, s=True) botLocator.setPivots(botLocator.c.get()) self.rbnLocs.append(topLocator) self.rbnLocs.append(midLocator) self.rbnLocs.append(botLocator) pm.pointConstraint(topLocator, botLocator, midLocatorGrp) locGrp = pm.group([topLocator, midLocatorGrp, botLocator], n=self.rbnName + '_loc_grp') pm.parent(locGrp, self.rbnTransformGrp) # -------------------------- Create the wire deformer -----------------------------# wireDef = pm.wire(self.rbnBsSrf, w=self.rbnWireCrv, en=1, gw=False, ce=0, li=0, dds=[0, 200], n=self.rbnName + '_wire') self.clustersOnCurve() for i in range(3): self.rbnLocs[i].translate.connect(self.rbnCls[i].translate) # -------------------------- Create the twist deformer -----------------------------# self.addTwist() botLocator.rotateX.connect(self.rbnTwist.startAngle) topLocator.rotateX.connect(self.rbnTwist.endAngle) pm.reorderDeformers(wireDef[0], self.rbnTwist, self.rbnBsSrf) pm.parent(self.rbnTwist, self.rbnNoTransformGrp) # -------------------------------- Add volume --------------------------------------# self.addVolume()
def blink(self): dupeLeft = pm.duplicate("l_low_up_CURV", n="l_blink_CURV") blendLeftEye = pm.blendShape("l_low_down_CURV", "l_low_up_CURV", dupeLeft, n="l_blinkHeight_BLD") dupeRight = pm.duplicate("r_low_up_CURV", n="r_blink_CURV") blendRightEye = pm.blendShape("r_low_down_CURV", "r_low_up_CURV", dupeRight, n="r_blinkHeight_BLD") lBlinkHeightAttr = pm.addAttr("l_eye_upMiddle_CTL", longName="blinkHeight", attributeType="float", min=0, max=1, defaultValue=0, keyable=True) rBlinkHeightAttr = pm.addAttr("r_eye_upMiddle_CTL", longName="blinkHeight", attributeType="float", min=0, max=1, defaultValue=0, keyable=True) pm.setAttr("l_blinkHeight_BLD.l_low_up_CURV", 1) pm.setAttr("r_blinkHeight_BLD.r_low_up_CURV", 1) pm.connectAttr("l_eye_upMiddle_CTL.blinkHeight", "l_blinkHeight_BLD.l_low_up_CURV", f=1) rev1 = pm.shadingNode("reverse", asUtility=True, n="l_blinkHeightBS_REV") pm.connectAttr("l_eye_upMiddle_CTL.blinkHeight", rev1 + ".inputX", f=1) pm.connectAttr(rev1 + ".outputX", "l_blinkHeight_BLD.l_low_down_CURV") pm.connectAttr("r_eye_upMiddle_CTL.blinkHeight", "r_blinkHeight_BLD.r_low_up_CURV", f=1) rev2 = pm.shadingNode("reverse", asUtility=True, n="r_blinkHeightBS_REV") pm.connectAttr("r_eye_upMiddle_CTL.blinkHeight", rev2 + ".inputX", f=1) pm.connectAttr(rev2 + ".outputX", "r_blinkHeight_BLD.r_low_down_CURV") dupeLeftup = pm.duplicate("l_up_CURV", n="l_up_blink_CURV") dupeLeftdown = pm.duplicate("l_down_CURV", n="l_down_blink_CURV") dupeRightup = pm.duplicate("r_up_CURV", n="r_up_blink_CURV") dupeRightdown = pm.duplicate("r_down_CURV", n="r_down_blink_CURV") pm.setAttr("l_eye_upMiddle_CTL.blinkHeight", 1) lupw = pm.wire("l_up_blink_CURV", gw=False, en=1.000000, ce=0.000000, li=0.000000, wire="l_blink_CURV", n="l_up_blink_WIR") pm.setAttr(lupw[0] + ".scale[0]", 0) pm.setAttr("l_eye_upMiddle_CTL.blinkHeight", 0) ldownw = pm.wire("l_down_blink_CURV", gw=False, en=1.000000, ce=0.000000, li=0.000000, wire="l_blink_CURV", n="l_down_blink_WIR") pm.setAttr(ldownw[0] + ".scale[0]", 0) blendLeftEyeUp = pm.blendShape("l_up_blink_CURV", "l_up_CURV", n="l_blink_up_BLD") blendLeftEyeDown = pm.blendShape("l_down_blink_CURV", "l_down_CURV", n="l_blink_down_BLD") pm.setAttr("r_eye_upMiddle_CTL.blinkHeight", 1) rupw = pm.wire("r_up_blink_CURV", gw=False, en=1.000000, ce=0.000000, li=0.000000, wire="r_blink_CURV", n="r_up_blink_WIR") pm.setAttr(rupw[0] + ".scale[0]", 0) pm.setAttr("r_eye_upMiddle_CTL.blinkHeight", 0) rdownw = pm.wire("r_down_blink_CURV", gw=False, en=1.000000, ce=0.000000, li=0.000000, wire="r_blink_CURV", n="r_down_blink_WIR") pm.setAttr(rdownw[0] + ".scale[0]", 0) blendRightEyeUp = pm.blendShape("r_up_blink_CURV", "r_up_CURV", n="r_blink_up_BLD") blendRightEyeDown = pm.blendShape("r_down_blink_CURV", "r_down_CURV", n="r_blink_down_BLD") lBlinkUpAttr = pm.addAttr("l_eye_upMiddle_CTL", longName="blink", attributeType="float", min=0, max=1, defaultValue=0, keyable=True) lBlinkDownAttr = pm.addAttr("l_eye_downMiddle_CTL", longName="blink", attributeType="float", min=0, max=1, defaultValue=0, keyable=True) rBlinkUpAttr = pm.addAttr("r_eye_upMiddle_CTL", longName="blink", attributeType="float", min=0, max=1, defaultValue=0, keyable=True) rBlinkDownAttr = pm.addAttr("r_eye_downMiddle_CTL", longName="blink", attributeType="float", min=0, max=1, defaultValue=0, keyable=True) pm.connectAttr("l_eye_upMiddle_CTL.blink", "l_blink_up_BLD.l_up_blink_CURV", f=1) pm.connectAttr("l_eye_downMiddle_CTL.blink", "l_blink_down_BLD.l_down_blink_CURV", f=1) pm.connectAttr("r_eye_upMiddle_CTL.blink", "r_blink_up_BLD.r_up_blink_CURV", f=1) pm.connectAttr("r_eye_downMiddle_CTL.blink", "r_blink_down_BLD.r_down_blink_CURV", f=1) pm.setAttr("l_eye_upMiddle_CTL.blinkHeight", 0.25) pm.setAttr("r_eye_upMiddle_CTL.blinkHeight", 0.25)
def addControllers(self): axis_list = ["sx", "sy", "sz", "ro"] upCtlOptions = [["corner", "R", "square", 4, .05, axis_list], ["upOuter", "R", "circle", 14, .03, []], ["upInner", "R", "circle", 14, .03, []], ["upper", "C", "square", 4, .05, axis_list], ["upInner", "L", "circle", 14, .03, []], ["upOuter", "L", "circle", 14, .03, []], ["corner", "L", "square", 4, .05, axis_list]] lowCtlOptions = [["lowOuter", "R", "circle", 14, .03, []], ["lowInner", "R", "circle", 14, .03, []], ["lower", "C", "square", 4, .05, axis_list], ["lowInner", "L", "circle", 14, .03, []], ["lowOuter", "L", "circle", 14, .03, []]] self.upNpos, self.upCtls, self.upUpvs = self._addControls( self.upCrv_ctl, upCtlOptions, False) self.lowNpos, self.lowCtls, self.lowUpvs = self._addControls( self.lowCrv_ctl, lowCtlOptions, True) self.lips_R_Corner_ctl = self.upCtls[0] self.lips_R_upOuter_ctl = self.upCtls[1] self.lips_R_upInner_ctl = self.upCtls[2] self.lips_C_upper_ctl = self.upCtls[3] self.lips_L_upInner_ctl = self.upCtls[4] self.lips_L_upOuter_ctl = self.upCtls[5] self.lips_L_Corner_ctl = self.upCtls[6] self.lips_R_lowOuter_ctl = self.lowCtls[0] self.lips_R_lowInner_ctl = self.lowCtls[1] self.lips_C_lower_ctl = self.lowCtls[2] self.lips_L_lowInner_ctl = self.lowCtls[3] self.lips_L_lowOuter_ctl = self.lowCtls[4] self.lips_R_Corner_npo = self.upNpos[0] self.lips_R_upOuter_npo = self.upNpos[1] self.lips_R_upInner_npo = self.upNpos[2] self.lips_C_upper_npo = self.upNpos[3] self.lips_L_upInner_npo = self.upNpos[4] self.lips_L_upOuter_npo = self.upNpos[5] self.lips_L_Corner_npo = self.upNpos[6] self.lips_R_lowOuter_npo = self.lowNpos[0] self.lips_R_lowInner_npo = self.lowNpos[1] self.lips_C_lower_npo = self.lowNpos[2] self.lips_L_lowInner_npo = self.lowNpos[3] self.lips_L_lowOuter_npo = self.lowNpos[4] upvec = self.upUpvs + self.lowUpvs pm.parent(self.lips_R_upOuter_npo, self.lips_R_lowOuter_npo, self.lips_R_Corner_ctl) pm.parent(self.lips_R_upInner_npo, self.lips_L_upInner_npo, self.lips_C_upper_ctl) pm.parent(self.lips_L_upOuter_npo, self.lips_L_lowOuter_npo, self.lips_L_Corner_ctl) pm.parent(self.lips_R_lowInner_npo, self.lips_L_lowInner_npo, self.lips_C_lower_ctl) # Connecting control crvs with controls applyop.gear_curvecns_op(self.upCrv_ctl, self.upCtls) applyop.gear_curvecns_op(self.lowCrv_ctl, [self.upCtls[0]] + self.lowCtls + [self.upCtls[-1]]) applyop.gear_curvecns_op(self.upCrv_upv, upvec) applyop.gear_curvecns_op(self.lowCrv_upv, [upvec[0]] + self.lowUpvs + [upvec[-1]]) # adding wires pm.wire(self.upCrv, w=self.upCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(self.lowCrv, w=self.lowCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(self.upRope, w=self.upCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(self.lowRope, w=self.lowCrv_ctl, dropoffDistance=[0, 1000]) pm.wire(self.upRope_upv, w=self.upCrv_upv, dropoffDistance=[0, 1000]) pm.wire(self.lowRope_upv, w=self.lowCrv_upv, dropoffDistance=[0, 1000]) return
def rig( eyeMesh=None, edgeLoop="", blinkH=20, namePrefix="eye", offset=0.05, rigidLoops=2, falloffLoops=4, headJnt=None, doSkin=True, parent_node=None, ctlName="ctl", sideRange=False, customCorner=False, intCorner=None, extCorner=None, ctlSet=None, defSet=None, upperVTrack=0.02, upperHTrack=0.01, lowerVTrack=0.02, lowerHTrack=0.01, aim_controller="", deformers_group="", everyNVertex=1, ): """Create eyelid and eye rig Args: eyeMesh (TYPE): Description edgeLoop (TYPE): Description blinkH (TYPE): Description namePrefix (TYPE): Description offset (TYPE): Description rigidLoops (TYPE): Description falloffLoops (TYPE): Description headJnt (TYPE): Description doSkin (TYPE): Description parent_node (None, optional): Description ctlName (str, optional): Description sideRange (bool, optional): Description customCorner (bool, optional): Description intCorner (None, optional): Description extCorner (None, optional): Description ctlSet (None, optional): Description defSet (None, optional): Description upperVTrack (None, optional): Description upperHTrack (None, optional): Description lowerVTrack (None, optional): Description lowerHTrack (None, optional): Description aim_controller (None, optional): Description deformers_group (None, optional): Description everyNVertex (int, optional): Will create a joint every N vertex No Longer Returned: TYPE: Description """ ########################################## # INITIAL SETUP ########################################## up_axis = pm.upAxis(q=True, axis=True) if up_axis == "z": z_up = True else: z_up = False # getters edgeLoopList = get_edge_loop(edgeLoop) eyeMesh = get_eye_mesh(eyeMesh) # checkers if not edgeLoopList or not eyeMesh: return if doSkin: if not headJnt: pm.displayWarning("Please set the Head Jnt or unCheck " "Compute Topological Autoskin") return # Convert data blinkH = blinkH / 100.0 # Initial Data bboxCenter = meshNavigation.bboxCenter(eyeMesh) extr_v = meshNavigation.getExtremeVertexFromLoop(edgeLoopList, sideRange, z_up) upPos = extr_v[0] lowPos = extr_v[1] inPos = extr_v[2] outPos = extr_v[3] edgeList = extr_v[4] vertexList = extr_v[5] # Detect the side L or R from the x value if inPos.getPosition(space="world")[0] < 0.0: side = "R" inPos = extr_v[3] outPos = extr_v[2] normalPos = outPos npw = normalPos.getPosition(space="world") normalVec = npw - bboxCenter else: side = "L" normalPos = outPos npw = normalPos.getPosition(space="world") normalVec = bboxCenter - npw # Manual Vertex corners if customCorner: if intCorner: try: if side == "R": inPos = pm.PyNode(extCorner) else: inPos = pm.PyNode(intCorner) except pm.MayaNodeError: pm.displayWarning("%s can not be found" % intCorner) return else: pm.displayWarning("Please set the internal eyelid corner") return if extCorner: try: normalPos = pm.PyNode(extCorner) npw = normalPos.getPosition(space="world") if side == "R": outPos = pm.PyNode(intCorner) normalVec = npw - bboxCenter else: outPos = pm.PyNode(extCorner) normalVec = bboxCenter - npw except pm.MayaNodeError: pm.displayWarning("%s can not be found" % extCorner) return else: pm.displayWarning("Please set the external eyelid corner") return # Check if we have prefix: if namePrefix: namePrefix = string.removeInvalidCharacter(namePrefix) else: pm.displayWarning("Prefix is needed") return def setName(name, ind=None): namesList = [namePrefix, side, name] if ind is not None: namesList[1] = side + str(ind) name = "_".join(namesList) return name if pm.ls(setName("root")): pm.displayWarning("The object %s already exist in the scene. Please " "choose another name prefix" % setName("root")) return ########################################## # CREATE OBJECTS ########################################## # Eye root eye_root = primitive.addTransform(None, setName("root")) eyeCrv_root = primitive.addTransform(eye_root, setName("crvs")) # Eyelid Main crvs try: upEyelid_edge = meshNavigation.edgeRangeInLoopFromMid( edgeList, upPos, inPos, outPos) up_crv = curve.createCurveFromOrderedEdges(upEyelid_edge, inPos, setName("upperEyelid"), parent=eyeCrv_root) upCtl_crv = curve.createCurveFromOrderedEdges(upEyelid_edge, inPos, setName("upCtl_crv"), parent=eyeCrv_root) pm.rebuildCurve(upCtl_crv, s=2, rt=0, rpo=True, ch=False) lowEyelid_edge = meshNavigation.edgeRangeInLoopFromMid( edgeList, lowPos, inPos, outPos) low_crv = curve.createCurveFromOrderedEdges(lowEyelid_edge, inPos, setName("lowerEyelid"), parent=eyeCrv_root) lowCtl_crv = curve.createCurveFromOrderedEdges(lowEyelid_edge, inPos, setName("lowCtl_crv"), parent=eyeCrv_root) pm.rebuildCurve(lowCtl_crv, s=2, rt=0, rpo=True, ch=False) except UnboundLocalError: if customCorner: pm.displayWarning("This error is maybe caused because the custom " "Corner vertex is not part of the edge loop") pm.displayError(traceback.format_exc()) return # blendshape curves. All crv have 30 point to allow blendshape connect upDriver_crv = curve.createCurveFromCurve(up_crv, setName("upDriver_crv"), nbPoints=30, parent=eyeCrv_root) upDriver_crv.attr("lineWidth").set(5) lowDriver_crv = curve.createCurveFromCurve(low_crv, setName("lowDriver_crv"), nbPoints=30, parent=eyeCrv_root) lowDriver_crv.attr("lineWidth").set(5) upRest_target_crv = curve.createCurveFromCurve( up_crv, setName("upRest_target_crv"), nbPoints=30, parent=eyeCrv_root) lowRest_target_crv = curve.createCurveFromCurve( low_crv, setName("lowRest_target_crv"), nbPoints=30, parent=eyeCrv_root) upProfile_target_crv = curve.createCurveFromCurve( up_crv, setName("upProfile_target_crv"), nbPoints=30, parent=eyeCrv_root, ) lowProfile_target_crv = curve.createCurveFromCurve( low_crv, setName("lowProfile_target_crv"), nbPoints=30, parent=eyeCrv_root, ) # mid driver midUpDriver_crv = curve.createCurveFromCurve(up_crv, setName("midUpDriver_crv"), nbPoints=30, parent=eyeCrv_root) midLowDriver_crv = curve.createCurveFromCurve(low_crv, setName("midLowDriver_crv"), nbPoints=30, parent=eyeCrv_root) # curve that define the close point of the eyelid closeTarget_crv = curve.createCurveFromCurve(up_crv, setName("closeTarget_crv"), nbPoints=30, parent=eyeCrv_root) eyeCrv_root.attr("visibility").set(False) # localBBOX localBBox = eyeMesh.getBoundingBox(invisible=True, space="world") wRadius = abs((localBBox[0][0] - localBBox[1][0])) dRadius = abs((localBBox[0][1] - localBBox[1][1]) / 1.7) # Groups if not ctlSet: ctlSet = "rig_controllers_grp" try: ctlSet = pm.PyNode(ctlSet) except pm.MayaNodeError: pm.sets(n=ctlSet, em=True) ctlSet = pm.PyNode(ctlSet) if not defSet: defSet = "rig_deformers_grp" try: defset = pm.PyNode(defSet) except pm.MayaNodeError: pm.sets(n=defSet, em=True) defset = pm.PyNode(defSet) # Calculate center looking at averagePosition = (upPos.getPosition(space="world") + lowPos.getPosition( space="world") + inPos.getPosition(space="world") + outPos.getPosition(space="world")) / 4 if z_up: axis = "zx" else: axis = "z-x" t = transform.getTransformLookingAt(bboxCenter, averagePosition, normalVec, axis=axis, negate=False) over_npo = primitive.addTransform(eye_root, setName("center_lookatRoot"), t) center_lookat = primitive.addTransform(over_npo, setName("center_lookat"), t) if side == "R": over_npo.attr("rx").set(over_npo.attr("rx").get() * -1) over_npo.attr("ry").set(over_npo.attr("ry").get() + 180) over_npo.attr("sz").set(-1) t = transform.getTransform(over_npo) # Tracking # Eye aim control t_arrow = transform.getTransformLookingAt( bboxCenter, averagePosition, upPos.getPosition(space="world"), axis="zy", negate=False, ) radius = abs((localBBox[0][0] - localBBox[1][0]) / 1.7) arrow_ctl = None arrow_npo = None if aim_controller: arrow_ctl = pm.PyNode(aim_controller) else: arrow_npo = primitive.addTransform(eye_root, setName("aim_npo"), t_arrow) arrow_ctl = icon.create( arrow_npo, setName("aim_%s" % ctlName), t_arrow, icon="arrow", w=1, po=datatypes.Vector(0, 0, radius), color=4, ) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=arrow_ctl) attribute.setKeyableAttributes(arrow_ctl, params=["rx", "ry", "rz"]) attribute.addAttribute(arrow_ctl, "isCtl", "bool", keyable=False) # tracking custom trigger if side == "R": tt = t_arrow else: tt = t aimTrigger_root = primitive.addTransform(center_lookat, setName("aimTrigger_root"), tt) # For some unknown reason the right side gets scewed rotation values mgear.core.transform.resetTransform(aimTrigger_root) aimTrigger_lvl = primitive.addTransform(aimTrigger_root, setName("aimTrigger_lvl"), tt) # For some unknown reason the right side gets scewed rotation values mgear.core.transform.resetTransform(aimTrigger_lvl) aimTrigger_lvl.attr("tz").set(1.0) aimTrigger_ref = primitive.addTransform(aimTrigger_lvl, setName("aimTrigger_ref"), tt) # For some unknown reason the right side gets scewed rotation values mgear.core.transform.resetTransform(aimTrigger_ref) aimTrigger_ref.attr("tz").set(0.0) # connect trigger with arrow_ctl pm.parentConstraint(arrow_ctl, aimTrigger_ref, mo=True) # Blink driver controls if z_up: trigger_axis = "tz" ro_up = [0, 1.57079633 * 2, 1.57079633] ro_low = [0, 0, 1.57079633] po = [0, offset * -1, 0] low_pos = 2 # Z else: trigger_axis = "ty" ro_up = (1.57079633, 1.57079633, 0) ro_low = [1.57079633, 1.57079633, 1.57079633 * 2] po = [0, 0, offset] low_pos = 1 # Y # upper ctl p = upRest_target_crv.getCVs(space="world")[15] ut = transform.setMatrixPosition(datatypes.Matrix(), p) npo = primitive.addTransform(over_npo, setName("upBlink_npo"), ut) up_ctl = icon.create( npo, setName("upBlink_ctl"), ut, icon="arrow", w=2.5, d=2.5, ro=datatypes.Vector(ro_up[0], ro_up[1], ro_up[2]), po=datatypes.Vector(po[0], po[1], po[2]), color=4, ) attribute.setKeyableAttributes(up_ctl, [trigger_axis]) pm.sets(ctlSet, add=up_ctl) # use translation of the object to drive the blink blink_driver = primitive.addTransform(up_ctl, setName("blink_drv"), ut) # lowe ctl p_low = lowRest_target_crv.getCVs(space="world")[15] p[low_pos] = p_low[low_pos] lt = transform.setMatrixPosition(ut, p) npo = primitive.addTransform(over_npo, setName("lowBlink_npo"), lt) low_ctl = icon.create( npo, setName("lowBlink_ctl"), lt, icon="arrow", w=1.5, d=1.5, ro=datatypes.Vector(ro_low[0], ro_low[1], ro_low[2]), po=datatypes.Vector(po[0], po[1], po[2]), color=4, ) attribute.setKeyableAttributes(low_ctl, [trigger_axis]) pm.sets(ctlSet, add=low_ctl) # Controls lists upControls = [] trackLvl = [] track_corner_lvl = [] corner_ctl = [] ghost_ctl = [] # upper eyelid controls upperCtlNames = ["inCorner", "upInMid", "upMid", "upOutMid", "outCorner"] cvs = upCtl_crv.getCVs(space="world") if side == "R" and not sideRange: # if side == "R": cvs = [cv for cv in reversed(cvs)] # offset = offset * -1 for i, cv in enumerate(cvs): if utils.is_odd(i): color = 14 wd = 0.3 icon_shape = "circle" params = ["tx", "ty", "tz"] else: color = 4 wd = 0.6 icon_shape = "circle" params = [ "tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz", ] t = transform.setMatrixPosition(t, cvs[i]) npo = primitive.addTransform(center_lookat, setName("%s_npo" % upperCtlNames[i]), t) npoBase = npo # track for corners and mid point level if i in [0, 2, 4]: # we add an extra level to input the tracking ofset values npo = primitive.addTransform(npo, setName("%s_trk" % upperCtlNames[i]), t) if i == 2: trackLvl.append(npo) else: track_corner_lvl.append(npo) if i in [1, 2, 3]: ctl = primitive.addTransform(npo, setName("%s_loc" % upperCtlNames[i]), t) # ghost controls if i == 2: gt = transform.setMatrixPosition( t, transform.getPositionFromMatrix(ut)) else: gt = t npo_g = primitive.addTransform( up_ctl, setName("%sCtl_npo" % upperCtlNames[i]), gt) ctl_g = icon.create( npo_g, setName("%s_%s" % (upperCtlNames[i], ctlName)), gt, icon=icon_shape, w=wd, d=wd, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, offset), color=color, ) # define the ctl_param to recive the ctl configuration ctl_param = ctl_g ghost_ctl.append(ctl_g) # connect local SRT rigbits.connectLocalTransform([ctl_g, ctl]) else: ctl = icon.create( npo, setName("%s_%s" % (upperCtlNames[i], ctlName)), t, icon=icon_shape, w=wd, d=wd, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, offset), color=color, ) # define the ctl_param to recive the ctl configuration ctl_param = ctl attribute.addAttribute(ctl_param, "isCtl", "bool", keyable=False) attribute.add_mirror_config_channels(ctl_param) node.add_controller_tag(ctl_param, over_npo) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=ctl_param) attribute.setKeyableAttributes(ctl_param, params) upControls.append(ctl) # add corner ctls to corner ctl list for tracking if i in [0, 4]: corner_ctl.append(ctl) # if side == "R": # npoBase.attr("ry").set(180) # npoBase.attr("sz").set(-1) # adding parent constraints to odd controls for i, ctl in enumerate(upControls): if utils.is_odd(i): cns_node = pm.parentConstraint(upControls[i - 1], upControls[i + 1], ctl.getParent(), mo=True) # Make the constraint "noFlip" cns_node.interpType.set(0) # adding parent constraint ghost controls cns_node = pm.parentConstraint(ghost_ctl[1], upControls[0], ghost_ctl[0].getParent(), mo=True) cns_node.interpType.set(0) cns_node = pm.parentConstraint(ghost_ctl[1], upControls[-1], ghost_ctl[2].getParent(), mo=True) cns_node.interpType.set(0) # lower eyelid controls lowControls = [upControls[0]] lowerCtlNames = [ "inCorner", "lowInMid", "lowMid", "lowOutMid", "outCorner", ] cvs = lowCtl_crv.getCVs(space="world") if side == "R" and not sideRange: cvs = [cv for cv in reversed(cvs)] for i, cv in enumerate(cvs): # we skip the first and last point since is already in the uper eyelid if i in [0, 4]: continue if utils.is_odd(i): color = 14 wd = 0.3 icon_shape = "circle" params = ["tx", "ty", "tz"] else: color = 4 wd = 0.6 icon_shape = "circle" params = [ "tx", "ty", "tz", "ro", "rx", "ry", "rz", "sx", "sy", "sz", ] t = transform.setMatrixPosition(t, cvs[i]) npo = primitive.addTransform(center_lookat, setName("%s_npo" % lowerCtlNames[i]), t) npoBase = npo if i in [1, 2, 3]: if i == 2: # we add an extra level to input the tracking ofset values npo = primitive.addTransform( npo, setName("%s_trk" % lowerCtlNames[i]), t) trackLvl.append(npo) ctl = primitive.addTransform(npo, setName("%s_loc" % lowerCtlNames[i]), t) # ghost controls if i == 2: gt = transform.setMatrixPosition( t, transform.getPositionFromMatrix(lt)) else: gt = t # ghost controls npo_g = primitive.addTransform( low_ctl, setName("%sCtl_npo" % lowerCtlNames[i]), gt) ctl_g = icon.create( npo_g, setName("%s_%s" % (lowerCtlNames[i], ctlName)), gt, icon=icon_shape, w=wd, d=wd, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, offset), color=color, ) # define the ctl_param to recive the ctl configuration ctl_param = ctl_g ghost_ctl.append(ctl_g) # connect local SRT rigbits.connectLocalTransform([ctl_g, ctl]) else: ctl = icon.create( npo, setName("%s_%s" % (lowerCtlNames[i], ctlName)), t, icon=icon_shape, w=wd, d=wd, ro=datatypes.Vector(1.57079633, 0, 0), po=datatypes.Vector(0, 0, offset), color=color, ) # define the ctl_param to recive the ctl configuration ctl_param = ctl attribute.addAttribute(ctl_param, "isCtl", "bool", keyable=False) attribute.add_mirror_config_channels(ctl_param) lowControls.append(ctl) if len(ctlName.split("_")) == 2 and ctlName.split("_")[-1] == "ghost": pass else: pm.sets(ctlSet, add=ctl_param) attribute.setKeyableAttributes(ctl_param, params) # mirror behaviout on R side controls # if side == "R": # npoBase.attr("ry").set(180) # npoBase.attr("sz").set(-1) for lctl in reversed(lowControls[1:]): node.add_controller_tag(lctl, over_npo) lowControls.append(upControls[-1]) # adding parent constraints to odd controls for i, ctl in enumerate(lowControls): if utils.is_odd(i): cns_node = pm.parentConstraint( lowControls[i - 1], lowControls[i + 1], ctl.getParent(), mo=True, ) # Make the constraint "noFlip" cns_node.interpType.set(0) # adding parent constraint ghost controls cns_node = pm.parentConstraint(ghost_ctl[4], upControls[0], ghost_ctl[3].getParent(), mo=True) cns_node.interpType.set(0) cns_node = pm.parentConstraint(ghost_ctl[4], upControls[-1], ghost_ctl[5].getParent(), mo=True) cns_node.interpType.set(0) ########################################## # OPERATORS ########################################## # Connecting control crvs with controls applyop.gear_curvecns_op(upCtl_crv, upControls) applyop.gear_curvecns_op(lowCtl_crv, lowControls) # adding wires w1 = pm.wire(up_crv, w=upDriver_crv)[0] w2 = pm.wire(low_crv, w=lowDriver_crv)[0] w3 = pm.wire(upProfile_target_crv, w=upCtl_crv)[0] w4 = pm.wire(lowProfile_target_crv, w=lowCtl_crv)[0] if z_up: trigger_axis = "tz" else: trigger_axis = "ty" # connect blink driver pm.pointConstraint(low_ctl, blink_driver, mo=False) rest_val = blink_driver.attr(trigger_axis).get() up_div_node = node.createDivNode(up_ctl.attr(trigger_axis), rest_val) low_div_node = node.createDivNode(low_ctl.attr(trigger_axis), rest_val * -1) # contact driver minus_node = node.createPlusMinusAverage1D( [rest_val, blink_driver.attr(trigger_axis)], operation=2) contact_div_node = node.createDivNode(minus_node.output1D, rest_val) # wire tension for w in [w1, w2, w3, w4]: w.dropoffDistance[0].set(100) # TODO: what is the best solution? # trigger using proximity # remap_node = pm.createNode("remapValue") # contact_div_node.outputX >> remap_node.inputValue # remap_node.value[0].value_Interp.set(2) # remap_node.inputMin.set(0.995) # reverse_node = node.createReverseNode(remap_node.outColorR) # for w in [w1, w2]: # reverse_node.outputX >> w.scale[0] # trigger at starting movement for up and low # up remap_node = pm.createNode("remapValue") up_ctl.attr(trigger_axis) >> remap_node.inputValue remap_node.value[0].value_Interp.set(2) remap_node.inputMax.set(rest_val / 8) reverse_node = node.createReverseNode(remap_node.outColorR) reverse_node.outputX >> w1.scale[0] # low remap_node = pm.createNode("remapValue") low_ctl.attr(trigger_axis) >> remap_node.inputValue remap_node.value[0].value_Interp.set(2) remap_node.inputMin.set((rest_val / 8) * -1) remap_node.outColorR >> w2.scale[0] # mid position drivers blendshapes bs_midUpDrive = pm.blendShape( lowRest_target_crv, upProfile_target_crv, midUpDriver_crv, n="midUpDriver_blendShape", ) bs_midLowDrive = pm.blendShape( upRest_target_crv, lowProfile_target_crv, midLowDriver_crv, n="midlowDriver_blendShape", ) bs_closeTarget = pm.blendShape( midUpDriver_crv, midLowDriver_crv, closeTarget_crv, n="closeTarget_blendShape", ) pm.connectAttr( up_div_node.outputX, bs_midUpDrive[0].attr(lowRest_target_crv.name()), ) pm.connectAttr( low_div_node.outputX, bs_midLowDrive[0].attr(upRest_target_crv.name()), ) pm.setAttr(bs_closeTarget[0].attr(midUpDriver_crv.name()), 0.5) pm.setAttr(bs_closeTarget[0].attr(midLowDriver_crv.name()), 0.5) # Main crv drivers bs_upBlink = pm.blendShape( lowRest_target_crv, closeTarget_crv, upProfile_target_crv, upDriver_crv, n="upBlink_blendShape", ) bs_lowBlink = pm.blendShape( upRest_target_crv, closeTarget_crv, lowProfile_target_crv, lowDriver_crv, n="lowBlink_blendShape", ) # blink contact connections cond_node_up = node.createConditionNode(contact_div_node.outputX, 1, 3, 0, up_div_node.outputX) pm.connectAttr( cond_node_up.outColorR, bs_upBlink[0].attr(lowRest_target_crv.name()), ) cond_node_low = node.createConditionNode(contact_div_node.outputX, 1, 3, 0, low_div_node.outputX) pm.connectAttr( cond_node_low.outColorR, bs_lowBlink[0].attr(upRest_target_crv.name()), ) cond_node_close = node.createConditionNode(contact_div_node.outputX, 1, 2, 1, 0) cond_node_close.colorIfFalseR.set(0) pm.connectAttr( cond_node_close.outColorR, bs_upBlink[0].attr(closeTarget_crv.name()), ) pm.connectAttr( cond_node_close.outColorR, bs_lowBlink[0].attr(closeTarget_crv.name()), ) pm.setAttr(bs_upBlink[0].attr(upProfile_target_crv.name()), 1) pm.setAttr(bs_lowBlink[0].attr(lowProfile_target_crv.name()), 1) # joints root jnt_root = primitive.addTransformFromPos(eye_root, setName("joints"), pos=bboxCenter) if deformers_group: deformers_group = pm.PyNode(deformers_group) pm.parentConstraint(eye_root, jnt_root, mo=True) pm.scaleConstraint(eye_root, jnt_root, mo=True) deformers_group.addChild(jnt_root) # head joint if headJnt: try: headJnt = pm.PyNode(headJnt) jnt_base = headJnt except pm.MayaNodeError: pm.displayWarning("Aborted can not find %s " % headJnt) return else: # Eye root jnt_base = jnt_root eyeTargets_root = primitive.addTransform(eye_root, setName("targets")) eyeCenter_jnt = rigbits.addJnt(arrow_ctl, jnt_base, grp=defset, jntName=setName("center_jnt")) # Upper Eyelid joints ################################################## cvs = up_crv.getCVs(space="world") upCrv_info = node.createCurveInfoNode(up_crv) # aim constrain targets and joints upperEyelid_aimTargets = [] upperEyelid_jnt = [] upperEyelid_jntRoot = [] if z_up: axis = "zy" wupVector = [0, 0, 1] else: axis = "-yz" wupVector = [0, 1, 0] for i, cv in enumerate(cvs): if i % everyNVertex: continue # aim targets trn = primitive.addTransformFromPos(eyeTargets_root, setName("upEyelid_aimTarget", i), pos=cv) upperEyelid_aimTargets.append(trn) # connecting positions with crv pm.connectAttr(upCrv_info + ".controlPoints[%s]" % str(i), trn.attr("translate")) # joints jntRoot = primitive.addJointFromPos(jnt_root, setName("upEyelid_jnt_base", i), pos=bboxCenter) jntRoot.attr("radius").set(0.08) jntRoot.attr("visibility").set(False) upperEyelid_jntRoot.append(jntRoot) applyop.aimCns(jntRoot, trn, axis=axis, wupObject=jnt_root, wupVector=wupVector) jnt_ref = primitive.addJointFromPos(jntRoot, setName("upEyelid_jnt_ref", i), pos=cv) jnt_ref.attr("radius").set(0.08) jnt_ref.attr("visibility").set(False) jnt = rigbits.addJnt(jnt_ref, jnt_base, grp=defset, jntName=setName("upEyelid_jnt", i)) upperEyelid_jnt.append(jnt) # Lower Eyelid joints ################################################## cvs = low_crv.getCVs(space="world") lowCrv_info = node.createCurveInfoNode(low_crv) # aim constrain targets and joints lowerEyelid_aimTargets = [] lowerEyelid_jnt = [] lowerEyelid_jntRoot = [] for i, cv in enumerate(cvs): if i in [0, len(cvs) - 1]: continue if i % everyNVertex: continue # aim targets trn = primitive.addTransformFromPos(eyeTargets_root, setName("lowEyelid_aimTarget", i), pos=cv) lowerEyelid_aimTargets.append(trn) # connecting positions with crv pm.connectAttr(lowCrv_info + ".controlPoints[%s]" % str(i), trn.attr("translate")) # joints jntRoot = primitive.addJointFromPos(jnt_root, setName("lowEyelid_base", i), pos=bboxCenter) jntRoot.attr("radius").set(0.08) jntRoot.attr("visibility").set(False) lowerEyelid_jntRoot.append(jntRoot) applyop.aimCns(jntRoot, trn, axis=axis, wupObject=jnt_root, wupVector=wupVector) jnt_ref = primitive.addJointFromPos(jntRoot, setName("lowEyelid_jnt_ref", i), pos=cv) jnt_ref.attr("radius").set(0.08) jnt_ref.attr("visibility").set(False) jnt = rigbits.addJnt(jnt_ref, jnt_base, grp=defset, jntName=setName("lowEyelid_jnt", i)) lowerEyelid_jnt.append(jnt) # Adding channels for eye tracking upVTracking_att = attribute.addAttribute(up_ctl, "vTracking", "float", upperVTrack, minValue=0) upHTracking_att = attribute.addAttribute(up_ctl, "hTracking", "float", upperHTrack, minValue=0) lowVTracking_att = attribute.addAttribute(low_ctl, "vTracking", "float", lowerVTrack, minValue=0) lowHTracking_att = attribute.addAttribute(low_ctl, "hTracking", "float", lowerHTrack, minValue=0) # vertical tracking connect up_mult_node = node.createMulNode(upVTracking_att, aimTrigger_ref.attr("ty")) low_mult_node = node.createMulNode(lowVTracking_att, aimTrigger_ref.attr("ty")) # remap to use the low or the up eyelid as driver contact base on # the eyetrack trigger direction uT_remap_node = pm.createNode("remapValue") aimTrigger_ref.attr("ty") >> uT_remap_node.inputValue uT_remap_node.inputMax.set(0.1) uT_remap_node.inputMin.set(-0.1) up_mult_node.outputX >> uT_remap_node.outputMax low_mult_node.outputX >> uT_remap_node.outputMin # up u_remap_node = pm.createNode("remapValue") contact_div_node.outputX >> u_remap_node.inputValue u_remap_node.value[0].value_Interp.set(2) u_remap_node.inputMin.set(0.9) up_mult_node.outputX >> u_remap_node.outputMin uT_remap_node.outColorR >> u_remap_node.outputMax # low l_remap_node = pm.createNode("remapValue") contact_div_node.outputX >> l_remap_node.inputValue l_remap_node.value[0].value_Interp.set(2) l_remap_node.inputMin.set(0.9) low_mult_node.outputX >> l_remap_node.outputMin uT_remap_node.outColorR >> l_remap_node.outputMax # up connect and turn down to low when contact pm.connectAttr(u_remap_node.outColorR, trackLvl[0].attr("ty")) pm.connectAttr(l_remap_node.outColorR, trackLvl[1].attr("ty")) # horizontal tracking connect mult_node = node.createMulNode(upHTracking_att, aimTrigger_ref.attr("tx")) # Correct right side horizontal tracking # if side == "R": # mult_node = node.createMulNode(mult_node.attr("outputX"), -1) pm.connectAttr(mult_node + ".outputX", trackLvl[0].attr("tx")) mult_node = node.createMulNode(lowHTracking_att, aimTrigger_ref.attr("tx")) # Correct right side horizontal tracking # if side == "R": # mult_node = node.createMulNode(mult_node.attr("outputX"), -1) pm.connectAttr(mult_node + ".outputX", trackLvl[1].attr("tx")) # adding channels for corner tracking # track_corner_lvl for i, ctl in enumerate(corner_ctl): VTracking_att = attribute.addAttribute(ctl, "vTracking", "float", 0.1, minValue=0) if z_up: mult_node = node.createMulNode(VTracking_att, up_ctl.tz) mult_node2 = node.createMulNode(VTracking_att, low_ctl.tz) plus_node = node.createPlusMinusAverage1D( [mult_node.outputX, mult_node2.outputX]) mult_node3 = node.createMulNode(plus_node.output1D, -1) pm.connectAttr(mult_node3.outputX, track_corner_lvl[i].attr("ty")) else: mult_node = node.createMulNode(VTracking_att, up_ctl.ty) mult_node2 = node.createMulNode(VTracking_att, low_ctl.ty) plus_node = node.createPlusMinusAverage1D( [mult_node.outputX, mult_node2.outputX]) pm.connectAttr(plus_node.output1D, track_corner_lvl[i].attr("ty")) ########################################### # Reparenting ########################################### if parent_node: try: if isinstance(parent_node, string_types): parent_node = pm.PyNode(parent_node) parent_node.addChild(eye_root) except pm.MayaNodeError: pm.displayWarning("The eye rig can not be parent to: %s. Maybe " "this object doesn't exist." % parent_node) ########################################### # Auto Skinning ########################################### if doSkin: # eyelid vertex rows totalLoops = rigidLoops + falloffLoops vertexLoopList = meshNavigation.getConcentricVertexLoop( vertexList, totalLoops) vertexRowList = meshNavigation.getVertexRowsFromLoops(vertexLoopList) # we set the first value 100% for the first initial loop skinPercList = [1.0] # we expect to have a regular grid topology for r in range(rigidLoops): for rr in range(2): skinPercList.append(1.0) increment = 1.0 / float(falloffLoops) # we invert to smooth out from 100 to 0 inv = 1.0 - increment for r in range(falloffLoops): for rr in range(2): if inv < 0.0: inv = 0.0 skinPercList.append(inv) inv -= increment # this loop add an extra 0.0 indices to avoid errors for r in range(10): for rr in range(2): skinPercList.append(0.0) # base skin geo = pm.listRelatives(edgeLoopList[0], parent=True)[0] # Check if the object has a skinCluster objName = pm.listRelatives(geo, parent=True)[0] skinCluster = skin.getSkinCluster(objName) if not skinCluster: skinCluster = pm.skinCluster(headJnt, geo, tsb=True, nw=2, n="skinClsEyelid") eyelidJoints = upperEyelid_jnt + lowerEyelid_jnt pm.progressWindow(title="Auto skinning process", progress=0, max=len(eyelidJoints)) firstBoundary = False for jnt in eyelidJoints: pm.progressWindow(e=True, step=1, status="\nSkinning %s" % jnt) skinCluster.addInfluence(jnt, weight=0) v = meshNavigation.getClosestVertexFromTransform(geo, jnt) for row in vertexRowList: if v in row: it = 0 # iterator inc = 1 # increment for i, rv in enumerate(row): try: perc = skinPercList[it] t_val = [(jnt, perc), (headJnt, 1.0 - perc)] pm.skinPercent(skinCluster, rv, transformValue=t_val) if rv.isOnBoundary(): # we need to compare with the first boundary # to check if the row have inverted direction # and offset the value if not firstBoundary: firstBoundary = True firstBoundaryValue = it else: if it < firstBoundaryValue: it -= 1 elif it > firstBoundaryValue: it += 1 inc = 2 except IndexError: continue it = it + inc pm.progressWindow(e=True, endProgress=True) # Eye Mesh skinning skinCluster = skin.getSkinCluster(eyeMesh) if not skinCluster: skinCluster = pm.skinCluster(eyeCenter_jnt, eyeMesh, tsb=True, nw=1, n="skinClsEye")
def doRig(self): anchorList = [] cntrlList = [] locList = [] dummyCrv = self.ribbonDict['moveallSetup']['nameTempl'] + '_dummy_crv' pm.hide(pm.polyCube(n=dummyCrv)) if pm.objExists(self.ribbonDict['noMoveSetup']['nameTempl']): pm.delete(self.ribbonDict['noMoveSetup']['nameTempl']) if pm.objExists(self.ribbonDict['moveallSetup']['nameTempl']): pm.delete(self.ribbonDict['moveallSetup']['nameTempl']) logger ###Estrutura que nao deve ter transformacao noMoveSpace = pm.group(empty=True, n=self.ribbonDict['noMoveSetup']['nameTempl']) if not pm.objExists('NOMOVE'): pm.group(self.ribbonDict['noMoveSetup']['nameTempl'], n='NOMOVE') else: pm.parent(self.ribbonDict['noMoveSetup']['nameTempl'], 'NOMOVE') pm.parent(self.ribbonDict['moveallSetup']['nameTempl'] + '_dummy_crv', noMoveSpace) noMoveSpace.visibility.set(0) noMoveBend1 = pm.nurbsPlane(p=(self.size * 0.5, 0, 0), ax=(0, 0, 1), w=self.size, lr=0.1, d=3, u=5, v=1) # noMoveCrvJnt = pm.curve ( bezier=True, d=3, p=[(self.size*-0.5,0,0),(self.size*-0.4,0,0),(self.size*-0.1,0,0),(0,0,0),(self.size*0.1,0,0),(self.size*0.4,0,0),(self.size*0.5,0,0)], k=[0,0,0,1,1,1,2,2,2]) noMoveCrvJnt = pm.curve( bezier=True, d=3, p=[(self.size * -0.50, 0, 0), (self.size * -0.499, 0, 0), (self.size * -0.496, 0, 0), (self.size * -0.495, 0, 0), (self.size * -0.395, 0, 0), (self.size * -0.10, 0, 0), (0, 0, 0), (self.size * 0.10, 0, 0), (self.size * 0.395, 0, 0), (self.size * 0.495, 0, 0), (self.size * 0.496, 0, 0), (self.size * 0.499, 0, 0), (self.size * 0.50, 0, 0)], k=[0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10]) noMoveCrvJnt.translate.set(self.size * 0.5, 0, 0) # Deformers das superficies noMove twist1 = pm.nonLinear(noMoveBend1[0], type='twist') # twist das superficies noMove twist1[1].rotateZ.set(90) # IMPLEMENTAR O TWIST DO MEIO twist2 = pm.nonLinear(noMoveBend1[0].name() + '.cv[0:3][0:3]', type='twist') # twist das superficies noMove twist2[1].rotateZ.set(90) twist3 = pm.nonLinear(noMoveBend1[0].name() + '.cv[4:7][0:3]', type='twist') # twist das superficies noMove twist3[1].rotateZ.set(90) wireDef = pm.wire(noMoveBend1[0], w=noMoveCrvJnt, dds=[(0, 50)]) # Wire das superficies noMove wireDef[0].rotation.set(1) # seta rotacao pra acontecer baseWire = [ x for x in wireDef[0].connections() if 'BaseWire' in x.name() ] pm.group(baseWire, noMoveCrvJnt, noMoveBend1[0], p=noMoveSpace, n=self.name + 'Deforms_grp') pm.parent(twist1[1], twist2[1], twist3[1], noMoveSpace) ###Estrutura que pode ser movida cntrlsSpace = pm.group(empty=True, n=self.ribbonDict['moveallSetup']['nameTempl']) bendSurf1 = pm.nurbsPlane(p=(self.size * -0.5, 0, 0), ax=(0, 0, 1), w=self.size * 0.5, lr=.1, d=3, u=5, v=1) blend1 = pm.blendShape(noMoveBend1[0], bendSurf1[0]) pm.blendShape(blend1, e=True, w=[(0, 1)]) pm.parent(bendSurf1[0], cntrlsSpace) ##Cntrls for i in range(0, 7): anchor = pm.cluster(noMoveCrvJnt.name() + '.cv[' + str(i + 3) + ']') pm.cluster(anchor[1], e=True, g=dummyCrv) clsHandle = anchor[1] anchorGrp = pm.group(em=True, n='clusterGrp' + str(i)) anchorDrn = pm.group(em=True, n='clusterDrn' + str(i), p=anchorGrp) pos = pm.xform(anchor, q=True, ws=True, rp=True) pm.xform(anchorGrp, t=pos, ws=True) pm.parent(anchor[1], anchorDrn) anchorList.append(anchor[1]) if i == 0 or i == 6: displaySetup = self.ribbonDict['cntrlSetup'].copy() cntrlName = displaySetup['nameTempl'] + str(i) cntrl = controlTools.cntrlCrv(name=cntrlName, obj=anchor[1], **displaySetup) elif i == 3: displaySetup = self.ribbonDict['midCntrlSetup'].copy() cntrlName = displaySetup['nameTempl'] + str(i) cntrl = controlTools.cntrlCrv(name=cntrlName, obj=anchor[1], **displaySetup) else: displaySetup = self.ribbonDict['cntrlTangSetup'].copy() cntrlName = displaySetup['nameTempl'] + str(i) cntrl = controlTools.cntrlCrv(name=cntrlName, obj=anchor[1], **displaySetup) # Nao pode fazer conexao na criacao do controle, pois tera conexao direta pm.xform(cntrl.getParent(), t=pos, ws=True) # estrutura de buffers para conexao direta auxLocGrp = pm.group(em=True, n=self.name + 'auxLoc_grp') auxLoc = pm.group(em=True, p=auxLocGrp, n=self.name + 'aux_loc') pm.xform(auxLocGrp, t=pos, ws=True) loc = pm.PyNode(auxLoc) if i == 1 or i == 4: pm.xform(anchorGrp, s=(-1, 1, 1), r=True) pm.xform(cntrl.getParent(), s=(-1, 1, 1), r=True) pm.xform(loc.getParent(), s=(-1, 1, 1), r=True) # Conexoes dos buffers cm os clusters e com os controles pm.parentConstraint(cntrl, loc) loc.translate >> anchorDrn.translate loc.rotate >> anchorDrn.rotate cntrlList.append(cntrl) locList.append(loc) startCls = pm.cluster(noMoveCrvJnt.name() + '.cv[0:2]') endCls = pm.cluster(noMoveCrvJnt.name() + '.cv[10:14]') pm.cluster(startCls[1], e=True, g=dummyCrv) pm.cluster(endCls[1], e=True, g=dummyCrv) pm.parent(startCls, anchorList[0]) pm.parent(endCls, anchorList[6]) cntrlsSpace.addAttr('cntrlsVis', at='double', dv=1, k=True, h=False) cntrlsSpace.addAttr('extraCntrlsVis', at='double', dv=0, k=True, h=False) cntrlList[0].addAttr('twist', at='double', dv=0, k=True) cntrlList[0].addAttr('stretchDist', at='double', dv=0, k=True) cntrlList[0].addAttr('autoVolumStregth', at='double', dv=0, k=True) cntrlList[3].addAttr('twist', at='double', dv=0, k=True) cntrlList[3].addAttr('autoVolume', at='double', dv=0, k=True) cntrlList[6].addAttr('twist', at='double', dv=0, k=True) cntrlList[6].addAttr('stretchDist', at='double', dv=0, k=True) cntrlList[6].addAttr('autoVolumStregth', at='double', dv=0, k=True) cntrlList[0].twist >> twist1[0].endAngle cntrlList[3].twist >> twist2[0].startAngle cntrlList[3].twist >> twist3[0].endAngle cntrlList[6].twist >> twist1[0].startAngle # hierarquia pm.parent(anchorList[1].getParent(2), anchorList[0]) pm.parent(anchorList[5].getParent(2), anchorList[6]) pm.parent(anchorList[2].getParent(2), anchorList[4].getParent(2), anchorList[3]) pm.parent(cntrlList[1].getParent(), cntrlList[0]) pm.parent(cntrlList[5].getParent(), cntrlList[6]) pm.parent(cntrlList[2].getParent(), cntrlList[4].getParent(), cntrlList[3]) pm.parent(cntrlList[3].getParent(), cntrlList[0].getParent(), cntrlList[6].getParent(), cntrlsSpace) pm.parent(locList[1].getParent(), locList[0]) pm.parent(locList[5].getParent(), locList[6]) pm.parent(locList[2].getParent(), locList[4].getParent(), locList[3]) pm.parent(locList[3].getParent(), locList[0].getParent(), locList[6].getParent(), cntrlsSpace) pm.parent(anchorList[3].getParent(2), anchorList[0].getParent(2), anchorList[6].getParent(2), noMoveSpace) # Skin joints do ribbon skinJntsGrp = pm.group(em=True, n=self.name + 'SkinJnts_grp') follGrp = pm.group(em=True, n=self.name + 'Foll_grp') # cria ramps para controlar o perfil de squash e stretch ramp1 = pm.createNode('ramp', n=self.name + 'SquashRamp1') ramp1.attr('type').set(1) # ramp2 = pm.createNode ('ramp') # ramp2.attr('type').set(1) expre1 = "float $dummy = " + ramp1.name( ) + ".outAlpha;float $output[];float $color[];" # expre2 = "float $dummy = "+ramp2.name()+".outAlpha;float $output[];float $color[];" extraCntrlsGrp = pm.group(em=True, r=True, p=cntrlsSpace, n=self.name + 'extraCntrls_grp') # loop pra fazer os colocar o numero escolhido de joints ao longo do ribbon. # cria tmb node tree pro squash/stretch # e controles extras vIncrement = float( (1.0 - (self.offsetStart + self.offsetEnd)) / (self.numJnts - 1)) for i in range(1, self.numJnts + 1): # cria estrutura pra superficie 1 pm.select(cl=True) jntName = self.ribbonDict['jntSetup']['nameTempl'] + str( i) + self.jntSulfix jnt1 = pm.joint(p=(0, 0, 0), n=jntName) self.skinJoints.append(jnt1) displaySetup = self.ribbonDict['cntrlExtraSetup'].copy() cntrlName = displaySetup['nameTempl'] + 'A' + str(i) cntrl1 = controlTools.cntrlCrv(name=cntrlName, obj=jnt1, connType='parentConstraint', **displaySetup) # node tree blend1A = pm.createNode('blendTwoAttr', n=self.name + 'VolumeBlend1A') blend1B = pm.createNode('blendTwoAttr', n=self.name + 'VolumeBlend1B') gammaCorr1 = pm.createNode('gammaCorrect', n=self.name + 'VolumeGamma1') cntrlList[0].attr('autoVolumStregth') >> gammaCorr1.gammaX cntrlList[0].attr('stretchDist') >> gammaCorr1.value.valueX blend1A.input[0].set(1) gammaCorr1.outValueX >> blend1A.input[1] blend1B.input[0].set(1) blend1A.output >> blend1B.input[1] cntrlList[3].attr('autoVolume') >> blend1B.attributesBlender blend1B.output >> cntrl1.getParent().scaleY blend1B.output >> cntrl1.getParent().scaleZ # expressao que le a rampa para setar valores da escala de cada joint quando fizer squash/stretch expre1 = expre1 + "$color = `colorAtPoint -o RGB -u " + str( self.offsetStart + (i - 1) * vIncrement) + " -v 0.5 " + ramp1.name( ) + " `;$output[" + str(i) + "] = $color[0];" + blend1A.name( ) + ".attributesBlender=$output[" + str(i) + "];" # prende joints nas supeficies com follicules foll1 = self.attachObj(cntrl1.getParent(), bendSurf1[0], self.offsetStart + (i - 1) * vIncrement, 0.5, 4) pm.parent(cntrl1.getParent(), extraCntrlsGrp) pm.parent(jnt1, skinJntsGrp) pm.parent(foll1, follGrp) # seta expressoes para so serem avaliadas por demanda pm.expression(s=expre1, ae=False) pm.parent(skinJntsGrp, cntrlsSpace) pm.parent(follGrp, noMoveSpace) # hideCntrls pm.toggle(bendSurf1[0], g=True) bendSurf1[0].visibility.set(0) # skinJntsGrp.visibility.set(0) cntrlsSpace.extraCntrlsVis >> extraCntrlsGrp.visibility cntrlsSpace.cntrlsVis >> cntrlList[0].getParent().visibility cntrlsSpace.cntrlsVis >> cntrlList[3].getParent().visibility cntrlsSpace.cntrlsVis >> cntrlList[6].getParent().visibility # povoa ribbon Dict self.ribbonDict['name'] = 'bezierRibbon' self.ribbonDict['ribbonMoveAll'] = cntrlsSpace for i in range(0, 7): self.ribbonDict['cntrl' + str(i)] = cntrlList[i] self.startCntrl = cntrlList[0] self.midCntrl = cntrlList[3] self.endCntrl = cntrlList[6] self.moveall = cntrlsSpace
def flexiplane(self, prefix=''): """ Build FlexiPlane :param index: number of flexiplane in scene (auto managed by maya) :return: FlexiPlane group node """ fp_name = '%sflexiPlane' % prefix fp_name = nameCheck.nameCheck(fp_name + '*_GRP').replace( '_GRP', '', 1) # flexiPlane_GRP fp_surf = self.create_plane('%s_NURBS' % (fp_name))[0] fp_surf.overrideEnabled.set(1) fp_surf.overrideDisplayType.set(2) # Assign Material self.create_lambret(fp_surf, color=(0.067, 0.737, 0.749), transparency=(0.75, 0.75, 0.75)) # Create Follicles # flc_name = 'flexiPlane' v = 0.1 # 1/width flcs = [] how_many_flc = 5 # width/2 for i in range(0, how_many_flc): ofoll = self.create_follicle( fp_surf, '%s_flc_%s_FLC' % (fp_name, letters[i + 26]), v, 0.5) flcs.append(ofoll) v += 0.2 # (1/width)*2 # Group Follicles flc_grp = pm.group(flcs, name='%s_flcs_GRP' % (fp_name)) # creates flexiPlane controls curves at each end self.ctrl_a = self.ctrl_square(name='%s_ctrl_a_CTRL' % (fp_name), pos=[-5, 0, 0]) ctrl_ashape = self.ctrl_a.getShape() pm.rename(ctrl_ashape, '%sShape' % self.ctrl_a) self.ctrl_b = self.ctrl_square(name='%s_ctrl_b_CTRL' % (fp_name), pos=[5, 0, 0]) ctrl_bshape = self.ctrl_b.getShape() pm.rename(ctrl_bshape, '%sShape' % self.ctrl_b) pm.select(cl=True) # creates flexiPlane blendshape # blendshape suffix: _bShp_ fp_bshp = pm.duplicate(fp_surf, n='%s_bshp_NURBS' % (fp_name))[0] pm.move(0, 0, -5, fp_bshp) fps_bshp_node = pm.blendShape(fp_bshp, fp_surf, n='%s_BSHP' % (fp_name))[0] pm.setAttr('%s.%s' % (fps_bshp_node, fp_bshp), 1) # pm.rename('tweak1', '%sbshp_%stweak_01' % (fp_name, sur)) # creates curve for wire deformer fp_curve = pm.curve(d=2, p=[(-5, 0, -5), (0, 0, -5), (5, 0, -5)], k=[0, 0, 1, 1], n='%s_wire_CV' % (fp_name)) cl_a, cl_b, cl_mid = self.cluster_curve(fp_curve, fp_name) # create and place twist deformer pm.select(fp_bshp) fp_twist = pm.nonLinear(type='twist', lowBound=-1, highBound=1) # displays warning: pymel.core.general : could not create desired mfn. Defaulting MfnDependencyNode. # doesn't seem to affect anything though pm.rename(fp_twist[0], '%s_twistAttr_surface_NURBS' % (fp_name)) pm.rename(fp_twist[1], '%s_twist_Handle_DEFORMER' % (fp_name)) fp_twist[1].rz.set(90) # connect start and end angle to their respective control connect = self.ctrl_b.rx >> fp_twist[0].startAngle connect = self.ctrl_a.rx >> fp_twist[0].endAngle # skins wire to blendshape fp_wire = pm.wire( fp_bshp, w=fp_curve, gw=False, en=1, ce=0, li=0, # dds=(0, 20), n='%s_wireAttrs_DEFORMER' % (fp_name)) fp_wire[0].dropoffDistance[0].set(20) hist = pm.listHistory(fp_surf) tweaks = [t for t in hist if 'tweak' in t.nodeName()] pm.rename(tweaks[2], '%s_cl_cluster_tweak' % (fp_name)) pm.rename(tweaks[0], '%s_wireAttrs_tweak' % (fp_name)) pm.rename(tweaks[1], '%s_extra_tweak' % (fp_name)) # group clusters cl_grp = pm.group(cl_a[1], cl_b[1], cl_mid[1], n='%s_cls_GRP' % (fp_name)) util.lock_and_hide_all(cl_grp) # creates mid control self.ctrl_mid = self.flexiplane_mid_ctrl(name='%s_ctrl_mid_CTRL' % (fp_name)) ctrl_mid_grp = pm.group(self.ctrl_mid, n='%s_grp_midBend_GRP' % (fp_name)) pm.pointConstraint(self.ctrl_a, self.ctrl_b, ctrl_mid_grp, o=[0, 0, 0], w=1) # groups controls together and locks and hides group attributes ctrl_grp = pm.group(self.ctrl_a, self.ctrl_b, ctrl_mid_grp, n='%s_ctrl_GRP' % (fp_name)) util.lock_and_hide_all(ctrl_grp) # connecting translate attrs of control curves for to the clusters connect = [] connect.append(self.ctrl_a.t >> cl_a[1].t) connect.append(self.ctrl_b.t >> cl_b[1].t) connect.append(self.ctrl_mid.t >> cl_mid[1].t) # makes mid_ctrl, flexiPlane and blendShape surfaces non renderable util.no_render(fp_surf) util.no_render(fp_bshp) util.no_render(self.ctrl_mid) # groups everything under 1 group then locks and hides the transform attrs of that group #flexiPlane_wire_surface0101BaseWire self.fp_grp = pm.group( fp_surf, flc_grp, fp_bshp, fp_wire, # '%s_wire_%s_BaseWire_GRP' % (fp_name, self.surfaceSuffix), cl_grp, ctrl_grp, n='%s_GRP' % (fp_name)) util.lock_and_hide_all(self.fp_grp) # creates global move group and extraNodes fp_gm_grp = pm.group(fp_surf, ctrl_grp, n='%s_globalMove_GRP' % (fp_name)) fp_xnodes_grp = pm.group(flc_grp, fp_bshp, fp_wire, '%s_wire_CVBaseWire' % (fp_name), cl_grp, n='%s_extraNodes_GRP' % (fp_name)) pm.parent(fp_twist, fp_xnodes_grp) pm.parent(fp_xnodes_grp, self.fp_grp) fp_xnodes_grp.overrideEnabled.set(1) fp_xnodes_grp.overrideDisplayType.set(2) # scale constrains follicles to global move group for follicle in flcs: mparent = follicle.getParent() pm.scaleConstraint(fp_gm_grp, mparent) # creates global move control self.fp_gm_ctrl = self.global_ctrl(name=fp_name) # moves global control into flexiPlane group then parent global move group to global move control. pm.parent(self.fp_gm_ctrl, self.fp_grp) pm.parent(fp_gm_grp, self.fp_gm_ctrl) # joints placement jnts = [] for i in range(0, len(flcs)): posx = round(flcs[i].getParent().translateX.get(), 4) jnt = pm.joint(p=(posx, 0, 0), rad=0.5, n='%sbind_%s_JNT' % (fp_name, letters[i + 26])) jnts.append(jnt) # parent joint under follicle pm.parent(jnt, flcs[i].getParent()) # locks and hides transformNodes flexiPlane surface util.lock_and_hide_all(fp_surf) # hides blendShape, clusters and twist Deformer fp_twist[1].visibility.set(0) cl_grp.visibility.set(0) fp_bshp.visibility.set(0) fp_curve.visibility.set(0) # selects the wire deformer and creates a curve info node... # ...to get the wire deformers length pm.select(fp_curve, r=True) length = pm.arclen(ch=1) length.rename('%scurveInfo_DEFORMER' % (fp_name)) # creates a multiplyDivideNode for squashStretch length... # ...and sets it operation to divide fp_div = pm.createNode('multiplyDivide', n='%sdiv_squashStretch_length' % (fp_name)) fp_div.operation.set(2) # secondary multDivNode for volume, sets input1X to 1 fp_div_vol = pm.createNode('multiplyDivide', n='%sdiv_volume' % (fp_name)) fp_div_vol.operation.set(2) fp_div_vol.input1X.set(1) # creates a conditionNode for global_ctrl enable attr fp_cond = pm.createNode('condition', n='%scond_volume' % (fp_name)) fp_cond.secondTerm.set(1) # connects curve all the nodes connect = length.arcLength >> fp_div.input1.input1X fp_div.input2.input2X.set(10) connect = fp_div.outputX >> fp_div_vol.input2.input2X connect = self.fp_gm_ctrl.enable >> fp_cond.firstTerm connect = fp_div_vol.outputX >> fp_cond.colorIfTrueR fp_ctrl_global = self.fp_gm_ctrl.getShape() for i in range(0, len(flcs)): connect = fp_cond.outColorR >> jnts[i].sy connect = fp_cond.outColorR >> jnts[i].sz flcs[i].visibility.set(0) # hides blendShape, clusters and twist Deformer fp_twist[1].visibility.set(0) cl_grp.visibility.set(0) fp_bshp.visibility.set(0) fp_curve.visibility.set(0) pm.select(self.fp_gm_ctrl, r=True) return self.fp_gm_ctrl