def applyUvToWorldRatioToSelection(self, targetRatio=None): oSel = pm.ls(sl=True) pm.mel.eval("ConvertSelectionToFaces;") sel = pm.ls(sl=True) if targetRatio == None: targetRatio = input() currentRatio = self.calcUvToWorldAreaRatio() amountToScaleBeforeSqrt = targetRatio / currentRatio amountToScale = math.sqrt(amountToScaleBeforeSqrt) ## Calc a bounding box in uv space, and it's center, for a scale pivot bb = pm.polyEvaluate(sel, boundingBoxComponent2d=True) bbUMin = bb[0][0] bbUMax = bb[0][1] bbVMin = bb[1][0] bbVMax = bb[1][1] bbUCenter = (bbUMax + bbUMin) * 0.5 bbVCenter = (bbVMax + bbVMin) * 0.5 pm.polyEditUV(sel, pu=bbUCenter, pv=bbVCenter, su=amountToScale, sv=amountToScale) pm.select(oSel)
def unfold3dOnlySelected(self): origSel = pm.ls(selection=True) pm.mel.eval("PolySelectConvert 4;") ##"ConvertSelectionToUVs;" ) origUvs = pm.ls(selection=True) pm.mel.eval("InvertSelection;") selCount = len(pm.ls(selection=True)) ## In case all uvs are selected, the inverted selection will be zero! if selCount == 0: pm.select(origSel) pm.mel.eval("ConvertSelectionToUVs;") pm.mel.eval( "Unfold3D -unfold -iterations 1 -p 1 -borderintersection 1 -triangleflip 1;" ) pm.select(origSel) else: ## Beware! there's a huge potential bug in this commands behavior ## the way it is now working here is to get u and v values, as back to back entries added into a list ## so the list is twice as long as the number of uvs eg. v = coords[i*2 +1] uvsToRestore = pm.ls(selection=True, flatten=True) coords = pm.polyEditUV(uvsToRestore, query=True, uValue=True, vValue=True) pm.select(origSel) pm.mel.eval("ConvertSelectionToUVs;") pm.mel.eval( "Unfold3D -unfold -iterations 1 -p 1 -borderintersection 1 -triangleflip 1;" ) #print( uvsToRestore ) #print len(coordsU) #print len( uvsToRestore ) #print( coords ) for i, uv in enumerate(uvsToRestore): #print( coords ) pm.polyEditUV(uv, relative=False, uValue=coords[i * 2], vValue=coords[i * 2 + 1]) #cmds.Unfold3D( cmds.ls(sl=True), u=True, p=True, ite=1, bi=True, tf=True, ms=1024, rs=2 ) pm.select(origSel)
def sd_randomize_uvs(rand=0.3): """ After selecting uv's in the uv editor, this script will move around uv's randomly according to the object with which they belong. :param rand: The distance to be moved randomized between -rand and rand. :return: None """ # Check if rand is a float or integer. if isinstance(rand, basestring): raise ValueError('please input a float or integer value') # define selection. o_sel = pm.ls(sl=True, flatten=True) # Check if there are any objects in the selection that are not MeshUVs. non_mesh_uv_objects = [o for o in o_sel if not isinstance(o, pm.MeshUV)] if non_mesh_uv_objects: raise TypeError('please only select uv points') # List the objects that the UVs belong to. u_list = [o.name().split('.')[0] for o in o_sel] # Create a Dictionary containing the objects and the UV vertices selected. uv_coord_dict = { o: [ u.index() for u in o_sel if o == u.name().split('.')[0] ] for o in u_list } # Create random numbers relating to the objects selected. random_nums = { o: [ random.uniform(-rand, rand), random.uniform(-rand, rand) ] for o in u_list } # Cycle through the dictionary moving the object's contained UV vertices. for uv in uv_coord_dict: for vtx in uv_coord_dict[uv]: pm.polyEditUV( '{}.map[{}]'.format(uv, vtx), u=random_nums[uv][0], v=random_nums[uv][1], relative=True ) return None
def unfold3dOnlySelected(self): origSel = pm.ls(selection=True) pm.mel.eval("PolySelectConvert 4;") ##"ConvertSelectionToUVs;" ) origUvs = pm.ls(selection=True) pm.mel.eval("InvertSelection;") selCount = len(pm.ls(selection=True)) ## In case all uvs are selected, the inverted selection will be zero! if selCount == 0: pm.select(origSel) pm.mel.eval("ConvertSelectionToUVs;") pm.mel.eval("Unfold3D -unfold -iterations 1 -p 1 -borderintersection 1 -triangleflip 1;") pm.select(origSel) else: ## Beware! there's a huge potential bug in this commands behavior ## the way it is now working here is to get u and v values, as back to back entries added into a list ## so the list is twice as long as the number of uvs eg. v = coords[i*2 +1] uvsToRestore = pm.ls(selection=True, flatten=True) coords = pm.polyEditUV(uvsToRestore, query=True, uValue=True, vValue=True) pm.select(origSel) pm.mel.eval("ConvertSelectionToUVs;") pm.mel.eval("Unfold3D -unfold -iterations 1 -p 1 -borderintersection 1 -triangleflip 1;") # print( uvsToRestore ) # print len(coordsU) # print len( uvsToRestore ) # print( coords ) for i, uv in enumerate(uvsToRestore): # print( coords ) pm.polyEditUV(uv, relative=False, uValue=coords[i * 2], vValue=coords[i * 2 + 1]) # cmds.Unfold3D( cmds.ls(sl=True), u=True, p=True, ite=1, bi=True, tf=True, ms=1024, rs=2 ) pm.select(origSel)
def scale_uvs(self, s=None, u=None, v=None, pu=0, pv=0): if not s is None: u = s v = s pm.polyEditUV(su=u, sv=v, pu=pu, pv=pv)
def move_uvs(self, u, v): pm.polyEditUV(u=u, v=v)
def bake( self, modelsPath="", highSuffix="", xnormalExe="", xmlFiles="", cageSuffix="", typeSuffixes="", cageOffset=None ): try: cmds.progressWindow( endProgress=True ) except: pass #print( "..." ) cmds.progressWindow(isInterruptable=1) if highSuffix=="": highSuffix="_hi" if cageSuffix=="": cageSuffix= "_cage" if cageOffset==None: cageOffset=2.0 if typeSuffixes=="": typeSuffixes=['normals','heights','vcols', 'occlusion', 'curvature', 'cavity'] typeOfTypeSuffixes = type(typeSuffixes) if typeOfTypeSuffixes==type( "a_string" ) or typeOfTypeSuffixes==type( u"a_unicode_string" ): typeSuffixes = typeSuffixes.split(",") xnormal_exe = xnormalExe.replace("\\","/") folder_with_high_models = modelsPath.replace("\\","/") xml_files = xmlFiles.split(',') objExt = ".obj" ## Set pythons current working directory os.chdir( folder_with_high_models ) ## Get the selected objects, store as both an original selection ## and a copy of the original selection, objs osel = pm.ls(selection=True) objs = osel[:] scriptIsCanceled = False cancelCheckSleepTimeStartup = 0.5 cancelCheckSleepTime = 0.01 for obj in objs: time.sleep( cancelCheckSleepTimeStartup ) if cmds.progressWindow(query=1, isCancelled=1): print( "Script canceled by user, eg. escape key." ) scriptIsCanceled = True break try: ## try each obj ## Select the object and set up some basic variables, ## such as the name and the python cwd pm.select( obj ) obj_name = obj.name() cwd = os.getcwd() cwdUni = unicode(cwd) ## Triangulate before export print( obj ) tri_op = pm.polyTriangulate( obj ) ## Export lo, triangulated export_target_including_file_and_path = os.getcwd().replace("\\","/") + "/" + obj_name + objExt pm.select( obj ) pm.exportSelected( export_target_including_file_and_path,sh = 1, pr = 1, typ = "OBJexport", es = 1, force=True ) print( obj ) try: cageOffsetCustom = obj.mmmmBakerCageOffset.get() except: cageOffsetCustom = cageOffset print( "no custom cage offset found, using default" ) trans_op = pm.polyMoveVertex( obj, localTranslateZ=cageOffsetCustom ) ## Export Cage export_target_including_file_and_path = \ os.getcwd().replace("\\","/") + "/" + obj_name + cageSuffix + objExt pm.select( obj ) pm.exportSelected( export_target_including_file_and_path, sh = 1, pr = 1, typ = "OBJexport", es = 1, force=True ) ## Cleanup cage offset and triangulation pm.delete( trans_op ) pm.delete( tri_op ) #if obj_name.endswith( lo_suffix ): # high_name = obj_name.replace( lo_suffix, highSuffix ) #else: high_name = obj_name + highSuffix for i, xml_file in enumerate(xml_files): time.sleep( cancelCheckSleepTime ) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled=True print( "Script canceled by user, eg. escape key." ) break pm.select( obj ) pm.mel.eval( "ConvertSelectionToUVs;" ) uvs = pm.ls(selection=True, flatten=True) coUV = pm.polyEditUV( uvs, query=True ) coU, coV = coUV[::2], coUV[1::2] pm.select(obj) """" for c in coU: if c >= 0.0 and c < 1.0: udim1001=True if c >= 1.0 and c < 2.0: udim1002=True if c >= 2.0 and c < 3.0: udim1003=True if c >= 3.0 and c < 4.0: udim1004=True """ dictOfUsedUvRanges = {} for cIndex in xrange( len(coU) ): tu = coU[cIndex] tv = coV[cIndex] tuInt = math.floor( tu ) tvInt = math.floor( tv ) dictOfUsedUvRanges[ tuInt,tvInt ] = int( 1000 + (tuInt+1) + (tvInt*10) ) #print( "length of dictionary:") #print( len( dictOfUsedUvRanges.keys() ) ) #break for keyRange, udim in dictOfUsedUvRanges.items(): uInKey = keyRange[0] vInKey = keyRange[1] uOffset = uInKey * -1.0 vOffset = vInKey * -1.0 if uOffset==0.0: uOffset=0.0 #in case of negative 0.0, f*****g hell! if vOffset==0.0: vOffset=0.0 #in case of negative 0.0, f*****g hell! # do something similar for vOffset. ## edit xml export with uOffset and uOffset here! """" if udim1001==True: uOffsets.append( 0.0 ) if udim1002==True: uOffsets.append( -1.0 ) if udim1003==True: uOffsets.append( -2.0 ) if udim1004==True: uOffsets.append( -3.0 ) for uOffset in uOffsets: """ time.sleep( cancelCheckSleepTime ) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled=True print( "Script canceled by user, eg. escape key." ) break xml_file_abs = os.path.join( cwdUni, xml_file ) print( xml_file_abs ) xml_file_modified = u'tmp_mmmmBaker.xml' xml_file_modified_abs = os.path.join( cwdUni, xml_file_modified ) xml_in_mem = '' with open( xml_file_abs, 'r' ) as fh: xml_in_mem = fh.read() xml_in_mem = xml_in_mem.replace( 'UOffset="0.', 'UOffset="' + str(uOffset) ) xml_in_mem = xml_in_mem.replace( 'VOffset="0.', 'VOffset="' + str(vOffset) ) uOffsetAsInt = int( -1 * uOffset) vOffsetAsInt = int( -1 * uOffset) folder_with_high_models__no_trailing_slash = \ folder_with_high_models if folder_with_high_models__no_trailing_slash.endswith("/"): folder_with_high_models__no_trailing_slash =\ folder_with_high_models__no_trailing_slash[:-1] xml_in_mem = xml_in_mem.replace( "C:\\Users\\Public\\mmmmBaker", folder_with_high_models.replace("/","\\") ) root = XmlTree.fromstring(xml_in_mem) ## Print the entire xml tree for reference' #print( XmlTree.tostring( root ) ) ## find used udims on objects ## find u offset and v offset for low objects ## set up a list to run a for loop for to ## handle each udim found ## find low object ## find cage object ## find use cage option # ## find hi objects ## find output with open( xml_file_modified_abs, 'w' ) as fh: fh.write( xml_in_mem ) print( obj ) ##print( xml_in_mem ) print( uOffsetAsInt, vOffsetAsInt ) try: lo_to_copy_for_replacement = obj_name + objExt cage_to_copy_for_replacement = obj_name + cageSuffix + objExt hi_to_copy_for_replacement = obj_name + highSuffix + objExt shutil.copy2(lo_to_copy_for_replacement, "replaceme_lo" + objExt) shutil.copy2(hi_to_copy_for_replacement, "replaceme_hi" + objExt) shutil.copy2(cage_to_copy_for_replacement, "replaceme_cage" + objExt) print( "xnormal subprocess starting...") print( xnormal_exe + " " + str(xml_file_modified) ) subprocess.check_call( [ xnormal_exe, str(xml_file_modified) ] ) print( "xnormal subprocess complete! Continuing...") for typeSuffix in typeSuffixes: try: baked_name = "replaceme_" + typeSuffix + ".exr" proper_name = obj_name + "_" + "xml"+str(i).zfill(2) + "_" + "udim" + str( udim ) + "_" + typeSuffix + ".exr" shutil.copy2( baked_name, proper_name ) except: print( traceback.format_exc() ) except: print( traceback.format_exc() ) except: ## except each obj print( traceback.format_exc() ) pm.select( osel ) ## Do something here to attempt to combine/composite textures together. ## Until then, just tell the user to use the photoshop action ## which should be provided with MmmmTools ## Add some explaination for how to use the action cmds.progressWindow( endProgress=True ) if not scriptIsCanceled: print( "Baking complete!") print( "Baked (or at least attempted to bake) " + str( len(objs) ) + " objects." )
def bake(self, modelsPath="", highSuffix="", xnormalExe="", xmlFiles="", cageSuffix="", typeSuffixes="", cageOffset=None): try: cmds.progressWindow(endProgress=True) except: pass #print( "..." ) cmds.progressWindow(isInterruptable=1) if highSuffix == "": highSuffix = "_hi" if cageSuffix == "": cageSuffix = "_cage" if cageOffset == None: cageOffset = 2.0 if typeSuffixes == "": typeSuffixes = [ 'normals', 'heights', 'vcols', 'occlusion', 'curvature', 'cavity' ] typeOfTypeSuffixes = type(typeSuffixes) if typeOfTypeSuffixes == type( "a_string") or typeOfTypeSuffixes == type(u"a_unicode_string"): typeSuffixes = typeSuffixes.split(",") xnormal_exe = xnormalExe.replace("\\", "/") folder_with_high_models = modelsPath.replace("\\", "/") xml_files = xmlFiles.split(',') objExt = ".obj" ## Set pythons current working directory os.chdir(folder_with_high_models) ## Get the selected objects, store as both an original selection ## and a copy of the original selection, objs osel = pm.ls(selection=True) objs = osel[:] scriptIsCanceled = False cancelCheckSleepTimeStartup = 0.5 cancelCheckSleepTime = 0.01 for obj in objs: time.sleep(cancelCheckSleepTimeStartup) if cmds.progressWindow(query=1, isCancelled=1): print("Script canceled by user, eg. escape key.") scriptIsCanceled = True break try: ## try each obj ## Select the object and set up some basic variables, ## such as the name and the python cwd pm.select(obj) obj_name = obj.name() cwd = os.getcwd() cwdUni = unicode(cwd) ## Triangulate before export print(obj) tri_op = pm.polyTriangulate(obj) ## Export lo, triangulated export_target_including_file_and_path = os.getcwd().replace( "\\", "/") + "/" + obj_name + objExt pm.select(obj) pm.exportSelected(export_target_including_file_and_path, sh=1, pr=1, typ="OBJexport", es=1, force=True) print(obj) try: cageOffsetCustom = obj.mmmmBakerCageOffset.get() except: cageOffsetCustom = cageOffset print("no custom cage offset found, using default") trans_op = pm.polyMoveVertex(obj, localTranslateZ=cageOffsetCustom) ## Export Cage export_target_including_file_and_path = \ os.getcwd().replace("\\","/") + "/" + obj_name + cageSuffix + objExt pm.select(obj) pm.exportSelected(export_target_including_file_and_path, sh=1, pr=1, typ="OBJexport", es=1, force=True) ## Cleanup cage offset and triangulation pm.delete(trans_op) pm.delete(tri_op) #if obj_name.endswith( lo_suffix ): # high_name = obj_name.replace( lo_suffix, highSuffix ) #else: high_name = obj_name + highSuffix for i, xml_file in enumerate(xml_files): time.sleep(cancelCheckSleepTime) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled = True print("Script canceled by user, eg. escape key.") break pm.select(obj) pm.mel.eval("ConvertSelectionToUVs;") uvs = pm.ls(selection=True, flatten=True) coUV = pm.polyEditUV(uvs, query=True) coU, coV = coUV[::2], coUV[1::2] pm.select(obj) """" for c in coU: if c >= 0.0 and c < 1.0: udim1001=True if c >= 1.0 and c < 2.0: udim1002=True if c >= 2.0 and c < 3.0: udim1003=True if c >= 3.0 and c < 4.0: udim1004=True """ dictOfUsedUvRanges = {} for cIndex in xrange(len(coU)): tu = coU[cIndex] tv = coV[cIndex] tuInt = math.floor(tu) tvInt = math.floor(tv) dictOfUsedUvRanges[tuInt, tvInt] = int(1000 + (tuInt + 1) + (tvInt * 10)) #print( "length of dictionary:") #print( len( dictOfUsedUvRanges.keys() ) ) #break for keyRange, udim in dictOfUsedUvRanges.items(): uInKey = keyRange[0] vInKey = keyRange[1] uOffset = uInKey * -1.0 vOffset = vInKey * -1.0 if uOffset == 0.0: uOffset = 0.0 #in case of negative 0.0, f*****g hell! if vOffset == 0.0: vOffset = 0.0 #in case of negative 0.0, f*****g hell! # do something similar for vOffset. ## edit xml export with uOffset and uOffset here! """" if udim1001==True: uOffsets.append( 0.0 ) if udim1002==True: uOffsets.append( -1.0 ) if udim1003==True: uOffsets.append( -2.0 ) if udim1004==True: uOffsets.append( -3.0 ) for uOffset in uOffsets: """ time.sleep(cancelCheckSleepTime) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled = True print("Script canceled by user, eg. escape key.") break xml_file_abs = os.path.join(cwdUni, xml_file) print(xml_file_abs) xml_file_modified = u'tmp_mmmmBaker.xml' xml_file_modified_abs = os.path.join( cwdUni, xml_file_modified) xml_in_mem = '' with open(xml_file_abs, 'r') as fh: xml_in_mem = fh.read() xml_in_mem = xml_in_mem.replace( 'UOffset="0.', 'UOffset="' + str(uOffset)) xml_in_mem = xml_in_mem.replace( 'VOffset="0.', 'VOffset="' + str(vOffset)) uOffsetAsInt = int(-1 * uOffset) vOffsetAsInt = int(-1 * uOffset) folder_with_high_models__no_trailing_slash = \ folder_with_high_models if folder_with_high_models__no_trailing_slash.endswith( "/"): folder_with_high_models__no_trailing_slash =\ folder_with_high_models__no_trailing_slash[:-1] xml_in_mem = xml_in_mem.replace( "C:\\Users\\Public\\mmmmBaker", folder_with_high_models.replace("/", "\\")) root = XmlTree.fromstring(xml_in_mem) ## Print the entire xml tree for reference' #print( XmlTree.tostring( root ) ) ## find used udims on objects ## find u offset and v offset for low objects ## set up a list to run a for loop for to ## handle each udim found ## find low object ## find cage object ## find use cage option # ## find hi objects ## find output with open(xml_file_modified_abs, 'w') as fh: fh.write(xml_in_mem) print(obj) ##print( xml_in_mem ) print(uOffsetAsInt, vOffsetAsInt) try: lo_to_copy_for_replacement = obj_name + objExt cage_to_copy_for_replacement = obj_name + cageSuffix + objExt hi_to_copy_for_replacement = obj_name + highSuffix + objExt shutil.copy2(lo_to_copy_for_replacement, "replaceme_lo" + objExt) shutil.copy2(hi_to_copy_for_replacement, "replaceme_hi" + objExt) shutil.copy2(cage_to_copy_for_replacement, "replaceme_cage" + objExt) print("xnormal subprocess starting...") print(xnormal_exe + " " + str(xml_file_modified)) subprocess.check_call( [xnormal_exe, str(xml_file_modified)]) print( "xnormal subprocess complete! Continuing...") for typeSuffix in typeSuffixes: try: baked_name = "replaceme_" + typeSuffix + ".exr" proper_name = obj_name + "_" + "xml" + str( i).zfill(2) + "_" + "udim" + str( udim) + "_" + typeSuffix + ".exr" shutil.copy2(baked_name, proper_name) except: print(traceback.format_exc()) except: print(traceback.format_exc()) except: ## except each obj print(traceback.format_exc()) pm.select(osel) ## Do something here to attempt to combine/composite textures together. ## Until then, just tell the user to use the photoshop action ## which should be provided with MmmmTools ## Add some explaination for how to use the action cmds.progressWindow(endProgress=True) if not scriptIsCanceled: print("Baking complete!") print("Baked (or at least attempted to bake) " + str(len(objs)) + " objects.")
def create_mesh( xml_path, name, locator=None ) : pm.select( None ) tree = et.parse( xml_path ) root_keys = tree.getroot().keys() if( not 'imagePath' in root_keys ) : pm.error( 'The XML file does not appear to be a Texture Packer XML' ) texture_size = ( tree.getroot().get( 'width' ), tree.getroot().get( 'height' ) ) sprite = tree.find( ".//*[@n='%s']" % ( name ) ) material = create_material( xml_path ) if( not len( material.shadingGroups() ) ) : pm.error( 'Material %s is not connected to a Shading Group. Aborting.' ) plane_name = __get_filename_noext( name ) + '_G' if( locator ) : plane_name = '%s_%s' % ( locator.name(), plane_name ) try : plane_trans = pm.PyNode( plane_name ) except : # v = pm.datatypes.Vector( float(sprite.get('w')) / 100.0, float(sprite.get('h')) / 100.0 ) # v = v.normal() w_scale = float(sprite.get('w')) / 100.0 h_scale = float(sprite.get('h')) / 100.0 w_h = w_scale / h_scale h_w = h_scale / w_scale if( w_h > h_w ) : wp = 1.0 / w_h # print wp w_scale = 1.0 h_scale = 1.0 / w_h # print 'w_h', w_scale, h_scale else : hp = 1.0 / h_w # print hp h_scale = 1.0 w_scale = 1.0 / h_w # print w_h, h_w # print 'h_w', w_scale, h_scale plane_trans = pm.polyPlane( name=plane_name, sw=1, sh=1, w=w_scale, h=h_scale )[0] plane_shape = plane_trans.getShape() if( not plane_trans.hasAttr( THU_MFT_SPRITE_ATTR ) ) : plane_trans.addAttr( THU_MFT_SPRITE_ATTR, dt='string' ) plane_trans.setAttr( THU_MFT_SPRITE_ATTR, name.replace( '.png', '' ) ) pm.sets( material.shadingGroups()[0], edit=True, forceElement=plane_trans ) sx = ( float( sprite.get( 'x' ) ) / float( texture_size[0] ) ) sy = 1 - ( float( sprite.get( 'y' ) ) / float( texture_size[1] ) ) sw = ( float( sprite.get( 'w' ) ) / float( texture_size[0] ) ) sh = ( float( sprite.get( 'h' ) ) / float( texture_size[1] ) ) uv_positions = ( ( sx, sy - sh ), ( sx + sw, sy - sh ), ( sx, sy ), ( sx + sw, sy ) ) for uv, uv_position in zip( plane_shape.uvs, uv_positions ) : pm.polyEditUV( uv, r=False, u=uv_position[0], v=uv_position[1] ) if( locator ) : # print locator plane_trans.setParent( locator ) plane_trans.setTranslation( ( 0, 0, 0 ) ) plane_trans.setRotation( ( 0, 0, 0 ) ) plane_trans.setScale( ( 1, 1, 1 ) ) locator_bounds = locator.getBoundingBox() plane_bounds = plane_trans.getBoundingBox() if( plane_bounds.width() > plane_bounds.height() ) : pass else : s = locator_bounds.height() / plane_bounds.height() # plane_trans.setScale( (s, s, s) ) pm.select( plane_trans ) return plane_trans
def createRivet(self): """ Create one rivet for each selected vertex """ selObjs = pm.ls(selection=True) if not selObjs: ## Nothing is selected, so print out warning and raise error print( self.emsgPleaseSelect ) return #raise Exception, self.emsgPleaseSelect self.originalSel = selObjs #### Store this step of of the selection in case we want it again later uvs = [] uvs.extend( pm.polyListComponentConversion( selObjs, tuv=True ) ) #### Change this to the full version #uvs.extend( [uv for uv in selObjs if '.uv' in uv] ) #### This is a very good list comprehension, perhaps expand it though ## the extend method of a list adds all items from another given list to the list uvsFromNurbs = [] for i in selObjs: if pm.objectType( i ) == 'nurbsSurface' : uvs.append( i ) ## select our new, smaller/filtered uvs pm.select( uvs ) uvs = pm.ls( flatten = True, selection = True ) ## The flatten command returns each component individually in the list, rather than using strings that specify ranges of selections. It takes more RAM but is often much more suitable to work with. ## Create a group so that we can organize the rivets - **** Note that this should be improved with the MmmmTools upcoming unique naming system if not pm.objExists('_follicle_grp'): #### This line and the next should eventually be improved to not use a hardcoded name group = pm.group( em = True, w=True, n='_follicle_grp' ) #### **** Totally recreate this line, use a variable name or at least a unique one else: group = pm.PyNode('_follicle_grp') rivets = [] pm.select( selObjs ) failCount = 0 ## Give an error msg if the user didn't use the script on a compatible selection if not uvs: failCount += 1 print( self.emsgPleaseSelect ) ## Everything is good, proceed to investigate and create rivets for uv in uvs: ## The commented out print line are simple useful for debugging print pm.objectType( uv ) objShapeName, index = tuple( uv.split( '.', 1 ) ) obj = pm.PyNode( objShapeName ) loc = pm.createNode( 'locator' ) tr = getT( loc ) #print( "Transform was: " + tr ) hair = pm.createNode( 'follicle', parent = tr ) pm.parent( tr, group ) #### This line sucks because it's using a f*****g stupid name again rivets.append( tr ) ## Poly mesh handler if pm.objectType( obj ) == 'mesh': obj.outMesh >> hair.inputMesh uvPos = pm.polyEditUV( uv, query=True ) ## Nurbs surface handler elif pm.objectType( obj ) == 'nurbsSurface': obj.local >> hair.inputSurface ## The index is a messy string, so we need to pull uv data out of it uvTuple = ( index.strip('.uv[]').split('][') ) ## We need to create the tuple as floats, because we got it as strings uvPos = ( float(uvTuple[0]), float(uvTuple[1]) ) #uvPos = ( uvTuple[0], uv[1] )#index.strip('.uv[]').split('][') ## Handle conditions where the uvs aren't normalized, this may not be required often maxU = float( obj.maxValueU.get() ) maxV = float( obj.maxValueV.get() ) uvPos = ( uvPos[0]/maxU, uvPos[1]/maxV ) ## Handle other cases, where this script can't do anything useful else: print( obj + ' with uv: ' + uv + \ ' was incompatible, it much be either polygons or Nurbs' ) failCount += 1 continue u, v = uvPos ## Make the hair follow the model, both by parenting, and by keeping its translate and rotate matched obj.worldMatrix >> hair.inputWorldMatrix hair.outTranslate >> tr.translate hair.outRotate >> tr.rotate ## Note: The hair has no outScale ## Set the u and v parameters of the hair so that it sticks to the correct place on the model hair.parameterU.set( u ) hair.parameterV.set( v ) ## Put the rivet into a group so we can select it afterwards self.lastRivetsCreated.append( loc ) ## Select all the new rivets we created pm.select( self.lastRivetsCreated, replace=True ) if failCount: print( str(failCount) + """ rivets failed to be created. Most likely because the selection was not correct. Try selecting vertices on a nurbs surface or a polygon mesh and running the script again. """) else: print( self.msgSucess ) return
def create_mesh(xml_path, name, locator=None): pm.select(None) tree = et.parse(xml_path) root_keys = tree.getroot().keys() if (not 'imagePath' in root_keys): pm.error('The XML file does not appear to be a Texture Packer XML') texture_size = (tree.getroot().get('width'), tree.getroot().get('height')) sprite = tree.find(".//*[@n='%s']" % (name)) material = create_material(xml_path) if (not len(material.shadingGroups())): pm.error('Material %s is not connected to a Shading Group. Aborting.') plane_name = __get_filename_noext(name) + '_G' if (locator): plane_name = '%s_%s' % (locator.name(), plane_name) try: plane_trans = pm.PyNode(plane_name) except: # v = pm.datatypes.Vector( float(sprite.get('w')) / 100.0, float(sprite.get('h')) / 100.0 ) # v = v.normal() w_scale = float(sprite.get('w')) / 100.0 h_scale = float(sprite.get('h')) / 100.0 w_h = w_scale / h_scale h_w = h_scale / w_scale if (w_h > h_w): wp = 1.0 / w_h # print wp w_scale = 1.0 h_scale = 1.0 / w_h # print 'w_h', w_scale, h_scale else: hp = 1.0 / h_w # print hp h_scale = 1.0 w_scale = 1.0 / h_w # print w_h, h_w # print 'h_w', w_scale, h_scale plane_trans = pm.polyPlane(name=plane_name, sw=1, sh=1, w=w_scale, h=h_scale)[0] plane_shape = plane_trans.getShape() if (not plane_trans.hasAttr(THU_MFT_SPRITE_ATTR)): plane_trans.addAttr(THU_MFT_SPRITE_ATTR, dt='string') plane_trans.setAttr(THU_MFT_SPRITE_ATTR, name.replace('.png', '')) pm.sets(material.shadingGroups()[0], edit=True, forceElement=plane_trans) sx = (float(sprite.get('x')) / float(texture_size[0])) sy = 1 - (float(sprite.get('y')) / float(texture_size[1])) sw = (float(sprite.get('w')) / float(texture_size[0])) sh = (float(sprite.get('h')) / float(texture_size[1])) uv_positions = ((sx, sy - sh), (sx + sw, sy - sh), (sx, sy), (sx + sw, sy)) for uv, uv_position in zip(plane_shape.uvs, uv_positions): pm.polyEditUV(uv, r=False, u=uv_position[0], v=uv_position[1]) if (locator): # print locator plane_trans.setParent(locator) plane_trans.setTranslation((0, 0, 0)) plane_trans.setRotation((0, 0, 0)) plane_trans.setScale((1, 1, 1)) locator_bounds = locator.getBoundingBox() plane_bounds = plane_trans.getBoundingBox() if (plane_bounds.width() > plane_bounds.height()): pass else: s = locator_bounds.height() / plane_bounds.height() # plane_trans.setScale( (s, s, s) ) pm.select(plane_trans) return plane_trans
def scale_uvs( self, s=None, u=None, v=None, pu=0,pv=0 ): if not s is None: u = s v = s pm.polyEditUV( su=u, sv=v, pu=pu, pv=pv )
def move_uvs( self, u, v ): pm.polyEditUV( u=u, v=v )