Edit Tools 2: fix register error, mesh_check cleanup
DATA_OP_facetype_select operator was included in mesh_check but was also present in mesh_select_by_type Pep8 cleanup removed the panel draw code as it was already merged in init (displayMeshCheckPanel)
This commit is contained in:
parent
a1515dddab
commit
b54e4c07b2
|
@ -1,19 +1,19 @@
|
|||
# gpl author: Pistiwique
|
||||
|
||||
bl_info = {"name": "Mesh Check BGL edition",
|
||||
"description": "Display the triangles and ngons of the mesh",
|
||||
"author": "Pistiwique",
|
||||
"version": (1, 0, 0),
|
||||
"version": (1, 0, 1),
|
||||
"blender": (2, 75, 0),
|
||||
"location": "3D View(s) -> Properties -> Shading",
|
||||
"category": "3D View"
|
||||
}
|
||||
|
||||
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
from bgl import (
|
||||
glBegin,
|
||||
glLineWidth,
|
||||
glColor3f,
|
||||
glColor4f,
|
||||
glVertex3f,
|
||||
glEnd,
|
||||
|
@ -23,14 +23,21 @@ from bgl import (
|
|||
GL_DEPTH_TEST,
|
||||
GL_BLEND,
|
||||
GL_POLYGON
|
||||
)
|
||||
|
||||
)
|
||||
from mathutils.geometry import tessellate_polygon as tessellate
|
||||
import bmesh
|
||||
from mathutils import Vector
|
||||
from bpy.types import (
|
||||
Operator,
|
||||
PropertyGroup,
|
||||
)
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
PointerProperty,
|
||||
)
|
||||
|
||||
from bpy.props import EnumProperty, PointerProperty
|
||||
|
||||
# -- Globals -- #
|
||||
mesh_check_handle = []
|
||||
draw_enabled = [False]
|
||||
edge_width = [1.0]
|
||||
|
@ -41,133 +48,73 @@ edges_ngons_color = [(1.0, 0.0, 0.0, 1.0)]
|
|||
faces_ngons_color = [(1.0, 0.0, 0.0, face_opacity[0])]
|
||||
bm_old = [None]
|
||||
finer_lines = [False]
|
||||
|
||||
|
||||
|
||||
|
||||
def draw_poly(points):
|
||||
for i in range(len(points)):
|
||||
glVertex3f(points[i][0], points[i][1], points[i][2])
|
||||
|
||||
|
||||
|
||||
|
||||
def mesh_check_draw_callback():
|
||||
obj = bpy.context.object
|
||||
if obj and obj.type == 'MESH':
|
||||
if draw_enabled[0]:
|
||||
mesh = obj.data
|
||||
matrix_world = obj.matrix_world
|
||||
|
||||
|
||||
glLineWidth(edge_width[0])
|
||||
|
||||
|
||||
if bpy.context.mode == 'EDIT_MESH':
|
||||
|
||||
use_occlude = True
|
||||
|
||||
|
||||
if bm_old[0] is None or not bm_old[0].is_valid:
|
||||
bm = bm_old[0] = bmesh.from_edit_mesh(mesh)
|
||||
|
||||
else:
|
||||
bm = bm_old[0]
|
||||
|
||||
|
||||
no_depth = not bpy.context.space_data.use_occlude_geometry
|
||||
|
||||
|
||||
if no_depth:
|
||||
glDisable(GL_DEPTH_TEST)
|
||||
|
||||
|
||||
use_occlude = False
|
||||
|
||||
|
||||
if finer_lines[0]:
|
||||
glLineWidth(edge_width[0]/4.0)
|
||||
glLineWidth(edge_width[0] / 4.0)
|
||||
use_occlude = True
|
||||
|
||||
for face in bm.faces:
|
||||
if len([verts for verts in face.verts]) == 3:
|
||||
faces = [matrix_world*vert.co for vert in face.verts]
|
||||
faces = [matrix_world * vert.co for vert in face.verts]
|
||||
glColor4f(*faces_tri_color[0])
|
||||
glEnable(GL_BLEND)
|
||||
glBegin(GL_POLYGON)
|
||||
draw_poly(faces)
|
||||
glEnd()
|
||||
|
||||
|
||||
for edge in face.edges:
|
||||
if edge.is_valid:
|
||||
edges = [matrix_world*vert.co for vert in edge.verts]
|
||||
edges = [matrix_world * vert.co for vert in edge.verts]
|
||||
glColor4f(*edges_tri_color[0])
|
||||
glBegin(GL_LINES)
|
||||
draw_poly(edges)
|
||||
glEnd()
|
||||
|
||||
|
||||
elif len([verts for verts in face.verts]) > 4:
|
||||
new_faces = []
|
||||
faces = []
|
||||
coords = [v.co for v in face.verts]
|
||||
indices = [v.index for v in face.verts]
|
||||
indices = [v.index for v in face.verts]
|
||||
for pol in tessellate([coords]):
|
||||
new_faces.append([indices[i] for i in pol])
|
||||
|
||||
|
||||
for f in new_faces:
|
||||
faces.append([((matrix_world*bm.verts[i].co)[0]+face.normal.x*0.001,
|
||||
(matrix_world*bm.verts[i].co)[1]+face.normal.y*0.001,
|
||||
(matrix_world*bm.verts[i].co)[2]+face.normal.z*0.001)
|
||||
for i in f])
|
||||
|
||||
for f in faces:
|
||||
glColor4f(*faces_ngons_color[0])
|
||||
glEnable(GL_BLEND)
|
||||
glBegin(GL_POLYGON)
|
||||
draw_poly(f)
|
||||
glEnd()
|
||||
|
||||
for edge in face.edges:
|
||||
if edge.is_valid:
|
||||
edges = [matrix_world*vert.co for vert in edge.verts]
|
||||
glColor4f(*edges_ngons_color[0])
|
||||
glBegin(GL_LINES)
|
||||
draw_poly(edges)
|
||||
glEnd()
|
||||
|
||||
glDisable(GL_BLEND)
|
||||
glColor4f(0.0, 0.0, 0.0, 1.0)
|
||||
glLineWidth(edge_width[0])
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
if use_occlude:
|
||||
|
||||
for face in bm.faces:
|
||||
if len([verts for verts in face.verts]) == 3:
|
||||
faces = []
|
||||
for vert in face.verts:
|
||||
vert_face = matrix_world*vert.co
|
||||
faces.append((vert_face[0]+face.normal.x*0.001, vert_face[1]+face.normal.y*0.001, vert_face[2]+face.normal.z*0.001))
|
||||
|
||||
glColor4f(*faces_tri_color[0])
|
||||
glEnable(GL_BLEND)
|
||||
glBegin(GL_POLYGON)
|
||||
draw_poly(faces)
|
||||
glEnd()
|
||||
|
||||
for edge in face.edges:
|
||||
if edge.is_valid:
|
||||
edges = []
|
||||
for vert in edge.verts:
|
||||
vert_edge = matrix_world*vert.co
|
||||
edges.append((vert_edge[0]+face.normal.x*0.001, vert_edge[1]+face.normal.y*0.001, vert_edge[2]+face.normal.z*0.001))
|
||||
glColor4f(*edges_tri_color[0])
|
||||
glBegin(GL_LINES)
|
||||
draw_poly(edges)
|
||||
glEnd()
|
||||
|
||||
elif len([verts for verts in face.verts]) > 4:
|
||||
new_faces = []
|
||||
faces = []
|
||||
coords = [v.co for v in face.verts]
|
||||
indices = [v.index for v in face.verts]
|
||||
for pol in tessellate([coords]):
|
||||
new_faces.append([indices[i] for i in pol])
|
||||
|
||||
for f in new_faces:
|
||||
faces.append([((matrix_world*bm.verts[i].co)[0]+face.normal.x*0.001,
|
||||
(matrix_world*bm.verts[i].co)[1]+face.normal.y*0.001,
|
||||
(matrix_world*bm.verts[i].co)[2]+face.normal.z*0.001)
|
||||
for i in f])
|
||||
faces.append(
|
||||
[((matrix_world * bm.verts[i].co)[0] + face.normal.x * 0.001,
|
||||
(matrix_world * bm.verts[i].co)[1] + face.normal.y * 0.001,
|
||||
(matrix_world * bm.verts[i].co)[2] + face.normal.z * 0.001)
|
||||
for i in f]
|
||||
)
|
||||
|
||||
for f in faces:
|
||||
glColor4f(*faces_ngons_color[0])
|
||||
|
@ -175,24 +122,97 @@ def mesh_check_draw_callback():
|
|||
glBegin(GL_POLYGON)
|
||||
draw_poly(f)
|
||||
glEnd()
|
||||
|
||||
|
||||
for edge in face.edges:
|
||||
if edge.is_valid:
|
||||
edges = []
|
||||
for vert in edge.verts:
|
||||
vert_edge = matrix_world*vert.co
|
||||
edges.append((vert_edge[0]+face.normal.x*0.001, vert_edge[1]+face.normal.y*0.001, vert_edge[2]+face.normal.z*0.001))
|
||||
edges = [matrix_world * vert.co for vert in edge.verts]
|
||||
glColor4f(*edges_ngons_color[0])
|
||||
glBegin(GL_LINES)
|
||||
draw_poly(edges)
|
||||
glEnd()
|
||||
|
||||
|
||||
|
||||
glDisable(GL_BLEND)
|
||||
glColor4f(0.0, 0.0, 0.0, 1.0)
|
||||
|
||||
|
||||
|
||||
glLineWidth(edge_width[0])
|
||||
glEnable(GL_DEPTH_TEST)
|
||||
|
||||
if use_occlude:
|
||||
|
||||
for face in bm.faces:
|
||||
if len([verts for verts in face.verts]) == 3:
|
||||
faces = []
|
||||
for vert in face.verts:
|
||||
vert_face = matrix_world * vert.co
|
||||
faces.append(
|
||||
(vert_face[0] + face.normal.x * 0.001,
|
||||
vert_face[1] + face.normal.y * 0.001,
|
||||
vert_face[2] + face.normal.z * 0.001)
|
||||
)
|
||||
|
||||
glColor4f(*faces_tri_color[0])
|
||||
glEnable(GL_BLEND)
|
||||
glBegin(GL_POLYGON)
|
||||
draw_poly(faces)
|
||||
glEnd()
|
||||
|
||||
for edge in face.edges:
|
||||
if edge.is_valid:
|
||||
edges = []
|
||||
for vert in edge.verts:
|
||||
vert_edge = matrix_world * vert.co
|
||||
edges.append(
|
||||
(vert_edge[0] + face.normal.x * 0.001,
|
||||
vert_edge[1] + face.normal.y * 0.001,
|
||||
vert_edge[2] + face.normal.z * 0.001)
|
||||
)
|
||||
glColor4f(*edges_tri_color[0])
|
||||
glBegin(GL_LINES)
|
||||
draw_poly(edges)
|
||||
glEnd()
|
||||
|
||||
elif len([verts for verts in face.verts]) > 4:
|
||||
new_faces = []
|
||||
faces = []
|
||||
coords = [v.co for v in face.verts]
|
||||
indices = [v.index for v in face.verts]
|
||||
for pol in tessellate([coords]):
|
||||
new_faces.append([indices[i] for i in pol])
|
||||
|
||||
for f in new_faces:
|
||||
faces.append([
|
||||
(
|
||||
(matrix_world * bm.verts[i].co)[0] + face.normal.x * 0.001,
|
||||
(matrix_world * bm.verts[i].co)[1] + face.normal.y * 0.001,
|
||||
(matrix_world * bm.verts[i].co)[2] + face.normal.z * 0.001)
|
||||
for i in f]
|
||||
)
|
||||
|
||||
for f in faces:
|
||||
glColor4f(*faces_ngons_color[0])
|
||||
glEnable(GL_BLEND)
|
||||
glBegin(GL_POLYGON)
|
||||
draw_poly(f)
|
||||
glEnd()
|
||||
|
||||
for edge in face.edges:
|
||||
if edge.is_valid:
|
||||
edges = []
|
||||
for vert in edge.verts:
|
||||
vert_edge = matrix_world * vert.co
|
||||
edges.append(
|
||||
(vert_edge[0] + face.normal.x * 0.001,
|
||||
vert_edge[1] + face.normal.y * 0.001,
|
||||
vert_edge[2] + face.normal.z * 0.001)
|
||||
)
|
||||
glColor4f(*edges_ngons_color[0])
|
||||
glBegin(GL_LINES)
|
||||
draw_poly(edges)
|
||||
glEnd()
|
||||
|
||||
glDisable(GL_BLEND)
|
||||
glColor4f(0.0, 0.0, 0.0, 1.0)
|
||||
|
||||
|
||||
def updateBGLData(self, context):
|
||||
if self.mesh_check_use and self.display_faces:
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
@ -212,77 +232,74 @@ def updateBGLData(self, context):
|
|||
self.custom_ngons_color[1],
|
||||
self.custom_ngons_color[2],
|
||||
1)
|
||||
|
||||
|
||||
faces_ngons_color[0] = (self.custom_ngons_color[0],
|
||||
self.custom_ngons_color[1],
|
||||
self.custom_ngons_color[2],
|
||||
self.face_opacity)
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
draw_enabled[0] = False
|
||||
|
||||
|
||||
class FaceTypeSelect(bpy.types.Operator):
|
||||
|
||||
|
||||
class FaceTypeSelect(Operator):
|
||||
bl_idname = "object.face_type_select"
|
||||
bl_label = "Face type select"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
face_type = bpy.props.EnumProperty(
|
||||
|
||||
face_type = EnumProperty(
|
||||
items=(('tris', 'Tris', ""),
|
||||
('ngons', 'Ngons', "")),
|
||||
default='ngons'
|
||||
)
|
||||
|
||||
default='ngons'
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.active_object is not None and context.active_object.type == 'MESH'
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
context.tool_settings.mesh_select_mode=(False, False, True)
|
||||
|
||||
context.tool_settings.mesh_select_mode = (False, False, True)
|
||||
|
||||
if self.face_type == "tris":
|
||||
bpy.ops.mesh.select_face_by_sides(number=3, type='EQUAL')
|
||||
else:
|
||||
bpy.ops.mesh.select_face_by_sides(number=4, type='GREATER')
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class MeshCheckCollectionGroup(bpy.types.PropertyGroup):
|
||||
mesh_check_use = bpy.props.BoolProperty(
|
||||
|
||||
|
||||
class MeshCheckCollectionGroup(PropertyGroup):
|
||||
mesh_check_use = BoolProperty(
|
||||
name="Mesh Check",
|
||||
description="Display Mesh Check options",
|
||||
default=False,
|
||||
update=updateBGLData
|
||||
update=updateBGLData
|
||||
)
|
||||
|
||||
|
||||
display_faces = bpy.props.BoolProperty(
|
||||
display_faces = BoolProperty(
|
||||
name="Display Faces",
|
||||
description="Use BGL to display ngons en tris of the mesh",
|
||||
default=False,
|
||||
update=updateBGLData
|
||||
update=updateBGLData
|
||||
)
|
||||
|
||||
edge_width = bpy.props.FloatProperty(
|
||||
edge_width = FloatProperty(
|
||||
name="Width",
|
||||
description="Edges width in pixels",
|
||||
min=1.0,
|
||||
max=10.0,
|
||||
default=3.0,
|
||||
subtype='PIXEL',
|
||||
update=updateBGLData)
|
||||
|
||||
finer_lines_behind_use = bpy.props.BoolProperty(
|
||||
update=updateBGLData
|
||||
)
|
||||
finer_lines_behind_use = BoolProperty(
|
||||
name="Finer Lines behind",
|
||||
description="Display partially hidden edges finer in non-occlude mode",
|
||||
default=True,
|
||||
update=updateBGLData)
|
||||
|
||||
custom_tri_color = bpy.props.FloatVectorProperty(
|
||||
update=updateBGLData
|
||||
)
|
||||
custom_tri_color = FloatVectorProperty(
|
||||
name="Tri Color",
|
||||
description="Custom color for the triangles",
|
||||
min=0.0,
|
||||
|
@ -290,9 +307,9 @@ class MeshCheckCollectionGroup(bpy.types.PropertyGroup):
|
|||
default=(1.0, 1.0, 0.0),
|
||||
size=3,
|
||||
subtype='COLOR',
|
||||
update=updateBGLData)
|
||||
|
||||
custom_ngons_color = bpy.props.FloatVectorProperty(
|
||||
update=updateBGLData
|
||||
)
|
||||
custom_ngons_color = FloatVectorProperty(
|
||||
name="Ngons Color",
|
||||
description="custom color for the ngons",
|
||||
min=0.0,
|
||||
|
@ -300,143 +317,39 @@ class MeshCheckCollectionGroup(bpy.types.PropertyGroup):
|
|||
default=(1.0, 0.0, 0.0),
|
||||
size=3,
|
||||
subtype='COLOR',
|
||||
update=updateBGLData)
|
||||
|
||||
face_opacity = bpy.props.FloatProperty(
|
||||
update=updateBGLData
|
||||
)
|
||||
face_opacity = FloatProperty(
|
||||
name="Face Opacity",
|
||||
description="Opacity of the color for the face",
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
default=0.2,
|
||||
subtype='FACTOR',
|
||||
update=updateBGLData)
|
||||
|
||||
class DATA_OP_facetype_select(bpy.types.Operator):
|
||||
"""Select all faces of a certain type"""
|
||||
bl_idname = "data.facetype_select"
|
||||
bl_label = "Select by face type"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
select_mode = bpy.props.StringProperty()
|
||||
face_type = EnumProperty(name="Select faces:",
|
||||
items=(("3", "Triangles", "Faces made up of 3 vertices"),
|
||||
("5", "Ngons", "Faces made up of 5 and more vertices")),
|
||||
default="5")
|
||||
update=updateBGLData
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.object is not None and context.object.type == 'MESH'
|
||||
|
||||
def execute(self, context):
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
if tuple(bpy.context.tool_settings.mesh_select_mode) == (True, False, False):
|
||||
self.select_mode = "VERT"
|
||||
elif tuple(bpy.context.tool_settings.mesh_select_mode) == (False, True, False):
|
||||
self.select_mode = "EDGE"
|
||||
elif tuple(bpy.context.tool_settings.mesh_select_mode) == (False, False, True):
|
||||
self.select_mode = "FACE"
|
||||
context.tool_settings.mesh_select_mode = (False, False, True)
|
||||
if self.face_type == "3":
|
||||
bpy.ops.mesh.select_face_by_sides(number=3, type='EQUAL')
|
||||
bpy.ops.mesh.select_mode(type=self.select_mode)
|
||||
else:
|
||||
bpy.ops.mesh.select_face_by_sides(number=4, type='GREATER')
|
||||
bpy.ops.mesh.select_mode(type=self.select_mode)
|
||||
return {'FINISHED'}
|
||||
|
||||
def displayMeshCheckPanel(self, context):
|
||||
layout = self.layout
|
||||
icons = load_icons()
|
||||
tris = icons.get("triangles")
|
||||
ngons = icons.get("ngons")
|
||||
|
||||
|
||||
mesh_check = context.window_manager.mesh_check
|
||||
|
||||
layout.prop(mesh_check, "mesh_check_use")
|
||||
|
||||
if mesh_check.mesh_check_use:
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split2 = split.split()
|
||||
row = split2.row(align=True)
|
||||
row.operator("object.face_type_select", text="Tris", icon_value=tris.icon_id).face_type = 'tris'
|
||||
row.operator("object.face_type_select", text="Ngons",icon_value=ngons.icon_id).face_type = 'ngons'
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split.prop(mesh_check, "display_faces", text="Display Faces")
|
||||
if mesh_check.display_faces:
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split2 = split.split()
|
||||
row = split2.row(align=True)
|
||||
row.prop(mesh_check, "edge_width")
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split2 = split.split()
|
||||
row = split2.row()
|
||||
row.prop(mesh_check, "custom_tri_color",text="Tris color" )
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split2 = split.split()
|
||||
row = split2.row()
|
||||
row.prop(mesh_check, "custom_ngons_color")
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split2 = split.split()
|
||||
row = split2.row()
|
||||
row.prop(mesh_check, "face_opacity")
|
||||
if bpy.context.object.mode == 'EDIT':
|
||||
obj = bpy.context.object
|
||||
me = obj.data
|
||||
bm = bmesh.from_edit_mesh(me)
|
||||
|
||||
info_str = ""
|
||||
tris = ngons = 0
|
||||
|
||||
for f in bm.faces:
|
||||
|
||||
v = len(f.verts)
|
||||
if v == 3:
|
||||
tris += 1
|
||||
elif v > 4:
|
||||
ngons += 1
|
||||
|
||||
bmesh.update_edit_mesh(me)
|
||||
info_str = " Ngons: %i Tris: %i" % (ngons, tris)
|
||||
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split.label(info_str, icon='MESH_DATA')
|
||||
|
||||
if context.mode == 'EDIT_MESH' and not context.space_data.use_occlude_geometry:
|
||||
split = layout.split(percentage=0.1)
|
||||
split.separator()
|
||||
split2 = split.split()
|
||||
row = split2.row()
|
||||
row.prop(mesh_check, "finer_lines_behind_use")
|
||||
|
||||
|
||||
# Register
|
||||
classes = (
|
||||
FaceTypeSelect,
|
||||
MeshCheckCollectionGroup,
|
||||
DATA_OP_facetype_select
|
||||
)
|
||||
|
||||
def register():
|
||||
|
||||
def register():
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
bpy.types.WindowManager.mesh_check = bpy.props.PointerProperty(
|
||||
type=MeshCheckCollectionGroup)
|
||||
|
||||
bpy.types.WindowManager.mesh_check = PointerProperty(
|
||||
type=MeshCheckCollectionGroup
|
||||
)
|
||||
if mesh_check_handle:
|
||||
bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
|
||||
mesh_check_handle[:] = [bpy.types.SpaceView3D.draw_handler_add(mesh_check_draw_callback, (), 'WINDOW', 'POST_VIEW')]
|
||||
mesh_check_handle[:] = [bpy.types.SpaceView3D.draw_handler_add(mesh_check_draw_callback,
|
||||
(), 'WINDOW', 'POST_VIEW')]
|
||||
|
||||
|
||||
def unregister():
|
||||
|
||||
del bpy.types.WindowManager.mesh_check
|
||||
if mesh_check_handle:
|
||||
bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
|
||||
|
@ -444,5 +357,6 @@ def unregister():
|
|||
for cls in classes:
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
Loading…
Reference in New Issue