fix for error in line 164
[blender-addons-contrib.git] / mesh_extra_tools / mesh_vertex_chamfer.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
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.
7 #
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.
12 #
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.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 bl_info = {
22     "name": "Vertex Chamfer",
23     "author": "Andrew Hale (TrumanBlending)",
24     "version": (0, 1),
25     "blender": (2, 6, 3),
26     "location": "Spacebar Menu",
27     "description": "Chamfer vertex",
28     "wiki_url": "",
29     "tracker_url": "",
30     "category": "Mesh"}
31
32
33 import bpy
34 import bmesh
35
36
37 class VertexChamfer(bpy.types.Operator):
38     bl_idname = "mesh.vertex_chamfer"
39     bl_label = "Chamfer Vertex"
40     bl_description = "Tri chamfer selected vertices"
41     bl_options = {'REGISTER', 'UNDO'}
42
43     factor = bpy.props.FloatProperty(name="Factor",
44                                      default=0.1,
45                                      min=0.0,
46                                      soft_max=1.0)
47     relative = bpy.props.BoolProperty(name="Relative", default=True)
48     dissolve = bpy.props.BoolProperty(name="Remove", default=True)
49     displace = bpy.props.FloatProperty(name="Displace",
50                                        soft_min=-5.0,
51                                        soft_max=5.0)
52
53     @classmethod
54     def poll(self, context):
55         return (context.active_object.type == 'MESH' and
56                 context.mode == 'EDIT_MESH')
57
58     def draw(self, context):
59         layout = self.layout
60         layout.prop(self, "factor", text="Fac" if self.relative else "Dist")
61         sub = layout.row()
62         sub.prop(self, "relative")
63         sub.prop(self, "dissolve")
64         if not self.dissolve:
65             layout.prop(self, "displace")
66
67     def execute(self, context):
68         ob = context.active_object
69         me = ob.data
70         bm = bmesh.from_edit_mesh(me)
71
72         bm.select_flush(True)
73
74         fac = self.factor
75         rel = self.relative
76         dissolve = self.dissolve
77         displace = self.displace
78
79         for v in bm.verts:
80             v.tag = False
81
82         # Loop over edges to find those with both verts selected
83         for e in bm.edges[:]:
84             e.tag = e.select
85             if not e.select:
86                 continue
87             elen = e.calc_length()
88             val = fac if rel else fac / elen
89             val = min(val, 0.5)
90             # Loop over the verts of the edge to split
91             for v in e.verts:
92                 #if val == 0.5 and e.other_vert(v).tag:
93                 #    continue
94                 en, vn = bmesh.utils.edge_split(e, v, val)
95                 en.tag = vn.tag = True
96                 val = 1.0 if val == 1.0 else val / (1.0 - val)
97
98         # Get all verts which are selected but not created previously
99         verts = [v for v in bm.verts if v.select and not v.tag]
100
101         # Loop over all verts to split their linked edges
102         for v in verts:
103             for e in v.link_edges[:]:
104                 if e.tag:
105                     continue
106                 elen = e.calc_length()
107                 val = fac if rel else fac / elen
108                 bmesh.utils.edge_split(e, v, val)
109
110             # Loop over all the loops of the vert
111             for l in v.link_loops:
112                 # Split the face
113                 bmesh.utils.face_split(l.face,
114                                        l.link_loop_next.vert,
115                                        l.link_loop_prev.vert)
116
117             # Remove the vert or displace otherwise
118             if dissolve:
119                 bmesh.utils.vert_dissolve(v)
120             else:
121                 v.co += displace * v.normal
122
123         me.calc_tessface()
124
125         return {'FINISHED'}
126
127 class chamfer_help(bpy.types.Operator):
128         bl_idname = 'help.vertexchamfer'
129         bl_label = ''
130
131         def draw(self, context):
132                 layout = self.layout
133                 layout.label('To use:')
134                 layout.label('Make a selection or selection of verts ')
135                 layout.label('Result is triangle chamfer, works on single vert.')
136                 layout.label('In some cases may need to press F to fill result.')
137         
138         def execute(self, context):
139                 return {'FINISHED'}
140
141         def invoke(self, context, event):
142                 return context.window_manager.invoke_popup(self, width = 300)
143
144 def register():
145     bpy.utils.register_module(__name__)
146
147
148 def unregister():
149     bpy.utils.unregister_module(__name__)
150
151
152 if __name__ == "__main__":
153     register()