def dpCreateWireDeform(self, *args): """ Create two wire deformer for first and second curves. """ firstWireDef = cmds.wire(self.deformMesh, groupWithBase=False, crossingEffect=0, localInfluence=1, dropoffDistance=(0, 1), name=utils.extractSuffix(self.deformMesh) + "_First_Wire")[0] secondWireDef = cmds.wire(self.deformMesh, groupWithBase=False, crossingEffect=0, localInfluence=1, dropoffDistance=(0, 1), name=utils.extractSuffix(self.deformMesh) + "_Second_Wire")[0] cmds.connectAttr(self.firstCurve + ".worldSpace[0]", firstWireDef + ".baseWire[0]", force=True) cmds.connectAttr(self.secondCurve + ".worldSpace[0]", secondWireDef + ".baseWire[1]", force=True) cmds.connectAttr(self.firstBlendCurve + ".worldSpace[0]", firstWireDef + ".deformedWire[0]", force=True) cmds.connectAttr(self.secondBlendCurve + ".worldSpace[0]", secondWireDef + ".deformedWire[1]", force=True)
def createCrv(self,*a): cmds.radioCollection('rc_ancUv',q=1,select=1) cmds.radioCollection('rc_ancCct',q=1,select=1) cmds.radioCollection('rc_ancNct',q=1,select=1) sl = cmds.ls(selection=1,long=1) sls = cmds.ls(selection=1) selList = [] for i,x in enumerate(sl): sn = sls[i] if cmds.nodeType(x) == 'transform': ns = cmds.listRelatives(x,type='nurbsSurface') if ns : x= ns[0] if cmds.nodeType(x) == 'nurbsSurface': svAttr = '.spansV' ; vAttr = '.v' ; maxAttr = '.minMaxRangeV' if cmds.radioCollection('rc_ancUv',q=1,select=1) == 'rb_ancU' : svAttr = '.spansU' ; vAttr = '.u' ; maxAttr = '.minMaxRangeU' v = cmds.getAttr(x+svAttr) crvList = [] for j in range(v): vv = float(j) if cmds.getAttr(x+maxAttr)[0][1] == 1.0 : vv = 1.0 / v * j dc = cmds.duplicateCurve(x+vAttr+'['+str(vv)+']',constructionHistory=0,object=1)[0] crvList.append(dc) cCrv = cmds.duplicateCurve(x+vAttr+'[0]',constructionHistory=0,object=1,name='crv_'+sls[i])[0] bs = cmds.blendShape(crvList,cCrv)[0] cmds.delete(crvList) for j in range(v): cmds.setAttr(bs+'.'+crvList[j],1.0/v) cmds.delete(cCrv,constructionHistory=1) selList.append(cCrv) if cmds.radioCollection('rc_ancNct',q=1,select=1) == 'rb_ancWire' : cmds.wire(x,w=cCrv,dropoffDistance=[0,100]) if len(selList) > 0 : cmds.select(selList,replace=1) else : sys.stderr.write('No NURBS surface select.')
def _setup_wire_deformer(self, mesh, wire, wirebase, curve, parent, complexity): """Setup the wire deformer. If complexity is 1 or higher call this function recursively to create a wire deformer on the nurbs surface. @param mesh(string): PolyMesh used to wire deform @param wire(string): Descriptive part of the name of the wire deformer @param wirebase(string): Descriptive part of the name of the base wire @param curve(string): Curve used for wireTool deformer @param parent(string): Parent node of the wire setup @param complexity(uint): complexity level value """ w = wire wb = wirebase cmds.wire(mesh, w=curve, dds=[0, 10000], n=w, foc=False) cmds.rename(cmds.listConnections('%s.baseWire[0]' % w)[0], wb) if not cmds.listRelatives(curve, p=True) == [self.wire_grp]: cmds.parent(curve, wb, self.wire_grp) # end if wbs = cmds.listRelatives(wb, ad=True, type='shape')[0] cs = cmds.listRelatives(curve, ad=True, type='shape')[0] cmds.setAttr('%s.rotation' % w, 0) # connect to showHistory cmds.connectAttr('%s.showHistory' % self.mod_grp, '%s.ihi' % w) cmds.connectAttr('%s.showHistory' % self.mod_grp, '%s.ihi' % wb) cmds.connectAttr('%s.showHistory' % self.mod_grp, '%s.ihi' % wbs) cmds.connectAttr('%s.showHistory' % self.mod_grp, '%s.ihi' % cs) if complexity: cmds.duplicate(self.curve, n=self.nrbcurve) return self._setup_wire_deformer(self.surface, self.nrbwire, self.nrbwirebase, self.nrbcurve, self.parent, 0)
def set_curves(self): cmds.select(self.mesh) # Fetching commands from mel LPC script. # Since now don't want to rewrite on python try: mel.eval("setDeformGeom();") except: print 'LPC not loaded. Please, initialize it.' a_objects = cmds.ls('*', flatten=True, transforms=True) cmds.select(clear=True) ctrl_grp = cmds.group(name=self.mesh + '_curve_ctrls', empty=True) for region in self.data.keys(): locs = self.set_lpc_for_region(self.data[region]) if region != 'excluded': curve_name = region + self.hi if self.curve_vtx_match: closest_vtx = '%s.vtx[%s]' % ( self.mesh, str(self.curve_vtx_match[region])) init_loc = self.get_init_loc(closest_vtx, locs) locs = self.order_locs(locs, init=init_loc) else: locs = self.order_locs(locs) hi_curve = self.create_hi_curve(locs, region) self.connect_locs_to_curve(locs, hi_curve) low_curve = self.create_low_curve(region) cmds.hide(hi_curve) cmds.wire(hi_curve, w=low_curve, gw=0, en=1, ce=0, li=0, dds=[(0, 100)]) cmds.parent(low_curve, ctrl_grp) # Not so handful, as I expected # self.create_controls(low_curve) b_objects = cmds.ls('*', flatten=True, transforms=True) rig_objects = [o for o in b_objects if o not in a_objects] self.rig_objects = rig_objects if not self.curve_vtx_match: for c in self.data.keys(): if c != 'excluded': self.curve_vtx_match[c] = self.get_closest_vtx( '%s_%s%s.cv[0]' % (self.mesh, c, self.low), self.mesh) func.dict_io(self.save_dir + self.current_rig + self.match_prefix + self.ext, self.curve_vtx_match, set=True)
def CurveShapes(self): getSel=self.selection_grab() if getSel: pass else: return getNames=cmds.ls(sl=1, fl=1) if ".e[" not in str(getNames[0]): print "selection needs to be continuous edges of two seperate polygon objects: first select one, then continuous edge and then the continuous edge on a seperate poly object that you want to deform it along" return else: pass getFirstGrp = getNames[0].split(".")[0] getSecondGrp = getNames[-1:][0].split(".")[0] if getFirstGrp == getSecondGrp: print "Only one poly object has been detected. Select one object and it's continuous edge and then select another object and select it's continuous edge for the first object to align to." return else: pass firstList=[(each) for each in getNames if each.split(".")[0]==getFirstGrp] secondList=[(each) for each in getNames if each.split(".")[0]==getSecondGrp] '''create childfirst curve''' cmds.select(firstList) cmds.CreateCurveFromPoly() getFirstCurve=cmds.ls(sl=1, fl=1) '''get cv total of curve''' getFirstCurveInfo=cmds.ls(sl=1, fl=1) numberCV=str(pm.PyNode(getFirstCurveInfo[0]).numCVs()) cmds.delete(getFirstCurve[0], ch=1) '''wrap child mesh to curve''' cmds.select(cmds.ls(getFirstGrp)[0], r=1) cmds.wire(w=getFirstCurve[0], gw=0, en=1.000000, ce=0.000000, li=0.000000, dds=[(0, 500)] ) '''create parent curve''' cmds.select(secondList) cmds.CreateCurveFromPoly() getSecondCurve=cmds.ls(sl=1, fl=1) getSecondCurveInfo=cmds.ls(sl=1, fl=1) '''rebuilt curve to match first curve built''' cmds.rebuildCurve(getSecondCurve[0], getFirstCurve[0], rt=2 ) getSecondCurve=cmds.ls(sl=1, fl=1) getSecondCurveInfo=cmds.ls(sl=1, fl=1) cmds.delete(getSecondCurve[0], ch=1) '''wrap parent curve to parent mesh''' cmds.select(getSecondCurve[0], r=1) cmds.select(cmds.ls(getSecondGrp)[0], add=1) cmds.CreateWrap() '''blend child curve to parent curve''' cmds.blendShape(getSecondCurve[0], getFirstCurve[0],w=(0, 1.0)) return getFirstGrp, getSecondGrp
def createMulti(geo,wireList,dropoffDist=1.0,prefix=''): ''' Create a wire deformer using the specified geometry and curves @param geo: Geometry to deform @type geo: str @param wireList: Wire deformer curve list @type wireList: list @param dropoffDist: Wire influence dropoff distance @type dropoffDist: str @param prefix: Naming prefix @type prefix: str ''' # =================== # - Create Deformer - # =================== # Create Wire wire = mc.wire(geo,w=wireList,n=prefix+'_wire') wireNode = wire[0] # Set Dropoff Distance for i in range(len(wireList)): mc.setAttr(wireNode+'.dropoffDistance['+str(i)+']',dropoffDist) # ================= # - Return Result - # ================= return wire
def createMulti(geo, wireList, dropoffDist=1.0, prefix=''): """ Create a wire deformer using the specified geometry and curves @param geo: Geometry to deform @type geo: str @param wireList: Wire deformer curve list @type wireList: list @param dropoffDist: Wire influence dropoff distance @type dropoffDist: str @param prefix: Naming prefix @type prefix: str """ # =================== # - Create Deformer - # =================== # Create Wire wire = cmds.wire(geo, w=wireList, n=prefix + '_wire') wireNode = wire[0] # Set Dropoff Distance for i in range(len(wireList)): cmds.setAttr(wireNode + '.dropoffDistance[' + str(i) + ']', dropoffDist) # ================= # - Return Result - # ================= return wire
def sqCreateStikyLipsDeformers(self, *args): baseMesh = None mainCurveList = [self.mainCurveA, self.mainCurveB] for mainCurve in mainCurveList: if baseMesh == None: baseMesh = cmds.duplicate(self.receptList[0], name=self.receptList[0]+"Base")[0] cmds.setAttr(baseMesh+".visibility", 0) wrapNode = cmds.deformer(mainCurve, name="StickyLips_Wrap", type="wrap")[0] try: cmds.connectAttr(self.receptList[0]+".dropoff", wrapNode+".dropoff[0]", force=True) cmds.connectAttr(self.receptList[0]+".inflType", wrapNode+".inflType[0]", force=True) cmds.connectAttr(self.receptList[0]+".smoothness", wrapNode+".smoothness[0]", force=True) cmds.connectAttr(self.receptList[0]+"Shape.worldMesh[0]", wrapNode+".driverPoints[0]", force=True) except: pass cmds.connectAttr(baseMesh+"Shape.worldMesh[0]", wrapNode+".basePoints[0]", force=True) cmds.connectAttr(mainCurve+"Shape.worldMatrix[0]", wrapNode+".geomMatrix", force=True) cmds.setAttr(wrapNode+".maxDistance", 1) cmds.setAttr(wrapNode+".autoWeightThreshold", 1) cmds.setAttr(wrapNode+".exclusiveBind", 1) baseCurveList = [self.baseCurveA, self.baseCurveB] for c, baseCurve in enumerate(baseCurveList): wireNode = cmds.wire(self.receptList[1], name=baseCurve+"_Wire", groupWithBase=False, crossingEffect=0, localInfluence=0)[0] cmds.connectAttr(mainCurveList[c]+"Shape.worldSpace[0]", wireNode+".baseWire[0]", force=True) cmds.connectAttr(baseCurve+"Shape.worldSpace[0]", wireNode+".deformedWire[0]", force=True) self.wireNodeList.append(wireNode) wireLocList = [] for i in range(0, self.maxIter): wireLocList.append(baseCurve+".u["+str(i)+"]") cmds.dropoffLocator(1, 1, wireNode, wireLocList)
def makeWire(geo, CCurve, dropOffD=10): theWire = cmds.wire(geo, w=CCurve, n ="inputWire") wireNode = theWire[0] data.treadBaseWire = "{}BaseWire".format(CCurve) data.treadBaseWire = checkDuplicatedName(data.treadBaseWire) # Change dropoff distance cmds.setAttr("%s.dropoffDistance[0]"%wireNode, dropOffD)
def addSmartBlink (self, eyePrefix, upLidBaseCrv, upLidDriverCrv, lowLidBaseCrv, lowLidDriverCrv, ctrlList, rigGrp, upCrvRigGrp, lowCrvRigGrp): '''Add a 'smart blink' feature to the eyelid rig, allowing to blink wherever the controllers are (blendshapes + wire deformers system). Called by 'buildRig' function. Call functions: None ''' # Variables names containing 'SB' = smartBlink ctrlUpLidMain = ctrlList[2] ctrlLowLidMain = ctrlList[6] # - STEP 1: bothLidsSB_Crv = cmds.duplicate (upLidDriverCrv, n = (eyePrefix + "_Eyelids_smartBlink_curve")) [0] cmds.parent (bothLidsSB_Crv, rigGrp) bothLidsSB_BlndShp = cmds.blendShape (upLidDriverCrv, lowLidDriverCrv, bothLidsSB_Crv, n = (eyePrefix + "_Eyelids_smartBlink_BLENDSHAPE")) [0] cmds.select (cl = 1) cmds.select (ctrlUpLidMain) cmds.addAttr (ln = "SmartBlinkHeight", at = "float", min = 0, max = 1, k = 1) cmds.connectAttr ((ctrlUpLidMain + ".SmartBlinkHeight"), (bothLidsSB_BlndShp + "." + upLidDriverCrv), f = 1) SBReverse = cmds.shadingNode ("reverse", asUtility = 1, n = (eyePrefix + "_Eyelids_smartBlink_reverse")) cmds.connectAttr ((ctrlUpLidMain + ".SmartBlinkHeight"), (SBReverse + ".inputX"), f = 1) cmds.connectAttr ((SBReverse + ".outputX"), (bothLidsSB_BlndShp + "." + lowLidDriverCrv), f = 1) # STEP 2: upLidSB_Crv = cmds.duplicate (self.upLidCrv, n = (eyePrefix + "_UpEyelid_smartBlink_curve")) [0] lowLidSB_Crv = cmds.duplicate (self.lowLidCrv, n = (eyePrefix + "_LowEyelid_smartBlink_curve")) [0] cmds.setAttr ((ctrlUpLidMain + ".SmartBlinkHeight"), 1) cmds.select (cl = 1) wireUpLid = cmds.wire (upLidSB_Crv, n = (eyePrefix + "_UpEyelid_smartBlink_wire"), w = bothLidsSB_Crv, gw = 0, en = 1, ce = 0, li = 0) cmds.setAttr ((wireUpLid[0] + ".scale[0]"), 0) cmds.setAttr ((ctrlUpLidMain + ".SmartBlinkHeight"), 0) cmds.select (cl = 1) wireLowLid = cmds.wire (lowLidSB_Crv, n = (eyePrefix + "_LowEyelid_smartBlink_wire"), w = bothLidsSB_Crv, gw = 0, en = 1, ce = 0, li = 0) cmds.setAttr ((wireLowLid[0] + ".scale[0]"), 0) # STEP 3: upLidSB_BlndShp = cmds.blendShape (upLidSB_Crv, self.upLidCrv, n = (eyePrefix + "_UpEyelid_smartBlink_BLENDSHAPE")) [0] lowLidSB_BlndShp = cmds.blendShape (lowLidSB_Crv, self.lowLidCrv, n = (eyePrefix + "_LowEyelid_smartBlink_BLENDSHAPE")) [0] # FINAL STEP: cmds.select (ctrlUpLidMain, ctrlLowLidMain) cmds.addAttr (ln = "SmartBlink", at = "float", min = 0, max = 1, k = 1) cmds.connectAttr ((ctrlUpLidMain + ".SmartBlink"), (upLidSB_BlndShp + "." + upLidSB_Crv), f = 1) cmds.connectAttr ((ctrlLowLidMain + ".SmartBlink"), (lowLidSB_BlndShp + "." + lowLidSB_Crv), f = 1) cmds.setAttr ((ctrlUpLidMain + ".SmartBlinkHeight"), 0.15)
def sqCreateStikyLipsDeformers(self, *args): baseMesh = None mainCurveList = [self.mainCurveA, self.mainCurveB] for mainCurve in mainCurveList: if baseMesh == None: baseMesh = cmds.duplicate(self.receptList[0], name=self.receptList[0] + "Base")[0] cmds.setAttr(baseMesh + ".visibility", 0) wrapNode = cmds.deformer(mainCurve, name="StickyLips_Wrap", type="wrap")[0] try: cmds.connectAttr(self.receptList[0] + ".dropoff", wrapNode + ".dropoff[0]", force=True) cmds.connectAttr(self.receptList[0] + ".inflType", wrapNode + ".inflType[0]", force=True) cmds.connectAttr(self.receptList[0] + ".smoothness", wrapNode + ".smoothness[0]", force=True) cmds.connectAttr(self.receptList[0] + "Shape.worldMesh[0]", wrapNode + ".driverPoints[0]", force=True) except: pass cmds.connectAttr(baseMesh + "Shape.worldMesh[0]", wrapNode + ".basePoints[0]", force=True) cmds.connectAttr(mainCurve + "Shape.worldMatrix[0]", wrapNode + ".geomMatrix", force=True) cmds.setAttr(wrapNode + ".maxDistance", 1) cmds.setAttr(wrapNode + ".autoWeightThreshold", 1) cmds.setAttr(wrapNode + ".exclusiveBind", 1) baseCurveList = [self.baseCurveA, self.baseCurveB] for c, baseCurve in enumerate(baseCurveList): wireNode = cmds.wire(self.receptList[1], name=baseCurve + "_Wire", groupWithBase=False, crossingEffect=0, localInfluence=0)[0] cmds.connectAttr(mainCurveList[c] + "Shape.worldSpace[0]", wireNode + ".baseWire[0]", force=True) cmds.connectAttr(baseCurve + "Shape.worldSpace[0]", wireNode + ".deformedWire[0]", force=True) self.wireNodeList.append(wireNode) wireLocList = [] for i in range(0, self.maxIter): wireLocList.append(baseCurve + ".u[" + str(i) + "]") cmds.dropoffLocator(1, 1, wireNode, wireLocList)
def createWireDef(*args): #clusterList = [] #rebuiltCrv = "" #get geo and curve geo = cmds.ls(sl=True)[0] crv = cmds.ls(sl=True)[1] rebuiltCrv = rebuildCrv(crv) name = cmds.textFieldGrp(widgets["nameTFG"], q=True, tx=True) defName = "wire_" + name wireDef = cmds.wire(geo, w=rebuiltCrv, n=defName, gw=True) wireGroup = wireDef[1] + "Group" cmds.setAttr(wireGroup + ".v", 0) clusterList = clstrOnCurve(rebuiltCrv) #print clusterList ctrlGrp = createControls(clusterList) masterGrp = cmds.group(n=name + "_GRP", em=True) cmds.parent(ctrlGrp, masterGrp) cmds.parent(wireGroup, masterGrp) cmds.addAttr(masterGrp, ln="xxWireDeformerCtrlsXX", at="bool", k=True) cmds.setAttr(masterGrp + ".xxWireDeformerCtrlsXX", l=True) cmds.addAttr(masterGrp, ln='envelope', at="float", dv=1, min=0, max=1, k=True) cmds.addAttr(masterGrp, ln='DropoffDistance', at='float', dv=1, min=0, max=15, k=True) cmds.addAttr(masterGrp, ln='tension', at='float', dv=1, min=-10, max=10, k=True) cmds.addAttr(masterGrp, ln='rot', at='float', min=0, max=1, k=True) cmds.addAttr(masterGrp, ln='scl', at='float', dv=1, min=0, max=3, k=True) cmds.connectAttr(masterGrp + ".envelope", wireDef[0] + ".envelope") cmds.connectAttr(masterGrp + ".DropoffDistance", wireDef[0] + ".dropoffDistance[0]") cmds.connectAttr(masterGrp + ".tension", wireDef[0] + ".tension") cmds.connectAttr(masterGrp + ".rot", wireDef[0] + ".rotation") cmds.connectAttr(masterGrp + ".scl", wireDef[0] + ".scale[0]") cmds.select(masterGrp, r=True) incrementName()
def wireOnly(self,*args,**kwargs): '''if the rig already exists, just wire geo''' crv = cmds.textFieldButtonGrp(self.widgets["curveNameGrp"],q=True,text=True) geo = cmds.textFieldButtonGrp(self.widgets["geoNameGrp"],q=True,text=True) if not crv or not geo or not cmds.objExists(geo): raise RuntimeError("Specify a curve and a geo to wire to an already existing rig") #Find nodes based on name, do some error checking rigNode = crv + "_Rig" hiddenStuff = crv + "_NOTOUCH" wireCrv = crv + "_skinned" if not cmds.objExists(rigNode): raise RuntimeError("%s not found in scene, rig not built yet?"%rigNode) allKids = cmds.listRelatives(rigNode,ad=True) if not cmds.objExists(wireCrv) and not wireCrv in allKids: raise RuntimeError("wire curve %s not found under %s, wire curve deleted or not rigged?" %(wireCrv,rigNode)) if not cmds.objExists(hiddenStuff) and not hiddenStuff in allKids: raise RuntimeError("Couldn't find the NOTOUCH node for this rig, curve not rigged?") #Make wire cmds.wire(geo,w=wireCrv,n=crv + "_wire",dds=(0,10),en=1.0,ce=0,li=0) print "wire done"
def create(geo, wireCrv, baseCrv=None, dropoffDist=1.0, prefix=''): ''' Create a wire deformer using the specified geometry and curves @param geo: Geometry to deform @type geo: str @param wireCrv: Wire deformer curve @type wireCrv: str @param baseCrv: Wire base curve @type baseCrv: str @param dropoffDist: Wire influence dropoff distance @type dropoffDist: str @param prefix: Naming prefix @type prefix: str ''' # ========== # - Checks - # ========== if baseCrv and not mc.objExists(baseCrv): raise Exception('Base curve "' + baseCrv + '" does not exist!') # =================== # - Create Deformer - # =================== # Create Wire wire = mc.wire(geo, w=wireCrv, n=prefix + '_wire') wireNode = wire[0] # Set Dropoff Distance mc.setAttr(wireNode + '.dropoffDistance[0]', dropoffDist) # Connect Custome Base Curve if baseCrv: oldBase = mc.listConnections(wireNode + '.baseWire[0]', s=True, d=False) mc.connectAttr(baseCrv + '.worldSpace[0]', wireNode + '.baseWire[0]', f=True) if oldBase: mc.delete(oldBase) # ================= # - Return Result - # ================= return wire
def create(geo, wireCrv, baseCrv=None, dropoffDist=1.0, prefix=''): """ Create a wire deformer using the specified geometry and curves @param geo: Geometry to deform @type geo: str @param wireCrv: Wire deformer curve @type wireCrv: str @param baseCrv: Wire base curve @type baseCrv: str @param dropoffDist: Wire influence dropoff distance @type dropoffDist: str @param prefix: Naming prefix @type prefix: str """ # ========== # - Checks - # ========== if baseCrv and not cmds.objExists(baseCrv): raise Exception('Base curve "' + baseCrv + '" does not exist!') # =================== # - Create Deformer - # =================== # Create Wire wire = cmds.wire(geo, w=wireCrv, n=prefix + '_wire') wireNode = wire[0] # Set Dropoff Distance cmds.setAttr(wireNode + '.dropoffDistance[0]', dropoffDist) # Connect Custome Base Curve if baseCrv: oldBase = cmds.listConnections(wireNode + '.baseWire[0]', s=True, d=False) cmds.connectAttr(baseCrv + '.worldSpace[0]', wireNode + '.baseWire[0]', f=True) if oldBase: cmds.delete(oldBase) # ================= # - Return Result - # ================= return wire
def Transfer(self): sel = cmds.ls(sl=True) curves = [] joints = [] wires = [] obj = None for obj in sel: if cmds.nodeType(cmds.listRelatives(obj, shapes=True)) == 'nurbsCurve': curves.append(obj) elif cmds.joint(obj, exists=obj): joints.append(obj) else: obj = obj if obj is not None: verts = cmds.ls(obj + '.vtx[0: ]', fl=True) clusters = cmds.listConnections(cmds.listRelatives(object, shapes=True)[0], t='skinCluster')[0] i = 1 for curve in curves: wires.append(cmds.wire(object, dds=[i, 999999999], w=curve)[0]) i = 0 for jnt in joints: for vert in verts: skinWeight = cmds.skinPercent(clusters, vert, transform=jnt, q=True, value=True) cmds.percent(wires[i], vert, v=skinWeight) i += 1 else: cmds.warning('Tool requires an object to be selected')
def createCurves(self, verteces, locs, baseName ): """create the curves to controls the locators""" grp = mn.Node( mc.group( n = baseName + '_CRV_GRP', em = True ) ) tmp = mn.Node( mc.curve( n = baseName + "High" + '_CRV', d = 1, p = verteces, k = [ i for i in range( len( verteces ) ) ] ) ) tmp.name = baseName + "High" + '_CRV' highCurve = crv.Curve( tmp.shape.name.split( '|' )[-1] ) highCurve.parent = grp #attach locs to curve for l in locs: pos = mc.xform( l.name, q = True, ws = 1, t = 1 ) u = highCurve.uParam( pos ) pci = mn.createNode( "pointOnCurveInfo" ) pci.name = l.name.replace( '_LOC', '_PCI' ) highCurve.a.worldSpace >> pci.a.inputCurve pci.a.parameter.v = u pci.a.position >> l.a.t lowCurve = highCurve.rebuild( keep = True ) lowCurve.name = tmp.name.replace( 'High', 'Low' ) lowCurve.parent = grp wir = mn.Node( mc.wire( tmp.name, gw = False, en = 1.000000, ce = 0.000000, li = 0.000000, w = lowCurve.name )[0] ) wir.name = tmp.name.replace( '_CRV', '_WR' ) return crv.Curve( lowCurve.name ), grp
def createDfmSys(nodeName, drvLocs, ctls, geo): ''' drvLocs are used to drive baseCrv ctls are used to drive wireCrv wire deforms geo return dfmSysGrp ''' # create baseCrv baseCrv = rt.makeCrvThroughObjs(drvLocs, nodeName+'_wireOffset_baseCrv', True, 3) # create wireCrv wireCrv = rt.makeCrvThroughObjs(ctls, nodeName+'_wireOffset_wireCrv', True, 3) # create wireDfm wireDfm, wireCrv = mc.wire(geo, wire=wireCrv, n=nodeName+'_wireOffset_wireDfm', dds=(0,5)) wireBaseUnwanted = wireCrv+'BaseWire' # replace base mc.connectAttr(baseCrv+'.worldSpace[0]', wireDfm+'.baseWire[0]', f=True) mc.delete(wireBaseUnwanted) # create dfmSysGrp dfmSysGrp = mc.group(baseCrv, wireCrv, n=nodeName+'_wireOffset_dfmSys_grp') rt.connectVisibilityToggle(wireCrv, dfmSysGrp, 'wireCrvVis', False) rt.connectVisibilityToggle(baseCrv, dfmSysGrp, 'baseCrvVis', False) mc.addAttr(dfmSysGrp, ln='envelope', at='double', k=True, dv=1) mc.addAttr(dfmSysGrp, ln='dropoff', at='double', k=True, dv=5) mc.addAttr(dfmSysGrp, ln='rotation', at='double', k=True, dv=0) mc.connectAttr(dfmSysGrp+'.envelope', wireDfm+'.envelope', f=True) mc.connectAttr(dfmSysGrp+'.dropoff', wireDfm+'.dds[0]', f=True) mc.connectAttr(dfmSysGrp+'.rotation', wireDfm+'.rotation', f=True) mc.addAttr(dfmSysGrp, ln='enabled', at='bool', k=True, dv=True) rt.connectSDK(dfmSysGrp+'.enabled', wireDfm+'.nodeState', {1:0, 0:2}) return dfmSysGrp
def createArcAnimation(self, baseCurve, arcCurveGroup, translate, rotate, scale, rotateWire, dropoff): mesh = cmds.polyPlane(n="arcSystem_"+baseCurve[0]+"_card", w=24, h=24, sx=4, sy=20)[0] cmds.delete(ch = True) # create new curve and hide it wireMeshCurve = cmds.curve(d=3, p=[(0, 0, -12), (0, 0, -6), (0, 0, 0), (0, 0, 6), (0, 0, 12)]) cmds.setAttr(wireMeshCurve+".v", False) # rebuild curve cmds.rebuildCurve(wireMeshCurve, baseCurve, ch=1, rpo=1, rt=2, end=1, kr=0, kcp=0, kep=1, kt=0, s=26, d=3, tol = 0.01) cmds.select(mesh, r=True) # smooth the mesh smooth = cmds.polySmooth(dv=0) cmds.select(mesh, r=True) # create wire of the mesh on the new curve wire = cmds.wire(mesh, gw=True, en=1.0, ce=0.0, li=0.0, w=wireMeshCurve) cmds.pickWalk(d="up") wireGroup = cmds.ls(sl=True) # parent to the spiral curve cmds.parent(wireGroup, arcCurveGroup) # set wire values cmds.setAttr(wire[0]+".dropoffDistance[0]", dropoff) cmds.setAttr(wire[0]+".rotation", rotateWire) # create blendshape of the new curve on the base curve blendshape = cmds.blendShape(baseCurve, wireMeshCurve) cmds.setAttr(blendshape[0]+"."+baseCurve[0], 1) # tranform a bit the mesh cmds.setAttr(mesh+".tz", translate[0]) cmds.setAttr(mesh+".rz", rotate[0]) cmds.setAttr(mesh+".sz", scale[0]) return mesh, blendshape, wireMeshCurve, smooth
def createRibbon(*args): #Gather information width = cmds.floatField('widthField', query=True, value=True) numJoints = cmds.intField('jointsField', query=True, value=True) prefix = cmds.textField('prefixField', query=True, text=True) scaleGrp = cmds.textField('scaleGrpField', query=True, text=True) topPoint = (width/2) endPoint = (width/2*-1) #Create the main groups grpNoTransform = cmds.group(empty=True, name=(prefix + 'noTransform_grp')) grpTransform = cmds.group(empty=True, name=(prefix + 'transform_grp')) grpCtrl = cmds.group(empty=True, name=(prefix + 'ctrl_grp'), parent=grpTransform) grpSurface = cmds.group(empty=True, name=(prefix + 'surface_grp'), parent=grpTransform) grpSurfaces = cmds.group(empty=True, name=(prefix + 'surfaces_grp'), parent=grpNoTransform) grpDeformers = cmds.group(empty=True, name=(prefix + 'deformer_grp'), parent=grpNoTransform) grpFollMain = cmds.group(empty=True, name=(prefix + 'follicles_skin_grp'), parent=grpNoTransform) grpFollVolume = cmds.group(empty=True, name=(prefix + 'follicles_volume_grp'), parent=grpNoTransform) grpCluster = cmds.group(empty=True, name=(prefix + 'cluster_grp'), parent=grpNoTransform) grpMisc = cmds.group(empty=True, name=(prefix + 'misc_grp'), parent=grpNoTransform) #Create a NURBS-plane to use as a base tmpPlane = cmds.nurbsPlane(axis=(0,1,0), width=width, lengthRatio=(1.0 / width), u=numJoints, v=1, degree=3, ch=0)[0] #Create the NURBS-planes to use in the setup geoPlane = cmds.duplicate(tmpPlane, name=(prefix + 'geo')) geoPlaneTwist = cmds.duplicate(tmpPlane, name=(prefix + 'twist_blnd_geo')) geoPlaneSine = cmds.duplicate(tmpPlane, name=(prefix + 'sine_blnd_geo')) geoPlaneWire = cmds.duplicate(tmpPlane, name=(prefix + 'wire_blnd_geo')) geoPlaneVolume = cmds.duplicate(tmpPlane, name=(prefix + 'volume_geo')) #Offset the volume-plane cmds.setAttr((geoPlaneVolume[0] + '.translateZ'), -0.5) #Delete the base surface cmds.delete(tmpPlane) #Create the controllers ctrlTop = createCurveCtrl(name=(prefix + 'top_ctrl'), freezeTransforms=1, color=9, pos=(topPoint,0,0)) ctrlMid = createCurveCtrl(name=(prefix + 'mid_ctrl'), freezeTransforms=1, color=9, pos=(0,0,0)) ctrlEnd = createCurveCtrl(name=(prefix + 'end_ctrl'), freezeTransforms=1, color=9, pos=(endPoint,0,0)) #Group the controllers grpTop = grpObject(objects=[ctrlTop], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpMid = grpObject(objects=[ctrlMid], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpEnd = grpObject(objects=[ctrlEnd], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] #PointConstraint the midCtrl between the top/end midConst = cmds.pointConstraint(ctrlTop, ctrlEnd, grpMid) #Add attributes: Twist/Roll attributes addAttribute(objects=[ctrlTop,ctrlMid,ctrlEnd],longName=['twistSep'],niceName=['---------------'],at="enum",en='Twist',lock=1,k=True) addAttribute(objects=[ctrlTop,ctrlEnd],longName=['twist'],at="float",k=True) addAttribute(objects=[ctrlTop,ctrlEnd],longName=['twistOffset'],at="float",k=True) addAttribute(objects=[ctrlTop,ctrlEnd],longName=['affectToMid'],at="float",min=0, max=10,dv=10,k=True) addAttribute(objects=[ctrlMid],longName=['roll'],at="float",k=True) addAttribute(objects=[ctrlMid],longName=['rollOffset'],at="float",k=True) #Add attributes: Volume attributes addAttribute(objects=[ctrlMid],longName=['volumeSep'],niceName=['---------------'],at="enum",en='Volume',lock=1,k=True) addAttribute(objects=[ctrlMid],longName=['volume'],at="float",min=-1,max=1,k=True) addAttribute(objects=[ctrlMid],longName=['volumeMultiplier'],at="float",min=1,dv=3,k=True) addAttribute(objects=[ctrlMid],longName=['startDropoff'],at="float",min=0, max=1, dv=1,k=True) addAttribute(objects=[ctrlMid],longName=['endDropoff'],at="float",min=0, max=1, dv=1, k=True) addAttribute(objects=[ctrlMid],longName=['volumeScale'],at="float",min=endPoint*0.9, max=topPoint*2,k=True) addAttribute(objects=[ctrlMid],longName=['volumePosition'],min=endPoint,max=topPoint,at="float",k=True) #Add attributes: Sine attributes addAttribute(objects=[ctrlMid], longName=['sineSep'], niceName=['---------------'], attributeType='enum', en="Sine:", keyable=True, lock=1) addAttribute(objects=[ctrlMid], longName=['amplitude'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['offset'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['twist'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['sineLength'], min=0.1, dv=2, attributeType="float", keyable=True) #Add attributes: Extra attributes addAttribute(objects=[ctrlMid],longName=['extraSep'],niceName=['---------------'],at="enum",en='Extra',lock=1,k=True) addAttribute(objects=[ctrlMid],longName=['showExtraCtrl'],at="enum",en='Hide:Show:',k=True) cmds.setAttr((ctrlMid + '.showExtraCtrl'), 1) #Create deformers: Twist deformer, Sine deformer, Squash deformer twistDef = nonlinearDeformer(objects=[geoPlaneTwist[0]], defType='twist', name=geoPlaneTwist[0], lowBound=-1, highBound=1, rotate=(0,0,90)) sineDef = nonlinearDeformer(objects=[geoPlaneSine[0]], defType='sine', name=geoPlaneSine[0], lowBound=-1, highBound=1, rotate=(0,0,90)) squashDef = nonlinearDeformer(objects=[geoPlaneVolume[0]], defType='squash', name=geoPlaneVolume[0], lowBound=-1, highBound=1, rotate=(0,0,90)) cmds.setAttr((sineDef[0] + '.dropoff'), 1) #Create deformers: Wire deformer deformCrv = cmds.curve(p=[(topPoint,0,0),(0,0,0),(endPoint,0,0)], degree=2) deformCrv = cmds.rename(deformCrv, (prefix + 'ribbon_wire_crv')) wireDef = cmds.wire(geoPlaneWire, dds=(0,15), wire=deformCrv) wireDef[0] = cmds.rename(wireDef[0], (geoPlaneWire[0] + '_wire')) #Create deformers: Clusters clsTop = cmds.cluster((deformCrv + '.cv[0:1]'), relative=1) clsMid = cmds.cluster((deformCrv + '.cv[1]'), relative=1) clsEnd = cmds.cluster((deformCrv + '.cv[1:2]'), relative=1) clsTop[0] = cmds.rename(clsTop[0], (ctrlTop + '_top_cluster')) clsTop[1] = cmds.rename(clsTop[1], (ctrlTop + '_top_clusterHandle')) clsMid[0] = cmds.rename(clsMid[0], (ctrlMid + '_mid_cluster')) clsMid[1] = cmds.rename(clsMid[1], (ctrlMid + '_mid_clusterHandle')) clsEnd[0] = cmds.rename(clsEnd[0], (ctrlEnd + '_end_cluster')) clsEnd[1] = cmds.rename(clsEnd[1], (ctrlEnd + '_end_clusterHandle')) cmds.setAttr((cmds.listRelatives(clsTop[1], type="shape")[0] + '.originX'), topPoint) cmds.setAttr((cmds.listRelatives(clsEnd[1], type="shape")[0] + '.originX'), endPoint) setPivot(objects=[clsTop[1]], rotatePivot=1, scalePivot=1, pivot=(topPoint,0,0)) setPivot(objects=[clsEnd[1]], rotatePivot=1, scalePivot=1, pivot=(endPoint,0,0)) cmds.percent(clsTop[0], (deformCrv + '.cv[1]'), v=0.5) cmds.percent(clsEnd[0], (deformCrv + '.cv[1]'), v=0.5) posTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'top_ctrl_pos_pma')) cmds.connectAttr((ctrlTop + '.translate'), (posTopPma + '.input3D[0]')) cmds.connectAttr((grpTop + '.translate'), (posTopPma + '.input3D[1]')) posEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'end_ctrl_pos_pma')) cmds.connectAttr((ctrlEnd + '.translate'), (posEndPma + '.input3D[0]')) cmds.connectAttr((grpEnd + '.translate'), (posEndPma + '.input3D[1]')) cmds.connectAttr((posTopPma + '.output3D'), (clsTop[1] + '.translate')) cmds.connectAttr((ctrlMid + '.translate'), (clsMid[1] + '.translate')) cmds.connectAttr((posEndPma + '.output3D'), (clsEnd[1] + '.translate')) #Create deformers: Blendshape blndDef = cmds.blendShape(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlane[0], name=(prefix + 'blendShape'),weight=[(0,1),(1,1),(2,1)]) #Twist deformer: Sum the twist and the roll sumTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'twist_top_sum_pma')) cmds.connectAttr((ctrlTop + '.twist'), (sumTopPma + '.input1D[0]')) cmds.connectAttr((ctrlTop + '.twistOffset'), (sumTopPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumTopPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumTopPma + '.input1D[3]')) cmds.connectAttr((sumTopPma + '.output1D'), (twistDef[0] + '.startAngle')) sumEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'twist_low_sum_pma')) cmds.connectAttr((ctrlEnd + '.twist'), (sumEndPma + '.input1D[0]')) cmds.connectAttr((ctrlEnd + '.twistOffset'), (sumEndPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumEndPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumEndPma + '.input1D[3]')) cmds.connectAttr((sumEndPma + '.output1D'), (twistDef[0] + '.endAngle')) #Twist deformer: Set up the affect of the deformer topAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name = (prefix + 'twist_top_affect_mdl')) cmds.setAttr((topAffMdl + '.input1'), -0.1) cmds.connectAttr((ctrlTop + '.affectToMid'), (topAffMdl + '.input2')) cmds.connectAttr((topAffMdl + '.output'), (twistDef[0] + '.lowBound')) endAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name = (prefix + 'twist_end_affect_mdl')) cmds.setAttr((endAffMdl + '.input1'), 0.1) cmds.connectAttr((ctrlEnd + '.affectToMid'), (endAffMdl + '.input2')) cmds.connectAttr((endAffMdl + '.output'), (twistDef[0] + '.highBound')) #Squash deformer: Set up the connections for the volume control volumeRevfMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name = (prefix + 'volume_reverse_mdl')) cmds.setAttr((volumeRevfMdl + '.input1'), -1) cmds.connectAttr((ctrlMid + '.volume'), (volumeRevfMdl + '.input2')) cmds.connectAttr((volumeRevfMdl + '.output'), (squashDef[0] + '.factor')) cmds.connectAttr((ctrlMid + '.startDropoff'), (squashDef[0] + '.startSmoothness')) cmds.connectAttr((ctrlMid + '.endDropoff'), (squashDef[0] + '.endSmoothness')) cmds.connectAttr((ctrlMid + '.volumePosition'), (squashDef[1] + '.translateX')) #Squash deformer: Set up the volume scaling sumScalePma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'volume_scale_sum_pma')) cmds.setAttr((sumScalePma + '.input1D[0]'), topPoint) cmds.connectAttr((ctrlMid + '.volumeScale'), (sumScalePma + '.input1D[1]')) cmds.connectAttr((sumScalePma + '.output1D'), (squashDef[1] + '.scaleY')) #Sine deformer: Set up the connections for the sine cmds.connectAttr((ctrlMid + '.amplitude'), (sineDef[0] + '.amplitude')) cmds.connectAttr((ctrlMid + '.offset'), (sineDef[0] + '.offset')) cmds.connectAttr((ctrlMid + '.twist'), (sineDef[1] + '.rotateY')) cmds.connectAttr((ctrlMid + '.sineLength'), (sineDef[0] + '.wavelength')) #Cleanup: Hierarchy cmds.parent(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlaneVolume[0], grpSurfaces) cmds.parent(twistDef[1], sineDef[1], squashDef[1], grpDeformers) cmds.parent(clsTop[1], clsMid[1], clsEnd[1], grpCluster) cmds.parent(grpTop, grpMid, grpEnd, grpCtrl) cmds.parent(geoPlane[0], grpSurface) cmds.parent(deformCrv, (cmds.listConnections(wireDef[0] + '.baseWire[0]')[0]), grpMisc) #Cleanup: Visibility cmds.hide(grpSurfaces, grpDeformers, grpCluster, grpMisc) for x in cmds.listConnections(ctrlMid): cmds.setAttr((x + '.isHistoricallyInteresting'), 0) for y in cmds.listConnections(x): cmds.setAttr((y + '.isHistoricallyInteresting'), 0) #Update the scale-group scaleGrp = scaleGrp if scaleGrp else grpTransform #Create follicles: The main-surface and the volume-surface for x in range(0, numJoints): #Declare a variable for the current index num = str(x + 1) #Get the normalized position of where to place the current follicle uVal = ((0.5 / numJoints) * (x + 1) * 2) - ((0.5 / (numJoints * 2)) * 2) #Create a follicle for the bind-plane and the volume-plane follicleS = createFollicle(scaleGrp=scaleGrp, inputSurface=cmds.listRelatives(geoPlane[0], type="shape"), uVal=uVal, name=(prefix + num + '_follicle')) follicleV = createFollicle(scaleGrp=None, inputSurface=cmds.listRelatives(geoPlaneVolume[0], type="shape"), uVal=uVal, vVal=0, name=(prefix + num + '_volume_follicle')) cmds.parent(follicleS[0], grpFollMain) cmds.parent(follicleV[0], grpFollVolume) #Create a joint, controller and a group for the current skin-follicle cmds.select(clear=True) follicleJoint = cmds.joint(name=(prefix + num + '_jnt'), radius=0.1) follicleCtrl = cmds.circle(name=(prefix + num + '_ctrl'), c=(0,0,0), nr=(1,0,0), sw=360, r=0.5, d=3, s=8, ch=0)[0] follicleXform = cmds.group(name=(prefix + num + '_xform_grp'), empty=True) cmds.parent(follicleXform, follicleS[0]) cmds.parent(follicleCtrl, follicleXform) cmds.parent(follicleJoint, follicleCtrl) cmds.delete(cmds.parentConstraint(follicleS[0], follicleXform)) #Set the color and connect the visibility-switch for the controller cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideEnabled'), 1) cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideColor'), 12) cmds.connectAttr((ctrlMid + '.showExtraCtrl'), (cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.visibility')) #Make the connections for the volume multMpd = cmds.shadingNode('multiplyDivide', asUtility=1, name = (prefix + num + '_multiplier_mpd')) cmds.connectAttr((ctrlMid + '.volumeMultiplier'), (multMpd + '.input1Z')) cmds.connectAttr((follicleV[0] + '.translate'), (multMpd + '.input2')) sumPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + num + '_volume_sum_pma')) cmds.connectAttr((multMpd + '.outputZ'), (sumPma + '.input1D[0]')) cmds.setAttr((sumPma + '.input1D[1]'), 1) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleY')) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleZ'))
def createRibbonSpine(self, name="ribbonSpine", joints=5): self.name = name self.joints = joints # Creates a hierarchy of groups to store our rig. self.masterGroup = cmds.group(name="%s_MST_GRP" % self.name, empty=True) self.moveGroup = cmds.group(name="%s_MOVE_GRP" % self.name, empty=True, parent=self.masterGroup) self.noMoveGroup = cmds.group(name="%s_NOMOVE_GRP" % self.name, empty=True, parent=self.masterGroup) # Create a NURBS plane that matches the distance between the two locators. self.plane = self.createPlane() self.blendOffset = (self.distance * (1.0 / self.joints)) * 2 # Duplicate the plane, shift it sideways, and apply it as a blend shape to the original. self.planeBlend = self.createPlaneBlend() self.planeBlendDeformer = cmds.blendShape(self.planeBlend, self.plane, weight=(0, 1), name=self.name + "_DFM") # Place a follicle on each patch on the original plane. Then parent joints beneath the follicles. self.follicles = self.createFollicles() self.bindJoints = self.createJoints() # Set up joints and curves as controls. self.controlCurves = self.createControlCurves() # Apply a wire deformer to the blend shape. self.wireDeformerCurve = cmds.curve( degree=2, point=[(self.blendOffset, (self.distance / 2) * -1, 0), (self.blendOffset, 0, 0), (self.blendOffset, (self.distance / 2), 0)], name="%s_WIRE_CRV" % self.name) self.planeWireDeformer = cmds.wire(self.planeBlend, wire=self.wireDeformerCurve, groupWithBase=False, envelope=1.0, crossingEffect=0, localInfluence=0, dropoffDistance=[0, 20]) # Apply clusters to the wire deformer and connect them to the control curves. self.clusterDeformers = self.createClusterDeformers() # A twist deformer allows for better rotation on the X axis. # Add a switch to allow squash and stretch. self.twistDeformer = self.createTwistDeformer() self.createStretchDeformer() # Initial clean-up. Move objects into their respective groups. self.parentObject(self.plane, self.moveGroup) self.parentObject(self.planeBlend, self.noMoveGroup) self.parentObject(self.wireDeformerCurve, self.noMoveGroup) self.parentObject("%sBaseWire" % str(self.wireDeformerCurve), self.noMoveGroup) self.parentObject(self.moveGroup, self.masterControlCurve) masterControlGroup = cmds.group(self.masterControlCurve, name="%s_MST_CTRL_GRP" % self.name, parent=self.masterGroup) # Hide objects. self.hideObject(self.planeBlend) self.hideObject(self.wireDeformerCurve) self.hideObject("%sBaseWire" % str(self.wireDeformerCurve)) # Constrain the plane to the locators. Then delete the constraint and the locators. constraint = cmds.pointConstraint(self.locators[0], self.locators[1], masterControlGroup) cmds.delete(constraint) for locator in self.locators: cmds.delete(locator)
def makeDynamicWire(jnts, geo, name, ctl): ''' ''' # make curve through joints startCrv = rt.makeCrvThroughObjs(jnts, name + '_startCrv', True, 2) # make curve dynamic mc.select(startCrv, r=True) meval('makeCurvesDynamic 2 { "0", "0", "1", "1", "0"};') # get a handle on new (badly named) nodes hairSys = mc.ls(sl=True)[0] foll = mc.listConnections(hairSys + '.outputHair[0]', d=True)[0] dynCrv = mc.listConnections(foll + '.outCurve', d=True)[0] # rename nodes properly hairSys = mc.rename(hairSys, name + '_hairSysShape') foll = mc.rename(foll, name + '_foll') dynCrv = mc.rename(dynCrv, name + '_dynCrv') # rename group and transform nodes as well hairSysTransform = mc.listRelatives(hairSys, p=True)[0] hairSysTransform = mc.rename(hairSysTransform, name + '_hairSys') startGrp = mc.listRelatives(foll, p=True)[0] startGrp = mc.rename(startGrp, name + '_hairSysFollicles') outputGrp = mc.listRelatives(dynCrv, p=True)[0] outputGrp = mc.rename(outputGrp, name + '_hairSysOutputCrvs') # since we now have start curve and end curve, we can make the wire deformer wireDfm, wireCrv = mc.wire(geo, wire=dynCrv, n=name + '_dyn_wireDfm', dds=(0, 50)) wireBaseUnwanted = wireCrv + 'BaseWire' # replace base mc.connectAttr(startCrv + '.worldSpace[0]', wireDfm + '.baseWire[0]', f=True) mc.delete(wireBaseUnwanted) # group nodes nicely masterGrp = mc.group(hairSysTransform, startGrp, outputGrp, n=name + '_hairSysMaster_grp') rt.connectVisibilityToggle([startGrp, outputGrp], masterGrp, 'curvesVis', False) rt.connectVisibilityToggle(hairSysTransform, masterGrp, 'hairSysVis', False) # attributes on ctl mc.addAttr(ctl, ln='tDynamics', nn='DYNAMICS', at='enum', en='-----', k=True) #mc.setAttr(ctl+'.tDynamics', l=True) mc.addAttr(ctl, ln='enabled', at='bool', dv=True, k=True) mc.addAttr(ctl, ln='weight', at='double', min=0, max=1, dv=1, k=True) mc.connectAttr(ctl + '.weight', wireDfm + '.envelope', f=True) rt.connectSDK(ctl + '.enabled', hairSys + '.simulationMethod', { 0: 0, 1: 3 }) # expose follicle attributes to ctl mc.addAttr(ctl, ln='pointLock', at='enum', en='No Attach:Base:Tip:Both Ends', k=True, dv=1) mc.connectAttr(ctl + '.pointLock', foll + '.pointLock', f=True) # expose hairSystem attributes to ctl mc.addAttr(ctl, ln='startCurveAttract', at='double', min=0, max=1, dv=0.05, k=True) mc.addAttr(ctl, ln='mass', at='double', min=0, dv=1, k=True) mc.addAttr(ctl, ln='drag', at='double', min=0, dv=0.05, k=True) mc.addAttr(ctl, ln='damp', at='double', min=0, dv=0, k=True) mc.connectAttr(ctl + '.startCurveAttract', hairSys + '.startCurveAttract', f=True) mc.connectAttr(ctl + '.mass', hairSys + '.mass', f=True) mc.connectAttr(ctl + '.drag', hairSys + '.drag', f=True) mc.connectAttr(ctl + '.damp', hairSys + '.damp', f=True)
def wire(*args, **kwargs): res = cmds.wire(*args, **kwargs) if not kwargs.get('query', kwargs.get('q', False)): res = _factories.maybeConvert(res, _general.PyNode) return res
def wire(self, character = None, mod = None, side = None, name = None, suffix = None, wire = None, geometry = None, position = [0,0,0], rotation = [0,0,0], envelope = 1, crossingEffect = 0, tension = 1, localInfluence = 0, wireRotation = 1, dropoffDistance = 1, wireScale = 1, parent = None, show = True, lockAttr = None, ihi = True): #--- this method creates a wire deformer node = [] if wire: if geometry: #--- create a wire deformer node = cmds.wire(geometry, wire = wire, groupWithBase = False) base = cmds.ls(node[-1] + 'BaseWire') #--- filter the individual name filter_name = (name + node[0][0].upper() + node[0][1:]) #--- rename the wire deformer node = self.__rename_node(mod = mod, side = side, name = filter_name, suffix = suffix, obj = node) #--- rename the baseWire curve base = self.__rename_node(mod = mod, side = side, name = filter_name + 'BaseWire', suffix = suffix, obj = base) #--- create a group on top and parent the deformer under the group node_grp = cmds.createNode('transform', parent = node[0]) cmds.parent(node_grp, world = True) cmds.parent(node[0], base[0], node_grp) #--- rename the node group node_grp = self.__rename_node(mod = mod, side = side, name = filter_name, suffix = 'GRP', obj = node_grp)[0] #--- reposition the transform of the deformer locally cmds.xform(node[0], translation = position, worldSpace = False) cmds.xform(node[0], rotation = rotation, worldSpace = False) #--- take care of the node's settings #--- envelope cmds.setAttr(node[-1] + '.envelope', envelope) #--- crossingEffect cmds.setAttr(node[-1] + '.crossingEffect', crossingEffect) #--- tension cmds.setAttr(node[-1] + '.tension', tension) #--- localInfluence cmds.setAttr(node[-1] + '.localInfluence', localInfluence) #--- wireRotation cmds.setAttr(node[-1] + '.rotation', wireRotation) #--- dropoffDistance cmds.setAttr(node[-1] + '.dropoffDistance[0]', dropoffDistance) #--- wireScale cmds.setAttr(node[-1] + '.scale[0]', wireScale) #--- parent the group under the specified parent if parent: if not isinstance(parent, list): cmds.parent(node_grp, parent) else: raise Exception("Specified parent: " + parent + 'is not a valid') #--- show or hide transform if not show: cmds.setAttr(node[0] + '.v', 0) #--- lock specified attributes if lockAttr: if node[-1]: cmds.setAttr(node[-1] + '.' + lockAttr, lock = True) #--- set isHistoricalInteresting attribute if not ihi: for n in node: cmds.setAttr(n + '.ihi', 0) #--- add the base wire to the node list node.append(base[0]) #--- return node return node
def ik_system(self): """ building up the ik system Args: Returns: """ self.ik_chain = joints_utils.related_clean_joint_chain(self.main_chain, self.side, "ikSpine", True) self.ik_system_objs.append(self.ik_chain[0]) # re-orient the last joint as his father cmds.joint(self.ik_chain[-1], edit=True, orientJoint="none", children=True, zeroScaleOrient=True) curve_points = [] for jnt in self.ik_chain: point = cmds.xform(jnt, query=True, worldSpace=True, translation=True) curve_points.append(point) # create curves and rebuilding them self.ik_spline_crv = cmds.curve(degree=1, point=curve_points) self.ik_spline_crv = cmds.rename(self.ik_spline_crv, "{}_{}_ikSplineHandle_crv".format(self.side, self.name)) cmds.rebuildCurve( self.ik_spline_crv, caching=True, replaceOriginal=True, rebuildType=0, endKnots=True, keepRange=False, keepControlPoints=True, keepEndPoints=True, keepTangents=False, spans=len(self.ik_chain), degree=1, tolerance=0.01 ) cmds.delete(self.ik_spline_crv, constructionHistory=True) rebuilded_crv = cmds.rebuildCurve( self.ik_spline_crv, caching=True, replaceOriginal=False, rebuildType=0, endKnots=True, keepRange=False, keepControlPoints=False, keepEndPoints=True, keepTangents=False, spans=len(self.ik_chain)/2, degree=7, tolerance=0.01 ) driver_ik_spline_crv = cmds.rename(rebuilded_crv, "{}_{}_ikSplineHandle_driver_crv".format(self.side, self.name)) cmds.delete(driver_ik_spline_crv, constructionHistory=True) self.ik_system_objs.extend([self.ik_spline_crv, driver_ik_spline_crv]) # wire deformer wire_def = cmds.wire(self.ik_spline_crv, wire=driver_ik_spline_crv, name="{}_{}_ikSplineCrvDriver_wre".format(self.side, self.name)) cmds.setAttr("{}.dropoffDistance[0]".format(wire_def[0]), 9999999999) self.ik_system_objs.append("{}BaseWire".format(driver_ik_spline_crv)) # creating locator for twisting ikSpline start_twist_loc = cmds.spaceLocator(name="{}_{}_startTwist_ikSpline_LOC".format(self.side, self.name)) transforms_utils.align_objs(self.ik_chain[0], start_twist_loc[0]) end_twist_loc = cmds.spaceLocator(name="{}_{}_endTwist_ikSpline_LOC".format(self.side, self.name)) transforms_utils.align_objs(self.ik_chain[-1], end_twist_loc[0]) # ik spline solver --- -scv false -pcv false -snc true ik_spline_solver = cmds.ikHandle(name="{}_{}_splineSolver_IKH".format(self.side, self.name), solver='ikSplineSolver', startJoint=self.ik_chain[0], endEffector=self.ik_chain[-1], createCurve=False, simplifyCurve=False, parentCurve=False, snapCurve=True, curve=self.ik_spline_crv) cmds.setAttr("{}.dTwistControlEnable".format(ik_spline_solver[0]), 1) cmds.setAttr("{}.dWorldUpType".format(ik_spline_solver[0]), 4) self.ik_system_objs.append(ik_spline_solver[0]) # twist ik spline solver cmds.connectAttr("{}.worldMatrix[0]".format(start_twist_loc[0]), "{}.dWorldUpMatrix".format(ik_spline_solver[0]), force=True) cmds.connectAttr("{}.worldMatrix[0]".format(end_twist_loc[0]), "{}.dWorldUpMatrixEnd".format(ik_spline_solver[0]), force=True) # make joint at parameter driver_joints = [] parameter = 0.0 driver_crv_dag_path = dag_node.DagNode(driver_ik_spline_crv) fn_curves = OM.MFnNurbsCurve(driver_crv_dag_path.get_dag_path()) point = OM.MPoint() parameter = 0.0 for i in range(0, self.num_ik_middle_ctrls + 2): if i == 0: point = fn_curves.getPointAtParam(parameter, 0) jnt = cmds.createNode("joint", name="{}_{}_{}_spineDriver_JNT".format(self.side, self.name, i)) cmds.xform(jnt, translation=[point.x, point.y, point.z]) driver_joints.append(jnt) else: # if i == self.num_ik_middle_ctrls-1: parameter += 1.0/float(self.num_ik_middle_ctrls + 1) point = fn_curves.getPointAtParam(parameter, 0) jnt = cmds.createNode("joint", name="{}_{}_{}_spineDriver_JNT".format(self.side, self.name, i)) cmds.xform(jnt, translation=[point.x, point.y, point.z]) driver_joints.append(jnt) driver_joints_grp = cmds.group(driver_joints, name="{}_{}_ikSystem_driverJoints_GRP".format(self.side, self.name)) self.ik_system_objs.append(driver_joints_grp) # parenting twist locators under the first and the end driver joints cmds.parent(start_twist_loc[0], driver_joints[0]) cmds.parent(end_twist_loc[0], driver_joints[-1]) # skinCluster which drives the driver curve cmds.skinCluster(driver_joints, driver_ik_spline_crv) # building controls ik_controls = [] # ik_controls_offset_grps = [] for i, jnt in enumerate(driver_joints): if i == 0: self.start_ik_ctrl = controller.Control("{}_{}_start_ik".format(self.side, self.name), 5.0, 'cube', jnt, jnt, '', ['s', 'v'], '', True, True, False) self.start_ik_ctrl.make_dynamic_pivot("{}_{}_startPivot_ik_".format(self.side, self.name), 2.5, self.start_ik_ctrl.get_control(), self.start_ik_ctrl.get_control()) ik_controls.append(self.start_ik_ctrl) cmds.parentConstraint(self.start_ik_ctrl.get_control(), jnt, maintainOffset=True) elif i == len(driver_joints) - 1: self.end_ik_ctrl = controller.Control("{}_{}_end_ik".format(self.side, self.name), 5.0, 'cube', jnt, jnt, '', ['s', 'v'], '', True, True, False) self.end_ik_ctrl.make_dynamic_pivot("{}_{}_endPivot_ik_".format(self.side, self.name), 2.5, self.end_ik_ctrl.get_control(), self.end_ik_ctrl.get_control()) ik_controls.append(self.end_ik_ctrl) cmds.parentConstraint(self.end_ik_ctrl.get_control(), jnt, maintainOffset=True) else: middle_ctrl = controller.Control("{}_{}_middle{}_ik".format(self.side, self.name, i-1), 5.0, 'square', jnt, jnt, '', ['s', 'v'], '', True, True, False) ik_controls.append(middle_ctrl) cmds.parentConstraint(middle_ctrl.get_control(), jnt, maintainOffset=True) # follow feature of middle controls pac_middleCtrls_follow = [] follow_factor = 0 for i, ctrl in enumerate(ik_controls): if i == 0: continue elif i == len(ik_controls) - 1: continue else: pac = cmds.parentConstraint([self.world_space_loc[0], ik_controls[0].get_control(), ik_controls[-1].get_control()], ctrl.get_offset_grp(), maintainOffset=True) cmds.setAttr("{}.interpType".format(pac[0]), 2) name_attr = "startEndFollow" attributes_utils.add_float_attr(ctrl.get_control(), name_attr, -5.0, 10.0, 0.0) cmds.setDrivenKeyframe(pac, attribute="{}W0".format(self.world_space_loc[0]), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=-5.0, value=1.0) cmds.setDrivenKeyframe(pac, attribute="{}W0".format(self.world_space_loc[0]), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=0.0, value=0.0) cmds.setDrivenKeyframe(pac, attribute="{}W0".format(self.world_space_loc[0]), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=10.0, value=0.0) cmds.setDrivenKeyframe(pac, attribute="{}W1".format(ik_controls[0].get_control()), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=-5.0, value=0.0) cmds.setDrivenKeyframe(pac, attribute="{}W1".format(ik_controls[0].get_control()), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=0.0, value=1.0) cmds.setDrivenKeyframe(pac, attribute="{}W1".format(ik_controls[0].get_control()), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=10.0, value=0.0) cmds.setDrivenKeyframe(pac, attribute="{}W2".format(ik_controls[-1].get_control()), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=-5.0, value=0.0) cmds.setDrivenKeyframe(pac, attribute="{}W2".format(ik_controls[-1].get_control()), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=0.0, value=0.0) cmds.setDrivenKeyframe(pac, attribute="{}W2".format(ik_controls[-1].get_control()), currentDriver="{}.{}".format(ctrl.get_control(), name_attr), driverValue=10.0, value=1.0) follow_factor += 10.0/float(self.num_ik_middle_ctrls + 1.0) cmds.setAttr("{}.{}".format(ctrl.get_control(), name_attr), follow_factor) # clean up the scene cmds.group(empty=True, name=self.ik_ctrls_main_grp) transforms_utils.align_objs(self.root_space, self.ik_ctrls_main_grp) cmds.parentConstraint(self.root_space, self.ik_ctrls_main_grp, maintainOffset=True) cmds.scaleConstraint(self.root_space, self.ik_ctrls_main_grp, maintainOffset=True) for ctrl in ik_controls: cmds.parent(ctrl.get_offset_grp(), self.ik_ctrls_main_grp) ik_system_grp = cmds.group(empty=True, name="{}_{}_ikSystem_GRP".format(self.side, self.name)) cmds.parent(self.ik_system_objs, ik_system_grp) self.module_main_grp(ik_system_grp) # connect to root """ if self.root_space == "" or self.root_space == None: print "###--- No root space found. It'll skipped ---###" else: name_attr = "spaces" transforms_utils.make_spaces(self.start_ik_ctrl.get_control(), self.start_ik_ctrl.get_offset_grp(), name_attr, [self.world_space_loc[0], self.root_space], naming=["world", "root"]) cmds.setAttr("{}.{}".format(self.start_ik_ctrl.get_control(), name_attr), 1) """ return True
def createRibbon(*args): #Gather information width = cmds.floatField('widthField', query=True, value=True) numJoints = cmds.intField('jointsField', query=True, value=True) prefix = cmds.textField('prefixField', query=True, text=True) scaleGrp = cmds.textField('scaleGrpField', query=True, text=True) topPoint = (width / 2) endPoint = (width / 2 * -1) #Create the main groups grpNoTransform = cmds.group(empty=True, name=(prefix + 'noTransform_grp')) grpTransform = cmds.group(empty=True, name=(prefix + 'transform_grp')) grpCtrl = cmds.group(empty=True, name=(prefix + 'ctrl_grp'), parent=grpTransform) grpSurface = cmds.group(empty=True, name=(prefix + 'surface_grp'), parent=grpTransform) grpSurfaces = cmds.group(empty=True, name=(prefix + 'surfaces_grp'), parent=grpNoTransform) grpDeformers = cmds.group(empty=True, name=(prefix + 'deformer_grp'), parent=grpNoTransform) grpFollMain = cmds.group(empty=True, name=(prefix + 'follicles_skin_grp'), parent=grpNoTransform) grpFollVolume = cmds.group(empty=True, name=(prefix + 'follicles_volume_grp'), parent=grpNoTransform) grpCluster = cmds.group(empty=True, name=(prefix + 'cluster_grp'), parent=grpNoTransform) grpMisc = cmds.group(empty=True, name=(prefix + 'misc_grp'), parent=grpNoTransform) #Create a NURBS-plane to use as a base tmpPlane = cmds.nurbsPlane(axis=(0, 1, 0), width=width, lengthRatio=(1.0 / width), u=numJoints, v=1, degree=3, ch=0)[0] #Create the NURBS-planes to use in the setup geoPlane = cmds.duplicate(tmpPlane, name=(prefix + 'geo')) geoPlaneTwist = cmds.duplicate(tmpPlane, name=(prefix + 'twist_blnd_geo')) geoPlaneSine = cmds.duplicate(tmpPlane, name=(prefix + 'sine_blnd_geo')) geoPlaneWire = cmds.duplicate(tmpPlane, name=(prefix + 'wire_blnd_geo')) geoPlaneVolume = cmds.duplicate(tmpPlane, name=(prefix + 'volume_geo')) #Offset the volume-plane cmds.setAttr((geoPlaneVolume[0] + '.translateZ'), -0.5) #Delete the base surface cmds.delete(tmpPlane) #Create the controllers ctrlTop = createCurveCtrl(name=(prefix + 'top_ctrl'), freezeTransforms=1, color=9, pos=(topPoint, 0, 0)) ctrlMid = createCurveCtrl(name=(prefix + 'mid_ctrl'), freezeTransforms=1, color=9, pos=(0, 0, 0)) ctrlEnd = createCurveCtrl(name=(prefix + 'end_ctrl'), freezeTransforms=1, color=9, pos=(endPoint, 0, 0)) #Group the controllers grpTop = grpObject(objects=[ctrlTop], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpMid = grpObject(objects=[ctrlMid], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpEnd = grpObject(objects=[ctrlEnd], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] #PointConstraint the midCtrl between the top/end midConst = cmds.pointConstraint(ctrlTop, ctrlEnd, grpMid) #Add attributes: Twist/Roll attributes addAttribute(objects=[ctrlTop, ctrlMid, ctrlEnd], longName=['twistSep'], niceName=['---------------'], at="enum", en='Twist', lock=1, k=True) addAttribute(objects=[ctrlTop, ctrlEnd], longName=['twist'], at="float", k=True) addAttribute(objects=[ctrlTop, ctrlEnd], longName=['twistOffset'], at="float", k=True) addAttribute(objects=[ctrlTop, ctrlEnd], longName=['affectToMid'], at="float", min=0, max=10, dv=10, k=True) addAttribute(objects=[ctrlMid], longName=['roll'], at="float", k=True) addAttribute(objects=[ctrlMid], longName=['rollOffset'], at="float", k=True) #Add attributes: Volume attributes addAttribute(objects=[ctrlMid], longName=['volumeSep'], niceName=['---------------'], at="enum", en='Volume', lock=1, k=True) addAttribute(objects=[ctrlMid], longName=['volume'], at="float", min=-1, max=1, k=True) addAttribute(objects=[ctrlMid], longName=['volumeMultiplier'], at="float", min=1, dv=3, k=True) addAttribute(objects=[ctrlMid], longName=['startDropoff'], at="float", min=0, max=1, dv=1, k=True) addAttribute(objects=[ctrlMid], longName=['endDropoff'], at="float", min=0, max=1, dv=1, k=True) addAttribute(objects=[ctrlMid], longName=['volumeScale'], at="float", min=endPoint * 0.9, max=topPoint * 2, k=True) addAttribute(objects=[ctrlMid], longName=['volumePosition'], min=endPoint, max=topPoint, at="float", k=True) #Add attributes: Sine attributes addAttribute(objects=[ctrlMid], longName=['sineSep'], niceName=['---------------'], attributeType='enum', en="Sine:", keyable=True, lock=1) addAttribute(objects=[ctrlMid], longName=['amplitude'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['offset'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['twist'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['sineLength'], min=0.1, dv=2, attributeType="float", keyable=True) #Add attributes: Extra attributes addAttribute(objects=[ctrlMid], longName=['extraSep'], niceName=['---------------'], at="enum", en='Extra', lock=1, k=True) addAttribute(objects=[ctrlMid], longName=['showExtraCtrl'], at="enum", en='Hide:Show:', k=True) cmds.setAttr((ctrlMid + '.showExtraCtrl'), 1) #Create deformers: Twist deformer, Sine deformer, Squash deformer twistDef = nonlinearDeformer(objects=[geoPlaneTwist[0]], defType='twist', name=geoPlaneTwist[0], lowBound=-1, highBound=1, rotate=(0, 0, 90)) sineDef = nonlinearDeformer(objects=[geoPlaneSine[0]], defType='sine', name=geoPlaneSine[0], lowBound=-1, highBound=1, rotate=(0, 0, 90)) squashDef = nonlinearDeformer(objects=[geoPlaneVolume[0]], defType='squash', name=geoPlaneVolume[0], lowBound=-1, highBound=1, rotate=(0, 0, 90)) cmds.setAttr((sineDef[0] + '.dropoff'), 1) #Create deformers: Wire deformer deformCrv = cmds.curve(p=[(topPoint, 0, 0), (0, 0, 0), (endPoint, 0, 0)], degree=2) deformCrv = cmds.rename(deformCrv, (prefix + 'ribbon_wire_crv')) wireDef = cmds.wire(geoPlaneWire, dds=(0, 15), wire=deformCrv) wireDef[0] = cmds.rename(wireDef[0], (geoPlaneWire[0] + '_wire')) #Create deformers: Clusters clsTop = cmds.cluster((deformCrv + '.cv[0:1]'), relative=1) clsMid = cmds.cluster((deformCrv + '.cv[1]'), relative=1) clsEnd = cmds.cluster((deformCrv + '.cv[1:2]'), relative=1) clsTop[0] = cmds.rename(clsTop[0], (ctrlTop + '_top_cluster')) clsTop[1] = cmds.rename(clsTop[1], (ctrlTop + '_top_clusterHandle')) clsMid[0] = cmds.rename(clsMid[0], (ctrlMid + '_mid_cluster')) clsMid[1] = cmds.rename(clsMid[1], (ctrlMid + '_mid_clusterHandle')) clsEnd[0] = cmds.rename(clsEnd[0], (ctrlEnd + '_end_cluster')) clsEnd[1] = cmds.rename(clsEnd[1], (ctrlEnd + '_end_clusterHandle')) cmds.setAttr((cmds.listRelatives(clsTop[1], type="shape")[0] + '.originX'), topPoint) cmds.setAttr((cmds.listRelatives(clsEnd[1], type="shape")[0] + '.originX'), endPoint) setPivot(objects=[clsTop[1]], rotatePivot=1, scalePivot=1, pivot=(topPoint, 0, 0)) setPivot(objects=[clsEnd[1]], rotatePivot=1, scalePivot=1, pivot=(endPoint, 0, 0)) cmds.percent(clsTop[0], (deformCrv + '.cv[1]'), v=0.5) cmds.percent(clsEnd[0], (deformCrv + '.cv[1]'), v=0.5) posTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'top_ctrl_pos_pma')) cmds.connectAttr((ctrlTop + '.translate'), (posTopPma + '.input3D[0]')) cmds.connectAttr((grpTop + '.translate'), (posTopPma + '.input3D[1]')) posEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'end_ctrl_pos_pma')) cmds.connectAttr((ctrlEnd + '.translate'), (posEndPma + '.input3D[0]')) cmds.connectAttr((grpEnd + '.translate'), (posEndPma + '.input3D[1]')) cmds.connectAttr((posTopPma + '.output3D'), (clsTop[1] + '.translate')) cmds.connectAttr((ctrlMid + '.translate'), (clsMid[1] + '.translate')) cmds.connectAttr((posEndPma + '.output3D'), (clsEnd[1] + '.translate')) #Create deformers: Blendshape blndDef = cmds.blendShape(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlane[0], name=(prefix + 'blendShape'), weight=[(0, 1), (1, 1), (2, 1)]) #Twist deformer: Sum the twist and the roll sumTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'twist_top_sum_pma')) cmds.connectAttr((ctrlTop + '.twist'), (sumTopPma + '.input1D[0]')) cmds.connectAttr((ctrlTop + '.twistOffset'), (sumTopPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumTopPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumTopPma + '.input1D[3]')) cmds.connectAttr((sumTopPma + '.output1D'), (twistDef[0] + '.startAngle')) sumEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'twist_low_sum_pma')) cmds.connectAttr((ctrlEnd + '.twist'), (sumEndPma + '.input1D[0]')) cmds.connectAttr((ctrlEnd + '.twistOffset'), (sumEndPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumEndPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumEndPma + '.input1D[3]')) cmds.connectAttr((sumEndPma + '.output1D'), (twistDef[0] + '.endAngle')) #Twist deformer: Set up the affect of the deformer topAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name=(prefix + 'twist_top_affect_mdl')) cmds.setAttr((topAffMdl + '.input1'), -0.1) cmds.connectAttr((ctrlTop + '.affectToMid'), (topAffMdl + '.input2')) cmds.connectAttr((topAffMdl + '.output'), (twistDef[0] + '.lowBound')) endAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name=(prefix + 'twist_end_affect_mdl')) cmds.setAttr((endAffMdl + '.input1'), 0.1) cmds.connectAttr((ctrlEnd + '.affectToMid'), (endAffMdl + '.input2')) cmds.connectAttr((endAffMdl + '.output'), (twistDef[0] + '.highBound')) #Squash deformer: Set up the connections for the volume control volumeRevfMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name=(prefix + 'volume_reverse_mdl')) cmds.setAttr((volumeRevfMdl + '.input1'), -1) cmds.connectAttr((ctrlMid + '.volume'), (volumeRevfMdl + '.input2')) cmds.connectAttr((volumeRevfMdl + '.output'), (squashDef[0] + '.factor')) cmds.connectAttr((ctrlMid + '.startDropoff'), (squashDef[0] + '.startSmoothness')) cmds.connectAttr((ctrlMid + '.endDropoff'), (squashDef[0] + '.endSmoothness')) cmds.connectAttr((ctrlMid + '.volumePosition'), (squashDef[1] + '.translateX')) #Squash deformer: Set up the volume scaling sumScalePma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'volume_scale_sum_pma')) cmds.setAttr((sumScalePma + '.input1D[0]'), topPoint) cmds.connectAttr((ctrlMid + '.volumeScale'), (sumScalePma + '.input1D[1]')) cmds.connectAttr((sumScalePma + '.output1D'), (squashDef[1] + '.scaleY')) #Sine deformer: Set up the connections for the sine cmds.connectAttr((ctrlMid + '.amplitude'), (sineDef[0] + '.amplitude')) cmds.connectAttr((ctrlMid + '.offset'), (sineDef[0] + '.offset')) cmds.connectAttr((ctrlMid + '.twist'), (sineDef[1] + '.rotateY')) cmds.connectAttr((ctrlMid + '.sineLength'), (sineDef[0] + '.wavelength')) #Cleanup: Hierarchy cmds.parent(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlaneVolume[0], grpSurfaces) cmds.parent(twistDef[1], sineDef[1], squashDef[1], grpDeformers) cmds.parent(clsTop[1], clsMid[1], clsEnd[1], grpCluster) cmds.parent(grpTop, grpMid, grpEnd, grpCtrl) cmds.parent(geoPlane[0], grpSurface) cmds.parent(deformCrv, (cmds.listConnections(wireDef[0] + '.baseWire[0]')[0]), grpMisc) #Cleanup: Visibility cmds.hide(grpSurfaces, grpDeformers, grpCluster, grpMisc) for x in cmds.listConnections(ctrlMid): cmds.setAttr((x + '.isHistoricallyInteresting'), 0) for y in cmds.listConnections(x): cmds.setAttr((y + '.isHistoricallyInteresting'), 0) #Update the scale-group scaleGrp = scaleGrp if scaleGrp else grpTransform #Create follicles: The main-surface and the volume-surface for x in range(0, numJoints): #Declare a variable for the current index num = str(x + 1) #Get the normalized position of where to place the current follicle uVal = ((0.5 / numJoints) * (x + 1) * 2) - ((0.5 / (numJoints * 2)) * 2) #Create a follicle for the bind-plane and the volume-plane follicleS = createFollicle(scaleGrp=scaleGrp, inputSurface=cmds.listRelatives( geoPlane[0], type="shape"), uVal=uVal, name=(prefix + num + '_follicle')) follicleV = createFollicle(scaleGrp=None, inputSurface=cmds.listRelatives( geoPlaneVolume[0], type="shape"), uVal=uVal, vVal=0, name=(prefix + num + '_volume_follicle')) cmds.parent(follicleS[0], grpFollMain) cmds.parent(follicleV[0], grpFollVolume) #Create a joint, controller and a group for the current skin-follicle cmds.select(clear=True) follicleJoint = cmds.joint(name=(prefix + num + '_jnt'), radius=0.1) follicleCtrl = cmds.circle(name=(prefix + num + '_ctrl'), c=(0, 0, 0), nr=(1, 0, 0), sw=360, r=0.5, d=3, s=8, ch=0)[0] follicleXform = cmds.group(name=(prefix + num + '_xform_grp'), empty=True) cmds.parent(follicleXform, follicleS[0]) cmds.parent(follicleCtrl, follicleXform) cmds.parent(follicleJoint, follicleCtrl) cmds.delete(cmds.parentConstraint(follicleS[0], follicleXform)) #Set the color and connect the visibility-switch for the controller cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideEnabled'), 1) cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideColor'), 12) cmds.connectAttr( (ctrlMid + '.showExtraCtrl'), (cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.visibility')) #Make the connections for the volume multMpd = cmds.shadingNode('multiplyDivide', asUtility=1, name=(prefix + num + '_multiplier_mpd')) cmds.connectAttr((ctrlMid + '.volumeMultiplier'), (multMpd + '.input1Z')) cmds.connectAttr((follicleV[0] + '.translate'), (multMpd + '.input2')) sumPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + num + '_volume_sum_pma')) cmds.connectAttr((multMpd + '.outputZ'), (sumPma + '.input1D[0]')) cmds.setAttr((sumPma + '.input1D[1]'), 1) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleY')) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleZ'))
def blinkSetup(self, sideRGT, sideLFT, eyeballJnt, prefixEyeball, prefixEyeballAim, crvUp, crvDown, scale, side, eyelidUp, eyelidDown, positionEyeAimCtrl, worldUpAimObject, eyeballAimMainCtrl, controllerBind03OffsetCtrlUp, controllerBind03OffsetCtrlDown, jointBind03GrpAllUp, jointBind03GrpAllDown, jointBind03GrpOffsetDown, jointBind03GrpOffsetUp): # ============================================================================================================== # EYEBALL CONTROLLER # ============================================================================================================== eyballGrp = au.createParentTransform(listparent=['Zro', 'Offset'], object=eyeballJnt, matchPos=eyeballJnt, prefix='eyeball', suffix='_jnt', side=side) self.eyeballCtrl = ct.Control(matchPos=eyeballJnt, prefix=prefixEyeball, shape=ct.JOINTPLUS, groupsCtrl=['Zro', 'Offset'], ctrlSize=scale * 2, ctrlColor='blue', lockChannels=['v', 's'], side=side, connect=['connectMatrixAll']) self.eyeballController = self.eyeballCtrl.control # ADD ATTRIBUTE au.addAttribute(objects=[self.eyeballCtrl.control], longName=['eyelidDegree'], niceName=[' '], at="enum", en='Eyelid Degree', cb=True) self.eyelidPos = au.addAttribute(objects=[self.eyeballCtrl.control], longName=['eyelidPos'], attributeType="float", min=0, max=1, dv=0.5, k=True) self.eyelidFollow = au.addAttribute(objects=[self.eyeballCtrl.control], longName=['eyelidFollow'], attributeType="float", min=0, max=2, dv=1, k=True) # ============================================================================================================== # EYEBALL AIM # ============================================================================================================== if mc.xform(eyeballJnt, q=1, ws=1, t=1)[0] > 0: ctrlColor = 'red' else: ctrlColor = 'yellow' self.eyeballAimCtrl = ct.Control(matchPos=eyeballJnt, prefix=prefixEyeballAim, shape=ct.LOCATOR, groupsCtrl=['Zro', 'Offset'], ctrlSize=scale * 0.2, ctrlColor=ctrlColor, lockChannels=['v', 'r', 's'], side=side) eyeballAimCtrl = self.eyeballAimCtrl.control getAttribute = mc.getAttr(self.eyeballAimCtrl.parentControl[0] + '.translateZ') mc.setAttr(self.eyeballAimCtrl.parentControl[0] + '.translateZ', getAttribute + (positionEyeAimCtrl * scale)) mc.aimConstraint(self.eyeballAimCtrl.control, eyballGrp[1], mo=1, weight=1, aimVector=(0, 0, 1), upVector=(0, 1, 0), worldUpType="object", worldUpObject=worldUpAimObject) # PARENT EYE AIM TO EYEBALL AIM MAIN CTRL mc.parent(self.eyeballAimCtrl.parentControl[0], eyeballAimMainCtrl) # EXPRESSION UP AND DOWN FOLLOW EYELID CTRL expressionEyelidCtrl= "$range = {5}.{1}; " \ "$a = 20 /$range; " \ "$b = 30 /$range; " \ "$c = 80 /$range;" \ "{2}.translateX = {3}.translateX /$c + {0}.translateX /$c;" \ "{2}.translateY = {3}.translateY /$a + {0}.translateY /$a;" \ "{4}.translateX = {3}.translateX /$c + {0}.translateX /$c;" \ "{4}.translateY = -{3}.translateY /$b - {0}.translateY /$b;"\ \ .format(eyeballAimCtrl, # 0 self.eyelidFollow, # 1 controllerBind03OffsetCtrlUp, # 2 eyeballAimMainCtrl,# 3 controllerBind03OffsetCtrlDown, self.eyeballCtrl.control ) mc.expression(s=expressionEyelidCtrl, n="%s%s%s" % ('eyelidCtrl', side, '_expr'), ae=0) # EXPRESSION UP AND DOWN FOLLOW EYELID BIND expressionEyelidBind = "$range = {7}.{1}; " \ "$a = 30 /$range; " \ "$b = 8 /$range; " \ "$d = 12 /$range; " \ "$c = 60 /$range;" \ "if ({0}.translateY >= 0) " \ "{8} " \ "{2}.translateY = {0}.translateY /$b; " \ "{3}.translateY = {0}.translateY /$b;" \ "{9} " \ "else if ({0}.translateY < 0)" \ "{8}" \ "{2}.translateY = {0}.translateY /$d; " \ "{3}.translateY = {0}.translateY /$a;" \ "{9} " \ "{2}.translateX = {0}.translateX /$c; " \ "{3}.translateX = {0}.translateX /$c; " \ "if ({6}.translateY >= 0) " \ "{8}" \ "{4}.translateY = {6}.translateY /$b; " \ "{5}.translateY = {6}.translateY /$b;" \ "{9} " \ "else if ({6}.translateY < 0) " \ "{8}" \ "{4}.translateY = {6}.translateY /$d; " \ "{5}.translateY = {6}.translateY /$a;" \ "{9} " \ "{4}.translateX = {6}.translateX /$c; " \ "{5}.translateX = {6}.translateX /$c;" \ \ .format(eyeballAimCtrl, self.eyelidFollow, jointBind03GrpAllUp, jointBind03GrpAllDown, jointBind03GrpOffsetUp, jointBind03GrpOffsetDown, eyeballAimMainCtrl, self.eyeballCtrl.control, "{", "}") mc.expression(s=expressionEyelidBind, n="%s%s%s" % ('eyelidBind', side, '_expr'), ae=0) # ============================================================================================================== # BLINK # ============================================================================================================== # CREATE CURVE MID BLINK curveBlinkBindMidOld = mc.curve(d=3, ep=[(self.eyelidUp.xformJnt01), (self.eyelidUp.xformJnt05)]) curveBlinkBindMidReb = mc.rebuildCurve(curveBlinkBindMidOld, ch=0, rpo=1, rt=0, end=1, kr=0, kcp=0, kep=1, kt=0, s=8, d=3, tol=0.01) curveBlinkBindMid = mc.rename(curveBlinkBindMidReb, ('eyelidBlink' + side + '_crv')) curveBlinkUp = mc.duplicate(crvUp, n='eyelidBlinkUp' + side + '_crv')[0] curveBlinkDown = mc.duplicate(crvDown, n='eyelidBlinkDown' + side + '_crv')[0] blinkBsn = mc.blendShape(eyelidUp.deformCrv, eyelidDown.deformCrv, curveBlinkBindMid, n=('eyelidBlink' + side + '_bsn'), weight=[(0, 1), (1, 0)])[0] mc.select(cl=1) if sideRGT in crvUp: crvUpNewName = crvUp.replace(sideRGT, '') elif sideLFT in crvUp: crvUpNewName = crvUp.replace(sideLFT, '') else: crvUpNewName = crvUp # wire deform up on mid curves stickyMidwireDefUp = mc.wire(curveBlinkUp, dds=(0, 100 * scale), wire=curveBlinkBindMid) stickyMidwireDefUp[0] = mc.rename( stickyMidwireDefUp[0], (au.prefixName(crvUpNewName) + 'Blink' + side + '_wireNode')) # SET TO DOWN CURVE mc.setAttr(blinkBsn + '.%s' % eyelidUp.deformCrv, 0) mc.setAttr(blinkBsn + '.%s' % eyelidDown.deformCrv, 1) mc.select(cl=1) if sideRGT in crvDown: crvDownNewName = crvDown.replace(sideRGT, '') elif sideLFT in crvDown: crvDownNewName = crvDown.replace(sideLFT, '') else: crvDownNewName = crvDown # wire deform down on mid curves stickyMidwireDefDown = mc.wire(curveBlinkDown, dds=(0, 100 * scale), wire=curveBlinkBindMid) stickyMidwireDefDown[0] = mc.rename( stickyMidwireDefDown[0], (au.prefixName(crvDownNewName) + 'Blink' + side + '_wireNode')) # SET KEYFRAME mc.setDrivenKeyframe(blinkBsn + '.%s' % eyelidUp.deformCrv, cd='%s.%s' % (self.eyeballCtrl.control, self.eyelidPos), dv=0, v=1, itt='linear', ott='linear') mc.setDrivenKeyframe(blinkBsn + '.%s' % eyelidUp.deformCrv, cd='%s.%s' % (self.eyeballCtrl.control, self.eyelidPos), dv=1, v=0, itt='linear', ott='linear') mc.setDrivenKeyframe(blinkBsn + '.%s' % eyelidDown.deformCrv, cd='%s.%s' % (self.eyeballCtrl.control, self.eyelidPos), dv=0, v=0, itt='linear', ott='linear') mc.setDrivenKeyframe(blinkBsn + '.%s' % eyelidDown.deformCrv, cd='%s.%s' % (self.eyeballCtrl.control, self.eyelidPos), dv=1, v=1, itt='linear', ott='linear') # CONNECT TO BLENDSHAPE BIND CURVE eyelidUpBsn = mc.blendShape(curveBlinkUp, crvUp, n=('eyelidBlinkUp' + side + '_bsn'), weight=[(0, 1)])[0] mc.connectAttr( eyelidUp.controllerBind03Ctrl + '.%s' % eyelidUp.closeEyelid, eyelidUpBsn + '.%s' % curveBlinkUp) eyelidDownBsn = mc.blendShape(curveBlinkDown, crvDown, n=('eyelidBlinkDown' + side + '_bsn'), weight=[(0, 1)])[0] mc.connectAttr( eyelidDown.controllerBind03Ctrl + '.%s' % eyelidDown.closeEyelid, eyelidDownBsn + '.%s' % curveBlinkDown) # CREATE GROUP FOR EYELID STUFF eyelidGrp = mc.group(em=1, n='eyelid' + side + '_grp') return eyelidGrp
def flexiPlaneSetup(prefix='flexiPlane', numJoints=5): width = numJoints * 2 # Create Nurbs surface flexiPlane = cmds.nurbsPlane(w=width, lr=0.1, u=width / 2, v=1, ax=[0, 1, 0]) flexiPlane = cmds.rename(flexiPlane[0], '%s_surface01' % prefix) cmds.delete(flexiPlane, constructionHistory=1) # Create plane follicles mel.eval('createHair %s 1 2 0 0 0 0 1 0 1 1 1;' % str(width / 2)) for obj in ['hairSystem1', 'pfxHair1', 'nucleus1']: cmds.delete(obj) folChildren = cmds.listRelatives('hairSystem1Follicles', ad=1) cmds.delete([i for i in folChildren if 'curve' in i]) folGrp = cmds.rename('hairSystem1Follicles', '%s_flcs01' % prefix) alphabetList = map(chr, range(97, 123)) folChildren = cmds.listRelatives(str(folGrp), c=1) for obj, letter in zip(folChildren, alphabetList): folJnt = cmds.joint(p=cmds.xform(obj, t=1, q=1), n='%s_bind_%s01' % (prefix, letter)) cmds.parent(folJnt, obj) cmds.rename(obj, '%s_flc_%s01' % (prefix, letter)) # Add controls squareCons = ['%s_cnt_a01' % prefix, '%s_cnt_b01' % prefix, '%s_midBend01' % prefix] for squareCon in squareCons: squareCon = cmds.curve(n=squareCon, d=1, p=[(-1, 0, -1), (1, 0, -1), (1, 0, 1), (-1, 0, 1), (-1, 0, -1)]) cmds.scale(.75, .75, .75, squareCon, r=1) cmds.setAttr('%s.overrideEnabled' % squareCon, 1) cmds.setAttr('%s.overrideColor' % squareCon, 17) cmds.xform(squareCon, roo='xzy') cmds.xform(squareCons[0], t=(-width / 2, 0, 0), ws=1) cmds.xform(squareCons[1], t=(width / 2, 0, 0), ws=1) cmds.xform(squareCons[2], t=(0, 0, 0), ws=1) cmds.makeIdentity(squareCons, a=1) squareConGrp = cmds.group(squareCons[0], squareCons[1], n='%s_cnts01' % prefix) midConGrp = cmds.group(squareCons[2], n='%s_midCnt01' % prefix) cmds.parent(midConGrp, squareConGrp) cmds.pointConstraint(squareCons[1], squareCons[0], midConGrp, mo=0) # Create a target blendshape controlled by deformers flexiBlend = cmds.duplicate(flexiPlane, n='flexiPlaneSetup_bShp_surface01') flexiBlendNode = cmds.blendShape(flexiBlend, flexiPlane, n='%s_bShpNode_surface01' % prefix) cmds.setAttr('%s.%s' % (flexiBlendNode[0], flexiBlend[0]), 1) wireCurve = cmds.curve(n='%s_wire_surface01' % prefix, d=2, p=[(-width / 2, 0, 0), (0, 0, 0), (width / 2, 0, 0)]) topClstr = cmds.cluster('%s.cv[0:1]' % wireCurve, rel=1, n='%s_cl_a01' % prefix) midClstr = cmds.cluster('%s.cv[1]' % wireCurve, rel=1, n='%s_cl_mid01' % prefix) botClstr = cmds.cluster('%s.cv[1:2]' % wireCurve, rel=1, n='%s_cl_b01' % prefix) clsGrp = cmds.group(topClstr, midClstr, botClstr, n='%s_cls01' % prefix) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (topClstr[1], attr), -width / 2, 0, 0) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (botClstr[1], attr), width / 2, 0, 0) cmds.setAttr('%sShape.originX' % topClstr[1], (-width / 2)) cmds.setAttr('%sShape.originX' % botClstr[1], (width / 2)) cmds.percent(topClstr[0], '%s.cv[1]' % wireCurve, v=0.5) cmds.percent(botClstr[0], '%s.cv[1]' % wireCurve, v=0.5) # Create twist and wire blend shape deformers twistNode = cmds.nonLinear(flexiBlend, type='twist') cmds.wire(flexiBlend, w=wireCurve, dds=[0, 20], foc=0, n='%s_wireAttrs_surface01' % prefix) cmds.xform(twistNode, ro=(0, 0, 90)) twistNode[0] = cmds.rename(twistNode[0], '%s_twistAttrs_surface01' % prefix) twistNode[1] = cmds.rename(twistNode[1], '%s_twist_surface01' % prefix) # Connect controls to cluster deformers cmds.connectAttr('%s.translate' % squareCons[0], '%s.translate' % topClstr[1]) cmds.connectAttr('%s.translate' % squareCons[1], '%s.translate' % botClstr[1]) cmds.connectAttr('%s.translate' % squareCons[2], '%s.translate' % midClstr[1]) # Connect controls to twist deformer cmds.connectAttr('%s.rotateX' % squareCons[0], '%s.endAngle' % twistNode[0]) cmds.connectAttr('%s.rotateX' % squareCons[1], '%s.startAngle' % twistNode[0]) # Organize hiearchy nodes and groups rootGrp = cmds.group(em=1, n='%s01' % prefix) moveGrp = cmds.group(em=1, n='%s_globalMove01' % prefix) extrasGrp = cmds.group(em=1, n='%s_extraNodes01' % prefix) cmds.parent(flexiBlend, folGrp, wireCurve, twistNode[1], clsGrp, '%s_wire_surface01BaseWire' % prefix, extrasGrp) cmds.parent(flexiPlane, squareConGrp, moveGrp) cmds.parent(moveGrp, extrasGrp, rootGrp) # Scale contraint each follicle to global move group for fol in cmds.listRelatives(folGrp, c=1): cmds.scaleConstraint(moveGrp, fol, mo=0)
def rigFromCurve(self,crv,numSpans=8,numJoints=10,numCtrls=5,stripWidth = 1.0,ctrlWidth=2.0,geo=None,uMin=0.0,uMax=1.0): '''make a cable rig from the given curve numSpans = number of spans in Nurbs strip numJoints = number of joints riding on nurbs strip numCtrls = number of controls to make stripWidth = width of nurbs strip (can make it easier to paint weights if wider) ctrlWidth = size of ctrls ''' shapes = cmds.listRelatives(crv,s=1) crvShape = shapes[0] #Make rig top nulls to parent stuff under topNull = cmds.createNode('transform',n=crv + "_Rig") hiddenStuff = cmds.createNode('transform',n=crv + "_NOTOUCH",p=topNull) cmds.setAttr(hiddenStuff + ".inheritsTransform", 0) cmds.setAttr(hiddenStuff + ".visibility", 0) cmds.addAttr(topNull, ln="stretchAmount",dv=1.0,min=0,max=1) cmds.addAttr(topNull, ln='slideAmount',dv=0.0) #make nurbs strip using extrude crossCurve = cmds.curve(d=1,p=[(0,0,-0.5 * stripWidth),(0,0,0.5 * stripWidth)],k=(0,1)) cmds.select([crossCurve,crv],r=1) surf = cmds.extrude(ch=False,po=0,et=2,ucp=1,fpt=1,upn=1,rotation=0,scale=1,rsp=1)[0] cmds.delete(crossCurve) surf = cmds.rename(surf, crv + "_driverSurf") cmds.parent(surf,hiddenStuff) #Rebuild strip to proper number of spans cmds.rebuildSurface(surf,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=0,kc=1,sv=numSpans,su=0,du=1,tol=0.01,fr=0,dir=2) #make live curve on surface down the middle #this is used later for noStretch curvMaker = cmds.createNode('curveFromSurfaceIso', n = surf+"CurveIso") cmds.setAttr(curvMaker + ".isoparmValue", 0.5) cmds.setAttr(curvMaker + ".isoparmDirection", 1) cmds.connectAttr(surf + ".worldSpace[0]", curvMaker + ".inputSurface") offsetCrvShp = cmds.createNode("nurbsCurve", n=crv + "_driverSurfCrvShape") offsetCrv = cmds.listRelatives(p=1)[0] offsetCrv = cmds.rename(offsetCrv,crv + "_driverSurfCrv") cmds.connectAttr(curvMaker + ".outputCurve", offsetCrvShp + ".create") cmds.parent(offsetCrv, hiddenStuff) #Measure curve length and divide by start length. #This turns curve length into a normalized value that is #useful for multiplying by UV values later to control stretch crvInfo = cmds.createNode('curveInfo', n=offsetCrv + "Info") cmds.connectAttr(offsetCrv + ".worldSpace[0]", crvInfo + ".ic") arcLength = cmds.getAttr(crvInfo + ".al") stretchAmountNode = cmds.createNode('multiplyDivide', n=offsetCrv + "Stretch") cmds.setAttr(stretchAmountNode + ".op" , 2) #divide cmds.setAttr(stretchAmountNode + ".input1X", arcLength) cmds.connectAttr( crvInfo + ".al",stretchAmountNode + ".input2X") #Stretch Blender blends start length with current length #and pipes it back into stretchAmoundNode's startLength, to "trick" it into #thinking there is no stretch.. #That way, when user turns on this "noStretch" attr, the startLength will #be made to equal current length, and stretchAmountNode will always be 1. #so the chain will not stretch. stretchBlender = cmds.createNode('blendColors', n =offsetCrv + "StretchBlender") cmds.setAttr(stretchBlender + ".c1r", arcLength) cmds.connectAttr(crvInfo + ".al", stretchBlender + ".c2r") cmds.connectAttr(stretchBlender + ".opr", stretchAmountNode + ".input1X") cmds.connectAttr(topNull + ".stretchAmount",stretchBlender + ".blender") #make skin joints and attach to surface skinJoints = [] skinJointParent = cmds.createNode('transform',n=crv + "_skinJoints",p=topNull) for i in range(numJoints): cmds.select(clear=True) jnt = cmds.joint(p=(0,0,0),n=crv + "_driverJoint%02d"%i) locator = cmds.spaceLocator(n=crv + "driverLoc%02d"%i)[0] cmds.setAttr(locator + ".localScale",stripWidth,stripWidth,stripWidth) cmds.parent(locator,hiddenStuff) percentage = float(i)/(numJoints-1.0) print "percentage:", percentage print i if i > 1 and i < numJoints-2: percentage = uMin + (percentage * (uMax-uMin)) print "\tinterp percent", percentage posNode,aimCnss,moPath,slider = self.attachObjToSurf(locator,surf,offsetCrv,stretchAmountNode,percentage) cmds.connectAttr(topNull + ".slideAmount", slider + ".i2") cmds.parentConstraint(locator,jnt,mo=False) if len(skinJoints): cmds.parent(jnt,skinJoints[-1]) else: cmds.parent(jnt,skinJointParent) skinJoints.append(jnt) cmds.setAttr(jnt + ".radius",stripWidth) #just cosmetic #add controls ctrls = [] stripJoints = [] stripJointParent = cmds.createNode('transform',n=crv + "_stripJoints",p=hiddenStuff) ctrlParent = cmds.createNode('transform',n=crv+"_Ctrls",p=topNull) for i in range(numCtrls): #The first control is larger, and has the stretch attr if i == 0: zero,ctrl = self.makeCubeCtrl(crv + "_Ctrl%02d"%i,size=ctrlWidth*1.8) cmds.addAttr(ctrl,ln="noStretch",dv=0.0,min=0,max=1,k=1,s=1) cmds.addAttr(ctrl,ln='slideAmount',dv=0.0,min=-1.0,max=1.0,k=1,s=1) cmds.connectAttr(ctrl + ".noStretch",topNull + ".stretchAmount") cmds.connectAttr(ctrl + ".slideAmount",topNull + ".slideAmount") else: zero,ctrl = self.makeCubeCtrl(crv + "_Ctrl%02d"%i,size=ctrlWidth) #Make the joint the control. These drive the nurbs strip. cmds.select(clear=True) jnt = cmds.joint(p=(0,0,0),n=ctrl + "StripJnt") cmds.parentConstraint(ctrl,jnt,mo=False) cmds.setAttr(jnt + ".radius", stripWidth * 1.3) #just cosmetic #briefly attach ctrls to strip to align them percentage = float(i)/(numCtrls-1.0) print "ctrl percentage:",percentage if i > 0 and i < numCtrls-1: percentage = uMin + (percentage * (uMax-uMin)) print '\tinterp percentage:', percentage cmds.delete(self.attachObjToSurf(zero,surf,offsetCrv,stretchAmountNode,percentage)) ctrls.append(ctrl) cmds.parent(jnt,stripJointParent) stripJoints.append(jnt) cmds.parent(zero,ctrlParent) #skin strip to controls #Can get some different behavior by chaning the strip's weights #or perhaps using dual quat. mode on the skinCluster skinObjs = stripJoints + [surf] cmds.skinCluster(skinObjs, bindMethod=0, #closest Point sm=0, #standard bind method ih=True, #ignore hierarchy ) #rebuild curve and skin to joints newCurve = cmds.duplicate(crv)[0] newCurve = cmds.rename(newCurve, crv + "_skinned") cmds.parent(newCurve, topNull) cmds.rebuildCurve(newCurve,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=0,s=numJoints-2,d=3,tol=0.01) skinObjs = skinJoints + [newCurve] cmds.skinCluster(skinObjs, bindMethod = 0, sm = 0, ih=True, mi=1 ) if geo: wireDef,wireCrv = cmds.wire(geo,w=newCurve,n=crv + "_wire",dds=(0,10),en=1.0,ce=0,li=0) print wireDef cmds.parent(wireCrv,hiddenStuff) if cmds.objExists(wireCrv+"BaseWire"): cmds.parent(wireCrv+"BaseWire",hiddenStuff)
def sysFromEdgeLoop(edge, surface, name=""): # Extract curve from edge cmds.select(edge) anchor_curve = cmds.polyToCurve(name=name + '_Anchor_Crv', form=2, degree=1, conformToSmoothMeshPreview=0)[0] # Check curve direction and reverse reverse_crv = xDirection_positive(anchor_curve) if reverse_crv is False: cmds.reverseCurve(anchor_curve, ch=0, rpo=1) cmds.delete(anchor_curve, ch=1) # Create locators on each anchor curve CV locator_list = locatorOnCVs(anchor_curve, scale=0.2) # Connect locators to CVs loc_pci_node_list = connectLocatorToCrv(locator_list, anchor_curve) # Duplicate -> Rebuild to low res driver_crv = cmds.duplicate(anchor_curve, name=name + '_Driver_Crv')[0] cmds.rebuildCurve(driver_crv, ch=0, rpo=1, rt=0, end=1, kr=0, kcp=0, kep=1, kt=1, s=6, d=1, tol=0.01) cmds.rebuildCurve(driver_crv, ch=0, rpo=1, rt=0, end=1, kr=0, kcp=1, kep=1, kt=1, s=4, d=3, tol=0.01) cmds.delete(driver_crv, ch=1) # Wire high res to low res curve driver_wire_node = cmds.wire(anchor_curve, w=driver_crv, gw=False, en=1.000000, ce=0.000000, li=0.000000) # Create joints on each low res CV cv_postion = getCVAngle(driver_crv) driver_jnt_list = [] ctrl_dict = {} ctrl_list = [] remoteCtrl_loc_dict = {} remoteCtrl_loc_list = [] for n, position in enumerate(cv_postion): cmds.select(cl=1) driver_jnt = cmds.joint(rad=0.3, n="{}_{:02d}_Ctrl_Jnt".format(name, n)) driver_jnt_list.append(driver_jnt) cmds.xform(driver_jnt, t=position[0], ro=[0, position[1][1], 0]) # Create controls for each joint ctrl_data = tpu.build_ctrl(ctrl_type="cube", name="{}_{:02d}".format(name, n), scale=0.3, spaced=1) ctrl_dict.update({ctrl_data['control']: ctrl_data['group']}) ctrl_list.append(ctrl_data['control']) cmds.xform(ctrl_data['group'], t=position[0], ro=[0, position[1][1], 0]) # Create remote ctrl locator remoteCtrl_loc = cmds.spaceLocator( n="{}_{:02d}_RemoteCtrl_Loc".format(name, n))[0] for i in "X,Y,Z".split(","): cmds.setAttr("{}.localScale{}".format(remoteCtrl_loc, i), 0.3) remoteCtrl_loc_grp = cmds.group(remoteCtrl_loc, n=remoteCtrl_loc + "_Grp") remoteCtrl_loc_dict.update({remoteCtrl_loc: remoteCtrl_loc_grp}) remoteCtrl_loc_list.append(remoteCtrl_loc) cmds.xform(remoteCtrl_loc_grp, t=position[0], ro=[0, position[1][1], 0]) # Connect control/joint transforms cmds.parentConstraint(remoteCtrl_loc, driver_jnt, mo=1) for attr in ".t,.rotate,.s".split(','): cmds.connectAttr(ctrl_data['control'] + attr, remoteCtrl_loc + attr, f=1) # Bind low res curve to joints skinCluster_node = cmds.skinCluster(driver_jnt_list, driver_crv) # Create system on surface surface_sys_data = follicleOnClosestPoint(surface, locator_list, name) follicle_dict = surface_sys_data[0] # Create joints for each follicle follicle_jnt_list = jointsOnSelection(follicle_dict.keys(), constraint=True, rad=0.2) # Group and organize system on Outliner crv_grp = cmds.group(anchor_curve, driver_crv, driver_crv + "BaseWire", n="{}_Crv_Grp".format(name)) # Locator Groups remoteCtrl_loc_grp = cmds.group(remoteCtrl_loc_dict.values(), n="{}_RemoteCtrl_Loc_Grp".format(name)) aim_loc_grp = cmds.group(locator_list, n="{}_Aim_Loc_Grp".format(name)) locator_grp = cmds.group(remoteCtrl_loc_grp, aim_loc_grp, n="{}_Loc_Grp".format(name)) # Joint groups bind_joint_grp = cmds.group(follicle_jnt_list, n="{}_Bind_Jnt_Grp".format(name)) ctrl_joint_grp = cmds.group(driver_jnt_list, n="{}_Ctrl_Jnt_Grp".format(name)) joint_grp = cmds.group(bind_joint_grp, ctrl_joint_grp, n="{}_Jnt_Grp".format(name)) # Controls group ctrl_grp = cmds.group(ctrl_dict.values(), n="{}_Ctrl_Grp".format(name)) # Follicle group follicle_grp = cmds.group(follicle_dict.keys(), n="{}_Flc_Grp".format(name)) main_sys_grp = cmds.group(crv_grp, locator_grp, ctrl_grp, follicle_grp, joint_grp, n="{}_Sys_Grp".format(name)) sys_data = { "main_sys_grp": main_sys_grp, "loc_pci_node_list": loc_pci_node_list, "driver_wire_node": driver_wire_node, "skinCluster_node": skinCluster_node, "surface_closestPoint_node_list": surface_sys_data[1], "surface_setRange_node_list": surface_sys_data[2], "ctrl_list": ctrl_list, "ctrl_dict": ctrl_dict, "remoteCtrl_dict": remoteCtrl_loc_dict, "remoteCtrl_list": remoteCtrl_loc_list } return sys_data
def makeDynamicWire(jnts, geo, name, ctl): ''' ''' # make curve through joints startCrv = rt.makeCrvThroughObjs(jnts, name+'_startCrv', True, 2) # make curve dynamic mc.select(startCrv, r=True) meval('makeCurvesDynamic 2 { "0", "0", "1", "1", "0"};') # get a handle on new (badly named) nodes hairSys = mc.ls(sl=True)[0] foll = mc.listConnections(hairSys+'.outputHair[0]', d=True)[0] dynCrv = mc.listConnections(foll+'.outCurve', d=True)[0] # rename nodes properly hairSys = mc.rename(hairSys, name+'_hairSysShape') foll = mc.rename(foll, name+'_foll') dynCrv = mc.rename(dynCrv, name+'_dynCrv') # rename group and transform nodes as well hairSysTransform = mc.listRelatives(hairSys, p=True)[0] hairSysTransform = mc.rename(hairSysTransform, name+'_hairSys') startGrp = mc.listRelatives(foll, p=True)[0] startGrp = mc.rename(startGrp, name+'_hairSysFollicles') outputGrp = mc.listRelatives(dynCrv, p=True)[0] outputGrp = mc.rename(outputGrp, name+'_hairSysOutputCrvs') # since we now have start curve and end curve, we can make the wire deformer wireDfm, wireCrv = mc.wire(geo, wire=dynCrv, n=name+'_dyn_wireDfm', dds=(0,50)) wireBaseUnwanted = wireCrv+'BaseWire' # replace base mc.connectAttr(startCrv+'.worldSpace[0]', wireDfm+'.baseWire[0]', f=True) mc.delete(wireBaseUnwanted) # group nodes nicely masterGrp = mc.group(hairSysTransform, startGrp, outputGrp, n=name+'_hairSysMaster_grp') rt.connectVisibilityToggle([startGrp, outputGrp], masterGrp, 'curvesVis', False) rt.connectVisibilityToggle(hairSysTransform, masterGrp, 'hairSysVis', False) # attributes on ctl mc.addAttr(ctl, ln='tDynamics', nn='DYNAMICS', at='enum', en='-----', k=True) #mc.setAttr(ctl+'.tDynamics', l=True) mc.addAttr(ctl, ln='enabled', at='bool', dv=True, k=True) mc.addAttr(ctl, ln='weight', at='double', min=0, max=1, dv=1, k=True) mc.connectAttr(ctl+'.weight', wireDfm+'.envelope', f=True) rt.connectSDK(ctl+'.enabled', hairSys+'.simulationMethod', {0:0, 1:3}) # expose follicle attributes to ctl mc.addAttr(ctl, ln='pointLock', at='enum', en='No Attach:Base:Tip:Both Ends', k=True, dv=1) mc.connectAttr(ctl+'.pointLock', foll+'.pointLock', f=True) # expose hairSystem attributes to ctl mc.addAttr(ctl, ln='startCurveAttract', at='double', min=0, max=1, dv=0.05, k=True) mc.addAttr(ctl, ln='mass', at='double', min=0, dv=1, k=True) mc.addAttr(ctl, ln='drag', at='double', min=0, dv=0.05, k=True) mc.addAttr(ctl, ln='damp', at='double', min=0, dv=0, k=True) mc.connectAttr(ctl+'.startCurveAttract', hairSys+'.startCurveAttract', f=True) mc.connectAttr(ctl+'.mass', hairSys+'.mass', f=True) mc.connectAttr(ctl+'.drag', hairSys+'.drag', f=True) mc.connectAttr(ctl+'.damp', hairSys+'.damp', f=True)
def createDriverCrv (self, upLidBaseCrv, upRigGrp, lowLidBaseCrv, lowRigGrp): '''Create a driver curve for each lid curve and connect it to the base curve with a wire deformer. Called by 'buildRig' function. Call functions: 'eyelidsCorners', 'eyeLidsLeftAndRight' (unused), 'eyelidsCrvCVs', 'eyelidsMatchTopology' ''' ## Upper eyelid ## upLidDriverCrvTEMP = cmds.duplicate (upLidBaseCrv) [0] cmds.delete (upLidDriverCrvTEMP, ch = 1) # delete history cmds.rebuildCurve (upLidDriverCrvTEMP, rpo = 1, end = 1, kr = 2, kcp = 0, kep = 1, kt = 0, s = 4, d = 7, tol = 0.01) # list the position of the EPs of the upper lid driver curve upLidEpPosTEMP = [] x = 0 while x < 5 : posEp = cmds.xform ((upLidDriverCrvTEMP + ".ep[%d]" % x), q = 1, ws = 1, t = 1) upLidEpPosTEMP.append (posEp) x += 1 cmds.delete (upLidDriverCrvTEMP) # Create the upLid 'guide' curve for corner placement and query CVs positions and indexes upLidGuideCrv = cmds.curve (d = 3, ep = (upLidEpPosTEMP[0], upLidEpPosTEMP[1], upLidEpPosTEMP[2], upLidEpPosTEMP[3], upLidEpPosTEMP[4])) ## Lower eyelid ## lowLidDriverCrvTEMP = cmds.duplicate (lowLidBaseCrv) [0] cmds.delete (lowLidDriverCrvTEMP, ch = 1) # delete history cmds.rebuildCurve (lowLidDriverCrvTEMP, rpo = 1, end = 1, kr = 2, kcp = 0, kep = 1, kt = 0, s = 4, d = 7, tol = 0.01) # list the position of the EPs of the lower lid driver curve lowLidEpPosTEMP = [] x = 0 while x < 5 : posEp = cmds.xform ((lowLidDriverCrvTEMP + ".ep[%d]" % x), q = 1, ws = 1, t = 1) lowLidEpPosTEMP.append (posEp) x += 1 cmds.delete (lowLidDriverCrvTEMP) # Create the lowLid 'guide' curve for corner placement and query CVs positions and indexes lowLidGuideCrv = cmds.curve (d = 3, ep = (lowLidEpPosTEMP[0], lowLidEpPosTEMP[1], lowLidEpPosTEMP[2], lowLidEpPosTEMP[3], lowLidEpPosTEMP[4])) ## # Find position of eye corners self.cornerAPos, self.cornerBPos = self.eyelidsCorners (upLidEpPosTEMP, upLidGuideCrv, lowLidEpPosTEMP, lowLidGuideCrv) # Define "CornerA" and "CornerB" as "leftCorner" and "rightCorner" # ADD FUNC WHEN OK - self.eyeLidsLeftAndRight (self.cornerAPos, self.cornerBPos) # List CVs positions of upLidGuideCrv and lowLidGuideCrv upLidCVsPos, lowLidCVsPos = self.eyelidsCrvCVs (upLidGuideCrv, lowLidGuideCrv) # List CVs positions in the right order (to match topology) upLidCVsOrdered, lowLidCVsOrdered = self.eyelidsMatchTopology (self.cornerAPos, self.cornerBPos, upLidCVsPos, lowLidCVsPos) ## # Create upper driver curve self.upLidDriverCrv = cmds.curve (d = 3, p = (upLidCVsOrdered[0], upLidCVsOrdered[1], upLidCVsOrdered[2], upLidCVsOrdered[3], upLidCVsOrdered[4], upLidCVsOrdered[5], upLidCVsOrdered[6])) upLidDriverCrvName = upLidBaseCrv.replace ("_BASE_", "_DRIVER_") self.upLidDriverCrv = cmds.rename (self.upLidDriverCrv, upLidDriverCrvName) cmds.parent (self.upLidDriverCrv, upRigGrp) cmds.delete (upLidGuideCrv) # Create lower driver curve lowCrvTEMP = cmds.curve (d = 3, p = (lowLidCVsOrdered[0], lowLidCVsOrdered[1], lowLidCVsOrdered[2], lowLidCVsOrdered[3], lowLidCVsOrdered[4], lowLidCVsOrdered[5], lowLidCVsOrdered[6])) lowLidDriverCrvName = lowLidBaseCrv.replace ("_BASE_", "_DRIVER_") self.lowLidDriverCrv = cmds.rename (lowCrvTEMP, lowLidDriverCrvName) cmds.parent (self.lowLidDriverCrv, lowRigGrp) cmds.delete (lowLidGuideCrv) ## cmds.select (cl = 1) wireNodeUpLidName = upLidBaseCrv.replace ("_BASE_curve", "_controlCurve_wire") wireUpLid = cmds.wire (upLidBaseCrv, n = wireNodeUpLidName, w = self.upLidDriverCrv, gw = 0, en = 1, ce = 0, li = 0) cmds.select (cl = 1) wireNodeLowLidName = lowLidBaseCrv.replace ("_BASE_curve", "_controlCurve_wire") wireUpLid = cmds.wire (lowLidBaseCrv, n = wireNodeLowLidName, w = self.lowLidDriverCrv, gw = 0, en = 1, ce = 0, li = 0)
patchesU=numberOfBones, axis=(0, 1, 0)) sPlaneShape = cmds.listRelatives(sPlane, shapes=True)[0] cmds.delete(cmds.parentConstraint(startLoc, endLoc, sPlane)) cmds.delete(cmds.orientConstraint(startLoc, sPlane)) cmds.delete(sPlane, constructionHistory=True) sCurve = cmds.curve(degree=1, point=[startPoint, endPoint]) sCurve = cmds.rename( sCurve, un + 'stretchCurve' ) # If named at the creation time, the shape node doesn't get renamed cmds.parent(startLoc, endLoc, sPlane[0], sCurve, sGrp) # create wire deformer and dropoffLocator for twisting sWire = cmds.wire(sPlane[0], wire=sCurve, name=un + 'stretchWire') cmds.wire(sWire[1], edit=True, dropoffDistance=[(0, 20), (1, 20)]) cmds.select(sWire[1] + '.u[0]', r=True) cmds.dropoffLocator(1.0, 1.0, sWire[0]) cmds.select(sWire[1] + '.u[1]', r=True) cmds.dropoffLocator(1.0, 1.0, sWire[0]) # skin wire to bone driver, connect rotation of locators to drop off locators twist cmds.connectAttr(startLoc[0] + '.rotateX', sWire[0] + '.wireLocatorTwist[0]') cmds.connectAttr(endLoc[0] + '.rotateX', sWire[0] + '.wireLocatorTwist[1]') cmds.skinCluster(startWJoint, endWJoint, sWire[1],
import maya.cmds as cmds sels = cmds.ls( sl=1 ) source = sels[0] targets = sels[1:] hists = cmds.listHistory( source, pdo=1 ) hists.reverse() for hist in hists: print hist, cmds.nodeType( hist ) if cmds.nodeType( hist ) == 'nonLinear': for target in targets: cmds.nonLinear( hist, e=1, geometry=target ) elif cmds.nodeType( hist ) == 'wire': for target in targets: cmds.wire( hist, e=1, geometry=target ) elif cmds.nodeType( hist ) == 'ffd': for target in targets: cmds.lattice( hist, e=1, geometry=target )
def build(self): ''' This will build the rig. ''' super(Mouth, self).build() lipMainCurve = self.getAttributeByName('lipMainCurve').getValue() lipCurve = self.getAttributeByName('lipCurve').getValue() parentGroup = self.getAttributeByName('systemParent').getValue() geometry = self.getAttributeByName('geometry').getValue() headPinTrs = self.getAttributeByName('headPin').getValue() jawPinTrs = self.getAttributeByName('jawPin').getValue() orientFile = self.getAttributeByName('orientFile').getValue() bindmeshGeometry, follicleList, lipMainControlHieracrchyList, jointList = self.__buildCurveRig(lipMainCurve, "lip_main" , parentGroup) # delete the controls, tparent joint to the node above the control mainBaseCurveJointList = list() for jnt, lipMainControlList in zip(jointList, lipMainControlHieracrchyList): # create the joint that we will use later to deform the base wire. baseCurveJoint = mc.joint(name=jnt.replace("_jnt","_baseCurve_jnt")) mainBaseCurveJointList.append(baseCurveJoint) # hide the base curve joint. Then parent it under the null node mc.setAttr("{}.v".format(baseCurveJoint), 0) mc.parent(baseCurveJoint, lipMainControlList[1]) mc.setAttr("{}.t".format(baseCurveJoint), 0, 0, 0) mc.parent(jnt,lipMainControlList[-2]) mc.delete(lipMainControlList.pop(-1)) # create a bindMesh for mouth corner controls. jointListPos = [mc.xform(joint, q=True, ws=True, t=True) for joint in jointList] jointListPosX = [round(pos[0], 3) for pos in jointListPos] cornerPos = [jointListPos[jointListPosX.index(max(jointListPosX))], jointListPos[jointListPosX.index(min(jointListPosX))]] # create the bindmesh bindmeshGeometry, follicleList = bindmesh.create("{}_corner".format(self.name), cornerPos) # set the visibility of the bindmesh mc.setAttr("{}.v".format(bindmeshGeometry), 0 ) mouthCorner_l_follicle = mc.rename(follicleList[0], follicleList[0].replace('_0_','_l_')) mouthCorner_r_follicle = mc.rename(follicleList[1], follicleList[1].replace('_1_','_r_')) mc.parent([mouthCorner_l_follicle, mouthCorner_r_follicle, bindmeshGeometry], self.name) controlPrefix = "lip_main" # get the position of the controls for lip tweakers upperLeft = list() upperLeftPosXList = list() upperRight = list() upperRightPosXList = list() lowerLeft = list() lowerLeftPosXList = list() lowerRight = list() lowerRightPosXList = list() mouthCornerLeftPosY = round(mc.xform(mouthCorner_l_follicle, q=True, ws=True, t=True)[1], 3) mouthCornerRightPosY = round(mc.xform(mouthCorner_r_follicle, q=True, ws=True, t=True)[1], 3) for controlHieracrchy in lipMainControlHieracrchyList: #position of control controlPosition = mc.xform(controlHieracrchy[0], q=True, ws=True, t=True) posX = round(controlPosition[0], 3) posY = round(controlPosition[1], 3) if posX > .001: if round(abs(posY-mouthCornerLeftPosY),3) <.003: lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_corner_l")) for ctrl in controlHieracrchy] elif posY > mouthCornerLeftPosY: upperLeft.append(controlHieracrchy) upperLeftPosXList.append(posY) elif posY < mouthCornerLeftPosY: lowerLeft.append(controlHieracrchy) lowerLeftPosXList.append(posY) elif posX < -.001: if round(abs(posY-mouthCornerLeftPosY),3) <.003: lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_corner_r")) for ctrl in controlHieracrchy] elif posY > mouthCornerRightPosY: upperRight.append(controlHieracrchy) upperRightPosXList.append(posY) elif posY < mouthCornerRightPosY: lowerRight.append(controlHieracrchy) lowerRightPosXList.append(posY) else: if posY > mouthCornerLeftPosY: lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_center_up")) for ctrl in controlHieracrchy] elif posY < mouthCornerLeftPosY: lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_center_low")) for ctrl in controlHieracrchy] # reorder controls upperLeftPosXListCopy = list(upperLeftPosXList) upperLeftPosXList.sort() # rename the controls for left and right. for i, pos in enumerate(upperLeftPosXListCopy): # rename the center controls. lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(upperLeft[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_up_{}_l".format(upperLeftPosXList.index(pos)))) for ctrl in upperLeft[i]] # reorder controls upperRightPosXListCopy = list(upperRightPosXList) upperRightPosXList.sort() # rename the controls for left and right. for i, pos in enumerate(upperRightPosXListCopy): # rename the center controls. lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(upperRight[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_up_{}_r".format(upperRightPosXList.index(pos)))) for ctrl in upperRight[i]] # reorder controls lowerLeftPosXListCopy = list(lowerLeftPosXList) lowerLeftPosXList.sort() lowerLeftPosXList.reverse() # rename the controls for left and right. for i, pos in enumerate(lowerLeftPosXListCopy): # rename the center controls. lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(lowerLeft[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_low_{}_l".format(lowerLeftPosXList.index(pos)))) for ctrl in lowerLeft[i]] # reorder controls lowerRightPosXListCopy = list(lowerRightPosXList) lowerRightPosXList.sort() lowerRightPosXList.reverse() # rename the controls for left and right. for i, pos in enumerate(lowerRightPosXListCopy): # rename the center controls. lipMainControlHieracrchyList[lipMainControlHieracrchyList.index(lowerRight[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lipMain_low_{}_r".format(lowerRightPosXList.index(pos)))) for ctrl in lowerRight[i]] # create the controls # If there is a hierarchy argument passed in. We will loop through and create the hiearchy. # move the orients nodeDataObj = None if os.path.isfile(orientFile): nodeDataObj = node_data.NodeData() nodeDataObj.read(orientFile) for follicle in (mouthCorner_l_follicle, mouthCorner_r_follicle): parent = follicle controlName = follicle.split("_follicle")[0] # create the control with a large enough hierarchy to create proper SDK's ctrlHierarchy = control.create(name=controlName, controlType="square", hierarchy=['nul','ort', 'auto'], color=common.BLACK, parent=parent) driverMouthCorner = mc.createNode("joint", name="{}_driver".format(controlName)) # mover the driver to the orient and parent it under the orient mc.parent(driverMouthCorner, ctrlHierarchy[1]) #mc.xform(driverMouthCorner, ws=True, matrix=mc.xform(ctrlHierarchy[1], q=True, ws=True, matrix=True)) # turn off the visibility of the driver mc.setAttr("{}.drawStyle".format(driverMouthCorner), 2) # turn on the handle for the mouth corner control and move it mc.setAttr("{}.displayHandle".format(ctrlHierarchy[-1]), 1) mc.setAttr("{}.selectHandleX".format(ctrlHierarchy[-1]) ,0.2) # zero out the mouth corner hierarchy so it's in the correct position. mc.setAttr("{}.translate".format(ctrlHierarchy[0]), 0,0,0) #mc.setAttr("{}.rotate".format(ctrlHierarchy[0]), 0,0,0) mc.delete(mc.listRelatives(ctrlHierarchy[-1], c=True, shapes=True)[0]) # create the drivers for the lip_L/R neutral = mc.createNode("transform", name="{}_neutral".format(controlName)) headPin = mc.createNode("transform", name="{}_headPin".format(controlName)) jawPin = mc.createNode("transform", name="{}_jawPin".format(controlName)) for pinGrp in [neutral, headPin, jawPin]: mc.xform(pinGrp, ws=True, matrix=mc.xform(ctrlHierarchy[1], q=True, ws=True, matrix=True)) mc.parent(pinGrp, ctrlHierarchy[1]) cst = mc.parentConstraint(pinGrp, ctrlHierarchy[2])[0] # constrain the driver to the control mc.pointConstraint(ctrlHierarchy[-1], driverMouthCorner, mo=True) if nodeDataObj: nodeDataObj.applyData([ctrlHierarchy[1]]) # constrain the head and jaw pinning. mc.parentConstraint(jawPinTrs, jawPin, mo=True) mc.parentConstraint(headPinTrs, headPin, mo=True) # create the head and jaw pinning. mc.addAttr(controlName, ln="pinning", nn="----------", at="enum", enumName="Pinning", keyable=True) attribute.lock(controlName, "pinning") mc.addAttr(controlName, ln="pin", at="double", min=-10, max=10, dv=0, keyable=True) mc.setDrivenKeyframe("{}.{}W0".format(cst,neutral), cd="{}.pin".format(controlName), v=1, dv=0) mc.setDrivenKeyframe("{}.{}W1".format(cst,headPin), cd="{}.pin".format(controlName), v=0, dv=0) mc.setDrivenKeyframe("{}.{}W2".format(cst,jawPin), cd="{}.pin".format(controlName), v=0, dv=0) mc.setDrivenKeyframe("{}.{}W0".format(cst,neutral), cd="{}.pin".format(controlName), v=0, dv=-10) mc.setDrivenKeyframe("{}.{}W1".format(cst,headPin), cd="{}.pin".format(controlName), v=0, dv=-10) mc.setDrivenKeyframe("{}.{}W2".format(cst,jawPin), cd="{}.pin".format(controlName), v=1, dv=-10) mc.setDrivenKeyframe("{}.{}W0".format(cst,neutral), cd="{}.pin".format(controlName), v=0, dv=10) mc.setDrivenKeyframe("{}.{}W1".format(cst,headPin), cd="{}.pin".format(controlName), v=1, dv=10) mc.setDrivenKeyframe("{}.{}W2".format(cst,jawPin), cd="{}.pin".format(controlName), v=0, dv=10) # create the set driven keyframes for attr in ['x','y','z']: for lipMainControl in lipMainControlHieracrchyList: if "_l_" in lipMainControl[3] and follicle == mouthCorner_l_follicle: mc.setDrivenKeyframe("{}.t{}".format(lipMainControl[3],attr), cd="{}.t{}".format(driverMouthCorner,attr), v=0, dv=0) mc.setDrivenKeyframe("{}.t{}".format(lipMainControl[3],attr), cd="{}.t{}".format(driverMouthCorner,attr), v=1, dv=1) mc.setDrivenKeyframe("{}.t{}".format(lipMainControl[3],attr), cd="{}.t{}".format(driverMouthCorner,attr), v=-1, dv=-1) if attr == "x": mc.setDrivenKeyframe("{}.ry".format(lipMainControl[2]), cd="{}.t{}".format(driverMouthCorner,attr), v=0, dv=0) mc.setDrivenKeyframe("{}.ry".format(lipMainControl[2]), cd="{}.t{}".format(driverMouthCorner,attr), v=10, dv=1) mc.setDrivenKeyframe("{}.ry".format(lipMainControl[2]), cd="{}.t{}".format(driverMouthCorner,attr), v=-10, dv=-1) elif "_r_" in lipMainControl[3] and follicle == mouthCorner_r_follicle: mc.setDrivenKeyframe("{}.t{}".format(lipMainControl[3],attr), cd="{}.t{}".format(driverMouthCorner,attr), v=0, dv=0) mc.setDrivenKeyframe("{}.t{}".format(lipMainControl[3],attr), cd="{}.t{}".format(driverMouthCorner,attr), v=1, dv=1) mc.setDrivenKeyframe("{}.t{}".format(lipMainControl[3],attr), cd="{}.t{}".format(driverMouthCorner,attr), v=-1, dv=-1) if attr == "x": mc.setDrivenKeyframe("{}.ry".format(lipMainControl[2]), cd="{}.t{}".format(driverMouthCorner,attr), v=0, dv=0) mc.setDrivenKeyframe("{}.ry".format(lipMainControl[2]), cd="{}.t{}".format(driverMouthCorner,attr), v=10, dv=1) mc.setDrivenKeyframe("{}.ry".format(lipMainControl[2]), cd="{}.t{}".format(driverMouthCorner,attr), v=-10, dv=-1) # control prefix for the lips controlPrefix = "lip" bindmeshGeometry, follicleList, controlHieracrchyList, jointList = self.__buildCurveRig(lipCurve, controlPrefix , parentGroup) # get the position of the controls for lip tweakers upperLeft = list() upperLeftPosXList = list() upperRight = list() upperRightPosXList = list() lowerLeft = list() lowerLeftPosXList = list() lowerRight = list() lowerRightPosXList = list() mouthCornerLeftPosY = round(mc.xform(mouthCorner_l_follicle, q=True, ws=True, t=True)[1], 3) mouthCornerRightPosY = round(mc.xform(mouthCorner_r_follicle, q=True, ws=True, t=True)[1], 3) for controlHieracrchy in controlHieracrchyList: # create the joint that we will use later to deform the base wire. baseCurveJoint = mc.joint(name=jointList[controlHieracrchyList.index(controlHieracrchy)].replace("_jnt","_baseCurve_jnt")) # hide the base curve joint. Then parent it under the null node mc.setAttr("{}.v".format(baseCurveJoint), 0) mc.parent(baseCurveJoint, controlHieracrchy[0]) #position of control controlPosition = mc.xform(controlHieracrchy[0], q=True, ws=True, t=True) posX = round(controlPosition[0], 3) posY = round(controlPosition[1], 3) if posX > .001: if round(abs(posY-mouthCornerLeftPosY),3) <.003: controlHieracrchyList[controlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_corner_l")) for ctrl in controlHieracrchy] elif posY > mouthCornerLeftPosY: upperLeft.append(controlHieracrchy) upperLeftPosXList.append(posY) elif posY < mouthCornerLeftPosY: lowerLeft.append(controlHieracrchy) lowerLeftPosXList.append(posY) elif posX < -.001: if round(abs(posY-mouthCornerLeftPosY),3) <.003: controlHieracrchyList[controlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_corner_r")) for ctrl in controlHieracrchy] elif posY > mouthCornerRightPosY: upperRight.append(controlHieracrchy) upperRightPosXList.append(posY) elif posY < mouthCornerRightPosY: lowerRight.append(controlHieracrchy) lowerRightPosXList.append(posY) else: if posY > mouthCornerLeftPosY: controlHieracrchyList[controlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_center_up")) for ctrl in controlHieracrchy] elif posY < mouthCornerLeftPosY: controlHieracrchyList[controlHieracrchyList.index(controlHieracrchy)] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_center_low")) for ctrl in controlHieracrchy] # reorder controls upperLeftPosXListCopy = list(upperLeftPosXList) upperLeftPosXList.sort() # rename the controls for left and right. for i, pos in enumerate(upperLeftPosXListCopy): # rename the center controls. controlHieracrchyList[controlHieracrchyList.index(upperLeft[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_up_{}_l".format(upperLeftPosXList.index(pos)))) for ctrl in upperLeft[i]] # reorder controls upperRightPosXListCopy = list(upperRightPosXList) upperRightPosXList.sort() # rename the controls for left and right. for i, pos in enumerate(upperRightPosXListCopy): # rename the center controls. controlHieracrchyList[controlHieracrchyList.index(upperRight[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_up_{}_r".format(upperRightPosXList.index(pos)))) for ctrl in upperRight[i]] # reorder controls lowerLeftPosXListCopy = list(lowerLeftPosXList) lowerLeftPosXList.sort() lowerLeftPosXList.reverse() # rename the controls for left and right. for i, pos in enumerate(lowerLeftPosXListCopy): # rename the center controls. controlHieracrchyList[controlHieracrchyList.index(lowerLeft[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_low_{}_l".format(lowerLeftPosXList.index(pos)))) for ctrl in lowerLeft[i]] # reorder controls lowerRightPosXListCopy = list(lowerRightPosXList) lowerRightPosXList.sort() lowerRightPosXList.reverse() # rename the controls for left and right. for i, pos in enumerate(lowerRightPosXListCopy): # rename the center controls. controlHieracrchyList[controlHieracrchyList.index(lowerRight[i])] = [mc.rename(ctrl, "_".join([name for name in ctrl.split("_") if not name.isdigit()]).replace(controlPrefix, "lip_low_{}_r".format(lowerRightPosXList.index(pos)))) for ctrl in lowerRight[i]] # parent the curves to their respective systems mc.parent(lipMainCurve, "lip_main") mc.parent(lipCurve, "lip") #deform the lip bindmesh with the lip_main curve using a wire deformer. wireDeformer = mc.wire(bindmeshGeometry, gw=False, en=1.00, ce=0.00, li=0.00, w=lipMainCurve, name="{}_wire".format(lipMainCurve))[0] # set the default values for the wire deformer mc.setAttr("{}.rotation".format(wireDeformer), 0) mc.setAttr("{}.dropoffDistance[0]".format(wireDeformer), 100) # create skinCluster for the base wire baseCurve = "{}BaseWire".format(lipMainCurve) lipMainBaseCurveSkin = mc.skinCluster(*mainBaseCurveJointList+mc.ls(baseCurve), n="{}_skinCluster".format(baseCurve), tsb=True)[0] # set the weights to have proper weighting wtObj = rigrepo.libs.weights.getWeights(lipMainBaseCurveSkin) weightList = list() for i, inf in enumerate(wtObj): array = numpy.zeros_like(wtObj.getWeights(inf))[0] array[i] = 1 weightList.append(array) wtObj.setWeights(weightList) rigrepo.libs.weights.setWeights(lipMainBaseCurveSkin, wtObj) # create all of the lip clusters lipControls = list(set(mc.ls("lip_*.__control__", o=True)).difference(set(mc.ls(["lip_upper","lip_lower"])))) for node in lipControls: rigrepo.libs.cluster.create(geometry, "{}_cluster".format(node), contraintTypes=["orient","scale"], parent="{}_def_auto".format(node), parallel=False) nul = "{}_cluster_nul".format(node) mc.xform(nul, ws=True, matrix=mc.xform(node, q=True, ws=True, matrix=True)) mc.connectAttr("{}.t".format(node), "{}_cluster_auto.t".format(node), f=True) mc.connectAttr("{}.r".format(node), "{}_cluster_ctrl.r".format(node), f=True) mc.connectAttr("{}.s".format(node), "{}_cluster_ctrl.s".format(node), f=True)
def make_stretch_plane(prefix='', start_joint=cmds.ls(selection=True)[0], end_joint=cmds.listRelatives(start_joint)[0], number_of_bones=3, stretch_len=cmds.getAttr(end_joint + '.translateX')): """ :param prefix: str, name of objects :param start_joint: str, start point of stretch plane and parent bone :param end_joint: str, end point of stretch plane (right now its just the child of the start joint) :param number_of_bones: float, how many bones will be placed along the length of the plane :param stretch_len: float, the length of the plane, from start joint to end joint :return: list[], containing all stretch joints for skinning """ # TODO need to get actual distance between points for spine start_point = cmds.xform(start_joint, query=True, worldSpace=True, translation=True) end_point = cmds.xform(end_joint, query=True, worldSpace=True, translation=True) # create start + end locators, bones to skin the wire to, and an empty group start_loc = cmds.spaceLocator(name='start_loc') cmds.parent(start_loc, start_joint, relative=True) end_loc = cmds.spaceLocator(name='end_loc') cmds.parent(end_loc, end_joint, relative=True) start_w_joint = cmds.joint(name='startWireJoint') cmds.parent(start_w_joint, start_loc) end_w_joint = cmds.joint(name='endWireJoint') cmds.parent(end_w_joint, end_loc) s_grp = cmds.group(empty=True, name=prefix + 'stretchPlaneGrp') cmds.delete(cmds.parentConstraint(start_loc, s_grp)) # create NURBS plane and CV curve. Group everything into the new sGrp s_plane = cmds.nurbsPlane(name=prefix + 'stretchPlane', width=stretch_len, lengthRatio=.2, patchesU=number_of_bones, axis=(0, 1, 0)) s_plane_shape = cmds.listRelatives(s_plane, shapes=True)[0] cmds.delete(cmds.parentConstraint(start_loc, end_loc, s_plane)) cmds.delete(cmds.orientConstraint(start_loc, s_plane)) cmds.delete(s_plane, constructionHistory=True) s_curve = cmds.curve(degree=1, point=[start_point, end_point]) s_curve = cmds.rename( s_curve, prefix + 'stretchCurve' ) # If named at the creation time, the shape node doesn't get renamed cmds.parent(start_loc, end_loc, s_plane[0], s_curve, s_grp) # create wire deformer and dropoffLocator for twisting s_wire_deform = cmds.wire(s_plane[0], wire=s_curve, name=prefix + 'stretchWire')[0] cmds.wire(s_curve, edit=True, dropoffDistance=[(0, 20), (1, 20)]) cmds.select(s_curve + '.u[0]', r=True) cmds.dropoffLocator(1.0, 1.0, s_wire_deform) cmds.select(s_curve + '.u[1]', r=True) cmds.dropoffLocator(1.0, 1.0, s_wire_deform) # connect rotation of locators to drop off locators twist, skin wire to bone driver cmds.connectAttr(start_loc[0] + '.rotateX', s_wire_deform + '.wireLocatorTwist[0]') cmds.connectAttr(end_loc[0] + '.rotateZ', s_wire_deform + '.wireLocatorTwist[1]') cmds.skinCluster(start_w_joint, end_w_joint, s_curve, maximumInfluences=1, toSelectedBones=True) # crating follicles on sPlane and joints s_joints_collection = [] fol_grp = cmds.group(empty=True, name=prefix + 'follicleGrp') cmds.parent(fol_grp, s_grp) for x in range(number_of_bones): fol_shape = cmds.createNode("follicle") fol_trans = cmds.listRelatives(fol_shape, parent=True)[0] fol_trans = cmds.rename(fol_trans, prefix + "follicle_{:02d}".format(x + 1)) fol_shape = cmds.listRelatives(fol_trans, shapes=True)[0] fol_shape = cmds.rename(fol_shape, prefix + "follicleShape_{:02d}".format(x + 1)) cmds.connectAttr(s_plane_shape + '.worldMatrix[0]', fol_shape + '.inputWorldMatrix') cmds.connectAttr(s_plane_shape + '.local', fol_shape + '.inputSurface') cmds.connectAttr(fol_shape + '.outTranslate', fol_trans + '.translate') cmds.connectAttr(fol_shape + '.outRotate', fol_trans + '.rotate') v_position = (1.0 / (number_of_bones + 1)) * (x + 1) cmds.setAttr(fol_shape + '.parameterU', v_position) cmds.setAttr(fol_shape + '.parameterV', .5) # here I'm adding a joint, as the follicle is selected the joint is parented under it. # im also adding the joint to a list i can use later s_joints_collection.append( cmds.joint(name=prefix + "stretchJoint_{:02d}".format(x + 1))) cmds.parent(fol_trans, fol_grp) # creating nodes for stretching bones s_curve_shape = cmds.listRelatives(s_curve, shapes=True)[0] s_curve_info = cmds.createNode('curveInfo', name='SCurveInfo') cmds.rename(s_curve_info, 'SCurveInfo') cmds.connectAttr(s_curve_shape + '.worldSpace[0]', s_curve_info + '.inputCurve') joint_scale = cmds.createNode('multiplyDivide', name='sJointScale') cmds.setAttr(joint_scale + '.operation', 2) cmds.setAttr(joint_scale + '.input2X', stretch_len) cmds.connectAttr(s_curve_info + '.arcLength', joint_scale + '.input1X') # connecting up nodes to bones for joint in s_joints_collection: cmds.connectAttr(joint_scale + '.outputX', joint + '.scaleX') # creating a variable for the base wire of the wire deformer s_base_wire = cmds.listConnections(s_wire_deform + ".baseWire", destination=False, source=True)[0] # creating group inorder to help organisation and prevent double transforms s_rig_grp = cmds.group(empty=True, name=prefix + 'stretchPlaneRigGrp') align(start_joint, s_rig_grp) cmds.parent(s_rig_grp, s_grp) cmds.parent(s_plane[0], s_base_wire, start_loc, end_loc, s_rig_grp) cmds.setAttr(start_w_joint + ".visibility", False) cmds.setAttr(end_w_joint + ".visibility", False) # Connecting end locators to driving joints -will have to do this properly in the main script cmds.pointConstraint(end_joint, end_loc) cmds.connectAttr( end_joint + '.rotateZ', end_loc[0] + '.rotateZ') # TODO: add if statment for elbow/wrist rotations cmds.parent(s_rig_grp, start_joint) return s_joints_collection
def addIndividualOffsetRig(toothId, selVerts): """ returns top group node """ name = 'CT_toothOffset%d_' % toothId #=========================================================================== # ADD OFFSET CONTROLS #=========================================================================== # add offset controlA ctlA = rt.ctlCurve(name + 'ctlA', 'circle', 0, snap='CT_teethOffset_align_loc_%d' % toothId, size=1, ctlOffsets=['bend']) mc.aimConstraint('CT_teethOffset_aim_loc_%d' % toothId, ctlA.home, aim=(1, 0, 0), u=(0, 0, 1), wut='objectRotation', wuo='CT_teethOffset_align_loc_%d' % toothId, wu=(0, 0, 1)) mc.pointConstraint('CT_teethOffset_align_loc_%d' % toothId, ctlA.home) # add second offset control as child to first ctlB = rt.ctlCurve(name + 'ctlB', 'circle', 0, snap=ctlA.crv, size=1, ctlOffsets=['bend']) mc.parent(ctlB.home, ctlA.crv) mc.setAttr(ctlB.home + '.tx', 0.5) # local rig's bend should update CtlB mc.connectAttr('CT_teethLocal%d_bndB.ry' % (toothId + 1), ctlB.grp['bend'] + '.ry', f=True) #=============================================================================== # Connections from offsetCtls to localRig #=============================================================================== # since scale should always be local mc.connectAttr(ctlA.crv + '.sy', 'CT_teethLocal%d_bndA.sy' % (toothId + 1), f=True) mc.connectAttr(ctlA.crv + '.sz', 'CT_teethLocal%d_bndA.sz' % (toothId + 1), f=True) mc.connectAttr(ctlB.crv + '.sy', 'CT_teethLocal%d_bndB.sy' % (toothId + 1), f=True) mc.connectAttr(ctlB.crv + '.sz', 'CT_teethLocal%d_bndB.sz' % (toothId + 1), f=True) # twisting could also be local mc.connectAttr(ctlA.crv + '.rx', 'CT_teethLocal%d_bndA.rx' % (toothId + 1), f=True) mc.connectAttr(ctlB.crv + '.rx', 'CT_teethLocal%d_bndB.rx' % (toothId + 1), f=True) # slide tooth along path mc.addAttr(ctlA.crv, ln='slide', at='double', k=True) mc.connectAttr(ctlA.crv + '.slide', 'CT_teethLocal%d_bndA.ty' % (toothId + 1), f=True) #=============================================================================== # Complete CV point placement for curves #=============================================================================== # endLoc under ctlB endLoc = mc.spaceLocator(n=name + 'ctlB_endLoc')[0] rt.parentSnap(endLoc, ctlB.crv) mc.setAttr(endLoc + '.tx', 0.5) mc.setAttr(endLoc + '.localScale', 0.1, 0.1, 0.1) #=============================================================================== # second hierarchy for base curve #=============================================================================== ctlABase = mc.group(em=True, n=name + 'ctlABase_grp') mc.aimConstraint('CT_teethOffset_aim_loc_%d' % toothId, ctlABase, aim=(1, 0, 0), u=(0, 0, 1), wut='objectRotation', wuo='CT_teethOffset_align_loc_%d' % toothId, wu=(0, 0, 1)) mc.pointConstraint('CT_teethOffset_align_loc_%d' % toothId, ctlABase) ctlBBase = mc.group(em=True, n=name + 'ctlBBase_grp') rt.parentSnap(ctlBBase, ctlABase) mc.setAttr(ctlBBase + '.tx', 0.5) mc.connectAttr('CT_teethLocal%d_bndB.ry' % (toothId + 1), ctlBBase + '.ry', f=True) endBaseLoc = mc.spaceLocator(n=name + 'ctlB_endBaseLoc')[0] rt.parentSnap(endBaseLoc, ctlBBase) mc.setAttr(endBaseLoc + '.tx', 0.5) mc.setAttr(endBaseLoc + '.localScale', 0.1, 0.1, 0.1) # connect scale for base transforms mc.connectAttr(ctlA.crv + '.sy', ctlABase + '.sy', f=True) mc.connectAttr(ctlA.crv + '.sz', ctlABase + '.sz', f=True) mc.connectAttr(ctlB.crv + '.sy', ctlBBase + '.sy', f=True) mc.connectAttr(ctlB.crv + '.sz', ctlBBase + '.sz', f=True) #=============================================================================== # Make wire deformer #=============================================================================== # base curve baseCrv = rt.makeCrvThroughObjs([ctlABase, ctlBBase, endBaseLoc], name + 'baseCrv', True, 2) # wire curve wireCrv = rt.makeCrvThroughObjs([ctlA.crv, ctlB.crv, endLoc], name + 'wireCrv', True, 2) # make wire wireDfm, wireCrv = mc.wire(selVerts, wire=wireCrv, n=name + 'wire_dfm', dds=(0, 50)) wireBaseUnwanted = wireCrv + 'BaseWire' # replace base mc.connectAttr(baseCrv + '.worldSpace[0]', wireDfm + '.baseWire[0]', f=True) mc.delete(wireBaseUnwanted) #=========================================================================== # GROUPS & DEBUG UTILS #=========================================================================== dfmGrp = mc.group(baseCrv, wireCrv, n=name + 'dfg_0') ctlGrp = mc.group(ctlA.home, ctlABase, n=name + 'ctg_0') retGrp = mc.group(dfmGrp, ctlGrp, n=name + 'mod_0') rt.connectVisibilityToggle([endLoc, endBaseLoc], retGrp, 'endLocs', False) rt.connectVisibilityToggle(dfmGrp, retGrp, 'wires', False) return retGrp
def addIndividualOffsetRig(toothId, selVerts): """ returns top group node """ name = 'CT_toothOffset%d_'%toothId #=========================================================================== # ADD OFFSET CONTROLS #=========================================================================== # add offset controlA ctlA = rt.ctlCurve(name+'ctlA', 'circle', 0, snap='CT_teethOffset_align_loc_%d'%toothId, size=1, ctlOffsets=['bend']) mc.aimConstraint('CT_teethOffset_aim_loc_%d'%toothId, ctlA.home, aim=(1,0,0), u=(0,0,1), wut='objectRotation', wuo='CT_teethOffset_align_loc_%d'%toothId, wu=(0,0,1)) mc.pointConstraint('CT_teethOffset_align_loc_%d'%toothId, ctlA.home) # add second offset control as child to first ctlB = rt.ctlCurve(name+'ctlB', 'circle', 0, snap=ctlA.crv, size=1, ctlOffsets=['bend']) mc.parent(ctlB.home, ctlA.crv) mc.setAttr(ctlB.home+'.tx', 0.5) # local rig's bend should update CtlB mc.connectAttr('CT_teethLocal%d_bndB.ry'%(toothId+1), ctlB.grp['bend']+'.ry', f=True) #=============================================================================== # Connections from offsetCtls to localRig #=============================================================================== # since scale should always be local mc.connectAttr(ctlA.crv+'.sy', 'CT_teethLocal%d_bndA.sy'%(toothId+1), f=True) mc.connectAttr(ctlA.crv+'.sz', 'CT_teethLocal%d_bndA.sz'%(toothId+1), f=True) mc.connectAttr(ctlB.crv+'.sy', 'CT_teethLocal%d_bndB.sy'%(toothId+1), f=True) mc.connectAttr(ctlB.crv+'.sz', 'CT_teethLocal%d_bndB.sz'%(toothId+1), f=True) # twisting could also be local mc.connectAttr(ctlA.crv+'.rx', 'CT_teethLocal%d_bndA.rx'%(toothId+1), f=True) mc.connectAttr(ctlB.crv+'.rx', 'CT_teethLocal%d_bndB.rx'%(toothId+1), f=True) # slide tooth along path mc.addAttr(ctlA.crv, ln='slide', at='double', k=True) mc.connectAttr(ctlA.crv+'.slide', 'CT_teethLocal%d_bndA.ty'%(toothId+1), f=True) #=============================================================================== # Complete CV point placement for curves #=============================================================================== # endLoc under ctlB endLoc = mc.spaceLocator(n=name+'ctlB_endLoc')[0] rt.parentSnap(endLoc, ctlB.crv) mc.setAttr(endLoc+'.tx', 0.5) mc.setAttr(endLoc+'.localScale', 0.1,0.1,0.1) #=============================================================================== # second hierarchy for base curve #=============================================================================== ctlABase = mc.group(em=True, n=name+'ctlABase_grp') mc.aimConstraint('CT_teethOffset_aim_loc_%d'%toothId, ctlABase, aim=(1,0,0), u=(0,0,1), wut='objectRotation', wuo='CT_teethOffset_align_loc_%d'%toothId, wu=(0,0,1)) mc.pointConstraint('CT_teethOffset_align_loc_%d'%toothId, ctlABase) ctlBBase = mc.group(em=True, n=name+'ctlBBase_grp') rt.parentSnap(ctlBBase, ctlABase) mc.setAttr(ctlBBase+'.tx', 0.5) mc.connectAttr('CT_teethLocal%d_bndB.ry'%(toothId+1), ctlBBase+'.ry', f=True) endBaseLoc = mc.spaceLocator(n=name+'ctlB_endBaseLoc')[0] rt.parentSnap(endBaseLoc, ctlBBase) mc.setAttr(endBaseLoc+'.tx', 0.5) mc.setAttr(endBaseLoc+'.localScale', 0.1,0.1,0.1) # connect scale for base transforms mc.connectAttr(ctlA.crv+'.sy', ctlABase+'.sy', f=True) mc.connectAttr(ctlA.crv+'.sz', ctlABase+'.sz', f=True) mc.connectAttr(ctlB.crv+'.sy', ctlBBase+'.sy', f=True) mc.connectAttr(ctlB.crv+'.sz', ctlBBase+'.sz', f=True) #=============================================================================== # Make wire deformer #=============================================================================== # base curve baseCrv = rt.makeCrvThroughObjs([ctlABase, ctlBBase, endBaseLoc], name+'baseCrv', True, 2) # wire curve wireCrv = rt.makeCrvThroughObjs([ctlA.crv, ctlB.crv, endLoc], name+'wireCrv', True, 2) # make wire wireDfm, wireCrv = mc.wire(selVerts, wire=wireCrv, n=name+'wire_dfm', dds=(0,50)) wireBaseUnwanted = wireCrv+'BaseWire' # replace base mc.connectAttr(baseCrv+'.worldSpace[0]', wireDfm+'.baseWire[0]', f=True) mc.delete(wireBaseUnwanted) #=========================================================================== # GROUPS & DEBUG UTILS #=========================================================================== dfmGrp = mc.group(baseCrv, wireCrv, n=name+'dfg_0') ctlGrp = mc.group(ctlA.home, ctlABase, n=name+'ctg_0') retGrp= mc.group(dfmGrp, ctlGrp, n=name+'mod_0') rt.connectVisibilityToggle([endLoc, endBaseLoc], retGrp, 'endLocs', False) rt.connectVisibilityToggle(dfmGrp, retGrp, 'wires', False) return retGrp
def build( pelvis_jnt, spine_jnts, prefix='spine', rig_scale=1.0, base_rig=None ): """ @param spine_jnts: list(str), list of 6 spine jnts @param root_jnt: str, root_jnt @param prefix: str, prefix to name new object @param rig_scale: float, scale factor for size of controls @param base_rig: instance of base.module.Base class @return: dictionary with rig module objects """ #make rig module rig_module = module.Module(prefix=prefix, base_obj=base_rig, create_dnt_grp=True) #make spine controls body_ctrl = control.Control(shape='body_ctrl_template', prefix='body', translate_to=pelvis_jnt, scale=rig_scale, parent=rig_module.ctrl_grp, lock_channels=['s', 'v']) hip_ctrl = control.Control(shape='hip_ctrl_template', prefix='hip', translate_to=pelvis_jnt, scale=rig_scale, parent=body_ctrl.ctrl, lock_channels=['s', 'v']) ctrl_shape = cmds.listRelatives(hip_ctrl.ctrl, shapes=True)[0] cmds.setAttr(ctrl_shape + '.ove', 1) cmds.setAttr(ctrl_shape + '.ovc', 18) chest_ctrl = control.Control(shape='chest_ctrl_template', prefix='chest', translate_to=spine_jnts[len(spine_jnts)-1], scale=rig_scale, parent=body_ctrl.ctrl, lock_channels=['s', 'v']) spine_ctrl = control.Control(shape='spine_ctrl_template', prefix=prefix, translate_to=[hip_ctrl.ctrl, chest_ctrl.ctrl], scale=rig_scale, parent=body_ctrl.ctrl, lock_channels=['s', 'r', 'v']) ctrl_shape = cmds.listRelatives(spine_ctrl.ctrl, shapes=True)[0] cmds.setAttr(ctrl_shape + '.ove', 1) cmds.setAttr(ctrl_shape + '.ovc', 18) #SET UP RIBBON #create ribbon surface and add follicles ribbon.create_cv_curve('temp_spine_ribbon_crv_01', spine_jnts) ribbon_sfc = ribbon.loft_using_curve('temp_spine_ribbon_crv_01', 8, 'x', prefix) cmds.rebuildSurface(ribbon_sfc, su=0, sv=3, du=1, dv=3, ch=True) spine_follicles = ribbon.add_follicles(ribbon_sfc, 4, on_edges=True) spine_ik_jnts = joint.duplicate(spine_jnts, prefix='ik') spine_follicles_grp = '_'.join([prefix,'follicles','grp']) cmds.group(spine_follicles, n=spine_follicles_grp) for i in range(len(spine_ik_jnts)): cmds.parent(spine_ik_jnts[i], spine_follicles[i]) #create ribbon_wire_curve to drive the surface using wire deformer ribbon_wire_curve = 'ribbon_wire_crv' create_ep_curve(curve=ribbon_wire_curve, pos_ref_list=[spine_jnts[0], spine_jnts[len(spine_jnts)-1]], degree=2) #create and add clusters ribbon_clstr_list = [] for i in range(ribbon.get_curve_num_cvs(ribbon_wire_curve)): cmds.select(ribbon_wire_curve+'.cv[%d]' % i) temp_clstr_name = 'ribbon_clstr_'+str(i).zfill(2)+'_' ribbon_clstr_list.append(cmds.cluster(name=temp_clstr_name)[1]) cmds.setAttr(temp_clstr_name+'Handle.visibility', 0) ribbon_clstrs_grp = cmds.group(ribbon_clstr_list, n='ribbon_clstrs_grp') #create wire deformer cmds.wire(ribbon_sfc, w=ribbon_wire_curve, dds=(0,50)) ribbon_wire_grp = cmds.group([ribbon_wire_curve, ribbon_wire_curve+'BaseWire'], n='ribbon_wire_grp') #fix orientations for spine_ik_jnts for i in range(1,len(spine_ik_jnts))[::-1]: temp_jnt_driver = '_'.join(['ik', prefix, str(i+1).zfill(2)]) temp_jnt_driven = '_'.join(['ik', prefix, str(i).zfill(2)]) cmds.aimConstraint(temp_jnt_driver, temp_jnt_driven, aim=(1.0,0.0,0.0), wut='objectrotation', wuo=temp_jnt_driver) #setup ribbon twist ribbon_twist_sfc = 'spine_ribbon_twist_surface' cmds.duplicate(ribbon_sfc, n=ribbon_twist_sfc) twist_handle = ribbon.create_twist_deformer(sfc=ribbon_twist_sfc, prefix=prefix) twist_angle_plus_minus_node = connect_body_ctrl_to_ribbon(body_ctrl, twist_handle) connect_twist_ribbon(prefix, hip_ctrl, twist_angle_plus_minus_node, 'start') connect_twist_ribbon(prefix, chest_ctrl, twist_angle_plus_minus_node, 'end') twist_mult_node = 'spine_twist_master_mult_node' cmds.createNode('multiplyDivide', n=twist_mult_node) cmds.connectAttr(base_rig.master_ctrl.ctrl+'.rotateY', twist_mult_node+'.input1X') cmds.setAttr(twist_mult_node+'.input2X', -1) cmds.connectAttr(twist_mult_node+'.outputX', 'start'+twist_angle_plus_minus_node+'.input1D[2]') cmds.connectAttr(twist_mult_node+'.outputX', 'end'+twist_angle_plus_minus_node+'.input1D[2]') ribbon_bs = prefix+'_ribbon_blendshape' cmds.blendShape(ribbon_twist_sfc, ribbon_sfc, n=ribbon_bs) cmds.setAttr(ribbon_bs+'.'+ribbon_twist_sfc, 1) cmds.select(hip_ctrl.ctrl, chest_ctrl.ctrl) cmds.xform(rotateOrder='yzx') cmds.select(ribbon_sfc) cmds.reorderDeformers('wire1', ribbon_bs) #set up skel constraints cmds.select(d=True) for i in range(len(spine_jnts)-1): driver = spine_ik_jnts[i] driven = spine_jnts[i] cmds.pointConstraint(driver, driven, maintainOffset=False) cmds.orientConstraint(driver, driven, maintainOffset=False) ik_spine_04_orient_jnt = spine_ik_jnts[3]+'_orient' cmds.duplicate(spine_ik_jnts[3], n=ik_spine_04_orient_jnt) cmds.parent(ik_spine_04_orient_jnt, chest_ctrl.ctrl) cmds.makeIdentity(ik_spine_04_orient_jnt, t=0, r=1, s=0, apply=True) cmds.pointConstraint(ik_spine_04_orient_jnt, spine_jnts[3], maintainOffset=False) cmds.orientConstraint(ik_spine_04_orient_jnt, spine_jnts[3], maintainOffset=False) pelvis_orient_jnt = 'pelvis_orient' cmds.duplicate('pelvis', n=pelvis_orient_jnt, rc=True) cmds.delete(cmds.listRelatives(pelvis_orient_jnt)) cmds.parent(pelvis_orient_jnt, hip_ctrl.ctrl) cmds.makeIdentity(pelvis_orient_jnt, t=0, r=1, s=0, apply=True) cmds.pointConstraint(pelvis_orient_jnt, 'pelvis', maintainOffset=False) cmds.orientConstraint(pelvis_orient_jnt, 'pelvis', maintainOffset=False) #AUTO MOVEMENT FOR spine_ctrl spine_ctrl_drv = 'spine_ctrl_drv' cmds.select(d=True) cmds.group(n=spine_ctrl_drv, em=True) cmds.delete(cmds.parentConstraint(spine_ctrl.ofst, spine_ctrl_drv)) cmds.parent(spine_ctrl_drv, spine_ctrl.ofst) cmds.parent(spine_ctrl.ctrl, spine_ctrl_drv) #create joint for spine_ctrl create_spine_ctrl_auto_jnts(hip_ctrl, 'bottom', spine_ctrl, spine_ctrl_drv) create_spine_ctrl_auto_jnts(chest_ctrl, 'top', spine_ctrl, spine_ctrl_drv) #spine_ctrl auto switch cmds.addAttr(chest_ctrl.ctrl, shortName='midInfluence', keyable=True, defaultValue=0.0, minValue=0.0, maxValue=1.0) create_spine_ctrl_auto_switch(chest_ctrl, spine_ctrl_drv) #set up ctrl constraints cmds.parentConstraint(hip_ctrl.ctrl, ribbon_clstr_list[0], mo=True) cmds.parentConstraint(spine_ctrl.ctrl, ribbon_clstr_list[1], mo=True) cmds.parentConstraint(chest_ctrl.ctrl, ribbon_clstr_list[2], mo=True) #cleanup spine_sfc_grp = 'spine_sfc_grp' spine_deformers_grp = 'spine_deformers_grp' cmds.group([ribbon_sfc, ribbon_twist_sfc], name=spine_sfc_grp) cmds.group(twist_handle, name=spine_deformers_grp) cmds.parent([spine_follicles_grp, ribbon_wire_grp, ribbon_clstrs_grp, spine_sfc_grp, spine_deformers_grp], rig_module.dnt_grp) return [chest_ctrl, spine_ctrl, hip_ctrl, body_ctrl]
def wire(self, character=None, mod=None, side=None, name=None, suffix=None, wire=None, geometry=None, position=[0, 0, 0], rotation=[0, 0, 0], envelope=1, crossingEffect=0, tension=1, localInfluence=0, wireRotation=1, dropoffDistance=1, wireScale=1, parent=None, show=True, lockAttr=None, ihi=True): #--- this method creates a wire deformer node = [] if wire: if geometry: #--- create a wire deformer node = cmds.wire(geometry, wire=wire, groupWithBase=False) base = cmds.ls(node[-1] + 'BaseWire') #--- filter the individual name filter_name = (name + node[0][0].upper() + node[0][1:]) #--- rename the wire deformer node = self.__rename_node(mod=mod, side=side, name=filter_name, suffix=suffix, obj=node) #--- rename the baseWire curve base = self.__rename_node(mod=mod, side=side, name=filter_name + 'BaseWire', suffix=suffix, obj=base) #--- create a group on top and parent the deformer under the group node_grp = cmds.createNode('transform', parent=node[0]) cmds.parent(node_grp, world=True) cmds.parent(node[0], base[0], node_grp) #--- rename the node group node_grp = self.__rename_node(mod=mod, side=side, name=filter_name, suffix='GRP', obj=node_grp)[0] #--- reposition the transform of the deformer locally cmds.xform(node[0], translation=position, worldSpace=False) cmds.xform(node[0], rotation=rotation, worldSpace=False) #--- take care of the node's settings #--- envelope cmds.setAttr(node[-1] + '.envelope', envelope) #--- crossingEffect cmds.setAttr(node[-1] + '.crossingEffect', crossingEffect) #--- tension cmds.setAttr(node[-1] + '.tension', tension) #--- localInfluence cmds.setAttr(node[-1] + '.localInfluence', localInfluence) #--- wireRotation cmds.setAttr(node[-1] + '.rotation', wireRotation) #--- dropoffDistance cmds.setAttr(node[-1] + '.dropoffDistance[0]', dropoffDistance) #--- wireScale cmds.setAttr(node[-1] + '.scale[0]', wireScale) #--- parent the group under the specified parent if parent: if not isinstance(parent, list): cmds.parent(node_grp, parent) else: raise Exception("Specified parent: " + parent + 'is not a valid') #--- show or hide transform if not show: cmds.setAttr(node[0] + '.v', 0) #--- lock specified attributes if lockAttr: if node[-1]: cmds.setAttr(node[-1] + '.' + lockAttr, lock=True) #--- set isHistoricalInteresting attribute if not ihi: for n in node: cmds.setAttr(n + '.ihi', 0) #--- add the base wire to the node list node.append(base[0]) #--- return node return node
def buildDeformers(self, ribbonPlane, controls=(), folGrp=()): # Create a target blendshape controlled by deformers flexiBlend = cmds.duplicate(ribbonPlane, n='flexiPlaneSetup_bShp_surface01') flexiBlendNode = cmds.blendShape(flexiBlend, ribbonPlane, n='%s_bShpNode_surface01' % self.name) # Turn blendshape on cmds.setAttr('%s.%s' % (flexiBlendNode[0], flexiBlend[0]), 1) # Create a wire deformer controled by ribbon controls wireCurve = cmds.curve(n='%s_wire_surface01' % self.name, d=2, p=[(-self.numJnts, 0, 0), (0, 0, 0), (self.numJnts, 0, 0)]) topClstr = cmds.cluster('%s.cv[0:1]' % wireCurve, rel=1, n='%s_cl_a01' % self.name) midClstr = cmds.cluster('%s.cv[1]' % wireCurve, rel=1, n='%s_cl_mid01' % self.name) botClstr = cmds.cluster('%s.cv[1:2]' % wireCurve, rel=1, n='%s_cl_b01' % self.name) clsGrp = cmds.group(topClstr, midClstr, botClstr, n='%s_cls01' % self.name) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (topClstr[1], attr), -self.numJnts, 0, 0) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (botClstr[1], attr), self.numJnts, 0, 0) cmds.setAttr('%sShape.originX' % topClstr[1], (-self.numJnts)) cmds.setAttr('%sShape.originX' % botClstr[1], (self.numJnts)) cmds.percent(topClstr[0], '%s.cv[1]' % wireCurve, v=0.5) cmds.percent(botClstr[0], '%s.cv[1]' % wireCurve, v=0.5) # Create twist and wire blend shape deformers twistNode = cmds.nonLinear(flexiBlend, type='twist') cmds.wire(flexiBlend, w=wireCurve, dds=[0, 20], foc=0, n='%s_wireAttrs_surface01' % self.name) cmds.xform(twistNode, ro=(0, 0, 90)) twistNode[0] = cmds.rename(twistNode[0], '%s_twistAttrs_surface01' % self.name) twistNode[1] = cmds.rename(twistNode[1], '%s_twist_surface01' % self.name) # Setup squash and stretch via utilitiy nodes arcLen = cmds.arclen(wireCurve, ch=1) arcLen = cmds.rename(arcLen, '%s_curveInfo01' % self.name) arcLenValue = cmds.getAttr('%s.arcLength' % arcLen) squashDivNode = cmds.createNode('multiplyDivide', n='%s_div_squashStretch_length01' % self.name) volDivNode = cmds.createNode('multiplyDivide', n='%s_div_volume01' % self.name) squashCondNode = cmds.createNode('condition', n='%s_cond_volume01' % self.name) cmds.setAttr('%s.operation' % squashDivNode, 2) cmds.setAttr('%s.input2X' % squashDivNode, arcLenValue) cmds.setAttr('%s.operation' % volDivNode, 2) cmds.setAttr('%s.input1X' % volDivNode, 1) cmds.setAttr('%s.secondTerm' % squashCondNode, 1) cmds.connectAttr('%s.arcLength' % arcLen, '%s.input1X' % squashDivNode) cmds.connectAttr('%s.outputX' % squashDivNode, '%s.input2X' % volDivNode) cmds.connectAttr('%s.outputX' % volDivNode, '%s.colorIfTrueR' % squashCondNode) # Set visibility options for obj in [flexiBlend[0], wireCurve, twistNode[1], clsGrp]: cmds.setAttr('%s.visibility' % obj, 0) # Connect controls to cluster deformers if they exist if len(controls) > 1: topCon = controls[0][0] botCon = controls[0][1] midCon = controls[0][2] for con, clstr in zip([topCon, botCon], [topClstr[1], botClstr[1]]): cmds.connectAttr('%s.translate' % con, '%s.translate' % clstr) cmds.connectAttr('%s.translate' % midCon, '%s.translate' % midClstr[1]) # Connect controls to twist deformer cmds.connectAttr('%s.rotateX' % topCon, '%s.endAngle' % twistNode[0]) cmds.connectAttr('%s.rotateX' % botCon, '%s.startAngle' % twistNode[0]) cmds.connectAttr('%s.volEnable' % controls[1], '%s.firstTerm' % squashCondNode) # Scale contraint each follicle to global move group for fol in cmds.listRelatives(folGrp, c=1): cmds.scaleConstraint(self.moveGrp, fol, mo=0) for shape in cmds.listRelatives(fol, s=1): cmds.setAttr('%s.visibility' % shape, 0) # Parent nodes cmds.parent(flexiBlend, wireCurve, clsGrp, twistNode[1], '%s_wire_surface01BaseWire' % self.name, self.extrasGrp)
cmds.setAttr(ndCurInfo + '.parameter', float(i) / (len(vtxs) - 1)) cmds.connectAttr(ndCurInfo + '.position', loc + '.translate') cmds.select(loc, jntCenter) cnsAim = cmds.aimConstraint(offset=(0, 0, 0), w=1, aimVector=(1, 0, 0), upVector=(0, 1, 0), worldUpType='objectrotation', worldUpVector=(0, 1, 0), worldUpObject=upperLoc) print('Base curve finisshed') print ('creating control curve...') baseName(curva) ctlCurve = cmds.duplicate(curva, n= baseName(curva)+'_ctlCurve', rr=1)[0] cmds.rebuildCurve(ctlCurve, ch=0, rpo=1, rt=0, end=1, kr=0, kcp=0, kep=1, kt=0, s=2, d=3, n= ctlCurve) cmds.delete(ctlCurve, ch=1) print 'adjust '+ctlCurve+' manually...' cmds.wire(curva,w = ctlCurve) #CREATE CLUSTERS to control de ctlCurve. cmds.select (ctlCurve + '.cv[*]') vtxs_ctl = cmds.ls(sl =1, fl =1) print len(vtxs_ctl) listaJointsCtrCurve = None listaJointsCtrCurve = [] for i in range(len(vtxs_ctl)): cmds.select(cl=1) #cmds.select(ctlCurve+'.cv[{0}]'.format(i)) posCv = cmds.xform(vtxs_ctl[i], q =1, ws =1, t =1) jointt =cmds.joint( n= baseName(curva)+'_'+str(i)+'_jntCtlCurve',p=(posCv)) print jointt listaJointsCtrCurve.append(jointt)
def ribbonBuild(): # check for matrixNodes.mll plug (comes with Maya, but might be off) if cmds.pluginInfo('matrixNodes.mll', q=True) == False: cmds.loadPlugin('matixNodes.mll') max = 3 rstats = ["castsShadows", "receiveShadows", "motionBlur", "primaryVisibility", "smoothShading", "smoothShading", "visibleInReflections", "visibleInRefractions"] locGrp = cmds.group( em=True, n="ribbon_grp_#" ) # set primary vector (down the chain, i.e: x, y or z) and other default values jointDown = 'x' divisions = 3 planeW = divisions * 2 posIncr = 0 increment = 0.5 v = 0.5 # create the ribbon nurb surface nameFP = cmds.nurbsPlane( ch=False, u=divisions, v=1, ax=[0,1,0], p=[0,0,0], lr=0.2, w=planeW, n="ribbonPlane1" )[0] # diag print print( increment ) print( posIncr ) for i in xrange(0, divisions): posNode = cmds.pointOnSurface( nameFP, ch=True, top=1, u=posIncr, v=0.5 ) posLoc = cmds.group(em=True, n='posNode_'+ str(i)) cmds.connectAttr( '{0}.position'.format(posNode), '{0}.translate'.format(posLoc) ) posIncr += 0.5 posX = cmds.getAttr( '{0}.positionX'.format(posNode) ) posY = cmds.getAttr( '{0}.positionY'.format(posNode) ) posZ = cmds.getAttr( '{0}.positionZ'.format(posNode) ) newJoint = cmds.joint(p=[posX, posY, posZ], n='ribbon_jnt_bn') # set-up parent rotations for joints to follow surface correctly # this follows a process similar to Michael Bazhutkin's river script aimCon = cmds.createNode('aimConstraint') cmds.connectAttr( '{0}.normal'.format(posNode), '{0}.target[0].targetTranslate'.format(aimCon), f=True ) cmds.connectAttr( '{0}.tangentV'.format(posNode), '{0}.worldUpVector'.format(aimCon), f=True ) cmds.connectAttr( '{0}.constraintRotate'.format(aimCon), '{0}.rotate'.format(posLoc), f=True ) cmds.parent(aimCon, posLoc) cmds.parent(posLoc, locGrp) # switch statement look-alike for py.. for case in switch(jointDown): if case('x'): cmds.setAttr( '{0}.aimVector'.format(aimCon), type='double3', *list( (0,1,0) ) ) cmds.setAttr( '{0}.upVector'.format(aimCon), type='double3', *list( (0,0,1) ) ) break if case('y'): cmds.setAttr( '{0}.aimVector'.format(aimCon), type='double3', *list( (0,1,0) ) ) cmds.setAttr( '{0}.upVector'.format(aimCon), type='double3', *list( (0,0,1) ) ) break if case('z'): cmds.setAttr( '{0}.aimVector'.format(aimCon), type='double3', *list( (0,1,0) ) ) cmds.setAttr( '{0}.upVector'.format(aimCon), type='double3', *list( (0,0,1) ) ) break if case(): #default print("Couldn't found a valid joint down value (x, y, z") #print 'lol' topCtrl = cmds.circle( n='ribbon1_top_ctrl', ch=False )[0] botCtrl = cmds.circle( n='ribbon1_bottom_ctrl', ch=False )[0] midCtrl = cmds.circle( n='ribbon1_mid_ctrl', ch=False )[0] # set to origin (creation points were recorded away from origin, otherwise this would be unnecessary) setToOrigin(topCtrl) setToOrigin(botCtrl) # two more curves that will serve as the god ctrl leftMainCurve = cmds.circle( n='pHolder_1', ch=False, r=0.3)[0] rightMainCurve = cmds.circle( n='pHolder_2',ch=False, r=0.3)[0] setToOrigin(leftMainCurve) setToOrigin(rightMainCurve) # groupFreeze stuff topOffset = grpFreeze(topCtrl) botOffset = grpFreeze(botCtrl) midOffset = grpFreeze(midCtrl) # position things topCtrlPOS = cmds.pointOnSurface(nameFP, ch=False, p=True, u=1, v=0.5) midCtrlPOS = cmds.pointOnSurface(nameFP, ch=False, p=True, u=0.5, v=0.5) botCtrlPOS = cmds.pointOnSurface(nameFP, ch=False, p=True, u=0, v=0.5) cmds.setAttr('{0}.translate'.format(topOffset), *topCtrlPOS ) cmds.setAttr('{0}.translate'.format(midOffset), *midCtrlPOS ) cmds.setAttr('{0}.translate'.format(botOffset), *botCtrlPOS ) midCtrlPOS[2] -= 1.5 cmds.setAttr('{0}.translate'.format(rightMainCurve), *midCtrlPOS ) midCtrlPOS[2] += 3.0 cmds.setAttr('{0}.translate'.format(leftMainCurve), *midCtrlPOS ) midCtrlPOS[2] -= 1.5 # create god ctrl for ribbon mainCtrl = cmds.group(em=True, n='ribbon_main_ctrl') parentShape(rightMainCurve, mainCtrl) parentShape(leftMainCurve, mainCtrl) mainCtrlOffset = grpFreeze(mainCtrl) # point constraint god ctrl freeze grp between top and bot midCtrlPC = cmds.pointConstraint( topCtrl, botCtrl, midOffset, mo=False, w=1) # create bShape for surface bShape = cmds.duplicate(nameFP, n='ribbon_bShape_1')[0] cmds.xform(bShape, ws=True, t=[0,0,5]) bShapeNode = cmds.blendShape(bShape, nameFP, en=1, n='ribbon_blendNode_1') cmds.setAttr('{0}.{1}'.format(bShapeNode[0],bShape), 1) # get POSI position of 0%, 50% and 100% of surface to get wire curve positions cInitPOS = cmds.pointOnSurface(bShape, p=True, top=1, u=0.0, v=0.5) cMidPOS = cmds.pointOnSurface(bShape, p=True, top=1, u=0.5, v=0.5) cEndPOS = cmds.pointOnSurface(bShape, p=True, top=1, u=1, v=0.5) # wire, clusters rWireCurve = cmds.curve( n='ribbon_wire_curve_1', p=[ cInitPOS, cMidPOS, cEndPOS ], d=2, k=[0,0,1,1] ) wireCIn = cmds.cluster('{0}.cv[0:1]'.format(rWireCurve), rel=True, en=1, n='ribbon_wireCL_init_1') wireCMid = cmds.cluster('{0}.cv[1]'.format(rWireCurve), rel=True, en=1, n='ribbon_wireCL_mid_1') wireCEnd = cmds.cluster('{0}.cv[1:2]'.format(rWireCurve), rel=True, en=1, n='ribbon_wireCL_end_1') # cluster pivots and origins cDict = { wireCIn[1] : cInitPOS, wireCMid[1] : cMidPOS, wireCEnd[1] : cEndPOS } for cl, pos in cDict.items(): #print pos cmds.xform(cl, pivots= pos) cmds.setAttr('{0}Shape.origin'.format(cl), *pos) # cluster weights cmds.percent(wireCIn[0], '{0}.cv[1]'.format(rWireCurve), v=0.5 ) cmds.percent(wireCEnd[0], '{0}.cv[1]'.format(rWireCurve), v=0.5 ) # bShape deformers [could also just skin surface to previously created joints..] wireDeformer = cmds.wire(bShape, dds=[(1,25), (0,25)], en=1, ce=0, li=0, w=rWireCurve, n='ribbon_bShape_wireNode_1') twistDeformer = cmds.nonLinear( bShape, type='twist', foc=1, n='ribbon_bShape_twistNode_1') cmds.setAttr('{0}.rotateZ'.format(twistDeformer[1]), 90) cmds.hide(twistDeformer[1]) for attr in rstats: cmds.setAttr('{0}Shape.{1}'.format(bShape, attr), 0) cmds.setAttr('{0}Shape.{1}'.format(nameFP, attr), 0) # connect controls to cluster handles ctrlDict = {topCtrl : wireCEnd[1], midCtrl : wireCMid[1], botCtrl : wireCIn[1] } for ctrl, cl in ctrlDict.items(): cmds.connectAttr('{0}.translate'.format(ctrl), '{0}.translate'.format(cl), f=True ) cmds.connectAttr('{0}.rotateX'.format(botCtrl), '{0}.endAngle'.format(twistDeformer[0]) ) cmds.connectAttr('{0}.rotateX'.format(topCtrl), '{0}.startAngle'.format(twistDeformer[0]) ) # group stuff controlsGrp = cmds.group(em=True, n='ribbon_controls_grp_1') cmds.parent( topOffset, midOffset, botOffset, controlsGrp ) clustersGrp = cmds.group(em=True, n='ribbon_clusters_grp_1') cmds.parent( wireCIn[1], wireCMid[1], wireCEnd[1], clustersGrp ) moveGrp = cmds.group(em=True, n='ribbon_move_grp_1') cmds.parent(controlsGrp, nameFP, moveGrp) extraGrp = cmds.group(em=True, n='ribbon_extras_grp_1') cmds.parent( clustersGrp, locGrp, rWireCurve, '{0}BaseWire'.format(rWireCurve), bShape, twistDeformer[1], extraGrp) godGrp = cmds.group(em=True, n='ribbon_main_grp_1') cmds.parent( extraGrp, mainCtrlOffset, godGrp ) cmds.parent( moveGrp, mainCtrl ) toHideList = [ bShape, rWireCurve, clustersGrp ] for object in toHideList: cmds.hide(object) locators = cmds.listRelatives(locGrp, c=True) for loc in locators: cmds.scaleConstraint(moveGrp, loc, offset=[1,1,1])
sel.add(cam) sel.getDagPath(0, mdag_path) draw_traversal = omu.MDrawTraversal() draw_traversal.setFrustum(mdag_path, cmds.getAttr("defaultResolution.width"), cmds.getAttr("defaultResolution.height")) draw_traversal.traverse() print draw_traversal.numberOfItems() frustum_objs = [] for i in range(draw_traversal.numberOfItems()): shape_dag = om.MDagPath() draw_traversal.itemPath(i, shape_dag) transform_dag = om.MDagPath() om.MDagPath.getAPathTo(shape_dag.transform(), transform_dag) obj = transform_dag.fullPathName() if cmds.objExists(obj): frustum_objs.append(obj) cmds.select(frustum_objs) len(cmds.ls(sl=1)) a = cmds.ls(sl=1) #a.sort() #b = cmds.ls(sl=1) #b.sort() w = cmds.wire(a[1], w=a[0], gw=0, en=1, ce=0, li=0) cmds.wire(w[0], e=1, dds=[(0, 99999)])
def buildStickyLips(cls, *args): ''' Main method. ''' # Duplicate geometry oriGeo = cls.upperLipEdges[0].rsplit('.e')[0] logger.debug('Geometry Name: %s' % oriGeo) dupGeo = cmds.duplicate(oriGeo, n=oriGeo + '_stickyLipsSrcCrv_geo')[0] cmds.select(dupGeo, r=True) tak_cleanUpModel.delHis() tak_cleanUpModel.delInterMediObj() cmds.select(oriGeo, dupGeo, r=True) tak_misc.TransSkinWeights() # Convert polygon edges to curves dupGeoUpperEdges = cls.rplcStrInList(cls.upperLipEdges, oriGeo, dupGeo) cmds.select(dupGeoUpperEdges, r=True) upperLipCrv = mel.eval('polyToCurve -form 2 -degree 3;') upperLipCrv = cmds.rename(upperLipCrv[0], 'upper_lip_sticky_crv') dupGeoLowerEdges = cls.rplcStrInList(cls.lowerLipEdges, oriGeo, dupGeo) cmds.select(dupGeoLowerEdges, r=True) lowerLipCrv = mel.eval('polyToCurve -form 2 -degree 3;') lowerLipCrv = cmds.rename(lowerLipCrv[0], 'lower_lip_sticky_crv') # Create sticky lips curve stickyLipsCrv = cmds.duplicate(upperLipCrv, n='stickyLips_crv')[0] stickyLipsCrvShp = cmds.listRelatives(stickyLipsCrv, s=True)[0] upperLipCrvShp = cmds.listRelatives(upperLipCrv, s=True)[0] lowerLipCrvShp = cmds.listRelatives(lowerLipCrv, s=True)[0] avgCrvNode = cmds.createNode('avgCurves', n='stickyLips_avgCurve') cmds.setAttr('%s.automaticWeight' % avgCrvNode, 0) cmds.setAttr('%s.normalizeWeights' % avgCrvNode, 0) cmds.connectAttr('%s.worldSpace[0]' % upperLipCrvShp, '%s.inputCurve1' % avgCrvNode) cmds.connectAttr('%s.worldSpace[0]' % lowerLipCrvShp, '%s.inputCurve2' % avgCrvNode) cmds.connectAttr('%s.outputCurve' % avgCrvNode, '%s.create' % stickyLipsCrvShp) # Grouping stklGrp = cmds.createNode('transform', n='stickyLips_grp') cmds.parent(dupGeo, upperLipCrv, lowerLipCrv, stickyLipsCrv, stklGrp) cmds.setAttr('%s.visibility' % stklGrp, 0) # Assign wire deformer to the geometry wire = cmds.wire(oriGeo, w=stickyLipsCrv)[0] cmds.setAttr('%s.scale[0]' % wire, 0) cmds.setAttr('%s.envelope' % wire, 2) cmds.setAttr('%s.envelope' % wire, lock=True) cmds.connectAttr('%s.outputCurve' % avgCrvNode, '%sBaseWireShape.create' % stickyLipsCrv) # Weighting vtxNumber = cmds.polyEvaluate(oriGeo, vertex=True) cmds.percent(wire, '%s.vtx[0:%d]' % (oriGeo, vtxNumber - 1), v=0) wireVtxList = cmds.polyListComponentConversion(cls.upperLipEdges, cls.lowerLipEdges, tv=True) cmds.percent(wire, wireVtxList, v=1)
def buildDeformers(self, ribbonPlane, controls=(), folGrp=()): # Create a target blendshape controlled by deformers flexiBlend = cmds.duplicate(ribbonPlane, n='flexiPlaneSetup_bShp_surface01') flexiBlendNode = cmds.blendShape(flexiBlend, ribbonPlane, n='%s_bShpNode_surface01' % self.name) # Turn blendshape on cmds.setAttr('%s.%s' % (flexiBlendNode[0], flexiBlend[0]), 1) # Create a wire deformer controled by ribbon controls wireCurve = cmds.curve( n='%s_wire_surface01' % self.name, d=2, p=[(-self.numJnts, 0, 0), (0, 0, 0), (self.numJnts, 0, 0)]) topClstr = cmds.cluster('%s.cv[0:1]' % wireCurve, rel=1, n='%s_cl_a01' % self.name) midClstr = cmds.cluster('%s.cv[1]' % wireCurve, rel=1, n='%s_cl_mid01' % self.name) botClstr = cmds.cluster('%s.cv[1:2]' % wireCurve, rel=1, n='%s_cl_b01' % self.name) clsGrp = cmds.group(topClstr, midClstr, botClstr, n='%s_cls01' % self.name) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (topClstr[1], attr), -self.numJnts, 0, 0) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (botClstr[1], attr), self.numJnts, 0, 0) cmds.setAttr('%sShape.originX' % topClstr[1], (-self.numJnts)) cmds.setAttr('%sShape.originX' % botClstr[1], (self.numJnts)) cmds.percent(topClstr[0], '%s.cv[1]' % wireCurve, v=0.5) cmds.percent(botClstr[0], '%s.cv[1]' % wireCurve, v=0.5) # Create twist and wire blend shape deformers twistNode = cmds.nonLinear(flexiBlend, type='twist') cmds.wire(flexiBlend, w=wireCurve, dds=[0, 20], foc=0, n='%s_wireAttrs_surface01' % self.name) cmds.xform(twistNode, ro=(0, 0, 90)) twistNode[0] = cmds.rename(twistNode[0], '%s_twistAttrs_surface01' % self.name) twistNode[1] = cmds.rename(twistNode[1], '%s_twist_surface01' % self.name) # Setup squash and stretch via utilitiy nodes arcLen = cmds.arclen(wireCurve, ch=1) arcLen = cmds.rename(arcLen, '%s_curveInfo01' % self.name) arcLenValue = cmds.getAttr('%s.arcLength' % arcLen) squashDivNode = cmds.createNode('multiplyDivide', n='%s_div_squashStretch_length01' % self.name) volDivNode = cmds.createNode('multiplyDivide', n='%s_div_volume01' % self.name) squashCondNode = cmds.createNode('condition', n='%s_cond_volume01' % self.name) cmds.setAttr('%s.operation' % squashDivNode, 2) cmds.setAttr('%s.input2X' % squashDivNode, arcLenValue) cmds.setAttr('%s.operation' % volDivNode, 2) cmds.setAttr('%s.input1X' % volDivNode, 1) cmds.setAttr('%s.secondTerm' % squashCondNode, 1) cmds.connectAttr('%s.arcLength' % arcLen, '%s.input1X' % squashDivNode) cmds.connectAttr('%s.outputX' % squashDivNode, '%s.input2X' % volDivNode) cmds.connectAttr('%s.outputX' % volDivNode, '%s.colorIfTrueR' % squashCondNode) # Set visibility options for obj in [flexiBlend[0], wireCurve, twistNode[1], clsGrp]: cmds.setAttr('%s.visibility' % obj, 0) # Connect controls to cluster deformers if they exist if len(controls) > 1: topCon = controls[0][0] botCon = controls[0][1] midCon = controls[0][2] for con, clstr in zip([topCon, botCon], [topClstr[1], botClstr[1]]): cmds.connectAttr('%s.translate' % con, '%s.translate' % clstr) cmds.connectAttr('%s.translate' % midCon, '%s.translate' % midClstr[1]) # Connect controls to twist deformer cmds.connectAttr('%s.rotateX' % topCon, '%s.endAngle' % twistNode[0]) cmds.connectAttr('%s.rotateX' % botCon, '%s.startAngle' % twistNode[0]) cmds.connectAttr('%s.volEnable' % controls[1], '%s.firstTerm' % squashCondNode) # Scale contraint each follicle to global move group for fol in cmds.listRelatives(folGrp, c=1): cmds.scaleConstraint(self.moveGrp, fol, mo=0) for shape in cmds.listRelatives(fol, s=1): cmds.setAttr('%s.visibility' % shape, 0) # Parent nodes cmds.parent(flexiBlend, wireCurve, clsGrp, twistNode[1], '%s_wire_surface01BaseWire' % self.name, self.extrasGrp)