2025-12-01

This commit is contained in:
2026-03-17 14:58:51 -06:00
parent 183e865f8b
commit 4b82b57113
6846 changed files with 954887 additions and 162606 deletions
@@ -33,7 +33,7 @@ class AlignUv(Operator):
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bboxes.append(bbox)
@@ -41,13 +41,13 @@ class AlignUv(Operator):
return {'CANCELED'}
if self.align_uv == 'MAX_U':
max_u = max([bbox[1][0] for bbox in bboxes])
max_u = max(bbox[1][0] for bbox in bboxes)
for ob in context.objects_in_mode_unique_data:
seams = objects_seams[ob]
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_max_u = bbox[1][0]
distance = max_u - bbox_max_u
@@ -58,14 +58,14 @@ class AlignUv(Operator):
l[uv].uv = new_co
bmesh.update_edit_mesh(me)
if self.align_uv == 'MIN_U':
min_u = min([bbox[0][0] for bbox in bboxes])
elif self.align_uv == 'MIN_U':
min_u = min(bbox[0][0] for bbox in bboxes)
for ob in context.objects_in_mode_unique_data:
seams = objects_seams[ob]
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_min_u = bbox[0][0]
distance = bbox_min_u - min_u
@@ -76,14 +76,14 @@ class AlignUv(Operator):
l[uv].uv = new_co
bmesh.update_edit_mesh(me)
if self.align_uv == 'MAX_V':
max_v = max([bbox[1][1] for bbox in bboxes])
elif self.align_uv == 'MAX_V':
max_v = max(bbox[1][1] for bbox in bboxes)
for ob in context.objects_in_mode_unique_data:
seams = objects_seams[ob]
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_max_v = bbox[1][1]
distance = max_v - bbox_max_v
@@ -94,14 +94,14 @@ class AlignUv(Operator):
l[uv].uv = new_co
bmesh.update_edit_mesh(me)
if self.align_uv == 'MIN_V':
min_v = min([bbox[0][1] for bbox in bboxes])
elif self.align_uv == 'MIN_V':
min_v = min(bbox[0][1] for bbox in bboxes)
for ob in context.objects_in_mode_unique_data:
seams = objects_seams[ob]
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_min_v = bbox[0][1]
distance = bbox_min_v - min_v
@@ -121,10 +121,11 @@ class AlignUv(Operator):
uv = bm.loops.layers.uv.verify()
for f in bm.faces:
if f.select:
for l in f.loops:
if l[uv].select:
coords.append(l[uv].uv[:])
if not f.select:
continue
for l in f.loops:
if l.uv_select_edge:
coords.append(l[uv].uv[:])
if not coords:
return {'CANCELED'}
@@ -135,44 +136,53 @@ class AlignUv(Operator):
uv = bm.loops.layers.uv.verify()
if self.align_uv == 'MAX_U':
u = max([uv[0] for uv in coords])
u = max(uv[0] for uv in coords)
for f in bm.faces:
if f.select:
for l in f.loops:
if l[uv].select:
for l in l.vert.link_loops:
if l[uv].select:
l[uv].uv[0] = u
if not f.select:
continue
for l in f.loops:
if not l.uv_select_edge:
continue
for l in l.vert.link_loops:
if l.uv_select_edge:
l[uv].uv[0] = u
if self.align_uv == 'MIN_U':
u = min([uv[0] for uv in coords])
elif self.align_uv == 'MIN_U':
u = min(uv[0] for uv in coords)
for f in bm.faces:
if f.select:
for l in f.loops:
if l[uv].select:
for l in l.vert.link_loops:
if l[uv].select:
l[uv].uv[0] = u
if not f.select:
continue
for l in f.loops:
if not l.uv_select_edge:
continue
for l in l.vert.link_loops:
if l.uv_select_edge:
l[uv].uv[0] = u
if self.align_uv == 'MAX_V':
v = max([uv[1] for uv in coords])
elif self.align_uv == 'MAX_V':
v = max(uv[1] for uv in coords)
for f in bm.faces:
if f.select:
for l in f.loops:
if l[uv].select:
for l in l.vert.link_loops:
if l[uv].select:
l[uv].uv[1] = v
if not f.select:
continue
for l in f.loops:
if not l.uv_select_edge:
continue
for l in l.vert.link_loops:
if l.uv_select_edge:
l[uv].uv[1] = v
if self.align_uv == 'MIN_V':
v = min([uv[1] for uv in coords])
elif self.align_uv == 'MIN_V':
v = min(uv[1] for uv in coords)
for f in bm.faces:
if f.select:
for l in f.loops:
if l[uv].select:
for l in l.vert.link_loops:
if l[uv].select:
l[uv].uv[1] = v
if not f.select:
continue
for l in f.loops:
if not l.uv_select_edge:
continue
for l in l.vert.link_loops:
if l.uv_select_edge:
l[uv].uv[1] = v
bmesh.update_edit_mesh(me)
def execute(self, context):
@@ -247,7 +247,7 @@ class Distribute(Operator):
for f in bm.faces:
if f.select:
for l in f.loops:
if l[uv].select:
if l.uv_select_edge:
loops.add(l)
uv_edge_loops = get_sorted_uv_edge_loops(uv, loops)
@@ -4,6 +4,8 @@ from bpy.types import Operator
from bpy.props import StringProperty
from bpy_extras.io_utils import ExportHelper
from ..functions import get_addon_preferences
class ExportSettings(Operator, ExportHelper):
bl_idname = "uv.toolkit_export_settings"
@@ -19,16 +21,16 @@ class ExportSettings(Operator, ExportHelper):
)
def get_addon_properties(self):
addon_prefs_path = os.path.split(__file__)[0][:-9] + "addon_preferences.py"
addon_prefs_path = \
os.path.split(__file__)[0][:-9] + "addon_preferences.py"
with open(addon_prefs_path, 'r', encoding='utf-8') as file:
for line in file:
if ": EnumProperty" in line or ": StringProperty" in line:
yield line.split(" ")[4][:-1]
def execute(self, context):
preferences = context.preferences
def execute(self, _context):
with open(self.filepath, 'w', encoding='utf-8') as file:
for addon_property in self.get_addon_properties():
value = getattr(preferences.addons[__name__.partition('.')[0]].preferences, addon_property)
file.write(f"{addon_property}='{value}'" + '\n')
value = getattr(get_addon_preferences(), addon_property)
file.write(f"{addon_property}='{value}'\n")
return {'FINISHED'}
@@ -17,7 +17,7 @@ class FindShatteredIslands(Operator):
min=1,
default=3
)
pin: BoolProperty(
name="Pin to Corner",
description="Move and pin islands to the top-left corner within UV space\n(handy for testing your workflow under ideal conditions)",
@@ -53,11 +53,11 @@ class FindShatteredIslands(Operator):
face.select = True
for loop in face.loops:
if not use_uv_select_sync:
loop[uv_layer].select = True
loop.uv_select_edge_set(True)
if self.pin:
loop[uv_layer].uv = (0, 1)
loop[uv_layer].pin_uv = True
bmesh.update_edit_mesh(ob.data)
bm.free()
return {'FINISHED'}
@@ -46,12 +46,12 @@ class FindUdimCrossing(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
deselect_all_loops_uv(uv, bm)
deselect_all_loops_uv(bm)
if uv_sync_status:
select_all_faces(bm)
for island in get_islands(uv, bm, seams):
for island in get_islands(bm, seams):
bbox = get_bbox(uv, island)
bbox_u1, bbox_v1 = bbox[0][0], bbox[0][1]
bbox_u2, bbox_v2 = bbox[1][0], bbox[1][1]
@@ -70,7 +70,7 @@ class FindUdimCrossing(Operator):
for f in island:
for l in f.loops:
l[uv].select = True
l.uv_select_edge_set(True)
islands_count += 1
bmesh.update_edit_mesh(me)
@@ -51,7 +51,7 @@ class FitToBounds(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_center_u, bbox_center_v = calc_bbox_center(bbox)
bbox_width, bbox_height = get_bbox_size(bbox)
@@ -51,14 +51,14 @@ class InvertSelection(Operator):
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
bm.loops.layers.uv.verify()
loops = create_list_of_loops_from_uv_selection(uv, bm.faces)
loops = create_list_of_loops_from_uv_selection(bm.faces)
bpy.ops.uv.select_linked()
for l in loops:
l[uv].select = False
l.uv_select_edge_set(False)
bpy.ops.object.mode_set(mode='OBJECT')
ob.select_set(False)
@@ -103,7 +103,7 @@ class MatchIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for target_island in get_islands(uv, bm, seams, has_selected_faces=True):
for target_island in get_islands(bm, seams, has_selected_faces=True):
target_island_found = True
break
if target_island_found:
@@ -139,11 +139,11 @@ class MatchIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams):
for island in get_islands(bm, seams):
island_has_selection = False
for f in island:
for l in f.loops:
if l[uv].select:
if l.uv_select_edge:
island_has_selection = True
if island_has_selection:
break
@@ -9,9 +9,8 @@ class OpenAddonSettings(bpy.types.Operator):
def execute(self, context):
bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
bpy.data.window_managers["WinMan"].addon_search = "UV Toolkit"
bpy.context.preferences.active_section = 'ADDONS'
bpy.data.window_managers["WinMan"].addon_support = {
'OFFICIAL', 'COMMUNITY'
}
bpy.data.window_managers["WinMan"].addon_search = "UVToolkit"
context.preferences.active_section = 'ADDONS'
bpy.data.window_managers["WinMan"].addon_support = \
{'OFFICIAL', 'COMMUNITY'}
return {'FINISHED'}
@@ -93,7 +93,7 @@ class OrientIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
uv_edges_co = self.get_uv_edges_coordinates(uv, island)
uv_edges_angles = self.collect_uv_edges_angles(context, uv_edges_co)
rotation_angle = self.get_rotation_angle(uv_edges_angles)
@@ -37,11 +37,11 @@ class OrientToEdge(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
selected_uv_verts_co = {l[uv].uv.copy().freeze()
for f in island
for l in f.loops
if l[uv].select}
if l.uv_select_edge}
if not len(selected_uv_verts_co) >= 2:
continue
@@ -112,7 +112,7 @@ class RandomizeIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_center = calc_bbox_center(bbox)
@@ -47,11 +47,11 @@ class SelectFlippedIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams):
for island in get_islands(bm, seams):
if self.is_flipped_island(uv, island):
for f in island:
for l in f.loops:
l[uv].select = True
l.uv_select_edge_set(True)
scene.tool_settings.uv_select_mode = 'VERTEX'
scene.tool_settings.uv_select_mode = current_uv_select_mode
@@ -26,13 +26,12 @@ class SelectIslandBorder(Operator):
seams = objects_seams[ob]
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True):
for island in get_islands(bm, seams, has_selected_faces=True):
island_loops = set()
for f in island:
for l in f.loops:
l[uv].select = False
l.uv_select_edge_set(False)
island_loops.add(l)
for f in island:
@@ -41,12 +40,12 @@ class SelectIslandBorder(Operator):
for v in e.verts:
for l in v.link_loops:
if l in island_loops:
l[uv].select = True
l.uv_select_edge_set(True)
for l in f.loops:
if l.vert.is_boundary:
for l in l.vert.link_loops:
if l in island_loops:
l[uv].select = True
l.uv_select_edge_set(True)
bmesh.update_edit_mesh(me)
scene.tool_settings.uv_select_mode = 'VERTEX'
scene.tool_settings.uv_select_mode = current_uv_select_mode
@@ -61,7 +61,7 @@ class SelectSimilarIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True):
for island in get_islands(bm, seams, has_selected_faces=True):
current_bbox = get_bbox(uv, island)
current_bbox_size = get_bbox_size(current_bbox)
current_island_params = collect_island_params(uv, island)
@@ -83,7 +83,7 @@ class SelectSimilarIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
seams = objects_seams[ob]
for island in get_islands(uv, bm, seams):
for island in get_islands(bm, seams):
current_island_params = collect_island_params(uv, island)
target_island = islands_params.get(current_island_params)
if target_island:
@@ -94,7 +94,7 @@ class SelectSimilarIslands(Operator):
if self.is_same_bbox_size(target_bbox_size, current_bbox_size):
for f in island:
for l in f.loops:
l[uv].select = True
l.uv_select_edge_set(True)
bmesh.update_edit_mesh(me)
scene.tool_settings.uv_select_mode = 'VERTEX'
@@ -46,7 +46,6 @@ class SharpEdgesFromUvIslands(Operator):
for ob in mesh_ob:
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
view_layer.objects.active = ob
bpy.ops.mesh.customdata_custom_splitnormals_clear()
@@ -55,7 +54,7 @@ class SharpEdgesFromUvIslands(Operator):
f.smooth = True # Set all faces shaded smooth
for l in f.loops:
l.edge.smooth = True # Remove all sharp edges
if l[uv].select:
if l.uv_select_edge:
initial_selection[ob].add(l.index)
bpy.ops.uv.reveal()
@@ -70,13 +69,12 @@ class SharpEdgesFromUvIslands(Operator):
for ob in context.objects_in_mode_unique_data:
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for f in bm.faces:
for l in f.loops:
if l.index in initial_selection[ob]:
continue
l[uv].select = False
l.uv_select_edge_set(False)
if self.use_existing_seams:
for e in bm.edges:
if e.seam:
@@ -39,7 +39,7 @@ class StackIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_center = calc_bbox_center(bbox)
bbox_center_u = bbox_center[0]
@@ -62,6 +62,6 @@ class StackIslands(Operator):
else:
v = l[uv].uv[1] - offset_v
l[uv].uv = (u, v)
l[uv].select = True
l.uv_select_edge_set(True)
bmesh.update_edit_mesh(me)
return {'FINISHED'}
@@ -60,7 +60,7 @@ class StackSimilarIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
current_bbox = get_bbox(uv, island)
current_bbox_center = calc_bbox_center(current_bbox)
current_bbox_size = get_bbox_size(current_bbox)
@@ -83,7 +83,7 @@ class StackSimilarIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
seams = objects_seams[ob]
for island in get_islands(uv, bm, seams, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, islands_with_hidden_faces=False):
current_island_params = collect_island_params(uv, island)
target_island = islands_params.get(current_island_params)
if target_island:
@@ -113,6 +113,6 @@ class StackSimilarIslands(Operator):
else:
v = l[uv].uv[1] - offset_v
l[uv].uv = (u, v)
l[uv].select = True
l.uv_select_edge_set(True)
bmesh.update_edit_mesh(me)
return {'FINISHED'}
@@ -65,14 +65,14 @@ class StraightenIsland(Operator):
if l.edge.seam:
initial_seams.append(l.edge)
if l[uv].select:
if l.uv_select_edge:
initial_selection.add(l)
l[uv].pin_uv = True
for island in get_islands(uv, bm, seams, has_selected_faces=True):
for island in get_islands(bm, seams, has_selected_faces=True):
for f in island:
for l in f.loops:
if l[uv].select is False:
if l.uv_select_edge is False:
l[uv].pin_uv = False
if self.pin:
@@ -81,7 +81,7 @@ class StraightenIsland(Operator):
for f in bm.faces:
for l in f.loops:
l[uv].select = True
l.uv_select_edge_set(True)
bpy.ops.uv.seams_from_islands(mark_seams=True)
bpy.ops.uv.unwrap(method=self.method,
@@ -106,7 +106,7 @@ class StraightenIsland(Operator):
for l in f.loops:
if l in initial_selection:
continue
l[uv].select = False
l.uv_select_edge_set(False)
scene.tool_settings.uv_select_mode = current_uv_select_mode
@@ -461,7 +461,7 @@ class Straighten(Operator):
for l in uv_coords:
l[uv].uv = uv_coords[l]
for island in get_islands(uv, bm, seams, has_selected_faces=True):
for island in get_islands(bm, seams, has_selected_faces=True):
if self.properties.reshape_all:
island_has_an_hidden_faces = False
for f in island:
@@ -476,7 +476,7 @@ class Straighten(Operator):
for f in island:
for l in f.loops:
if not l[uv].select:
if not l.uv_select_edge:
deselected_loops_uv.add(f)
faces = {f for f in island
@@ -58,7 +58,7 @@ class UntackIslands(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
if self.axis == 'U':
if not is_initial_island:
@@ -57,7 +57,7 @@ class UnstackOverlappedUvs(Operator):
bm = bmesh.from_edit_mesh(me)
uv = bm.loops.layers.uv.verify()
for island in get_islands(uv, bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
for island in get_islands(bm, seams, has_selected_faces=True, islands_with_hidden_faces=False):
bbox = get_bbox(uv, island)
bbox_center_u, bbox_center_v = calc_bbox_center(bbox)
bbox_center = (float(f'{bbox_center_u:.5f}'), float(f'{bbox_center_v:.5f}'))
@@ -49,11 +49,11 @@ class UnwrapSelected(Operator):
if l.edge.seam:
initial_seams.append(l.edge)
if l[uv].select:
if l.uv_select_edge:
initial_selection.add(l)
else:
l[uv].pin_uv = True
l[uv].select = True
l.uv_select_edge_set(True)
bpy.ops.uv.seams_from_islands(mark_seams=True)
bpy.ops.uv.unwrap(method=self.method,
@@ -78,7 +78,7 @@ class UnwrapSelected(Operator):
for l in f.loops:
if l in initial_selection:
continue
l[uv].select = False
l.uv_select_edge_set(False)
def execute(self, context):
scene = context.scene
@@ -47,20 +47,16 @@ class UvSyncMode(Operator):
for ob in context.objects_in_mode_unique_data:
me = ob.data
bm = bmesh.from_edit_mesh(me)
uv_layer = bm.loops.layers.uv.verify()
if uv_sync_enable:
for face in bm.faces:
for loop in face.loops:
loop_uv = loop[uv_layer]
if not loop_uv.select:
if not loop.uv_select_edge:
face.select = False
for face in bm.faces:
for loop in face.loops:
loop_uv = loop[uv_layer]
if loop_uv.select:
if loop.uv_select_edge:
loop.vert.select = True
for edge in bm.edges:
@@ -71,31 +67,28 @@ class UvSyncMode(Operator):
if vert_count == 2:
edge.select = True
bmesh.update_edit_mesh(me)
continue
for face in bm.faces:
for loop in face.loops:
loop.uv_select_edge_set(False)
mesh_select_mode = context.tool_settings.mesh_select_mode[:]
if mesh_select_mode[2]: # face
for face in bm.faces:
if face.select:
for loop in face.loops:
if loop.vert.select:
loop.uv_select_edge_set(True)
else:
for face in bm.faces:
for loop in face.loops:
loop_uv = loop[uv_layer]
loop_uv.select = False
mesh_select_mode = context.tool_settings.mesh_select_mode[:]
if mesh_select_mode[2]: # face
for face in bm.faces:
if face.select:
for loop in face.loops:
loop_uv = loop[uv_layer]
if loop.vert.select:
loop_uv.select = True
else:
for face in bm.faces:
for loop in face.loops:
loop_uv = loop[uv_layer]
if loop.vert.select:
loop_uv.select = True
for face in bm.faces:
face.select = True
if loop.vert.select:
loop.uv_select_edge_set(True)
for face in bm.faces:
face.select = True
bmesh.update_edit_mesh(me)
def execute(self, context):