Update for 2.8
[blender-addons.git] / mesh_extra_tools / mesh_vertex_chamfer.py
blobd6fd8080b15c26608476d46ce12c9059fd0bd635
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 bl_info = {
22 "name": "Vertex Chamfer",
23 "author": "Andrew Hale (TrumanBlending)",
24 "version": (0, 1),
25 "blender": (2, 63, 0),
26 "location": "Spacebar Menu",
27 "description": "Chamfer vertex",
28 "wiki_url": "",
29 "category": "Mesh"}
32 import bpy
33 import bmesh
34 from bpy.types import Operator
35 from bpy.props import (
36 BoolProperty,
37 FloatProperty,
41 class VertexChamfer(Operator):
42 bl_idname = "mesh.vertex_chamfer"
43 bl_label = "Chamfer Vertex"
44 bl_description = "Tri chamfer selected vertices"
45 bl_options = {'REGISTER', 'UNDO'}
47 factor = FloatProperty(
48 name="Factor",
49 description="Size of the Champfer",
50 default=0.1,
51 min=0.0,
52 soft_max=1.0
54 relative = BoolProperty(
55 name="Relative",
56 description="If Relative, Champfer size is relative to the edge lenght",
57 default=True
59 dissolve = BoolProperty(
60 name="Remove",
61 description="Remove/keep the original selected vertices\n"
62 "Remove creates a new triangle face between the Champfer edges,\n"
63 "similar to the Dissolve Vertices operator",
64 default=True
66 displace = FloatProperty(
67 name="Displace",
68 description="Active only if Remove option is disabled\n"
69 "Displaces the original selected vertices along the normals\n"
70 "defined by the Champfer edges",
71 soft_min=-5.0,
72 soft_max=5.0
75 @classmethod
76 def poll(self, context):
77 return (context.active_object.type == 'MESH' and
78 context.mode == 'EDIT_MESH')
80 def draw(self, context):
81 layout = self.layout
82 layout.prop(self, "factor", text="Distance" if self.relative else "Factor")
83 sub = layout.row()
84 sub.prop(self, "relative")
85 sub.prop(self, "dissolve")
86 if not self.dissolve:
87 layout.prop(self, "displace")
89 def execute(self, context):
90 ob = context.active_object
91 me = ob.data
92 bm = bmesh.from_edit_mesh(me)
94 bm.select_flush(True)
96 fac = self.factor
97 rel = self.relative
98 dissolve = self.dissolve
99 displace = self.displace
101 for v in bm.verts:
102 v.tag = False
104 # Loop over edges to find those with both verts selected
105 for e in bm.edges[:]:
106 e.tag = e.select
107 if not e.select:
108 continue
109 elen = e.calc_length()
110 val = fac if rel else fac / elen
111 val = min(val, 0.5)
112 # Loop over the verts of the edge to split
113 for v in e.verts:
114 # if val == 0.5 and e.other_vert(v).tag:
115 # continue
116 en, vn = bmesh.utils.edge_split(e, v, val)
117 en.tag = vn.tag = True
118 val = 1.0 if val == 1.0 else val / (1.0 - val)
120 # Get all verts which are selected but not created previously
121 verts = [v for v in bm.verts if v.select and not v.tag]
123 # Loop over all verts to split their linked edges
124 for v in verts:
125 for e in v.link_edges[:]:
126 if e.tag:
127 continue
128 elen = e.calc_length()
129 val = fac if rel else fac / elen
130 bmesh.utils.edge_split(e, v, val)
132 # Loop over all the loops of the vert
133 for l in v.link_loops:
134 # Split the face
135 bmesh.utils.face_split(
136 l.face,
137 l.link_loop_next.vert,
138 l.link_loop_prev.vert
141 # Remove the vert or displace otherwise
142 if dissolve:
143 bmesh.utils.vert_dissolve(v)
144 else:
145 v.co += displace * v.normal
147 me.calc_tessface()
149 return {'FINISHED'}
152 def register():
153 bpy.utils.register_class(VertexChamfer)
156 def unregister():
157 bpy.utils.unregister_class(VertexChamfer)
160 if __name__ == "__main__":
161 register()