121 lines
4.0 KiB
Python
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)
|