def addSurfaceConstraintToBnd(bnd, surface): ''' ''' secDrv = bnd.getParent() matrix = secDrv.getMatrix(worldSpace=True) # create additional nulls gc = pm.group(em=True, n=bnd.nodeName().replace('_bnd', '_gc')) gc_offset = pm.group(em=True, n=bnd.nodeName().replace('_bnd', '_gc_offset')) acs = pm.group(em=True, n=bnd.nodeName().replace('_bnd', '_acs')) # point constraint first to get precise position to secDrv pm.pointConstraint(secDrv, gc) # geometry constraint to surface pm.geometryConstraint(surface, gc) # normal constraint, using secDrv-Y as up pm.normalConstraint(surface, gc, aim=(0,0,1), u=(0,1,0), wuo=secDrv, wut='objectrotation', wu=(0,1,0)) # ensure that gc_offset stores offset to secDrv gc_offset.setMatrix(matrix, worldSpace=True) acs.setMatrix(matrix, worldSpace=True) # hierarchy secDrv | gc | gc_offset | acs | bnd
def ghostSlider(ghostControls, surface, sliderParent): """Modify the ghost control behaviour to slide on top of a surface Args: ghostControls (dagNode): The ghost control surface (Surface): The NURBS surface sliderParent (dagNode): The parent for the slider. """ if not isinstance(ghostControls, list): ghostControls = [ghostControls] #Seleccionamos los controles Ghost que queremos mover sobre el surface surfaceShape = surface.getShape() for ctlGhost in ghostControls: ctl = pm.listConnections(ctlGhost, t="transform")[-1] t = ctl.getMatrix(worldSpace=True) gDriver = pri.addTransform(ctlGhost.getParent(), ctl.name()+"_slideDriver", t) try: pm.connectAttr(ctl + ".translate", gDriver + ".translate") pm.disconnectAttr(ctl + ".translate", ctlGhost + ".translate") except: pass try: pm.connectAttr(ctl + ".scale", gDriver + ".scale") pm.disconnectAttr(ctl + ".scale", ctlGhost + ".scale") except: pass try: pm.connectAttr(ctl + ".rotate", gDriver + ".rotate") pm.disconnectAttr(ctl + ".rotate", ctlGhost + ".rotate") except: pass oParent = ctlGhost.getParent() npoName = "_".join(ctlGhost.name().split("_")[:-1]) + "_npo" oTra = pm.PyNode(pm.createNode("transform", n=npoName, p=oParent, ss=True)) oTra.setTransformation(ctlGhost.getMatrix()) pm.parent(ctlGhost, oTra) slider = pri.addTransform(sliderParent, ctl.name()+"_slideDriven", t) #connexion dm_node = nod.createDecomposeMatrixNode(gDriver.attr("worldMatrix[0]")) cps_node = pm.createNode("closestPointOnSurface") dm_node.attr("outputTranslate") >> cps_node.attr("inPosition") surfaceShape.attr("worldSpace[0]") >> cps_node.attr("inputSurface") cps_node.attr("position") >> slider.attr("translate") pm.normalConstraint(surfaceShape, slider, aimVector=[0,0,1] , upVector=[0,1,0], worldUpType="objectrotation", worldUpVector=[0,1,0], worldUpObject=gDriver) pm.parent(ctlGhost.getParent(), slider)
def contextPress(self): button = cmds.draggerContext(_dragOnMeshContext, query=True, button=True) # left : 1, middle: 2 if button == 1: self.mainGrp = pm.group(em=True) pm.parent(self.mainGrp, self.growSel) # create trans self.currentTrans = list() self.consGrp = list() for i in range(0, self.copyNum): currentTrans = pm.duplicate(self.initTrans, rr=1)[0] # type: str self.currentTrans.append(currentTrans) consGrp = pm.group(em=1, name='dragOnMesh#') pm.parent(consGrp, self.mainGrp) pm.parent(currentTrans, consGrp) consGrp.scale.set(self.scaList[i] * self.secondSca, self.scaList[i] * self.secondSca, self.scaList[i] * self.secondSca) currentTrans.rotate.set(0, self.rotateList[i] + self.secondRotate, 0) self.consGrp.append(consGrp) pm.geometryConstraint(self.growSel, consGrp, weight=1) pm.normalConstraint(self.growSel, consGrp, weight=1, aimVector=(0, 1, 0), upVector=(0, 0, 1), worldUpType="scene") vpX, vpY, _ = cmds.draggerContext(self.context, q=True, anchorPoint=True) sourcePoint, direction = getIntersect(vpX, vpY) hitPoint = getPoints(self.growSel, sourcePoint, direction) for consGrp in self.consGrp: if hitPoint: consGrp.translate.set(hitPoint) else: consGrp.translate.set(sourcePoint) if hitPoint: self.dragInitPos = vpX, vpY, _ updateView() elif button == 2: pressPosition = cmds.draggerContext(self.context, query=True, anchorPoint=True) self.mouseX = pressPosition[0] self.currentTransRotXYZ = list() for each in self.currentTrans: self.currentTransRotXYZ.append(each.rotate.get())
def disperse(self, *args): """Called when the disperse button is pressed""" if self.sourceObj == None or self.targetObjs == None: pm.confirmDialog(t='Error', b=['OK'], m='Please make sure source and targets are selected.') return # get copy number copyNum = self.copyNum.getValue() copyNum = min(copyNum, len(self.vertIndexList)) # get rotation rotationMode = self.rotationModeRC.getSelect() rotationMode = pm.control(rotationMode, q=True, fpn=True) if rotationMode == self.rotBtnRand: origRot = pm.xform(self.sourceObj, ro=True, q=True) rotRange = self.rotationRange.getValue() # get scale scaleMode = self.scaleModeRC.getSelect() scaleMode = pm.control(scaleMode, q=True, fpn=True) if scaleMode == self.scaleBtnRand: scaleRange = self.scaleRange.getValue() # make copies randVertIndexList = random.sample(self.vertIndexList, copyNum) for i in randVertIndexList: newObj = pm.duplicate(self.sourceObj, n='%s_copy'%self.sourceObj) # decide which target the random vert index falls on vertSum = 0 targetIndex = 0 targetVertIndex = 0 for j, k in enumerate(self.targetVertNumList): vertSum += k if i + 1 <= vertSum: targetIndex = j targetVertIndex = i - (vertSum - k) break # apply scale if scaleMode == self.scaleBtnRand: randScale = random.uniform(scaleRange[0], scaleRange[1]) pm.xform(newObj, s=(randScale,randScale,randScale)) # apply rotation if rotationMode == self.rotBtnAlign: # normal constraint pm.normalConstraint(self.targetObjs[targetIndex], newObj, aim=(0,0,1), u=(0,1,0)) elif rotationMode == self.rotBtnRand: newRotX = random.uniform(origRot[0]-rotRange[0]/2,origRot[0]+rotRange[0]/2) newRotY = random.uniform(origRot[1]-rotRange[1]/2,origRot[1]+rotRange[1]/2) newRotZ = random.uniform(origRot[2]-rotRange[2]/2,origRot[2]+rotRange[2]/2) pm.xform(newObj, ro=(newRotX,newRotY,newRotZ)) rotatePivot = pm.xform(newObj, rp=True, q=True) newPos = pm.pointPosition('%s.vtx[%d]'%(self.targetObjs[targetIndex],targetVertIndex)) posOffset = [newPos[0]-rotatePivot[0], newPos[1]-rotatePivot[1], newPos[2]-rotatePivot[2]] pm.xform(newObj, t=posOffset) # remove constraint after translation if rotationMode == self.rotBtnAlign: pm.delete(newObj, cn=True)
def placeOnObject(src, dest, orient=False, keep=False): """ Moves & Orients Object in XYZ to Closest Point in dest """ geo_const = pm.geometryConstraint(dest, src) if not keep: pm.delete(geo_const) if orient: nrm_const = pm.normalConstraint(dest, src, wu=(0, 1, 0), wut="vector", u=(0, 1, 0), aim=(0, 1, 0)) if not keep: pm.delete(nrm_const)
def _aim_module(surface, target, aimed_object): cons = pm.normalConstraint(surface, target, upVector=(0, 1, 0), worldUpType=2, aimVector=(0, 0, 1), worldUpVector=(0, 1, 0)) aimed_object.worldMatrix.connect(cons.worldUpMatrix) cons.restRotate.set(0, 0, 0)
def loop_to_joints(s=0.025): """Convert a mesh loop edge selection to a nurbs curve that has joints (w/ tweak controls) at each vertex. Opens dialog for naming.""" edges = pmc.selected(flatten=True) cage = edges[0].node() try: n = make_dialog("Name of this curve/region?") + "{}" except TypeError: pmc.warning("Aborted.") return c = pmc.PyNode(pmc.polyToCurve(n=n.format("_rider"))[0]) verts = set([v for e in edges for v in e.connectedVertices()]) grp = pmc.group(em=True, n=n.format("_grp")) c.setParent(grp) jn = "" for i, v in enumerate(verts): pmc.select(c) pmc.selectMode(component=True) pmc.select(c.u[i]) pmc.refresh() jn = make_dialog("Name of this joint?", jn) poci = pmc.nt.PointOnCurveInfo(n=n.format(jn + "_poci")) c.ws >> poci.inputCurve poci.parameter.set(i) ctrl_grp = pmc.group(em=True, n=n.format(jn + "_offset")) ctrl_grp.setParent(grp) ctrl = pmc.sphere(r=s, s=1, nsp=1, ch=0, n=n.format(jn + "_tweakCtrl"))[0] ctrl.setParent(ctrl_grp) j = pmc.joint(n=n.format(jn + "_rig")) j.setParent(ctrl) j.hide() poci.position >> ctrl_grp.translate nCon = pmc.normalConstraint(cage, ctrl_grp) poci.nt >> nCon.worldUpVector # remove graph cluster nCon.crp.disconnect() nCon.crt.disconnect() nCon.cro.disconnect() nCon.cpim.disconnect() nCon.ct.disconnect() poci.position >> nCon.constraintTranslate grp.wim >> nCon.cpim pmc.selectMode(object=True)
def onVerts(target=None, normals=True, type="vector"): #1. make an array of all selected objects if not target: target = mc.ls(sl=1) #2. get the first selected object so it can be copied... foo = target[0] #3. then get the vertices of each other object and copy the first one there. for i in range(1,len(target)): v = getVertPos(target[i]) for j in range(0,len(v)): s(foo) foo2 = py.duplicate() mc.move(v[j][0],v[j][1],v[j][2]) if(normals==True): py.mel.eval("select -r " + target[i] + ".vtx[" + str(j) +"] " + foo2[0] + ";") py.normalConstraint(worldUpType=type) '''
def onVerts(target=None, normals=True, type="vector"): #1. make an array of all selected objects if not target: target = mc.ls(sl=1) #2. get the first selected object so it can be copied... foo = target[0] #3. then get the vertices of each other object and copy the first one there. for i in range(1, len(target)): v = getVertPos(target[i]) for j in range(0, len(v)): s(foo) foo2 = py.duplicate() mc.move(v[j][0], v[j][1], v[j][2]) if (normals == True): py.mel.eval("select -r " + target[i] + ".vtx[" + str(j) + "] " + foo2[0] + ";") py.normalConstraint(worldUpType=type) '''
def buildSurfaceFollow(joints, groupOrigin, surface=None, controlSpec={}): groupOrigin = dt.Vector(groupOrigin) container = util.parentGroup(joints[0]) container.setParent(lib.getNodes.mainGroup()) mainCtrl = controllerShape.build( util.trimName(joints[0].getParent()) + 'Surface_ctrl', controlSpec['main'], type=controllerShape.ControlType.TRANSLATE) mainCtrl = nodeApi.RigController.convert(mainCtrl) mainCtrl.setParent(container) xform(mainCtrl, ws=True, t=groupOrigin) core.dagObj.lockScale(mainCtrl) core.dagObj.zero(mainCtrl) subControls = [] locs = [] offsets = [] for i, j in enumerate(joints): loc = spaceLocator() locs.append(loc) core.dagObj.matchTo(loc, j) geometryConstraint(surface, loc) objUp, worldObjUp = getUpVectors(j) normalConstraint(surface, loc, wuo=mainCtrl, wut='objectrotation', upVector=objUp, worldUpVector=worldObjUp) offsetCtrl = controllerShape.build( util.trimName(j) + 'Offset_ctrl', controlSpec['offset'], type=controllerShape.ControlType.TRANSLATE) core.dagObj.matchTo(offsetCtrl, loc) offsets.append(offsetCtrl) offsetCtrl.setParent(loc) core.dagObj.zero(offsetCtrl) subCtrl = controllerShape.build( util.trimName(j) + '_ctrl', controlSpec['manual'], type=controllerShape.ControlType.TRANSLATE) subControls.append(subCtrl) core.dagObj.matchTo(subCtrl, loc) subCtrl.setParent(mainCtrl) core.dagObj.zero(subCtrl) pointConstraint(subCtrl, loc) core.dagObj.lockRot(subCtrl) core.dagObj.lockScale(subCtrl) core.dagObj.lockScale(offsetCtrl) loc.setParent(subCtrl) space.add(offsetCtrl, loc, spaceName='surface') mainCtrl.subControl[str(i)] = subCtrl mainCtrl.subControl[str(i) + '_offset'] = offsetCtrl constraints = util.constrainAtoB(joints, offsets) mainCtrl.container = container return mainCtrl, constraints
def scatter(self): all_vertexes = [] self.scatter_instances.append([]) for target in self.scatter_targets: if type(target) == pmc.general.MeshVertex: all_vertexes.append(target) else: all_vertexes.extend(target.vtx) vertexes = range(len(all_vertexes)) random.shuffle(vertexes) vertexes = vertexes[:int(self.scatter_density * len(vertexes))] for i in vertexes: vertex = all_vertexes[i] # Get the average normal of the vertex # pmc.select(vertex, r=True) # a = pmc.polyNormalPerVertex(q=True, xyz=True) # num_normals = len(a) / 3 # average_normal = [0, 0, 0] # i = 0 # while i < len(a): # average_normal[i % 3] += a[i] / num_normals # i += 1 # # print(average_normal) new_instance = pmc.instance(random.choice(self.scatter_sources)) self.scatter_instances[-1].append(new_instance) position = pmc.pointPosition(vertex, w=True) pmc.move(position[0], position[1], position[2], new_instance, a=True, ws=True) if self.alignment: pmc.normalConstraint(vertex, new_instance) pmc.normalConstraint(vertex, new_instance, rm=True) scale = random_between_two_vectors( self.attribute_array[0], self.attribute_array[1]) rotation = random_between_two_vectors( self.attribute_array[2], self.attribute_array[3]) position = random_between_two_vectors( self.attribute_array[4], self.attribute_array[5]) pmc.scale(new_instance, scale[0], scale[1], scale[2], r=True) pmc.rotate(new_instance, rotation[0], rotation[1], rotation[2], r=True) pmc.move(position[0], position[1], position[2], new_instance, r=True, os=True, wd=True) # hello = cmds.polyListComponentConversion(tv=True) # print(hello[0]) # vertices = cmds.polyEvaluate(scatter_target, v=True) # i = 0 # while i < vertices: # print(scatter_target.vtx) # i += 1 #print(cmds.filterExpand(selectionMask=31)) #self.scatterTargetsVertices.append(vertices) return
if not isinstance(surface,pm.nodetypes.NurbsSurface): pm.error("stoping. Select surface first") if not ctrl.hasAttr("slide"): pm.addAttr(ctrl,ln="slide",min=0,max=1,k=True) for x in range(1,nbJoints+1): PoSi=pm.createNode("pointOnSurfaceInfo") U_value=_u_spacing*x minus=pm.createNode("plusMinusAverage") clamp=pm.createNode("clamp") minus.operation.set(2) ctrl.slide.connect(minus.input1D[0]) ctrl.slide.connect(minus.input1D[1]) minus.input1D[1].disconnect() minus.input1D[1].set(1-U_value) minus.output1D.connect(clamp.inputR) clamp.minR.set(0) clamp.maxR.set(1) clamp.outputR.connect(PoSi.parameterU) PoSi.parameterV.set(0.5) surface.worldSpace[0].connect(PoSi.inputSurface) joint=pm.createNode("joint") PoSi.position.connect(joint.translate) pm.normalConstraint(surface,joint)
getSel = pm.ls(os=1) vtxGrp = pm.ls(pm.polyListComponentConversion(getSel,fe=1,tv=1),fl=1) vtxNum = len(vtxGrp) vtxPosGrp = [pm.xform(vtx, q=True, ws=True, t=True)for vtx in vtxGrp] tmpPoly = mc.polyCreateFacet(p=[tuple(vec) for vec in vtxPosGrp ])[0] pm.xform(tmpPoly,cp=1) centerPos = mc.xform(tmpPoly, q=True, ws=True, rp=True) distGrp = [((vec[0] - centerPos[0]) ** 2 + (vec[1] - centerPos[1]) ** 2 + (vec[2] - centerPos[2]) ** 2) ** 0.5 for vec in vtxPosGrp] dist = sum(distGrp)/vtxNum circle = pm.circle(s=vtxNum, r=dist, c=(0, 0, 0), d=3, ch=False)[0] pm.xform(circle, ws=True, t=tuple(centerPos)) wu = (vtxPosGrp[0][0] - centerPos[0]),(vtxPosGrp[0][1] - centerPos[1]),(vtxPosGrp[0][2] - centerPos[2]) pm.normalConstraint(tmpPoly,circle,aim=[0,0,1],u=[0,1,0],wu=(0,1,0)) e2vInfos= pm.polyInfo(getSel,ev=1) e2vDict = {} for info in e2vInfos: evList = [ int(i) for i in re.findall('\\d+', info) ] e2vDict.update(dict([(evList[0], evList[1:])])) # average normal vtxGrp = pm.mel.eval("PolySelectConvert 3;") avNmGrp = pm.polyNormalPerVertex(getSel,q=1,xyz=1)
def ghostSliderForMouth(ghostControls, intTra, surface, sliderParent): """Modify the ghost control behaviour to slide on top of a surface Args: ghostControls (dagNode): The ghost control surface (Surface): The NURBS surface sliderParent (dagNode): The parent for the slider. """ if not isinstance(ghostControls, list): ghostControls = [ghostControls] def conn(ctl, driver, ghost): for attr in ["translate", "scale", "rotate"]: try: pm.connectAttr("{}.{}".format(ctl, attr), "{}.{}".format(driver, attr)) pm.disconnectAttr("{}.{}".format(ctl, attr), "{}.{}".format(ghost, attr)) except RuntimeError: pass def connCenter(ctl, driver, ghost): # mul_node1 = pm.createNode("multMatrix") # mul_node2 = pm.createNode("multMatrix") down, _, up = ymt_util.findPathAtoB(ctl, driver) mult = pm.createNode("multMatrix") for i, d in enumerate(down): d.attr("matrix") >> mult.attr("matrixIn[{}]".format(i)) for j, u in enumerate(up[:-1]): u.attr("inverseMatrix") >> mult.attr( "matrixIn[{}]".format(i + j + 1)) decomp = pm.createNode("decomposeMatrix") dm_node = node.createDecomposeMatrixNode(mult.attr("matrixSum")) for attr in ["translate", "scale", "rotate"]: pm.connectAttr("{}.output{}".format(dm_node, attr.capitalize()), "{}.{}".format(driver, attr)) pm.disconnectAttr("{}.{}".format(ctl, attr), "{}.{}".format(ghost, attr)) surfaceShape = surface.getShape() sliders = [] for i, ctlGhost in enumerate(ghostControls): ctl = pm.listConnections(ctlGhost, t="transform")[-1] t = ctl.getMatrix(worldSpace=True) gDriver = primitive.addTransform(surface.getParent(), "{}_slideDriver".format(ctl.name()), t) if 0 == i: connCenter(ctl, gDriver, ctlGhost) else: conn(ctl, gDriver, ctlGhost) oParent = ctlGhost.getParent() npoName = "_".join(ctlGhost.name().split("_")[:-1]) + "_npo" oTra = pm.PyNode( pm.createNode("transform", n=npoName, p=oParent, ss=True)) oTra.setTransformation(ctlGhost.getMatrix()) pm.parent(ctlGhost, oTra) slider = primitive.addTransform(sliderParent, ctl.name() + "_slideDriven", t) sliders.append(slider) # connexion if 0 == i: dm_node = node.createDecomposeMatrixNode(gDriver.attr("matrix")) else: mul_node = pm.createNode("multMatrix") i = 0 parent = ctl while parent != sliderParent: parent.attr("matrix") >> mul_node.attr( "matrixIn[{}]".format(i)) parent = parent.getParent() i += 1 if 10 < i: logger.error("maximum recursion") break dm_node = node.createDecomposeMatrixNode( mul_node.attr("matrixSum")) cps_node = pm.createNode("closestPointOnSurface") dm_node.attr("outputTranslate") >> cps_node.attr("inPosition") surfaceShape.attr("local") >> cps_node.attr("inputSurface") cps_node.attr("position") >> slider.attr("translate") pm.normalConstraint(surfaceShape, slider, aimVector=[0, 0, 1], upVector=[0, 1, 0], worldUpType="objectrotation", worldUpVector=[0, 1, 0], worldUpObject=gDriver) pm.parent(ctlGhost.getParent(), slider) ymt_util.setKeyableAttributesDontLockVisibility(slider, []) for slider in sliders[1:]: _visi_off_lock(slider)
def create_handle(name=Vars.PLUGIN_NAME, camera="", light="", geometry=""): """ Handle creation master method. Params are accepted, no params means creating from selection. :param name : string, Optional. Handle name. :param camera : string, Optional. Camera name. :param light : string, Optional. Light name. :param geometry : string, Optional. Geometry to constraint to. :return Parameter dictionary {handle, node, camera, light, geo} """ # Get from selection ? if not any((camera, light, geometry)): camera, light, geometry = get_data_from_selection() # Store snap position before creating everything otherwise component_pos = get_components_pos() # Snap to component, or to cam if there's geo, otherwise at root if component_pos != (0, 0, 0): snap_pos = component_pos elif camera and geometry: snap_pos = pmc.PyNode(camera).getTranslation(ws=True) else: snap_pos = (0, 0, 0) # Create Sol Handle s_node = pmc.createNode(Vars.PLUGIN_NAME, n='{}Shape#'.format(name)) # Connect root world matrix and set position on component s_trans = s_node.getParent() s_trans.worldMatrix.connect(s_node.selfMatrix) s_trans.setTranslation(snap_pos, ws=True) # Add Parameters s_trans.addAttr("_", at='enum', en='Controls', k=1) s_trans.addAttr('normalReflectionBlend', at='double', min=0, max=1, dv=1, k=1) s_trans.addAttr('distance', at='double', dv=10, k=1) s_trans.addAttr('lightRoll', at='double', dv=0, k=1) s_trans.addAttr('drawMode', at='long', min=0, max=3, dv=2, k=1) s_trans.addAttr('normalLength', at='double', min=0, dv=3, k=1) # Set and connect parameters pmc.setAttr(s_trans.name() + '._', lock=1) s_trans.normalReflectionBlend.connect(s_node.normalReflectionBlend, f=1) s_trans.distance.connect(s_node.distance, f=1) s_trans.lightRoll.connect(s_node.lightRoll, f=1) s_trans.drawMode.connect(s_node.drawMode, f=1) s_trans.normalLength.connect(s_node.normalLength, f=1) # Connect Camera and light c_node = change_handle_camera(s_node, camera) # TODO : disconnected, here, might be useful ? _, l_node, disconnected = change_handle_light(s_node, light) # TODO : if l_node, create parameters from typelight settings... # Constrain to geometry if geometry: g_node = pmc.PyNode(geometry) pmc.geometryConstraint(g_node, s_trans) pmc.normalConstraint(g_node, s_trans, aimVector=(0, 1, 0)) else: g_node = None # Select node and return data pmc.select(s_trans, r=True) return Vars.HANDLE_DATA( handle=s_trans, node=s_node, camera=c_node, light=l_node, geometry=g_node )
def copyNum_changed(self, copyNum, rotate, randomRotate, secondRotate, sca, randomSca, secondSca): if not cmds.objExists(self.initTrans): return cmds.setAttr('{}.visibility'.format(self.initTrans), True) pm.delete(self.mainGrp) self.copyNum = copyNum self.rotate = rotate self.randomRotate = randomRotate self.secondRotate = secondRotate self.sca = sca self.randomSca = randomSca self.secondSca = secondSca if randomRotate == 0: self.rotateList = [rotate for i in range(copyNum)] else: rotateMin = rotate - randomRotate rotateMax = rotate + randomRotate getDev = abs(randomRotate) * 2 / copyNum self.rotateList = [ random.randrange(rotateMin, rotateMax + getDev, getDev) for i in range(0, copyNum) ] if randomSca == 0: self.scaList = [sca for i in range(0, copyNum)] else: scaMin = int(sca * 100 * (1 - randomSca)) scaMax = int(sca * 100 * (1 + randomSca)) getDev = int(abs(randomSca) * 200 / copyNum) self.scaList = [ random.randrange(scaMin, scaMax + getDev, getDev) / 100.00 for i in range(0, copyNum) ] self.mainGrp = pm.group(em=True) pm.parent(self.mainGrp, self.growSel) # create trans self.currentTrans = list() self.consGrp = list() for i in range(0, self.copyNum): currentTrans = pm.duplicate(self.initTrans, rr=1)[0] # type: str self.currentTrans.append(currentTrans) consGrp = pm.group(em=1, name='dragOnMesh#') pm.parent(consGrp, self.mainGrp) pm.parent(currentTrans, consGrp) consGrp.scale.set(self.scaList[i] * self.secondSca, self.scaList[i] * self.secondSca, self.scaList[i] * self.secondSca) currentTrans.rotate.set(0, self.rotateList[i] + self.secondRotate, 0) self.consGrp.append(consGrp) pm.geometryConstraint(self.growSel, consGrp, weight=1) pm.normalConstraint(self.growSel, consGrp, weight=1, aimVector=(0, 1, 0), upVector=(0, 0, 1), worldUpType="scene") vpX, vpY, _ = self.dragEndPos sourcePoint, direction = getIntersect(vpX, vpY) hitPoint = getPoints(self.growSel, sourcePoint, direction) if hitPoint: if self.copyNum == 1: self.consGrp[0].translate.set(hitPoint) else: endX, endY, _ = self.dragInitPos numLen = self.copyNum - 1.0 devX = (endX - vpX) / numLen devY = (endY - vpY) / numLen for i in range(self.copyNum): finX, finY = endX - i * devX, endY - i * devY sourcePoint, direction = getIntersect(finX, finY) hitPoint = getPoints(self.growSel, sourcePoint, direction) self.consGrp[i].translate.set(hitPoint) updateView()
def ghostSliderForEyeBrow(self, ghostControls, surface, sliderParent): """Modify the ghost control behaviour to slide on top of a surface Args: ghostControls (dagNode): The ghost control surface (Surface): The NURBS surface sliderParent (dagNode): The parent for the slider. """ if not isinstance(ghostControls, list): ghostControls = [ghostControls] def conn(ctl, driver, ghost): for attr in ["translate", "scale", "rotate"]: pm.connectAttr("{}.{}".format(ctl, attr), "{}.{}".format(driver, attr)) # pm.disconnectAttr("{}.{}".format(ctl, attr), "{}.{}".format(ghost, attr)) surfaceShape = surface.getShape() sliders = [] for i, ctlGhost in enumerate(ghostControls): ctl = pm.listConnections(ctlGhost, t="transform")[-1] t = ctl.getMatrix(worldSpace=True) scl = [1, 1, 1] if self.negate: scl = [-1, 1, 1] # t = transform.setMatrixScale(t, scl) gDriver = primitive.addTransform( ctlGhost.getParent(), "{}_slideDriver".format(ctl.name()), t) # conn(ctl, gDriver, ctlGhost) # print("ctlGhost.getParent: {}, ctl: {}, gDriver: {}, ctlGhost: {}".format(ctlGhost.getParent(), ctl, gDriver, ctlGhost)) oParent = ctlGhost.getParent() npoName = "_".join(ctlGhost.name().split("_")[:-1]) + "_npo" npo = pm.PyNode( pm.createNode("transform", n=npoName, p=oParent, ss=True)) npo.setTransformation(ctlGhost.getMatrix()) ymt_util.setKeyableAttributesDontLockVisibility(npo, []) pm.parent(ctlGhost, npo) slider = primitive.addTransform(sliderParent, ctl.name() + "_slideDriven", t) sliders.append(slider) down, _, up = findPathAtoB(ctl, sliderParent) mul_node = pm.createNode("multMatrix") j = k = 0 for j, d in enumerate(down): d.attr("matrix") >> mul_node.attr("matrixIn[{}]".format(j)) _.attr("matrix") >> mul_node.attr("matrixIn[{}]".format(j + 1)) for k, u in enumerate(up): u.attr("inverseMatrix") >> mul_node.attr( "matrixIn[{}]".format(k + j + 1)) dm_node = node.createDecomposeMatrixNode( mul_node.attr("matrixSum")) cps_node = pm.createNode("closestPointOnSurface") dm_node.attr("outputTranslate") >> cps_node.attr("inPosition") surfaceShape.attr("local") >> cps_node.attr("inputSurface") cps_node.attr("position") >> slider.attr("translate") if self.negate: aim = [0, 0, -1] else: aim = [0, 0, 1] pm.normalConstraint(surfaceShape, slider, aimVector=aim, upVector=[0, 1, 0], worldUpType="objectrotation", worldUpVector=[0, 1, 0], worldUpObject=gDriver) pm.parent(ctlGhost.getParent(), slider) pm.parent(gDriver.getParent(), self.mainControl)
def disperse(self, *args): """Called when the disperse button is pressed""" if self.sourceObj == None or self.targetObjs == None: pm.confirmDialog( t='Error', b=['OK'], m='Please make sure source and targets are selected.') return # get copy number copyNum = self.copyNum.getValue() copyNum = min(copyNum, len(self.vertIndexList)) # get rotation rotationMode = self.rotationModeRC.getSelect() rotationMode = pm.control(rotationMode, q=True, fpn=True) if rotationMode == self.rotBtnRand: origRot = pm.xform(self.sourceObj, ro=True, q=True) rotRange = self.rotationRange.getValue() # get scale scaleMode = self.scaleModeRC.getSelect() scaleMode = pm.control(scaleMode, q=True, fpn=True) if scaleMode == self.scaleBtnRand: scaleRange = self.scaleRange.getValue() # make copies randVertIndexList = random.sample(self.vertIndexList, copyNum) for i in randVertIndexList: newObj = pm.duplicate(self.sourceObj, n='%s_copy' % self.sourceObj) # decide which target the random vert index falls on vertSum = 0 targetIndex = 0 targetVertIndex = 0 for j, k in enumerate(self.targetVertNumList): vertSum += k if i + 1 <= vertSum: targetIndex = j targetVertIndex = i - (vertSum - k) break # apply scale if scaleMode == self.scaleBtnRand: randScale = random.uniform(scaleRange[0], scaleRange[1]) pm.xform(newObj, s=(randScale, randScale, randScale)) # apply rotation if rotationMode == self.rotBtnAlign: # normal constraint pm.normalConstraint(self.targetObjs[targetIndex], newObj, aim=(0, 0, 1), u=(0, 1, 0)) elif rotationMode == self.rotBtnRand: newRotX = random.uniform(origRot[0] - rotRange[0] / 2, origRot[0] + rotRange[0] / 2) newRotY = random.uniform(origRot[1] - rotRange[1] / 2, origRot[1] + rotRange[1] / 2) newRotZ = random.uniform(origRot[2] - rotRange[2] / 2, origRot[2] + rotRange[2] / 2) pm.xform(newObj, ro=(newRotX, newRotY, newRotZ)) rotatePivot = pm.xform(newObj, rp=True, q=True) newPos = pm.pointPosition( '%s.vtx[%d]' % (self.targetObjs[targetIndex], targetVertIndex)) posOffset = [ newPos[0] - rotatePivot[0], newPos[1] - rotatePivot[1], newPos[2] - rotatePivot[2] ] pm.xform(newObj, t=posOffset) # remove constraint after translation if rotationMode == self.rotBtnAlign: pm.delete(newObj, cn=True)