Cleanup: simplify file name incrementing logic
[blender-addons.git] / mesh_tools / split_solidify.py
blob7158089e91c10e805c9403a06e5a6be948b2a5bb
1 # -*- coding: utf-8 -*-
3 # ##### BEGIN GPL LICENSE BLOCK #####
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # ##### END GPL LICENSE BLOCK #####
21 bl_info = {
22 "name": "Split Solidify",
23 "author": "zmj100, updated by zeffii to BMesh",
24 "version": (0, 1, 2),
25 "blender": (2, 80, 0),
26 "location": "View3D > Tool Shelf",
27 "description": "",
28 "warning": "",
29 "doc_url": "",
30 "category": "Mesh",
33 import bpy
34 import bmesh
35 from bpy.types import Operator
36 from bpy.props import (
37 EnumProperty,
38 FloatProperty,
39 BoolProperty,
41 import random
42 from math import cos
45 # define the functions
46 def solidify_split(self, list_0):
48 loc_random = self.loc_random
49 random_dist = self.random_dist
50 distance = self.distance
51 thickness = self.thickness
52 normal_extr = self.normal_extr
54 bm = self.bm
56 for fi in list_0:
57 bm.faces.ensure_lookup_table()
58 f = bm.faces[fi]
59 list_1 = []
60 list_2 = []
62 if loc_random:
63 d = random_dist * random.randrange(0, 10)
64 elif not loc_random:
65 d = distance
67 # add new vertices
68 for vi in f.verts:
69 bm.verts.ensure_lookup_table()
70 v = bm.verts[vi.index]
72 if normal_extr == 'opt0':
73 p1 = (v.co).copy() + ((f.normal).copy() * d) # out
74 p2 = (v.co).copy() + ((f.normal).copy() * (d - thickness)) # in
75 elif normal_extr == 'opt1':
76 ang = ((v.normal).copy()).angle((f.normal).copy())
77 h = thickness / cos(ang)
78 p1 = (v.co).copy() + ((f.normal).copy() * d)
79 p2 = p1 + (-h * (f.normal).copy())
81 v1 = bm.verts.new(p1)
82 v2 = bm.verts.new(p2)
83 v1.select = False
84 v2.select = False
85 list_1.append(v1)
86 list_2.append(v2)
88 # add new faces, allows faces with more than 4 verts
89 n = len(list_1)
91 k = bm.faces.new(list_1)
92 k.select = False
93 for i in range(n):
94 j = (i + 1) % n
95 vseq = list_1[i], list_2[i], list_2[j], list_1[j]
96 k = bm.faces.new(vseq)
97 k.select = False
99 list_2.reverse()
100 k = bm.faces.new(list_2)
101 k.select = False
102 bpy.ops.mesh.normals_make_consistent(inside=False)
104 bmesh.update_edit_mesh(self.me, True)
107 class MESH_OT_split_solidify(Operator):
108 bl_idname = "mesh.split_solidify"
109 bl_label = "Split Solidify"
110 bl_description = "Split and Solidify selected Faces"
111 bl_options = {"REGISTER", "UNDO"}
113 distance: FloatProperty(
114 name="",
115 description="Distance of the splitted Faces to the original geometry",
116 default=0.4,
117 min=-100.0, max=100.0,
118 step=1,
119 precision=3
121 thickness: FloatProperty(
122 name="",
123 description="Thickness of the splitted Faces",
124 default=0.04,
125 min=-100.0, max=100.0,
126 step=1,
127 precision=3
129 random_dist: FloatProperty(
130 name="",
131 description="Randomization factor of the splitted Faces' location",
132 default=0.06,
133 min=-10.0, max=10.0,
134 step=1,
135 precision=3
137 loc_random: BoolProperty(
138 name="Random",
139 description="Randomize the locations of splitted faces",
140 default=False
142 del_original: BoolProperty(
143 name="Delete original faces",
144 default=True
146 normal_extr: EnumProperty(
147 items=(('opt0', "Face", "Solidify along Face Normals"),
148 ('opt1', "Vertex", "Solidify along Vertex Normals")),
149 name="Normal",
150 default='opt0'
153 def draw(self, context):
154 layout = self.layout
155 layout.label(text="Normal:")
156 layout.prop(self, "normal_extr", expand=True)
157 layout.prop(self, "loc_random")
159 if not self.loc_random:
160 layout.label(text="Distance:")
161 layout.prop(self, "distance")
162 elif self.loc_random:
163 layout.label(text="Random distance:")
164 layout.prop(self, "random_dist")
166 layout.label(text="Thickness:")
167 layout.prop(self, "thickness")
168 layout.prop(self, "del_original")
170 def execute(self, context):
171 obj = bpy.context.active_object
172 self.me = obj.data
173 self.bm = bmesh.from_edit_mesh(self.me)
174 self.me.update()
176 list_0 = [f.index for f in self.bm.faces if f.select]
178 if len(list_0) == 0:
179 self.report({'WARNING'},
180 "No suitable selection found. Operation cancelled")
182 return {'CANCELLED'}
184 elif len(list_0) != 0:
185 solidify_split(self, list_0)
186 context.tool_settings.mesh_select_mode = (True, True, True)
187 if self.del_original:
188 bpy.ops.mesh.delete(type='FACE')
189 else:
190 pass
192 return {'FINISHED'}
195 def register():
196 bpy.utils.register_class(MESH_OT_split_solidify)
199 def unregister():
200 bpy.utils.unregister_class(MESH_OT_split_solidify)
203 if __name__ == "__main__":
204 register()