Skip to content
Snippets Groups Projects
split_solidify.py 5.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • # SPDX-License-Identifier: GPL-2.0-or-later
    
    
    bl_info = {
        "name": "Split Solidify",
        "author": "zmj100, updated by zeffii to BMesh",
        "version": (0, 1, 2),
        "blender": (2, 80, 0),
        "location": "View3D > Tool Shelf",
        "description": "",
        "warning": "",
    
        "doc_url": "",
        "category": "Mesh",
    }
    
    
    import bpy
    import bmesh
    from bpy.types import Operator
    from bpy.props import (
            EnumProperty,
            FloatProperty,
            BoolProperty,
            )
    import random
    from math import cos
    
    
    # define the functions
    def solidify_split(self, list_0):
    
        loc_random = self.loc_random
        random_dist = self.random_dist
        distance = self.distance
        thickness = self.thickness
        normal_extr = self.normal_extr
    
        bm = self.bm
    
        for fi in list_0:
            bm.faces.ensure_lookup_table()
            f = bm.faces[fi]
            list_1 = []
            list_2 = []
    
            if loc_random:
                d = random_dist * random.randrange(0, 10)
            elif not loc_random:
                d = distance
    
            # add new vertices
            for vi in f.verts:
                bm.verts.ensure_lookup_table()
                v = bm.verts[vi.index]
    
                if normal_extr == 'opt0':
                    p1 = (v.co).copy() + ((f.normal).copy() * d)                # out
                    p2 = (v.co).copy() + ((f.normal).copy() * (d - thickness))  # in
                elif normal_extr == 'opt1':
                    ang = ((v.normal).copy()).angle((f.normal).copy())
                    h = thickness / cos(ang)
                    p1 = (v.co).copy() + ((f.normal).copy() * d)
                    p2 = p1 + (-h * (f.normal).copy())
    
                v1 = bm.verts.new(p1)
                v2 = bm.verts.new(p2)
                v1.select = False
                v2.select = False
                list_1.append(v1)
                list_2.append(v2)
    
            # add new faces, allows faces with more than 4 verts
            n = len(list_1)
    
            k = bm.faces.new(list_1)
            k.select = False
            for i in range(n):
                j = (i + 1) % n
                vseq = list_1[i], list_2[i], list_2[j], list_1[j]
                k = bm.faces.new(vseq)
                k.select = False
    
            list_2.reverse()
            k = bm.faces.new(list_2)
            k.select = False
        bpy.ops.mesh.normals_make_consistent(inside=False)
    
    
        bmesh.update_edit_mesh(self.me, loop_triangles=True)
    
    
    
    class MESH_OT_split_solidify(Operator):
        bl_idname = "mesh.split_solidify"
        bl_label = "Split Solidify"
        bl_description = "Split and Solidify selected Faces"
        bl_options = {"REGISTER", "UNDO"}
    
        distance: FloatProperty(
                name="",
                description="Distance of the splitted Faces to the original geometry",
                default=0.4,
                min=-100.0, max=100.0,
                step=1,
                precision=3
                )
        thickness: FloatProperty(
                name="",
                description="Thickness of the splitted Faces",
                default=0.04,
                min=-100.0, max=100.0,
                step=1,
                precision=3
                )
        random_dist: FloatProperty(
                name="",
                description="Randomization factor of the splitted Faces' location",
                default=0.06,
                min=-10.0, max=10.0,
                step=1,
                precision=3
                )
        loc_random: BoolProperty(
                name="Random",
                description="Randomize the locations of splitted faces",
                default=False
                )
        del_original: BoolProperty(
                name="Delete original faces",
                default=True
                )
        normal_extr: EnumProperty(
                items=(('opt0', "Face", "Solidify along Face Normals"),
                       ('opt1', "Vertex", "Solidify along Vertex Normals")),
                name="Normal",
                default='opt0'
               )
    
        def draw(self, context):
            layout = self.layout
            layout.label(text="Normal:")
            layout.prop(self, "normal_extr", expand=True)
            layout.prop(self, "loc_random")
    
            if not self.loc_random:
                layout.label(text="Distance:")
                layout.prop(self, "distance")
            elif self.loc_random:
                layout.label(text="Random distance:")
                layout.prop(self, "random_dist")
    
            layout.label(text="Thickness:")
            layout.prop(self, "thickness")
            layout.prop(self, "del_original")
    
        def execute(self, context):
            obj = bpy.context.active_object
            self.me = obj.data
            self.bm = bmesh.from_edit_mesh(self.me)
            self.me.update()
    
            list_0 = [f.index for f in self.bm.faces if f.select]
    
            if len(list_0) == 0:
                self.report({'WARNING'},
                            "No suitable selection found. Operation cancelled")
    
                return {'CANCELLED'}
    
            elif len(list_0) != 0:
                solidify_split(self, list_0)
                context.tool_settings.mesh_select_mode = (True, True, True)
                if self.del_original:
                    bpy.ops.mesh.delete(type='FACE')
                else:
                    pass
    
            return {'FINISHED'}
    
    
    def register():
        bpy.utils.register_class(MESH_OT_split_solidify)
    
    
    def unregister():
        bpy.utils.unregister_class(MESH_OT_split_solidify)
    
    
    if __name__ == "__main__":
        register()