forked from drewcassidy/TexTools-Blender
-
Notifications
You must be signed in to change notification settings - Fork 1
/
op_select_islands_overlap.py
140 lines (94 loc) · 3.5 KB
/
op_select_islands_overlap.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
import bpy
import bmesh
import operator
from mathutils import Vector
from collections import defaultdict
from math import pi
from . import utilities_uv
import imp
imp.reload(utilities_uv)
class op(bpy.types.Operator):
bl_idname = "uv.textools_select_islands_overlap"
bl_label = "Select outline"
bl_description = "Select all overlapping UV islands"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
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
#Only in UV editor mode
if bpy.context.area.type != 'IMAGE_EDITOR':
return False
##Requires UV map
if not bpy.context.object.data.uv_layers:
return False
#Not in Synced mode
if bpy.context.scene.tool_settings.use_uv_select_sync:
return False
return True
def execute(self, context):
selectOverlap(context)
return {'FINISHED'}
def selectOverlap(context):
print("Execute op_select_islands_overlap")
# https://developer.blender.org/D2865
bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
uv_layers = bm.loops.layers.uv.verify()
bpy.context.scene.tool_settings.uv_select_mode = 'FACE'
bpy.ops.uv.select_all(action='SELECT')
islands_all = utilities_uv.getSelectionIslands()
# count = len(islands_all)
islands_bounds = []
for island in islands_all:
islands_bounds.append( Island_bounds( island ) )
groups = []
unmatched = islands_bounds.copy()
for islandA in islands_bounds:
if islandA in unmatched:
group = [islandA]
for islandB in unmatched:
if islandA != islandB and islandA.isEqual(islandB):
group.append(islandB)
for item in group:
unmatched.remove(item)
groups.append(group)
print("Group: {} islands, unmatched: {}x".format(len(group), len(unmatched)))
# groups.append( )
bpy.ops.uv.select_all(action='DESELECT')
for group in groups:
if len(group) > 1:
for i in range(1, len(group)):
utilities_uv.set_selected_faces( group[i].faces )
print("Groups: "+str(len(groups)))
class Island_bounds:
faces = []
center = Vector([0,0])
min = Vector([0,0])
max = Vector([0,0])
def __init__(self, faces):
bm = bmesh.from_edit_mesh(bpy.context.active_object.data);
uv_layers = bm.loops.layers.uv.verify();
# Collect topology stats
self.faces = faces
#Select Island
bpy.ops.uv.select_all(action='DESELECT')
utilities_uv.set_selected_faces(faces)
bounds = utilities_uv.getSelectionBBox()
self.center = bounds['center']
self.min = bounds['min']
self.max = bounds['max']
def isEqual(A, B):
# Bounding Box AABB intersection?
min_x = max(A.min.x, B.min.x)
min_y = max(A.min.y, B.min.y)
max_x = min(A.max.x, B.max.x)
max_y = min(A.max.y, B.max.y)
if not (max_x < min_x or max_y < min_y):
return True
return False
bpy.utils.register_class(op)