2019-06-08 23:42:50 +00:00
|
|
|
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():
|
2019-12-18 20:53:16 +00:00
|
|
|
bm = bmesh.from_edit_mesh(bpy.context.active_object.data);
|
|
|
|
uv_layers = bm.loops.layers.uv.verify();
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
# 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()
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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)
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
settings.selection_face_indexies = []
|
|
|
|
for face in bm.faces:
|
|
|
|
if face.select:
|
|
|
|
settings.selection_face_indexies.append(face.index)
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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] )
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def selection_restore(bm = None, uv_layers = None):
|
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
if bpy.context.object.mode != 'EDIT':
|
|
|
|
bpy.ops.object.mode_set(mode = 'EDIT')
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
if not bm:
|
|
|
|
bm = bmesh.from_edit_mesh(bpy.context.active_object.data);
|
|
|
|
if not uv_layers:
|
|
|
|
uv_layers = bm.loops.layers.uv.verify();
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
# 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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
contextViewUV = utilities_ui.GetContextViewUV()
|
|
|
|
if contextViewUV:
|
|
|
|
bpy.ops.uv.cursor_set(contextViewUV, location=settings.selection_uv_pivot_pos)
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
bpy.ops.mesh.select_all(action='DESELECT')
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
if hasattr(bm.verts, "ensure_lookup_table"):
|
|
|
|
bm.verts.ensure_lookup_table()
|
|
|
|
# bm.edges.ensure_lookup_table()
|
|
|
|
bm.faces.ensure_lookup_table()
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#Selection Mode
|
|
|
|
bpy.context.scene.tool_settings.mesh_select_mode = settings.selection_mode
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
bpy.context.view_layer.update()
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_selected_faces():
|
2019-12-18 20:53:16 +00:00
|
|
|
bm = bmesh.from_edit_mesh(bpy.context.active_object.data);
|
|
|
|
faces = [];
|
|
|
|
for face in bm.faces:
|
|
|
|
if face.select:
|
|
|
|
faces.append(face)
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
return faces
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_selected_faces(faces):
|
2019-12-18 20:53:16 +00:00
|
|
|
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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_selected_uvs(bm, uv_layers):
|
2019-12-18 20:53:16 +00:00
|
|
|
"""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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_selected_uv_verts(bm, uv_layers):
|
2019-12-18 20:53:16 +00:00
|
|
|
"""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)
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_selected_uv_edges(bm, uv_layers):
|
2019-12-18 20:53:16 +00:00
|
|
|
"""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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_selected_uv_faces(bm, uv_layers):
|
2019-12-18 20:53:16 +00:00
|
|
|
"""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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_vert_to_uv(bm, uv_layers):
|
2019-12-18 20:53:16 +00:00
|
|
|
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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_uv_to_vert(bm, uv_layers):
|
2019-12-18 20:53:16 +00:00
|
|
|
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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getSelectionBBox():
|
2019-12-18 20:53:16 +00:00
|
|
|
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;
|
2019-06-08 23:42:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getSelectionIslands(bm=None, uv_layers=None):
|
2019-12-18 20:53:16 +00:00
|
|
|
if bm == None:
|
|
|
|
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
|
|
|
|
uv_layers = bm.loops.layers.uv.verify()
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#Extend selection
|
|
|
|
if bpy.context.scene.tool_settings.use_uv_select_sync == False:
|
|
|
|
bpy.ops.uv.select_linked()
|
2019-06-08 23:42:50 +00:00
|
|
|
|
2019-12-18 20:53:16 +00:00
|
|
|
#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
|