add_camera_rigs: refactor and cleanup
[blender-addons.git] / mesh_tools / split_solidify.py
blob690557ed584dc23f4accf3c8d14fc0a391fe68bc
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 "wiki_url": "",
30 "category": "Mesh"}
32 import bpy
33 import bmesh
34 from bpy.types import Operator
35 from bpy.props import (
36 EnumProperty,
37 FloatProperty,
38 BoolProperty,
40 import random
41 from math import cos
44 # define the functions
45 def solidify_split(self, list_0):
47 loc_random = self.loc_random
48 random_dist = self.random_dist
49 distance = self.distance
50 thickness = self.thickness
51 normal_extr = self.normal_extr
53 bm = self.bm
55 for fi in list_0:
56 bm.faces.ensure_lookup_table()
57 f = bm.faces[fi]
58 list_1 = []
59 list_2 = []
61 if loc_random:
62 d = random_dist * random.randrange(0, 10)
63 elif not loc_random:
64 d = distance
66 # add new vertices
67 for vi in f.verts:
68 bm.verts.ensure_lookup_table()
69 v = bm.verts[vi.index]
71 if normal_extr == 'opt0':
72 p1 = (v.co).copy() + ((f.normal).copy() * d) # out
73 p2 = (v.co).copy() + ((f.normal).copy() * (d - thickness)) # in
74 elif normal_extr == 'opt1':
75 ang = ((v.normal).copy()).angle((f.normal).copy())
76 h = thickness / cos(ang)
77 p1 = (v.co).copy() + ((f.normal).copy() * d)
78 p2 = p1 + (-h * (f.normal).copy())
80 v1 = bm.verts.new(p1)
81 v2 = bm.verts.new(p2)
82 v1.select = False
83 v2.select = False
84 list_1.append(v1)
85 list_2.append(v2)
87 # add new faces, allows faces with more than 4 verts
88 n = len(list_1)
90 k = bm.faces.new(list_1)
91 k.select = False
92 for i in range(n):
93 j = (i + 1) % n
94 vseq = list_1[i], list_2[i], list_2[j], list_1[j]
95 k = bm.faces.new(vseq)
96 k.select = False
98 list_2.reverse()
99 k = bm.faces.new(list_2)
100 k.select = False
101 bpy.ops.mesh.normals_make_consistent(inside=False)
103 bmesh.update_edit_mesh(self.me, True)
106 class MESH_OT_split_solidify(Operator):
107 bl_idname = "mesh.split_solidify"
108 bl_label = "Split Solidify"
109 bl_description = "Split and Solidify selected Faces"
110 bl_options = {"REGISTER", "UNDO"}
112 distance: FloatProperty(
113 name="",
114 description="Distance of the splitted Faces to the original geometry",
115 default=0.4,
116 min=-100.0, max=100.0,
117 step=1,
118 precision=3
120 thickness: FloatProperty(
121 name="",
122 description="Thickness of the splitted Faces",
123 default=0.04,
124 min=-100.0, max=100.0,
125 step=1,
126 precision=3
128 random_dist: FloatProperty(
129 name="",
130 description="Randomization factor of the splitted Faces' location",
131 default=0.06,
132 min=-10.0, max=10.0,
133 step=1,
134 precision=3
136 loc_random: BoolProperty(
137 name="Random",
138 description="Randomize the locations of splitted faces",
139 default=False
141 del_original: BoolProperty(
142 name="Delete original faces",
143 default=True
145 normal_extr: EnumProperty(
146 items=(('opt0', "Face", "Solidify along Face Normals"),
147 ('opt1', "Vertex", "Solidify along Vertex Normals")),
148 name="Normal",
149 default='opt0'
152 def draw(self, context):
153 layout = self.layout
154 layout.label(text="Normal:")
155 layout.prop(self, "normal_extr", expand=True)
156 layout.prop(self, "loc_random")
158 if not self.loc_random:
159 layout.label(text="Distance:")
160 layout.prop(self, "distance")
161 elif self.loc_random:
162 layout.label(text="Random distance:")
163 layout.prop(self, "random_dist")
165 layout.label(text="Thickness:")
166 layout.prop(self, "thickness")
167 layout.prop(self, "del_original")
169 def execute(self, context):
170 obj = bpy.context.active_object
171 self.me = obj.data
172 self.bm = bmesh.from_edit_mesh(self.me)
173 self.me.update()
175 list_0 = [f.index for f in self.bm.faces if f.select]
177 if len(list_0) == 0:
178 self.report({'WARNING'},
179 "No suitable selection found. Operation cancelled")
181 return {'CANCELLED'}
183 elif len(list_0) != 0:
184 solidify_split(self, list_0)
185 context.tool_settings.mesh_select_mode = (True, True, True)
186 if self.del_original:
187 bpy.ops.mesh.delete(type='FACE')
188 else:
189 pass
191 return {'FINISHED'}
194 def register():
195 bpy.utils.register_class(MESH_OT_split_solidify)
198 def unregister():
199 bpy.utils.unregister_class(MESH_OT_split_solidify)
202 if __name__ == "__main__":
203 register()