import bpy import bmesh import operator import time from mathutils import Vector from collections import defaultdict from math import pi from . import settings from . import utilities_ui def selection_store(): bm = bmesh.from_edit_mesh(bpy.context.active_object.data); uv_layers = bm.loops.layers.uv.verify(); # https://blender.stackexchange.com/questions/5781/how-to-list-all-selected-elements-in-python # print("selectionStore") settings.selection_uv_mode = bpy.context.scene.tool_settings.uv_select_mode settings.selection_uv_pivot = bpy.context.tool_settings.transform_pivot_point settings.selection_uv_pivot_pos = bpy.context.space_data.cursor_location.copy() #VERT Selection settings.selection_mode = tuple(bpy.context.scene.tool_settings.mesh_select_mode) settings.selection_vert_indexies = [] for vert in bm.verts: if vert.select: settings.selection_vert_indexies.append(vert.index) settings.selection_face_indexies = [] for face in bm.faces: if face.select: settings.selection_face_indexies.append(face.index) #Face selections (Loops) settings.selection_uv_loops = [] for face in bm.faces: for loop in face.loops: if loop[uv_layers].select: settings.selection_uv_loops.append( [face.index, loop.vert.index] ) def selection_restore(bm = None, uv_layers = None): if bpy.context.object.mode != 'EDIT': bpy.ops.object.mode_set(mode = 'EDIT') if not bm: bm = bmesh.from_edit_mesh(bpy.context.active_object.data); if not uv_layers: uv_layers = bm.loops.layers.uv.verify(); # print("selectionRestore") bpy.context.scene.tool_settings.uv_select_mode = settings.selection_uv_mode bpy.context.tool_settings.transform_pivot_point = settings.selection_uv_pivot contextViewUV = utilities_ui.GetContextViewUV() if contextViewUV: bpy.ops.uv.cursor_set(contextViewUV, location=settings.selection_uv_pivot_pos) bpy.ops.mesh.select_all(action='DESELECT') if hasattr(bm.verts, "ensure_lookup_table"): bm.verts.ensure_lookup_table() # bm.edges.ensure_lookup_table() bm.faces.ensure_lookup_table() #FACE selection bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE') for index in settings.selection_face_indexies: if index < len(bm.faces): bm.faces[index].select = True #VERT Selection bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT') for index in settings.selection_vert_indexies: if index < len(bm.verts): bm.verts[index].select = True #Selection Mode bpy.context.scene.tool_settings.mesh_select_mode = settings.selection_mode #UV Face-UV Selections (Loops) bpy.ops.uv.select_all(contextViewUV, action='DESELECT') for uv_set in settings.selection_uv_loops: for loop in bm.faces[ uv_set[0] ].loops: if loop.vert.index == uv_set[1]: loop[uv_layers].select = True break bpy.context.view_layer.update() def get_selected_faces(): bm = bmesh.from_edit_mesh(bpy.context.active_object.data); faces = []; for face in bm.faces: if face.select: faces.append(face) return faces def set_selected_faces(faces): bm = bmesh.from_edit_mesh(bpy.context.active_object.data); uv_layers = bm.loops.layers.uv.verify(); for face in faces: for loop in face.loops: loop[uv_layers].select = True def get_selected_uvs(bm, uv_layers): """Returns selected mesh vertices of selected UV's""" uvs = [] for face in bm.faces: if face.select: for loop in face.loops: if loop[uv_layers].select: uvs.append( loop[uv_layers] ) return uvs def get_selected_uv_verts(bm, uv_layers): """Returns selected mesh vertices of selected UV's""" verts = set() for face in bm.faces: if face.select: for loop in face.loops: if loop[uv_layers].select: verts.add( loop.vert ) return list(verts) def get_selected_uv_edges(bm, uv_layers): """Returns selected mesh edges of selected UV's""" verts = get_selected_uv_verts(bm, uv_layers) edges = [] for edge in bm.edges: if edge.verts[0] in verts and edge.verts[1] in verts: edges.append(edge) return edges def get_selected_uv_faces(bm, uv_layers): """Returns selected mesh faces of selected UV's""" faces = [] for face in bm.faces: if face.select: count = 0 for loop in face.loops: if loop[uv_layers].select: count+=1 if count == len(face.loops): faces.append(face) return faces def get_vert_to_uv(bm, uv_layers): vert_to_uv = {} for face in bm.faces: for loop in face.loops: vert = loop.vert uv = loop[uv_layers] if vert not in vert_to_uv: vert_to_uv[vert] = [uv]; else: vert_to_uv[vert].append(uv) return vert_to_uv def get_uv_to_vert(bm, uv_layers): uv_to_vert = {} for face in bm.faces: for loop in face.loops: vert = loop.vert uv = loop[uv_layers] if uv not in uv_to_vert: uv_to_vert[ uv ] = vert; return uv_to_vert def getSelectionBBox(): bm = bmesh.from_edit_mesh(bpy.context.active_object.data); uv_layers = bm.loops.layers.uv.verify(); bbox = {} boundsMin = Vector((99999999.0,99999999.0)) boundsMax = Vector((-99999999.0,-99999999.0)) boundsCenter = Vector((0.0,0.0)) countFaces = 0; for face in bm.faces: if face.select: for loop in face.loops: if loop[uv_layers].select is True: uv = loop[uv_layers].uv boundsMin.x = min(boundsMin.x, uv.x) boundsMin.y = min(boundsMin.y, uv.y) boundsMax.x = max(boundsMax.x, uv.x) boundsMax.y = max(boundsMax.y, uv.y) boundsCenter+= uv countFaces+=1 bbox['min'] = boundsMin bbox['max'] = boundsMax bbox['width'] = (boundsMax - boundsMin).x bbox['height'] = (boundsMax - boundsMin).y if countFaces == 0: bbox['center'] = boundsMin else: bbox['center'] = boundsCenter / countFaces bbox['area'] = bbox['width'] * bbox['height'] bbox['minLength'] = min(bbox['width'], bbox['height']) return bbox; def getSelectionIslands(bm=None, uv_layers=None): if bm == None: bm = bmesh.from_edit_mesh(bpy.context.active_object.data) uv_layers = bm.loops.layers.uv.verify() #Reference A: https://github.com/nutti/Magic-UV/issues/41 #Reference B: https://github.com/c30ra/uv-align-distribute/blob/v2.2/make_island.py #Extend selection if bpy.context.scene.tool_settings.use_uv_select_sync == False: bpy.ops.uv.select_linked() #Collect selected UV faces faces_selected = []; for face in bm.faces: if face.select and face.loops[0][uv_layers].select: faces_selected.append(face) #Collect UV islands # faces_parsed = [] faces_unparsed = faces_selected.copy() islands = [] for face in faces_selected: if face in faces_unparsed: #Select single face bpy.ops.uv.select_all(action='DESELECT') face.loops[0][uv_layers].select = True; bpy.ops.uv.select_linked()#Extend selection #Collect faces islandFaces = [face]; for faceAll in faces_unparsed: if faceAll != face and faceAll.select and faceAll.loops[0][uv_layers].select: islandFaces.append(faceAll) for faceAll in islandFaces: faces_unparsed.remove(faceAll) #Assign Faces to island islands.append(islandFaces) #Restore selection # for face in faces_selected: # for loop in face.loops: # loop[uv_layers].select = True print("Islands: {}x".format(len(islands))) return islands