forked from franMarz/TexTools-Blender
-
Notifications
You must be signed in to change notification settings - Fork 0
/
op_island_align_edge.py
142 lines (103 loc) · 3.42 KB
/
op_island_align_edge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import bpy
import bmesh
import operator
import math
from mathutils import Vector
from collections import defaultdict
from math import pi
from . import utilities_uv
class op(bpy.types.Operator):
bl_idname = "uv.textools_island_align_edge"
bl_label = "Align Island by Edge"
bl_description = "Align the island by selected edge"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
#Only in UV editor mode
if bpy.context.area.type != 'IMAGE_EDITOR':
return False
if not bpy.context.active_object:
return False
if bpy.context.active_object.type != 'MESH':
return False
#Only in Edit mode
if bpy.context.active_object.mode != 'EDIT':
return False
if bpy.context.scene.tool_settings.use_uv_select_sync:
return False
#Requires UV map
if not bpy.context.object.data.uv_layers:
return False
# Requires UV Edge select mode
if bpy.context.scene.tool_settings.uv_select_mode != 'EDGE':
return False
return True
def execute(self, context):
#Store selection
utilities_uv.selection_store()
main(context)
#Restore selection
utilities_uv.selection_restore()
return {'FINISHED'}
def main(context):
print("Executing operator_island_align_edge")
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
uv_layers = bm.loops.layers.uv.verify()
faces_selected = [];
for face in bm.faces:
if face.select:
for loop in face.loops:
if loop[uv_layers].select:
faces_selected.append(face)
break
print("faces_selected: "+str(len(faces_selected)))
# Collect 2 uv verts for each island
face_uvs = {}
for face in faces_selected:
uvs = []
for loop in face.loops:
if loop[uv_layers].select:
uvs.append(loop[uv_layers])
if len(uvs) >= 2:
break
if len(uvs) >= 2:
face_uvs[face] = uvs
faces_islands = {}
faces_unparsed = faces_selected.copy()
for face in face_uvs:
if face in faces_unparsed:
bpy.ops.uv.select_all(action='DESELECT')
face_uvs[face][0].select = True;
bpy.ops.uv.select_linked()#Extend selection
#Collect faces
faces_island = [face];
for f in faces_unparsed:
if f != face and f.select and f.loops[0][uv_layers].select:
print("append "+str(f.index))
faces_island.append(f)
for f in faces_island:
faces_unparsed.remove(f)
#Assign Faces to island
faces_islands[face] = faces_island
print("Sets: {}x".format(len(faces_islands)))
# Align each island to its edges
for face in faces_islands:
align_island(face_uvs[face][0].uv, face_uvs[face][1].uv, faces_islands[face])
def align_island(uv_vert0, uv_vert1, faces):
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
uv_layers = bm.loops.layers.uv.verify()
print("Align {}x faces".format(len(faces)))
# Select faces
bpy.ops.uv.select_all(action='DESELECT')
for face in faces:
for loop in face.loops:
loop[uv_layers].select = True
diff = uv_vert1 - uv_vert0
angle = math.atan2(diff.y, diff.x)%(math.pi/2)
bpy.ops.uv.select_linked()
bpy.context.tool_settings.transform_pivot_point = 'CURSOR'
bpy.ops.uv.cursor_set(location=uv_vert0 + diff/2)
if angle >= (math.pi/4):
angle = angle - (math.pi/2)
bpy.ops.transform.rotate(value=angle, orient_axis='Z', constraint_axis=(False, False, False), orient_type='GLOBAL', mirror=False, use_proportional_edit=False)
bpy.utils.register_class(op)