You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Blender-TexTools/utilities_uv.py

287 lines
8.5 KiB
Python

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