def _updateFilename(self): """Updates the filename with latest internal vars. Returns: str """ if self.fileDescr == "": pm.error("You need to enter a file description") # Checking whether or not to append an optional note to the filename formatter self.optionalNote = self.optionalNote_tf.getText() optional = self.optionalNote if optional == "(optional note)": optional = None self._formatFilename( self.fileDescr, self.discipline_om.getSelect(str=True), "v%s" % str(self.version_tf.getText() + str(self.versionOptional_om.getSelect(str=True))), self.initials, self.type.getSelect(str=True), optional=optional, ) if self.origFile_om.getSelect() == 1: self._updateFile(True) else: self._updateFile(False) return self.filename
def export(self): if self.export_dir is None: pm.warning('No folder has been set for export') return selection = pm.ls(sl=True) if not selection: pm.confirmDialog( title='No objects selected', message='Please select one or more object(s) to export.', button=['OK'], defaultButton='OK') self.original_selection = None return self.original_selection = pm.ls(sl=True) time_range = self.get_time_range() if time_range is None: pm.error('Could not determine time range.') return self.save_options() # if "bake animation" is checked if self.bake_animation_checkbox.isChecked(): self.bake(time_range) else: self.export_fbx(time_range)
def copyPlayblast(self): blastFiles = [] f='' wipPath = self.wipFolderEdit.text() selectedItems = self.wipAnimTable.selectedItems() if len(selectedItems): for item in selectedItems: if item.text() == 'Yes': animFile = self.wipAnimTable.item(item.row(),0).text() blastFile = self.hasPlayblast(animFile) wipBlastPath,blastFileName = os.path.split(blastFile) destPath = wipPath.replace('01_wip','03_preview') if destPath == wipPath: destPath = wipPath.replace('01_WIP','03_PREVIEW') dest = os.path.abspath(os.path.join(destPath,blastFileName)) if os.path.isfile(blastFile): if os.path.isfile(dest): pm.warning('Blast exists already, will not overwrite ( save new version ? )') else: try: print("copying") shutil.copyfile(blastFile, dest) try: os.remove(blastFile) except OSError: pass self.bdPopulateFiles() except: pm.error('Could not copy blast file to preview')
def makePVconstraint(): """function to create a pole vector constraint for an IK chain. Select ikHandle and control object to be used""" sel = pmc.ls(sl=True) if len(sel) is not 2: pmc.error("Select ikHandle and control object, in that order.") h = sel[0] ctrl = sel[1] midJoint = h.getJointList()[-1] orient = abs(midJoint.jointOrient.get().normal()) v = [] for d in orient: if d > .99: v.append(0) else: v.append(1) v = pmc.datatypes.Vector(v) if orient != midJoint.jointOrient.get().normal(): v = -v g = pmc.group(em=True, n=ctrl.name() + "_GRP") g.setParent(midJoint) ctrl.setParent(g) pmc.makeIdentity(g) pmc.makeIdentity(ctrl) g.translate.set(v) g.setParent(None)
def loadDeformerWeights(filename=None): ''' Usage: loadDeformerWeights(filename='/jobs/mercedesFable_5402587/build/charTortoise/maya/export/WEIGHTS/tortoiseAFacial/extraWeights/deformerWeights/v03/deformerWeights.json') loadDeformerWeights() ''' if not filename: try: filename = pm.fileDialog2(cap='Select a json file you stored', fm=1, okc='Load', ff='JSON (*.json)')[0] except: pm.error('file not found, whatever.') with open(filename, 'rb') as fp: data = json.load(fp) for key in data.keys(): if pm.objExists(key): deformer = Deformer(pm.PyNode(key)) print 'Loading weights for deformer:\t%s'%deformer for deformedShape in data[key].keys(): if pm.objExists(deformedShape): print '\tLoading deformer weights on shape:\t%s'%deformedShape deformedTransform = pm.PyNode(deformedShape).getParent() #print data[key][deformedShape] deformer.setWeights(data[key][deformedShape], deformedTransform) else: pm.warning('Object %s does not exist to apply deformer weights to...skipping'%deformedShape) else: pm.warning('Deformer %s doesn\'t exist...skipping'%key)
def rig_makeCtrlLabel(label): '''Creates a control that is displayed in customized choice of letters Args: label (string): the name of the desired control/visual display text Returns (pm.nt.Transform): returns the display control object Example Usage: rig_makeCtrlLabel("display") ''' if not pm.objExists(label + "_CTRL"): txt_crv=pm.PyNode( pm.textCurves(ch=0,t=label,f="Courier")[0] ) curves=[] i=1 for crvShp in pm.ls(txt_crv.getChildren(ad=True), et="nurbsCurve"): crvTrm = crvShp.getParent() crvShp.getParent().setParent(w=True) pm.makeIdentity(crvShp.getParent(),apply=True,s=1,r=1,t=1,n=0) crvTrm.rename("display_%02d_CRV" % i) curves.append(crvTrm) i+=1 displayCtrl=rig_combineCurves(curves,label+'_CTRL') pm.delete(txt_crv) displayCtrl.centerPivots() pm.move(displayCtrl, (0,0,0), rpr=True) pm.makeIdentity(displayCtrl,apply=True,s=1,r=1,t=1,n=0) displayGrp=pm.group(em=1,n=(label + "Offset_GRP")) displayCtrl.setParent(displayGrp) for displayCtrlShape in displayCtrl.listRelatives(shapes=True, fullPath=True): pm.setAttr(displayCtrlShape + ".overrideEnabled", 1) pm.setAttr(displayCtrlShape + ".overrideColor",17) rig_ctrlLock([displayCtrl], ["tx","ty","tz","rx","ry","rz","sx","sy","sz","v"], setKeyable=False, lock=True) return displayCtrl else: pm.error("That control already exists smarty pants!\n")
def __init__(self, light_obj, parent): self.labelWidth = (1,75) # Case 1: A list of light objects, to be made into a group for quick editing if len(light_obj): self.groupMode = True # If the input is a list of light objects, check that they are # all of the same type if self.checkTypes(light_obj): self.lightList = light_obj self.name = [(l.name + ", ") for l in self.lightList] else: pm.error('Cannot group lights of different types.') # Case 2: A single Light object, with a valid .type attribute elif light_obj.type: self.groupMode = False self.light = light_obj self.name = light_obj.name # The business: build the UI element, either as a single element linked # to multiple identical lights (Case 1: groupMode), # or a single element per light (Case 2: not groupMode) if self.groupMode: self.build(self.lightList, parent) elif not self.groupMode: self.build(self.light, parent)
def getRelativeArt(path='', name=''): """ Gets the relative art path of given path. If path not given will use current scene path. Args: path (string): Path to get relative art directory of. name (string): If given, will change the name of the file to the given name. Returns: (string): Path relative to art directory set through settings. """ if not path: path = pm.sceneName() if not path: pm.error('Scene is not saved! ') art_directory = store.get(pcfg.art_directory) if not path.startswith(art_directory): pm.error(path + ' is not in the art directory: ' + art_directory) if name: directory = os.path.dirname(path) old_name, extension = os.path.splitext(os.path.basename(path)) path = os.path.join(directory, name + extension) return path.lstrip(art_directory)
def create_tentacleSystem(self): jnt = pm.ls(selection=True) if not jnt: pm.error('Select a joint to create system') numFollicles = self.numFollicle_spinBox.value() name = self.name_lineEdit.text() if self.center_radioButton.isChecked(): side = None elif self.left_radioButton.isChecked(): side = 'left' else: side = 'right' if name: TipName = naming.TipName(base=name, side=side, suffix='bnd') else: TipName = naming.TipName(name=jnt[0]) tailTentacleSystem.TailTentacleSystem(startJnt=jnt[0], name=TipName, numFollicles=numFollicles, muscle=False, slide=False, wave=False, scale=False)
def export(self): # where to save file? if not self.set_export_path(): return # verify if anything is selected selection = pm.ls(sl=True) if not selection: pm.confirmDialog(title='No objects selected', message='Please select one or more object(s) to export.', button=['OK'], defaultButton='OK') self.original_selection = None return self.original_selection = pm.ls(sl=True) time_range = self.get_time_range() if time_range is None: pm.error('Could not determine time range.') return try: cycle_check = pm.cycleCheck(q=True, evaluation=True) pm.cycleCheck(evaluation=False) # if "bake animation" is checked if self.bake_animation_checkbox.isChecked(): self.bake(time_range) else: self.export_fbx(time_range) pm.cycleCheck(evaluation=cycle_check) except Exception as e: sys.stdout.write(str(e) + '\n')
def getGameExport(name=''): """ Gets the game path for the given scene. If no scene open, will use game root directory. Args: name (string): Name of file to return. Returns: (string): Full path with given name. """ scene_path = pm.sceneName() game_directory = store.get(pcfg.game_directory) relative_directory = '' if not game_directory: pm.error( 'Game directory is not set. Please use "Piper>Export>Set Game Directory" to set export directory.' ) if scene_path: source_directory = os.path.dirname(scene_path) art_directory = store.get(pcfg.art_directory) # gets the relative path using the art directory if scene_path.startswith(art_directory): relative_directory = source_directory.lstrip(art_directory) else: pm.warning( scene_path + ' is not in art directory! Returning game directory root.') export_path = os.path.join(game_directory, relative_directory, name).replace('\\', '/') return export_path
def createCmd(*args, **kwargs): ''' create cloth geometry cache ''' kx = kxTool.KXTool() kx.getSceneName() sceneName = kx.sceneName scenePath = kx.scenePath outputGrpName = 'output_Grp' if pm.objExists(outputGrpName): outputGrp = pm.PyNode(outputGrpName) else: pm.error("Maya Node does not exist: {0}".format(outputGrpName)) outputGeos = outputGrp.getChildren() for geo in outputGeos: cacheFile = "{path}/{scene}/{name}.mcc".format(path=scenePath.replace( 'scene', 'cache/nCache'), scene=sceneName, name=geo.name()) cache.exportMCCache(geo, cacheFile) cache.importMCCache(geo, cacheFile)
def importMixamoFbx(self): print "importMixamoFbx" pm.newFile(f=1) if self.fbxFile: if os.path.isfile(self.fbxFile): # import the FBX file pm.mel.eval('FBXImport -f "' + (self.fbxFile) + '"') # clean its namespace removeNamespace() # self.logger.info('Imported file %s',self.fbxFile) hips = pm.ls("Hips", type="joint") # add root joint for scale rootJnt = pm.joint(n="Root") pm.parent(hips[0], rootJnt) # self.logger.info('Added root joint %s',rootJnt) # clean up textures self.cleanUpTextures() pm.currentUnit(t="ntsc") # add shadow plane return 1 else: pm.error("Fbx file %s doesn't exist" % self.fbxFile) return 0 else: pm.error("No file was given") return 0
def _removeInBetweenNode(self): args = pm.ls(sl=True) for arg in args: #store the connections arg_inputs_raw = arg.listConnections(scn=True, s=False, p=True) arg_outputs = arg.listConnections(scn=True, d=False, p=True) print arg_outputs print arg_inputs_raw #check if there are no connections on either side if not len(arg_outputs) or not len(arg_inputs_raw): pm.error('Object is not connected on both sides numbnuts') #sort out unliked node types arg_inputs=[] for arg_input in arg_inputs_raw: for not_accept in ['initial', 'default']: add=1 if not_accept in arg_input.name(): add=0 break if add: arg_inputs.append(arg_input) #remove the old connection input arg.listConnections(c=True,d=False,p=True)[0][0].disconnect() #connect the two originals if they're the same type print "input is %s, output is %s" % (arg_inputs[0], arg_outputs[0]) print arg_inputs[0].type() print arg_outputs[0].type() if (arg_inputs[0].type() == arg_outputs[0].type()): arg_outputs[0].connect(arg_inputs[0], f=True) else: pm.error('Connections don\'t match!', sl=True)
def exportSelectionAsABC(): # check for AbcExport command if not 'AbcExport' in dir(pm): pm.error('AbcExport: command not found.') return # retrieve all selected node paths selection = pm.ls(sl=True, recursive=True, dagObjects=True) if not selection: return nodePathtoExport = [] for n in selection: if n.type() != 'transform': nodePathtoExport.append(n.getParent().fullPath()) # get out file path from user outfile = pm.fileDialog2(fileMode=0) if not outfile: return # ensure we use a '*.abc' file extension outfile = os.path.splitext(outfile[0])[0]+'.abc' # build the AbcExport command exportCmd = '-worldSpace -attr mvg_imageSourcePath -attr mvg_intrinsicParams -file %s -uvWrite'%outfile for p in nodePathtoExport: exportCmd += ' -root %s'%p exportCmd = ''' import pymel.core as pm pm.AbcExport(j="%s")'''%exportCmd pm.evalDeferred(exportCmd)
def make_pick_walk_button_click(name): button = main_buttons[name] if not button: raise NameError("Invalid button: " + name) direction = "" if name == UP_BUTTON: direction = "up" elif name == DOWN_BUTTON: direction = "down" elif name == LEFT_BUTTON: direction = "left" elif name == RIGHT_BUTTON: direction = "right" else: raise NameError("Invalid button: " + name) attr_name = dir_to_attr(direction) centre_obj = main_buttons[CENTRE_BUTTON] centre_obj_name = centre_obj.getLabel() print centre_obj_name print rad_pick_walk_mode if pm.objExists(centre_obj_name): if rad_pick_walk_mode == CREATE_MODE_NAME: selection = pm.ls(selection=True) if selection: if not pm.attributeQuery( attr_name, node=centre_obj_name, exists=True): pm.addAttr(centre_obj_name, longName=attr_name, attributeType="message") if centre_obj_name == selection[0]: pm.confirmDialog( message="Can't pickwalk to itself, silly...") pm.error("Can't pickwalk to self, silly...") else: make_pick_walk(centre_obj_name, selection[0], direction) else: label = button.getLabel() if label != "blank": result = pm.confirmDialog( message= "You have nothing selected. Do you want to clear the " + direction + " direction for " + centre_obj_name + "?", button=["Yes", "No"], cancelButton="No") if result == "Yes": connections = pm.listConnections(centre_obj_name + "." + attr_name) if connections: break_pick_walk(centre_obj_name, connections[0], direction) elif rad_pick_walk_mode == NAV_MODE_NAME: rad_pick_walk(direction, False) add_selected_obj_to_middle() update_pick_walk_window()
def replaceSuffix(suffix_replace, args=[], validSuffix=False): """ Function: To remove a suffix and replace it State: validSuffix = False: do not attempt to validate the suffix, replace no matter validSuffix = True: check if the suffix is valid and replace suffix if it is or append suffix if not Returns: list or string depending on type(args) """ outArgs = [] if args == []: args = pm.ls(sl=True) # if it's not a string do this if not isinstance(args, basestring): for arg in args: # if the arg has no valid suffix (and we're checking for that), just append the suffix if detectSuffix(arg) == None and validSuffix: outArgs.append(arg + "_" + suffix_replace) else: outArgs.append("_".join(arg.split("_")[:-1]) + "_" + suffix_replace) return outArgs[0] # otherwise it's a string so do this elif isinstance(args, basestring): # if it has no valid suffix (and we're checking for that) just append it to the end if detectSuffix(args) == None and validSuffix: return args + "_" + suffix_replace # if it has no underscores elif len(args.split("_")) == 1: return args + "_" + suffix_replace # otherwise replace the suffix as normal else: return "_".join(args.split("_")[:-1]) + "_" + suffix_replace else: pm.error("Argument not a string or a list, please fix your codezz")
def _attachRenderProxy( self, objects ): path = self.fileInput.text() proxy = [] if os.path.isdir(path): for file in glob.glob(path+"/*.mib"): bipx = pm.createNode('mip_binaryproxy',n=file.split('/').pop().split('.')[0]+'_BINARYPROXY') bipx.object_filename.set(file) proxy.append(bipx) else: bipx = pm.createNode('mip_binaryproxy',n=path.split('/').pop().split('.')[0]+'_BINARYPROXY') bipx.object_filename.set(path) proxy.append( bipx ) if not objects: for prx in proxy: objects.append(pm.polyCube()) for arg in objects: if len(proxy)==0: pm.error('No proxies found in folder. Womp Womp.') elif len(proxy)>1: print 'more than one proxy' #turn the lo geometry shader on arg.miExportGeoShader.set(1) #connect the proxy to the lo's geo shader proxy[random.randint(0,len(proxy)-1)].outValue.connect(arg.miGeoShader, f=True) else: print 'one proxy' #turn the lo geometry shader on arg.miExportGeoShader.set(1) #connect the proxy to the lo's geo shader proxy.pop().outValue.connect(arg.miGeoShader, f=True)
def getChain(start, end=None): """ Gets all the transforms parented between the given start and end transforms, inclusive. Args: start (pm.nodetypes.Transform): Top parent of the chain. end (pm.nodetypes.Transform): The child to end search at. If none given, will return only the given start. Returns: (list): All the transforms between given start and given end, including the given transforms in order. """ if not end: return [start] parents = end.getAllParents() if start not in parents: pm.error(start.nodeName() + ' is not a parent of: ' + end.nodeName()) parents.reverse() start_index = parents.index(start) chain = parents[start_index:] chain.append(end) return chain
def FindPVposition( objs=pm.ls(sl=True) ): if not len(objs) == 3: pm.error( 'ehm_tools...findPVposition: objs arguments takes exactly 3 objects. %s was given.'%len(objs) ) base = objs[0] mid = objs[1] tip = objs[2] A = dt.Vector( pm.xform( base, q=True, t=True, ws=True ) ) B = dt.Vector( pm.xform( mid, q=True, t=True, ws=True ) ) C = dt.Vector( pm.xform( tip, q=True, t=True, ws=True ) ) AC = C - A AB = B - A D = A + ( (dt.dot(AB,AC.normal())) * AC.normal() ) # AB projected on AC position = B + B - D if (position[0] - B[0] < 0.001) and (position[1] - B[1] < 0.001) and (position[2] - B[2] < 0.001): pm.warning( 'ehm_tools...FindPVposition: Limbs were straight. None was returned!' ) return None else: return position
def copyAnim(self): animFiles = [] f = '' wipPath = self.wipFolderEdit.text() selectedItems = self.wipAnimTable.selectedItems() if len(selectedItems): for item in selectedItems: if item.column() == 0: anim = item.text() print anim src = os.path.abspath(os.path.join(wipPath, anim)) destPath = wipPath.replace('01_wip', '03_preview') dest = os.path.abspath(os.path.join(destPath, anim)) if os.path.isfile(src): if os.path.isfile(dest): pm.warning( 'Preview file exists already, will not overwrite ( save new version ? )' ) else: try: shutil.copyfile(src, dest) except: pm.error('Could not copy anim file to preview') self.bdPopulateFiles()
def matchFollToObj(sel=None): """Select joint then follicle, and set the follicle's UVs to most closely match the joint's position. (Made when unable to mmb drag UV values.)""" if not sel: sel = pmc.ls(sl=True) try: j = sel[0] f = sel[1].getShapes()[0] except IndexError: pmc.error("Select target object then follicle.") return try: surf = f.inputSurface.listHistory(exactType="nurbsSurface")[0] except IndexError: pmc.error("Can't find surface of follicle.") # pymel bug in "\internal\factories.py" # surf.closestPoint(j.getTranslation(ws=True), space="world") cpos = pmc.nodetypes.ClosestPointOnSurface() surf.ws.connect(cpos.inputSurface) loc = pmc.spaceLocator() loc.translate.connect(cpos.inPosition) pmc.parentConstraint(j, loc, mo=False) f.pu.set(cpos.parameterU.get()) f.pv.set(cpos.parameterV.get()) pmc.delete(cpos, loc)
def importMaterialProperties(filePath, target): """ Import material properties to selected cloth node from file. :param target: :param filePath: :return: """ target = getQLClothNode(target) if not target: pm.warning("Please select a cloth object " "to import material properties to.") return try: with open(filePath, 'r') as f: attrs = json.load(f) except: pm.error("Error loading material property file.") return for attr, value in attrs.iteritems(): if value[1] != "string": pm.setAttr("{0}.{1}".format(target.name(), attr), value[0]) else: value[0] = "" if not value[0] else value[0] pm.setAttr("{0}.{1}".format(target.name(), attr), value[0], type="string")
def resetMuscleCtrls(surf, pts): """Repositions the neutral pose for a muscle spline system on given surface. User selects surface points for each control object in the muscle setup, and this moves and re-orients the controls to those points.""" try: dfm = surf.history(type="cMuscleSplineDeformer")[0] spl = surf.history(type="cMuscleSpline")[0] except IndexError: pmc.error( "Surface {0} has no muscle system associated with it.".format( surf.name())) # turn off deformer so I can move controls without the surface changing on me dfm.envelope.set(0) ctrls = [cd.insertMatrix.inputs()[0] for cd in spl.controlData] if len(ctrls) != len(pts): pmc.error( "Number of selected points must match the number of spline controls!" ) # must positions and normals BEFORE changing anything on the surface # zip an unpacked list comp - slick way to get two lists out of one comp positions, normals = zip(*[(surf.getPointAtParam(*pt, space="world"), surf.normal(*pt, space="world")) for pt in pts]) for i, ctrl in enumerate(ctrls): ctrl.setTranslation(positions[i], space="world") # positions must all be finalized before orientation can be fixed for i, ctrl in enumerate(ctrls): print(pts[i], normals[i]) print(positions[i], ctrl.getTranslation(space="world")) if i: # NOT first ctrl - negative aim vetor at previous aimObj = ctrls[i - 1] aimVec = (0, -1, 0) else: aimObj = ctrls[i + 1] aimVec = (0, 1, 0) pmc.delete( pmc.aimConstraint(aimObj, ctrl, aim=aimVec, u=(1, 0, 0), wut="vector", wu=normals[i])) # reset .controlDataBase and length pmc.mel.eval("cMS_resetSplineDefBasePose(\"{0}\")".format(dfm)) l = spl.curLen.get() spl.lenDefault.set(l) spl.lenSquash.set(l / 2) spl.lenStretch.set(l * 2) dfm.envelope.set(1)
def rig_attachToCurve(obj, crv, createGroup=True, constrainParent=False): ''' attaches an object to a curve Args: obj (pm.PyNode): Object to constrain to crv (pm.nt.NurbsCurve): Curve to get info from constrainParent (bool): if we constrain to the object's parent instead of the object Returns (pm.shadingNode.pointOnCurveInfo): pointOnCurveInfo node that results Usage: rig_attachToCurve(pm.ls(sl=True), pm.PyNode('curve1'), createGroup=False, constrainParent=False) for obj in pm.ls(sl=True): rig_attachToCurve(obj, pm.PyNode('curve1'), createGroup=False, constrainParent=False) ''' passArgs=[None,None] if constrainParent and obj.getParent(): passArgs = [obj.getParent(),obj.getParent()] elif not obj.getParent() and constrainParent: pm.error('Could not find a parent for object %s'%obj) return None elif createGroup: grp=pm.group(em=True, n='_'.join([obj.name(),crv.name(),'Offset_GRP'])) grp.inheritsTransform.set(0) grp.t.set(obj.getRotatePivot(space='world')) grp.r.set(pm.xform(obj, q=True, ro=True, a=True, ws=True)) pm.addAttr(grp, ln='connectPCObj', dt='string', k=True) passArgs=[obj,grp] else: passArgs=[obj, obj] poci = rig_getClosestPointNode(passArgs[0], crv, cpoc=True) mdpma = rig_connectPociWithOffset(poci, passArgs[1]) pm.tangentConstraint(crv, passArgs[1]) return [passArgs[1], poci] + mdpma
def selectKeyAttr(): window = QtWidgets.QWidget(qt.getMayaWindow()) window.setWindowFlags(QtCore.Qt.Window) window.resize(300, 500) layout = QtWidgets.QVBoxLayout(window) widget = QtWidgets.QPlainTextEdit(window) sels = pm.selected() try: print sels[0] except: pm.error('Nothing is selected') else: part = sels[0].split('.') widget.insertPlainText(part[0] + " = [\n") for sel in sels: widget.insertPlainText("\t'" + sel + "',\n") widget.insertPlainText("\t]") layout.addWidget(widget) button = QtWidgets.QPushButton('print', window) layout.addWidget(button) button.clicked.connect(main) window.show()
def copyAnim(self): animFiles = [] f='' wipPath = self.wipFolderEdit.text() selectedItems = self.wipAnimTable.selectedItems() if len(selectedItems): for item in selectedItems: if item.column() ==0: anim = item.text() print anim src = os.path.abspath(os.path.join(wipPath,anim)) destPath = wipPath.replace('01_wip','03_preview') dest = os.path.abspath(os.path.join(destPath,anim)) if os.path.isfile(src): if os.path.isfile(dest): pm.warning('Preview file exists already, will not overwrite ( save new version ? )') else: try: shutil.copyfile(src, dest) except: pm.error('Could not copy anim file to preview') self.bdPopulateFiles()
def exportSelectionAsABC(): # check for AbcExport command if not 'AbcExport' in dir(pm): pm.error('AbcExport: command not found.') return # retrieve all selected node paths selection = pm.ls(sl=True, recursive=True, dagObjects=True) if not selection: return nodePathtoExport = [] for n in selection: if n.type() != 'transform': nodePathtoExport.append(n.getParent().fullPath()) # get out file path from user outfile = pm.fileDialog2(fileMode=0) if not outfile: return # ensure we use a '*.abc' file extension outfile = os.path.splitext(outfile[0])[0] + '.abc' # build the AbcExport command exportCmd = '-worldSpace -attr mvg_imageSourcePath -attr mvg_intrinsicParams -file %s -uvWrite' % outfile for p in nodePathtoExport: exportCmd += ' -root %s' % p exportCmd = ''' import pymel.core as pm pm.AbcExport(j="%s")''' % exportCmd pm.evalDeferred(exportCmd)
def locInst_locSel(self): ''' Function: Takes a locator and instances it's target (set as an extra attr) Then sets the location of the instance. If the instance already exists it uses that Returns: None ''' locs = pm.ls(sl=True) grp_name = "_".join(locs[0].getParent().split('_')[:-2])+"_INST_GRP" print grp_name print pm.objExists(grp_name) if pm.objExists(grp_name): pm.PyNode(grp_name) else: grp=pm.group(em=True, n=grp_name) for loc in locs: #if the target isn't an instance create it targetExists = pm.ls(loc.target.get().split('_')[:-1][0]!='GEO', r=True, type='transform')[0] instanceExists = pm.ls(loc.target.get().split('_')[:-1][0]!='INST', r=True, type='transform')[0] if not instanceExists and targetExists: matchObj = pm.ls(loc.target.get(), r=True, type='transform')[0] instance = pm.instance(matchObj, n=('_'.join(matchObj.split('_')[:-1])+'_INST'))[0] #set the target to the new instance since it was created loc.target.set(instance) elif pm.objExists(loc.target.get()) and pm.objExists('_'.join(target.split('_')[:-1])+'_INST'): pm.error('Neither a GEO nor an INST object exists with this name') #otherwise initialize the instance variable else: instance = pm.PyNode('_'.join(arg.split('_')[:-1])+'_INST') loc.t.connect( instance.t ) loc.r.connect( instance.r ) loc.s.connect( instance.s ) instance.setParent(grp)
def create_follicle(transform, name=None, uPos=0.0, vPos=0.0): """ Create a follicle at u and v position (if polygon mesh, needs UV coords) Args: transform (pm.nt.Transform): PyNode transform of mesh Returns (pm.nt.Follicle): the resulting follicle Usage: create_follicle(pm.ls(sl=True)[0], uPos=0.5, vPos=0.5) """ shape = transform.getShape() print type(shape) == pm.nodetypes.Mesh if type(shape) not in [pm.nodetypes.Mesh, pm.nodetypes.NurbsSurface]: pm.error("You need to specify a mesh of type nurbs or poly, incorrect mesh specified") if not name: name = transform.name() + "_FOL" follicle_shp = pm.createNode("follicle", name=name) follicle_xfm = follicle_shp.getParent() # One different connection for poly/nurbs then all connections # (The polygons will need to have UVs in order to work.) if type(shape) == pm.nodetypes.Mesh: shape.outMesh.connect(follicle_shp.inputMesh) else: shape.local.connect(shape.inputSurface) shape.worldMatrix[0].connect(follicle_shp.inputWorldMatrix) follicle_shp.outRotate.connect(follicle_xfm.rotate) follicle_shp.outTranslate.connect(follicle_xfm.translate) # Now setup attributes follicle_shp.parameterU.set(uPos) follicle_shp.parameterV.set(vPos) follicle_xfm.t.lock() follicle_xfm.r.lock() return follicle
def cbsHookup(*args, **kwargs): base = kwargs.setdefault('base') #(string) The base mesh for the character bs = kwargs.setdefault('bs') #(string) The blendshape deformer to which the shape should be added (if blank, a new deformer will be created shape = kwargs.setdefault('shape') #(string) The new target to add to the blendshape driver = kwargs.setdefault('driver') #(string) Node and attribute to have drive the blendshape target weight driveRange = kwargs.setdefault('driveRange', [0, 1]) #(2 float list) The range of the driver to go from 0-1. [0]=target weight of 0, [1]=weight of 1 tan = kwargs.setdefault('tan', ['spline', 'spline']) # (2 string list) The tangent types for the set driven keys. [0]=start, [1]=end infinity = kwargs.setdefault('infinity', [False, False]) # (2 bool list) sets whether or not to give the set driven key pre or post infinity. [0]=pre, [1]=post #create a blendshape deformer if one hasn't been specified if not bs: bs = pm.blendShape(base, frontOfChain=True, n='%s_corrective_bs'%base)[0] #add the new target to the blendshape targs = pm.blendShape(bs, q=True, t=True) for targ in targs: if str(shape).split('|')[-1] == str(targ).split('|')[-1]: pm.error('It appears you already have a blendshape target named %s in the node %s. Please rename the new target with a unique name.'%(shape, bs)) pm.blendShape(bs, e=True, t=[base, len(targs), shape, 1]) #set up the set driven key to drive the blendshape pm.setDrivenKeyframe('%s.%s'%(bs, shape), cd=driver, dv=driveRange[0], v=0, itt=tan[0], ott=tan[0]) pm.setDrivenKeyframe('%s.%s'%(bs, shape), cd=driver, dv=driveRange[1], v=1, itt=tan[1], ott=tan[1]) #set up infinity if requested if infinity[0]: pm.setInfinity('%s.%s'%(bs, shape), pri='linear') if infinity[1]: pm.setInfinity('%s.%s'%(bs, shape), poi='linear') return bs
def _get_vert_weight_dict(): sel = pm.ls(sl=True) if (len(sel) != 1): pm.error('Please select ONE mesh transform') mesh = sel[0] if (mesh.type() != 'transform'): pm.error('Please select a MESH TRANSFORM') # get the skincluster skinclusters = [] for node in pm.listHistory(mesh): if (type(node) == pm.nodetypes.SkinCluster): skinclusters.append(node) vertweightdict = {} for skincluster in skinclusters: for joint in skincluster.getWeightedInfluence(): verts, weights = skincluster.getPointsAffectedByInfluence(joint) for i, vert in enumerate(verts[0]): weight = weights[i] if (not vert in vertweightdict.keys()): vertweightdict[vert] = [] vertweightdict[vert].append((joint, weight)) return vertweightdict, skinclusters
def convertLightmapSequence(ast, aet, res, occres, fileFormat, falloff=0.0): '''The first selected object will bake occlusion to it, with all other selected as inputs It automatically bakes to the "maya/sourcimages/occlusionBake/" folder and auto-versions Args: ast (int): animation start time aet (int): animation end time res (int): resolution for the map to bake occres (int): resolution for the occlusion fileFormat (string): accepts: TIFF,IFF,JPG,RGB,RLA,TGA,BMP,HDR falloff (float): float for controlling AO falloff Returns (None) Example: convertLightmapSequence(1,5,256,32) ''' sel=pm.ls(sl=True, type='transform') extension = {'TIFF':0,'IFF':1,'JPG':2,'RGB':3,'RLA':4,'TGA':5,'BMP':6,'HDR':7} pathBase = "/jobs/{JOB}/{SHOT}/{MAYA}/{OBJ}".format(JOB = os.getenv('JOB'), SHOT = os.getenv('SHOT'), MAYA='maya/sourceimages/occlusionBake', OBJ=sel[0]) #Create and add objects to the bakeSet if len(sel)>0: if not pm.objExists('tmpBakeSet'): bakeSet = pm.createNode('textureBakeSet', n='tmpBakeSet') else: bakeSet = pm.PyNode('tmpBakeSet') else: pm.error('No objects selected...') for obj in sel: bakeSet.add(obj.getShape()) #Set the shit for the bakeSet bakeSet.xResolution.set(res) bakeSet.yResolution.set(res) bakeSet.colorMode.set(3) bakeSet.occlusionRays.set(occres) bakeSet.bakeToOneMap.set(1) bakeSet.fileFormat.set(extension[fileFormat]) bakeSet.occlusionFalloff.set(falloff) #Version up the folder and now that's the pathBase if not os.path.exists(pathBase): os.makedirs(pathBase) folders = [folder for folder in os.listdir(pathBase) if os.path.isdir(os.path.join(pathBase, folder))] version = 'v%03d'% (len(folders)+1) if len(folders)==0: version = 'v001' pathLgt = os.path.join(pathBase,version) pathBase = os.path.join(pathBase,version,'lightMap') if not os.path.exists(pathBase): os.makedirs(pathBase) #Now finally bake for frame in range(ast,aet+1): bakeSet.prefix.set('occBake%04d'%frame) pm.currentTime(frame) pm.convertLightmap('initialShadingGroup', sel[0], camera='persp', prj=pathLgt, sh=True, bo=bakeSet) #Get dat selection bak pm.select(sel, r=True)
def _finalize(self, type): nparticles = pm.ls(sl=True) for nparticle in nparticles: if pm.objectType(nparticle.getShape()) != 'nParticle': nparticles.remove(nparticle) print nparticles[0].getShape() nparticle=[nparticles[0], nparticles[0].getShape()] emitterCons = nparticle[1].listConnections(type='pointEmitter') if emitterCons: emitter = nparticle[1].listConnections(type='pointEmitter')[0] else: pm.error('The particle doesn\'t have an emitter connected') if type==0: #set the max particles + emitter to max nparticle[1].maxCount.set(nparticle[1].getCount()) emitter.rate.set(20000) #arbitrary high value print 'Setting max particle count for %s to %s' % (nparticle[1].name(), nparticle[1].getCount()) mm.eval("setNClothStartState") mm.eval("performSetNClothStartState(1)") if type==1: #reset the max particles + emitter rate mm.eval("clearNClothStartState") mm.eval("performSetNClothStartState 0") nparticle[1].maxCount.set(-1) emitter.rate.set(5000)
def _get_vert_weight_dict() : sel = pm.ls( sl=True ) if( len( sel ) != 1 ) : pm.error( 'Please select ONE mesh transform' ) mesh = sel[0] if( mesh.type() != 'transform' ) : pm.error( 'Please select a MESH TRANSFORM' ) # get the skincluster skinclusters = [] for node in pm.listHistory( mesh ) : if( type( node ) == pm.nodetypes.SkinCluster ) : skinclusters.append( node ) vertweightdict = {} for skincluster in skinclusters : for joint in skincluster.getWeightedInfluence() : verts, weights = skincluster.getPointsAffectedByInfluence( joint ) for i, vert in enumerate( verts[0] ) : weight = weights[i] if( not vert in vertweightdict.keys() ) : vertweightdict[ vert ] = [] vertweightdict[ vert ].append( ( joint, weight ) ) return vertweightdict, skinclusters
def hookupRun(*args): baseTf, bsMen, driverTf, attrTf, zeroWtFf, oneWtFf, itMen, otMen, priCb, poiCb, ph = args #Check to make sure something's selected if not pm.ls(sl=True): pm.error('Nothing is selected') #Interpreting the blendshape menu if bsMen.getValue() == '<Create New>': bs = None else: bs = bsMen.getValue() bs = na_bsCorrectiveSculpt.cbsHookup( base=baseTf.getText(), bs=bs, shape=pm.ls(sl=True)[0], driver='%s.%s' % (driverTf.getText(), attrTf.getText()), driveRange=[zeroWtFf.getValue(), oneWtFf.getValue()], tan=[itMen.getValue(), otMen.getValue()], infinity=[priCb.getValue(), poiCb.getValue()]) if bsMen.getValue() == '<Create New>': pm.menuItem(p=bsMen, l=str(bs)) bsMen.setSelect(bsMen.getNumberOfItems())
def run_cmd_ui(self, *arg): if self.py_path: self.clear_script_reporter() self.cmds[0] = self.user_cmd cmd = "" with codecs.open(self.py_path, encoding="utf-8", mode="r") as f: cmd = f.read() if cmd: cmd += u"\n" + self.user_cmd with codecs.open(self.exec_path, encoding="utf-8", mode="w") as f: f.write(cmd) try: execfile(self.exec_path, globals()) except Exception, error: traceback.print_exc(file=sys.stdout) if "encoding declaration in Unicode string" == error.args[0]: try: exec(cmd.encode("cp850")) except Exception, error: pmc.error(error) traceback.print_exc(file=sys.stdout) else: pmc.error(error)
def __init__(self, skinCluster=None, transform=None, verbose=0): #Conditional argument setting if verbose: print dir(skinCluster) if transform: if transform.getShape().listHistory(type='skinCluster'): skinCluster = transform.getShape().listHistory(type='skinCluster')[0] if verbose: print 'Found skinCluster connected to transform: %s'%skinCluster else: pm.warning('no skinCluster found on transform %s'%transform) skinCluster = None if transform==None and skinCluster==None: pm.error('You have to specify either a skinCluster or a transform') #generating information self.skinCluster = skinCluster if self.skinCluster: self.node = self.skinCluster.node() self.shape = self.skinCluster.getGeometry()[0] self.transform = self.shape.getParent() self.outputMesh = self.skinCluster.getOutputGeometry() self.inputMesh = self.skinCluster.getInputGeometry() self.weights = self._convertWeightsToList( self.skinCluster.getWeights( self.shape ) ) self.influences = self.skinCluster.getInfluence() else: self.node = None self.shape = None self.transform = None self.outputMesh = None self.inputMesh = None self.weights = [] self.influences = []
def bdMirrorCtrl(): selection = pm.ls(sl=True) if selection: try: source,target = pm.ls(sl=True) except: pm.warning('Select source and target controller') return sourceShape = source.getShape() if sourceShape.type() != 'nurbsCurve': pm.error('Selected source is not nurbs curve') return targetCvsPos = [ (dt.Point(-x.x, x.y, x.z) ) for x in sourceShape.getCVs(space='world')] targetShape = target.getShape() if targetShape.type() != 'nurbsCurve': pm.error('Selected target is not nurbs curve') return targetShape.setCVs(targetCvsPos,space='world') targetShape.updateCurve() else: print 'Select source and target controller' '''
def setWeightsAtIndex(self, index, weights, autoAddInfluence=True): ''' Returns the weight dict for the given index of the object (verts/cvs do not matter) Args: index (int): index of shape node component you want queried weights (list[list]): weights stored as: [[influence (string), weight (float)], w2...w(n)] autoAddInfluence (Boolean): detects whether influence wasn't added and auto-adds if not Returns: (dict): dictionary of {influence:weights} ''' # TODO: allow this to input dict weights since that's way easier to manipulate. # Error checking if 0 > index or index > len(self.weights) -1: pm.error('Index does not exist on skinCluster for given shape') weightTotal=0 for weight in weights: if not type(weight) == list: pm.error('Unsupported format for input weights, please read help') weightTotal+=weight[1] if weightTotal > 1: pass #this used to error check, but maya normalizes anyways. pm.warning('Your input weight values you surpassed 1, normalization will occur. Results may vary') component=None if self.shape.type() == 'nurbsCurve': component = self.shape.cv[index] if self.shape.type() == 'mesh': component = self.shape.vtx[index] if autoAddInfluence: for weight in weights: sourceInfluence = weight[0] if sourceInfluence not in self.influences: self.addInfluence(sourceInfluence) pm.skinPercent(self.skinCluster, component, transformValue=(weights)) self._update() return True
def importMixamoFbx(self): print 'importMixamoFbx' pm.newFile(f=1) if self.fbxFile: if os.path.isfile(self.fbxFile): # import the FBX file pm.mel.eval('FBXImport -f "' + (self.fbxFile) + '"') # clean its namespace removeNamespace() # self.logger.info('Imported file %s',self.fbxFile) hips = pm.ls("Hips", type='joint') # add root joint for scale rootJnt = pm.joint(n='Root') pm.parent(hips[0], rootJnt) # self.logger.info('Added root joint %s',rootJnt) # clean up textures self.cleanUpTextures() pm.currentUnit(t='ntsc') # add shadow plane return 1 else: pm.error('Fbx file %s doesn\'t exist' % self.fbxFile) return 0 else: pm.error('No file was given') return 0
def findAttributeHolder(self): selection = pm.selected() heirarchy = pm.listRelatives(selection, ap=True) componentRoot = None attributeHolder = None while componentRoot == None: attributes = pm.listAttr(selection, userDefined=True) if attributes == None: heirarchy = pm.listRelatives(selection, ap=True) selection = heirarchy else: if 'componentRoot' in attributes: componentRoot = selection else: heirarchy = pm.listRelatives(selection, ap=True) selection = heirarchy if componentRoot != None: self.componentRoot = componentRoot children = pm.listRelatives(componentRoot, c=True) for x in children: attributes = pm.listAttr(x, userDefined=True) if attributes == None: continue else: if 'attributeHolder' in attributes: attributeHolder = x self.attributeHolder = attributeHolder else: self.componentRoot = componentRoot pm.error('Component Root not found') if attributeHolder == None: self.attributeHolder = attributeHolder pm.error('Attribute Holder not found')
def copyPlayblast(self): blastFiles = [] f = '' wipPath = self.wipFolderEdit.text() selectedItems = self.wipAnimTable.selectedItems() if len(selectedItems): for item in selectedItems: if item.text() == 'Yes': animFile = self.wipAnimTable.item(item.row(), 0).text() blastFile = self.hasPlayblast(animFile) wipBlastPath, blastFileName = os.path.split(blastFile) destPath = wipPath.replace('01_wip', '03_preview') dest = os.path.abspath( os.path.join(destPath, blastFileName)) if os.path.isfile(blastFile): if os.path.isfile(dest): pm.warning( 'Blast exists already, will not overwrite ( save new version ? )' ) else: try: print("copying") shutil.copyfile(blastFile, dest) except: pm.error( 'Could not copy blast file to preview')
def matchFKIK( self, objs=None, *args ): objs = pm.ls( sl=True ) for obj in objs: name = obj.name() # find out whether "FK" and "IK" in control names is lower case or upper case if ('IK' in name) or ('FK' in name): IK = 'IK' FK = 'FK' elif ('ik' in name) or ('fk' in name): IK = 'ik' FK = 'fk' else: pm.warning( "Make sure your controls have 'IK' or 'FK' in their name" ) continue if IK in name: # IKtoFK try: MatchTransform( folower=obj, lead=pm.PyNode(name.replace(IK,FK)) ) except: pass #pm.error( "The only difference between IK and FK control names must be 'IK' and 'FK', for example: 'L_hand_IK_ctrl' and 'L_hand_FK_ctrl'." ) elif FK in name: # FKtoIK try: obj.rotate.set( pm.PyNode(name.replace('FK_ctrl','IK_jnt')).rotate.get() ) obj.scale.set( pm.PyNode(name.replace('FK_ctrl','IK_jnt')).scale.get() ) except: try: obj.rotate.set( pm.PyNode(name.replace('FK_ctrl','IK_jnt')).rotate.get() ) obj.length.set( pm.PyNode(name.replace('FK_ctrl','IK_jnt')).scaleX.get() ) except: pm.error( "The only difference between FK control and IK joint names must be 'FK_ctrl' and 'IK_jnt', for example: 'L_hand_FK_ctrl' and 'L_hand_IK_jnt'." )
def importMap(target, filePath, attrList=None): """ import quoloth map from file. :param target: `PyNode` qualoth object to import map to :param filePath: `string` map file path :param attrList: `list` list of map attributes for import :return: """ targetType = getQLType(target) if targetType not in qlTypes: pm.warning("Please select a cloth or collider to import map.") return try: with open(filePath, 'r') as f: maps = json.load(f) except: pm.error("Error loading map file.") return attrList = mapAttrs if not attrList else attrList target = getQLClothNode(target) if targetType==qlTypes[0] \ else getQLColliderNode(target) for attr, mapValue in maps.iteritems(): if attr in attrList: pm.setAttr("{0}.{1}".format(target.name(), attr), mapValue)
def list_AllShaders(self, specObj, ignorID=False): """ :param specObj: specify object is the DAG Shape node :param ignorID: :return: return a dict ,key is the shader's name, key is a dict too """ # specObj = pm.selected()[0] print "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" if specObj.type() != u'mesh': specObj = specObj.getShape() print specObj.name() ls_sgs = specObj.listConnections(type='shadingEngine') sgs_opmt = [ ls_sgs[i] for i in range(len(ls_sgs)) if ls_sgs[i] not in ls_sgs[:i] ] shder_dict = {} for eachSG in sgs_opmt: try: get_shd = eachSG.attr('surfaceShader').listConnections()[0] except: pm.error( "The SG node doesn't be connected in surfaceShader Attribute!!!please Check!!" ) sd_nm_label = get_shd.name(stripNamespace=True) sg_shd_pair = {} if ignorID: sd_nm_label_spl = sd_nm_label.split('_') if len(sd_nm_label_spl) == 1: sd_nm_label = sd_nm_label_spl[0] else: sd_nm_label = '_'.join(sd_nm_label_spl[1:]) sg_shd_pair[get_shd] = eachSG shd_nm_label = self.re_nm(sd_nm_label, shder_dict) shder_dict[shd_nm_label] = sg_shd_pair return shder_dict
def storeDeformerWeights(selection=True, type='rig_vertSnap'): ''' Usage: storeDeformerWeights(selection=False) storeDeformerWeights(selection=True, type=['rig_vertSnap']) storeDeformerWeights(selection=False, type=['rig_vertSnap', 'wire']) ''' deformers = pm.ls(type=type) if selection: if len(pm.ls(sl=True))==0: pm.error('select something numbnuts!') deformers = pm.ls(sl=True)[0].listHistory(type='rig_vertSnap') vsFile = {} for deformer in deformers: vs = Deformer(deformer) vs.initializeWeights() if len(vs.weightsList) > 0: vsFile[deformer.name()] = vs.weightsList try: filename = os.path.join( pm.fileDialog2(cap='Select a folder to store the weights', fm=3, okc='Select')[0], 'deformerWeights.json' ) except: pm.error('Why did you cancel? :(') with open(filename, 'wb') as fp: print 'Storing weights in file:\n\t%s'%(filename) print '\t\tDeformers Stored:\n\t\t\t%s'%('\n\t\t\t'.join([deformer.name() for deformer in deformers])) json.dump(vsFile, fp, indent=4)
def matrixParent(sels): if len(sels) >= 3 or len(sels) <= 1: pm.error('Please select two') exSel = sels[0] inSel = sels[1] exSelPart = exSel.split('_') inSelPart = inSel.split('_') prcMmxName = pm.createNode( 'multMatrix', n='mmx_' + exSelPart[1] + '_Trs' + '_' + exSelPart[0] + inSelPart[0] + '_' + exSelPart[-3] + '_' + exSelPart[-2] + '_' + exSelPart[-1]) prcDmxName = pm.createNode( 'decomposeMatrix', n='dmx_' + exSelPart[1] + '_Trs' + '_' + exSelPart[0] + inSelPart[0] + '_' + exSelPart[-3] + '_' + exSelPart[-2] + '_' + exSelPart[-1]) pm.connectAttr(exSel + '.matrix', prcMmxName + '.matrixIn[0]') pm.connectAttr(exSel + '.parentMatrix', prcMmxName + '.matrixIn[1]') pm.connectAttr(inSel + '.parentInverseMatrix', prcMmxName + '.matrixIn[2]') pm.connectAttr(prcMmxName + '.matrixSum', prcDmxName + '.inputMatrix') pm.connectAttr(prcDmxName + '.outputTranslate', inSel + '.translate') pm.connectAttr(prcDmxName + '.outputScale', inSel + '.scale') pm.connectAttr(prcDmxName + '.outputRotate', inSel + '.rotate') pm.connectAttr(prcDmxName + '.outputShear', inSel + '.shear')
def importMixamoFbx(self) : print 'importMixamoFbx' pm.newFile(f=1) if self.fbxFile: if os.path.isfile(self.fbxFile): #import the FBX file pm.mel.eval( 'FBXImport -f "' + (self.fbxFile) + '"') #check for a default mesh in T-Pose. If found, replace geometry self.replaceGeometry() #clean its namespace removeNamespace() hips = pm.ls("Hips",type='joint') #add root joint for scale rootJnt = pm.joint(n='Root') pm.parent(hips[0],rootJnt) #clean up textures self.cleanUpTextures() pm.currentUnit(t='ntsc') return 1 else: pm.error('Fbx file %s doesn\'t exist'%self.fbxFile) return 0 else: pm.error('No file was given') return 0
def toVector(transform, invalid_zero=False, error=False): """ Converts given transform to a PyMel Vector. Args: transform (Any): Node or list to convert to Vector. invalid_zero (boolean): If True and given transform is not a valid type, will return a zero Vector. error (boolean): If given transform is not a valid type and given invalid_zero is False, will return error. Returns: (pm.dt.Vector): Vector of given transform. """ if isinstance(transform, (pm.nodetypes.Transform, str)): location = pm.dt.Vector(pm.xform(transform, q=True, ws=True, rp=True)) elif isinstance(transform, (list, tuple)): location = pm.dt.Vector(transform) elif isinstance(transform, pm.dt.Vector): location = transform else: # if we cant convert, return zero or error or pass and return given location if invalid_zero: location = pm.dt.Vector((0, 0, 0)) elif error: location = None pm.error( str(type(transform)) + ' is not a valid type to convert to Vector!') else: location = transform return location
def get_skin_cluster(ob): '''return skin cluster from ob, if cannot find raise error''' ob_shape = get_shape(ob) try: getSkin = [c for c in ob_shape.listHistory(type='skinCluster')] if getSkin: return getSkin[0] else: msg = '{} have no skin bind'.format(ob) return pm.error(msg) # if 'skinCluster' in connection.name(): # shape_connections = ob_shape.inputs(type=['skinCluster', 'objectSet']) # for connection in shape_connections: # # if 'skinCluster' in connection.name(): # if isinstance(connection, pm.nt.SkinCluster): # return connection # try_get_skinCluster = connection.listConnections(type='skinCluster') # if try_get_skinCluster: # return try_get_skinCluster[0] # else: # msg = '{} have no skin bind'.format(ob) # return pm.error(msg) except: msg = 'Cannot get skinCluster from {}'.format(ob) return pm.error(msg)
def constraint_store(): filepath = os.path.basename( cmds.file(q=True, sn=True) ) constraints_folder = os.path.join( pm.workspace( q=True, rd=True ), 'data/constraints/') if not os.path.exists(os.path.dirname(constraints_folder)): os.makedirs(os.path.dirname(constraints_folder)) sel = pm.ls(sl=True) constraintFile=None if len(sel)==0: pm.error('Select something numbnuts!') for obj in sel: for child in obj.getChildren(): type = pm.objectType(child) constraintString = None if 'Constraint' in type: constrainer = child.getWeightAliasList()[0].split('.')[1][:-2] #print 'Constraint found of type = %s on object: %s from object: %s' % (type, obj, constrainer) #print child.connections(p=True,c=True,d=True) if constraintString == None: constraintString = type+':'+constrainer+':'+obj else: constraintString = constraintString + ',' + type+':'+constrainer+':'+obj #print constraintString if constraintString: if constraintFile: constraintFile=constraintFile+'\n'+constraintString else: constraintFile=constraintString constraints_file = os.path.join(constraints_folder, gp.getuser(), (filepath[:-3]+'_'+time.strftime("%Y%m%dT%H%M%S")+'.constraints')) if not os.path.exists(os.path.dirname(constraints_file)): os.makedirs(os.path.dirname(constraints_file)) with open(constraints_file, 'w') as f: f.write(constraintFile) print 'Successfully wrote constraints file:\n\t%s' % (constraints_file)
def bdMirrorCtrlPymel(): selection = pm.ls(sl=True) if selection: try: source, target = pm.ls(sl=True) except: pm.warning('Select source and target controller') return sourceShape = source.getShape() if sourceShape.type() != 'nurbsCurve': pm.error('Selected source is not nurbs curve') return targetCvsPos = [(dt.Point(-x.x, x.y, x.z)) for x in sourceShape.getCVs(space='world')] targetShape = target.getShape() if targetShape.type() != 'nurbsCurve': pm.error('Selected target is not nurbs curve') return targetShape.setCVs(targetCvsPos, space='world') targetShape.updateCurve() else: print 'Select source and target controller'
def vPrint(txt, verb=2, type=0): """global verbose print function # gVerb = 2 print each step # gVerb = 1 print problemes # gVerb = 0 print nothing # type = 0 print # type = 1 warning # type = 2 error """ global gVerb if verb <= gVerb: # to properly distinguish probleme from everything else if verb == 1: start = '\t1# ' else: start = '\t # ' # and then print everything if type == 0: print start + txt elif type == 1: pmc.warning(start + txt) else: pmc.error(start + txt)
def playblastCurrent(self): playblastFormat = self.animFormatComboBox.currentText() print playblastFormat qtPlayblastMelCmd = 'playblast -format qt -sequenceTime 0 -clearCache 1 -viewer 1 -showOrnaments 1 -fp 4 -percent 100 -compression "H.264" -quality 100 -widthHeight 1280 720;'; xvidPlayblastMelCmd = 'playblast -format avi -sequenceTime 0 -clearCache 1 -viewer 1 -showOrnaments 1 -fp 4 -percent 100 -compression "XVID" -quality 100 -widthHeight 1280 720;'; uncommpresedPlayblastMelCmd = 'playblast -format avi -sequenceTime 0 -clearCache 1 -viewer 1 -showOrnaments 1 -fp 4 -percent 100 -compression "none" -quality 100 -widthHeight 1280 720;'; tempFile = '' if playblastFormat == 'mov': tempFile = pm.mel.eval(qtPlayblastMelCmd) elif playblastFormat == 'avi': tempFile = pm.mel.eval(xvidPlayblastMelCmd) elif playblastFormat == 'uncompressed': tempFile = pm.mel.eval(uncommpresedPlayblastMelCmd) if os.path.isfile(tempFile): path,fileName = os.path.split(pm.sceneName()) extension = '.mov' if playblastFormat == 'avi' or playblastFormat == 'uncompressed': extension = '.avi' movFile = fileName.split('.')[0] + extension try: shutil.copy2(tempFile, os.path.join(path,movFile)) except: pm.error("Coulnd't copy the temp blast") self.updatePlayblastStatus(fileName)
def recreate_constraint(constraint_in, source, target, mo=True): """ Recreates a constraint from the given example to a source and target Args: constraint_in (pm.PyNode): constraint to model after source (pm.nt.Transform): object to do the constraining target (pm.nt.Transform): object to be constrained mo (bool): maintain offset Usage: recreate_constraint(*pm.ls(sl=True)[:3]) """ constraint_types = ['parentConstraint','scaleConstraint','pointConstraint','scaleConstraint'] constraint_parent = constraint_in.getParent() constraint_type = constraint_in.type() constraint_func = getattr(pm, constraint_type) # Create the constraint and parent if it's not an "auto parent" if source and target: constraint = constraint_func(source, target, mo=mo) if not shortest_name(constraint_parent.name()) in shortest_name(target.name()): pm.parent(constraint, constraint_parent) if constraint_type in constraint_types: for attr in constraint_in.listAttr(): try: constraint.attr(attr.name(includeNode=False)).set(attr.get()) except (RuntimeError, pm.MayaAttributeError) as e: pass #print constraint_parent, constraint_type else: pm.error('Constraint type not supported yet, sorry')
def pymelList(inout, args): if args==[]: pm.error('pymelList passed an empty list as args...exiting') # inout 0 : given a string returns a List of 2 of [list of PyNode from a space separated string, list of objects that don't exist as strings] # inout 1 : given a list returns a string of pynodes.name() in a space separated string if inout: pymelListStr='' for node in args: if isinstance (node, basestring): pymelListStr+=node+' ' else: pymelListStr+=node.name() + ' ' return pymelListStr else: #print 'object list is '+args pymelListStrList=[] pymelListNotExist=[] if args.split(' ')[:-1]==[]: objects=[args] else: objects = args.split(' ') for object in objects: #print 'running for '+object if pm.ls(object,r=True)!=[]: #print 'object: %s exists, adding to existing list' % object pymelListStrList.append(pm.PyNode(pm.ls(object,r=True)[0])) else: #print 'object: %s doesn\'t exist, adding to create list' % object pymelListNotExist.append(object) return [pymelListStrList, pymelListNotExist]
def setWeightsAtIndex(self, index, weights, autoAddInfluence=True): """Returns the weight dict for the given index of the object (verts/cvs do not matter) Args: index (int): index of shape node component you want queried weights (list[list]): weights stored as: [[influence (string), weight (float)], w2...w(n)] Returns: (dict): dictionary of {influence:weights} """ # error checking if 0 > index or index > len(self.weights) - 1: pm.error("Index does not exist on skinCluster for given shape") weightTotal = 0 for weight in weights: if not type(weight) == list: pm.error("Unsupported format for input weights, please read help") weightTotal += weight[1] if weightTotal > 1: pass # this used to error check, but maya normalizes anyways. # pm.error('All your weights must be normalized to 1') pm.warning("Your input weight values you surpassed 1, normalization will occur. Results may vary") # meat component = None if self.shape.type() == "nurbsCurve": component = self.shape.cv[index] if self.shape.type() == "mesh": component = self.shape.vtx[index] if autoAddInfluence: for weight in weights: sourceInfluence = weight[0] if sourceInfluence not in self.influences: self.addInfluence(sourceInfluence) pm.skinPercent(self.skinCluster, component, transformValue=(weights)) self._update() return True