Import_3ds: Improved distance cue node setup
[blender-addons.git] / mesh_tools / split_solidify.py
blob1b14ec76fee525f18969a7b1dda3319fa22bcf4f
1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 bl_info = {
6 "name": "Split Solidify",
7 "author": "zmj100, updated by zeffii to BMesh",
8 "version": (0, 1, 2),
9 "blender": (2, 80, 0),
10 "location": "View3D > Tool Shelf",
11 "description": "",
12 "warning": "",
13 "doc_url": "",
14 "category": "Mesh",
17 import bpy
18 import bmesh
19 from bpy.types import Operator
20 from bpy.props import (
21 EnumProperty,
22 FloatProperty,
23 BoolProperty,
25 import random
26 from math import cos
29 # define the functions
30 def solidify_split(self, list_0):
32 loc_random = self.loc_random
33 random_dist = self.random_dist
34 distance = self.distance
35 thickness = self.thickness
36 normal_extr = self.normal_extr
38 bm = self.bm
40 for fi in list_0:
41 bm.faces.ensure_lookup_table()
42 f = bm.faces[fi]
43 list_1 = []
44 list_2 = []
46 if loc_random:
47 d = random_dist * random.randrange(0, 10)
48 elif not loc_random:
49 d = distance
51 # add new vertices
52 for vi in f.verts:
53 bm.verts.ensure_lookup_table()
54 v = bm.verts[vi.index]
56 if normal_extr == 'opt0':
57 p1 = (v.co).copy() + ((f.normal).copy() * d) # out
58 p2 = (v.co).copy() + ((f.normal).copy() * (d - thickness)) # in
59 elif normal_extr == 'opt1':
60 ang = ((v.normal).copy()).angle((f.normal).copy())
61 h = thickness / cos(ang)
62 p1 = (v.co).copy() + ((f.normal).copy() * d)
63 p2 = p1 + (-h * (f.normal).copy())
65 v1 = bm.verts.new(p1)
66 v2 = bm.verts.new(p2)
67 v1.select = False
68 v2.select = False
69 list_1.append(v1)
70 list_2.append(v2)
72 # add new faces, allows faces with more than 4 verts
73 n = len(list_1)
75 k = bm.faces.new(list_1)
76 k.select = False
77 for i in range(n):
78 j = (i + 1) % n
79 vseq = list_1[i], list_2[i], list_2[j], list_1[j]
80 k = bm.faces.new(vseq)
81 k.select = False
83 list_2.reverse()
84 k = bm.faces.new(list_2)
85 k.select = False
86 bpy.ops.mesh.normals_make_consistent(inside=False)
88 bmesh.update_edit_mesh(self.me, loop_triangles=True)
91 class MESH_OT_split_solidify(Operator):
92 bl_idname = "mesh.split_solidify"
93 bl_label = "Split Solidify"
94 bl_description = "Split and Solidify selected Faces"
95 bl_options = {"REGISTER", "UNDO"}
97 distance: FloatProperty(
98 name="",
99 description="Distance of the splitted Faces to the original geometry",
100 default=0.4,
101 min=-100.0, max=100.0,
102 step=1,
103 precision=3
105 thickness: FloatProperty(
106 name="",
107 description="Thickness of the splitted Faces",
108 default=0.04,
109 min=-100.0, max=100.0,
110 step=1,
111 precision=3
113 random_dist: FloatProperty(
114 name="",
115 description="Randomization factor of the splitted Faces' location",
116 default=0.06,
117 min=-10.0, max=10.0,
118 step=1,
119 precision=3
121 loc_random: BoolProperty(
122 name="Random",
123 description="Randomize the locations of splitted faces",
124 default=False
126 del_original: BoolProperty(
127 name="Delete original faces",
128 default=True
130 normal_extr: EnumProperty(
131 items=(('opt0', "Face", "Solidify along Face Normals"),
132 ('opt1', "Vertex", "Solidify along Vertex Normals")),
133 name="Normal",
134 default='opt0'
137 def draw(self, context):
138 layout = self.layout
139 layout.label(text="Normal:")
140 layout.prop(self, "normal_extr", expand=True)
141 layout.prop(self, "loc_random")
143 if not self.loc_random:
144 layout.label(text="Distance:")
145 layout.prop(self, "distance")
146 elif self.loc_random:
147 layout.label(text="Random distance:")
148 layout.prop(self, "random_dist")
150 layout.label(text="Thickness:")
151 layout.prop(self, "thickness")
152 layout.prop(self, "del_original")
154 def execute(self, context):
155 obj = bpy.context.active_object
156 self.me = obj.data
157 self.bm = bmesh.from_edit_mesh(self.me)
158 self.me.update()
160 list_0 = [f.index for f in self.bm.faces if f.select]
162 if len(list_0) == 0:
163 self.report({'WARNING'},
164 "No suitable selection found. Operation cancelled")
166 return {'CANCELLED'}
168 elif len(list_0) != 0:
169 solidify_split(self, list_0)
170 context.tool_settings.mesh_select_mode = (True, True, True)
171 if self.del_original:
172 bpy.ops.mesh.delete(type='FACE')
173 else:
174 pass
176 return {'FINISHED'}
179 def register():
180 bpy.utils.register_class(MESH_OT_split_solidify)
183 def unregister():
184 bpy.utils.unregister_class(MESH_OT_split_solidify)
187 if __name__ == "__main__":
188 register()