Files
blender-portable-repo/scripts/addons/TexTools_1_6_1/op_stitch.py
T
2026-03-17 14:30:01 -06:00

121 lines
4.0 KiB
Python

import bpy
import bmesh
import numpy as np
from mathutils import Vector
from . import op_select_islands_outline
from . import utilities_uv
class op(bpy.types.Operator):
bl_idname = "uv.textools_stitch"
bl_label = "Stitch"
bl_description = "Stitch other Islands to the selection"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
if bpy.context.area.ui_type != 'UV':
return False
if not bpy.context.active_object:
return False
if bpy.context.active_object.mode != 'EDIT':
return False
if bpy.context.active_object.type != 'MESH':
return False
if context.scene.tool_settings.use_uv_select_sync:
return False
if not bpy.context.object.data.uv_layers:
return False
return True
def execute(self, context):
utilities_uv.multi_object_loop(main, self, context)
return {'FINISHED'}
def main(self, context):
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
uv_layers = bm.loops.layers.uv.verify()
op_select_islands_outline.select_outline(self, context)
selection = {loop for face in bm.faces if face.select for loop in face.loops if loop[uv_layers].select_edge}
if selection:
selectionFaces = {loop.face for loop in selection}
selectionFacesTargets = {loop.link_loop_radial_next.face for loop in selection}
extended_selection = {loop.link_loop_radial_next for loop in selection}
extended_selection.update(selection)
#Store selection
utilities_uv.selection_store(bm, uv_layers)
islands, target_islands = utilities_uv.getSelectedUnselectedIslands(bm, uv_layers, selected_faces=selectionFaces, target_faces=selectionFacesTargets)
remaining_islands = islands.copy()
remaining_islands.extend(target_islands)
if islands:
for island in islands:
del remaining_islands[0]
if remaining_islands:
bpy.ops.uv.select_all(action='DESELECT')
loop1 = next(iter(island)).loops[0]
loop1[uv_layers].select=True
bpy.ops.uv.select_linked()
# Selection original coordinates
loop2 = loop1.link_loop_next
coords_before = (Vector((loop1[uv_layers].uv.x, loop1[uv_layers].uv.y)), Vector((loop2[uv_layers].uv.x, loop2[uv_layers].uv.y)))
# Stitch
op_select_islands_outline.select_outline(self, context)
selectionBorder = {loop for face in island for loop in face.loops if loop[uv_layers].select_edge}
selectionBorder.intersection_update(extended_selection)
loopsByTarget = [[] for _ in range(len(remaining_islands))]
for loop in selectionBorder:
targetFace = loop.link_loop_radial_next.face
if targetFace not in island:
for l, i in zip(loopsByTarget, remaining_islands):
if targetFace in i:
l.append(loop)
#l.append(loop.link_loop_next)
break
for grouped_loops in loopsByTarget:
bpy.ops.uv.select_all(action='DESELECT')
for base_loop in grouped_loops:
base_loop[uv_layers].select = True
base_loop[uv_layers].select_edge = True
bpy.ops.uv.stitch(use_limit=False, snap_islands=True, midpoint_snap=False, clear_seams=True, mode='EDGE')
# Relocate selection
coords_after = (Vector((loop1[uv_layers].uv.x, loop1[uv_layers].uv.y)), Vector((loop2[uv_layers].uv.x, loop2[uv_layers].uv.y)))
if coords_before != coords_after:
loop1[uv_layers].select = True
bpy.ops.uv.select_linked()
new_island = utilities_uv.get_selected_uv_faces(bm, uv_layers)
displace = coords_before[0] - coords_after[0]
vec_origin = coords_after[0]
V1 = coords_before[1] - coords_before[0]
V2 = coords_after[1] - coords_after[0]
theta = - np.math.atan2(np.linalg.det([V1,V2]),np.dot(V1,V2))
matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
for f in new_island:
for loop in f.loops:
uvs0 = loop[uv_layers].uv - vec_origin
loop[uv_layers].uv = (vec_origin.x + matrix[0][0]*uvs0.x + matrix[0][1]*uvs0.y + displace.x, vec_origin.y + matrix[1][0]*uvs0.x + matrix[1][1]*uvs0.y + displace.y)
#Restore selection
utilities_uv.selection_restore()
bpy.utils.register_class(op)