Update for 2.8
[blender-addons.git] / mesh_extra_tools / mesh_check.py
blobc3d42837a379a57a839bafce958db09cddaa85cf
1 # gpl author: Pistiwique
3 bl_info = {
4 "name": "Mesh Check BGL edition",
5 "description": "Display the triangles and ngons of the mesh",
6 "author": "Pistiwique",
7 "version": (1, 0, 1),
8 "blender": (2, 75, 0),
9 "location": "3D View(s) > Properties > Shading",
10 "category": "3D View"
13 import bpy
14 import bmesh
15 from bgl import (
16 glBegin,
17 glLineWidth,
18 glColor4f,
19 glVertex3f,
20 glEnd,
21 GL_LINES,
22 glEnable,
23 glDisable,
24 GL_DEPTH_TEST,
25 GL_BLEND,
26 GL_POLYGON
28 from mathutils.geometry import tessellate_polygon as tessellate
29 from bpy.types import (
30 Operator,
31 PropertyGroup,
33 from bpy.props import (
34 BoolProperty,
35 EnumProperty,
36 FloatProperty,
37 FloatVectorProperty,
38 PointerProperty,
41 # -- Globals -- #
42 mesh_check_handle = []
43 draw_enabled = [False]
44 edge_width = [1.0]
45 face_opacity = [0.2]
46 edges_tri_color = [(1.0, 1.0, 0.0, 1)]
47 faces_tri_color = [(1.0, 1.0, 0.0, face_opacity[0])]
48 edges_ngons_color = [(1.0, 0.0, 0.0, 1.0)]
49 faces_ngons_color = [(1.0, 0.0, 0.0, face_opacity[0])]
50 bm_old = [None]
51 finer_lines = [False]
54 def draw_poly(points):
55 for i in range(len(points)):
56 glVertex3f(points[i][0], points[i][1], points[i][2])
59 def mesh_check_draw_callback():
60 obj = bpy.context.object
61 if obj and obj.type == 'MESH':
62 if draw_enabled[0]:
63 mesh = obj.data
64 matrix_world = obj.matrix_world
66 glLineWidth(edge_width[0])
68 if bpy.context.mode == 'EDIT_MESH':
69 use_occlude = True
71 if bm_old[0] is None or not bm_old[0].is_valid:
72 bm = bm_old[0] = bmesh.from_edit_mesh(mesh)
73 else:
74 bm = bm_old[0]
76 no_depth = not bpy.context.space_data.use_occlude_geometry
78 if no_depth:
79 glDisable(GL_DEPTH_TEST)
81 use_occlude = False
83 if finer_lines[0]:
84 glLineWidth(edge_width[0] / 4.0)
85 use_occlude = True
87 for face in bm.faces:
88 if len([verts for verts in face.verts]) == 3:
89 faces = [matrix_world * vert.co for vert in face.verts]
90 glColor4f(*faces_tri_color[0])
91 glEnable(GL_BLEND)
92 glBegin(GL_POLYGON)
93 draw_poly(faces)
94 glEnd()
96 for edge in face.edges:
97 if edge.is_valid:
98 edges = [matrix_world * vert.co for vert in edge.verts]
99 glColor4f(*edges_tri_color[0])
100 glBegin(GL_LINES)
101 draw_poly(edges)
102 glEnd()
104 elif len([verts for verts in face.verts]) > 4:
105 new_faces = []
106 faces = []
107 coords = [v.co for v in face.verts]
108 indices = [v.index for v in face.verts]
109 for pol in tessellate([coords]):
110 new_faces.append([indices[i] for i in pol])
112 for f in new_faces:
113 faces.append(
114 [((matrix_world * bm.verts[i].co)[0] + face.normal.x * 0.001,
115 (matrix_world * bm.verts[i].co)[1] + face.normal.y * 0.001,
116 (matrix_world * bm.verts[i].co)[2] + face.normal.z * 0.001)
117 for i in f]
120 for f in faces:
121 glColor4f(*faces_ngons_color[0])
122 glEnable(GL_BLEND)
123 glBegin(GL_POLYGON)
124 draw_poly(f)
125 glEnd()
127 for edge in face.edges:
128 if edge.is_valid:
129 edges = [matrix_world * vert.co for vert in edge.verts]
130 glColor4f(*edges_ngons_color[0])
131 glBegin(GL_LINES)
132 draw_poly(edges)
133 glEnd()
135 glDisable(GL_BLEND)
136 glColor4f(0.0, 0.0, 0.0, 1.0)
137 glLineWidth(edge_width[0])
138 glEnable(GL_DEPTH_TEST)
140 if use_occlude:
142 for face in bm.faces:
143 if len([verts for verts in face.verts]) == 3:
144 faces = []
145 for vert in face.verts:
146 vert_face = matrix_world * vert.co
147 faces.append(
148 (vert_face[0] + face.normal.x * 0.001,
149 vert_face[1] + face.normal.y * 0.001,
150 vert_face[2] + face.normal.z * 0.001)
153 glColor4f(*faces_tri_color[0])
154 glEnable(GL_BLEND)
155 glBegin(GL_POLYGON)
156 draw_poly(faces)
157 glEnd()
159 for edge in face.edges:
160 if edge.is_valid:
161 edges = []
162 for vert in edge.verts:
163 vert_edge = matrix_world * vert.co
164 edges.append(
165 (vert_edge[0] + face.normal.x * 0.001,
166 vert_edge[1] + face.normal.y * 0.001,
167 vert_edge[2] + face.normal.z * 0.001)
169 glColor4f(*edges_tri_color[0])
170 glBegin(GL_LINES)
171 draw_poly(edges)
172 glEnd()
174 elif len([verts for verts in face.verts]) > 4:
175 new_faces = []
176 faces = []
177 coords = [v.co for v in face.verts]
178 indices = [v.index for v in face.verts]
179 for pol in tessellate([coords]):
180 new_faces.append([indices[i] for i in pol])
182 for f in new_faces:
183 faces.append([
184 ((matrix_world * bm.verts[i].co)[0] + face.normal.x * 0.001,
185 (matrix_world * bm.verts[i].co)[1] + face.normal.y * 0.001,
186 (matrix_world * bm.verts[i].co)[2] + face.normal.z * 0.001)
187 for i in f]
190 for f in faces:
191 glColor4f(*faces_ngons_color[0])
192 glEnable(GL_BLEND)
193 glBegin(GL_POLYGON)
194 draw_poly(f)
195 glEnd()
197 for edge in face.edges:
198 if edge.is_valid:
199 edges = []
200 for vert in edge.verts:
201 vert_edge = matrix_world * vert.co
202 edges.append(
203 (vert_edge[0] + face.normal.x * 0.001,
204 vert_edge[1] + face.normal.y * 0.001,
205 vert_edge[2] + face.normal.z * 0.001)
207 glColor4f(*edges_ngons_color[0])
208 glBegin(GL_LINES)
209 draw_poly(edges)
210 glEnd()
212 glDisable(GL_BLEND)
213 glColor4f(0.0, 0.0, 0.0, 1.0)
216 def updateBGLData(self, context):
217 if self.mesh_check_use and self.display_faces:
218 bpy.ops.object.mode_set(mode='EDIT')
219 draw_enabled[0] = True
220 edge_width[0] = self.edge_width
221 finer_lines[0] = self.finer_lines_behind_use
222 face_opacity[0] = self.face_opacity
223 edges_tri_color[0] = (
224 self.custom_tri_color[0],
225 self.custom_tri_color[1],
226 self.custom_tri_color[2],
228 faces_tri_color[0] = (
229 self.custom_tri_color[0],
230 self.custom_tri_color[1],
231 self.custom_tri_color[2],
232 self.face_opacity
234 edges_ngons_color[0] = (
235 self.custom_ngons_color[0],
236 self.custom_ngons_color[1],
237 self.custom_ngons_color[2],
239 faces_ngons_color[0] = (
240 self.custom_ngons_color[0],
241 self.custom_ngons_color[1],
242 self.custom_ngons_color[2],
243 self.face_opacity
245 return
247 draw_enabled[0] = False
250 class FaceTypeSelect(Operator):
251 bl_idname = "object.face_type_select"
252 bl_label = "Face type select"
253 bl_description = "Select Triangles and / or Ngons on the Active Object"
254 bl_options = {'REGISTER', 'UNDO'}
256 face_type = EnumProperty(
257 name="Face Type",
258 items=(('tris', "Tris", "Colorize Triangles in the Mesh"),
259 ('ngons', "Ngons", "Colorize Ngons in the Mesh")),
260 default='ngons'
263 @classmethod
264 def poll(cls, context):
265 return context.active_object is not None and context.active_object.type == 'MESH'
267 def execute(self, context):
268 bpy.ops.object.mode_set(mode='EDIT')
269 bpy.ops.mesh.select_all(action='DESELECT')
270 context.tool_settings.mesh_select_mode = (False, False, True)
272 if self.face_type == "tris":
273 bpy.ops.mesh.select_face_by_sides(number=3, type='EQUAL')
274 else:
275 bpy.ops.mesh.select_face_by_sides(number=4, type='GREATER')
277 return {'FINISHED'}
280 class MeshCheckCollectionGroup(PropertyGroup):
281 mesh_check_use = BoolProperty(
282 name="Mesh Check",
283 description="Display Mesh Check options",
284 default=False,
285 update=updateBGLData
287 display_faces = BoolProperty(
288 name="Display Faces",
289 description="Use BGL to display Ngons and Tris of the mesh",
290 default=False,
291 update=updateBGLData
293 edge_width = FloatProperty(
294 name="Width",
295 description="Drawn Edges width in pixels",
296 min=1.0,
297 max=10.0,
298 default=3.0,
299 subtype='PIXEL',
300 update=updateBGLData
302 finer_lines_behind_use = BoolProperty(
303 name="Finer Lines behind",
304 description="Display partially hidden edges finer in non-occlude mode",
305 default=True,
306 update=updateBGLData
308 custom_tri_color = FloatVectorProperty(
309 name="Tri Color",
310 description="Custom color for the Triangles",
311 min=0.0,
312 max=1.0,
313 default=(1.0, 1.0, 0.0),
314 size=3,
315 subtype='COLOR',
316 update=updateBGLData
318 custom_ngons_color = FloatVectorProperty(
319 name="Ngons Color",
320 description="Custom color for the Ngons",
321 min=0.0,
322 max=1.0,
323 default=(1.0, 0.0, 0.0),
324 size=3,
325 subtype='COLOR',
326 update=updateBGLData
328 face_opacity = FloatProperty(
329 name="Face Opacity",
330 description="Opacity of the color for the face",
331 min=0.0,
332 max=1.0,
333 default=0.2,
334 subtype='FACTOR',
335 update=updateBGLData
339 # Register
340 classes = (
341 FaceTypeSelect,
342 MeshCheckCollectionGroup,
346 def register():
347 for cls in classes:
348 bpy.utils.register_class(cls)
350 bpy.types.WindowManager.mesh_check = PointerProperty(
351 type=MeshCheckCollectionGroup
353 if mesh_check_handle:
354 bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
355 mesh_check_handle[:] = [bpy.types.SpaceView3D.draw_handler_add(mesh_check_draw_callback,
356 (), 'WINDOW', 'POST_VIEW')]
359 def unregister():
360 del bpy.types.WindowManager.mesh_check
361 if mesh_check_handle:
362 bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
363 mesh_check_handle[:] = []
365 for cls in classes:
366 bpy.utils.unregister_class(cls)
369 if __name__ == "__main__":
370 register()