Skip to content
Snippets Groups Projects
mesh_ktools.py 99.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### BEGIN GPL LICENSE BLOCK #####
    #
    #  This program is free software; you can redistribute it and/or
    #  modify it under the terms of the GNU General Public License
    #  as published by the Free Software Foundation; either version 2
    #  of the License, or (at your option) any later version.
    #
    #  This program is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with this program; if not, write to the Free Software Foundation,
    #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # ##### END GPL LICENSE BLOCK #####
    
    
    
    
    bl_info = {
            'name': "Kjartans Scripts",
            'author': "Kjartan Tysdal",
            'location': '"Shift+Q" and also in EditMode "W-Specials/ KTools"',
            'description': "Adds my personal collection of small handy scripts (mostly modeling tools)",
            'category': "Mesh",
    
            'blender': (2, 76, 0),
    
            'version': (0, 2, 8),
            'wiki_url': 'http://www.kjartantysdal.com/scripts',
    }
    
    
    
    import bpy, bmesh
    
    from bpy.props import (
            StringProperty,
            IntProperty,
            FloatProperty,
            EnumProperty,
            BoolProperty,
            BoolVectorProperty,
            FloatVectorProperty,
            )
    
    
    
    def testPrint():
    
        print('Hello')
    
    def checkScale(): # check if scale is 0 on any of the axis, if it is then set it to 0.01
    
        y = -1
        for x in bpy.context.object.scale:
            y += 1
            if x == 0.0:
                bpy.context.object.scale[y] = 0.01
    
    
    
    #Adds "Lattice to Selection" to the Addon
    
    class lattice_to_selection(bpy.types.Operator):
    
            """Add a lattice deformer to the selection"""
            bl_idname = "object.lattice_to_selection"
            bl_label = "Lattice to Selection"
            bl_options = {'REGISTER', 'UNDO'}
    
    
            apply_rot: BoolProperty(
    
                            name = "Local",
                            description = "Orient the lattice to the active object",
                            default = True
                            )
    
            parent_to: BoolProperty(
    
                            name = "Parent to Lattice",
                            description = "Parents all the objects to the Lattice",
                            default = False
                            )
    
            move_first: BoolProperty(name = "First in Modifier Stack", description = "Moves the lattice modifier to be first in the stack", default = False)
            interpolation: bpy.props.EnumProperty(
    
                                       items= (('KEY_LINEAR', 'Linear', 'Linear Interpolation'),
                                       ('KEY_CARDINAL', 'Cardinal', 'Cardinal Interpolation'),
                                       ('KEY_CATMULL_ROM', 'Catmull Rom', 'Catmull Rom Interpolation'),
                                       ('KEY_BSPLINE', 'BSpline', 'BSpline Interpolation')),
                                       name = "Interpolation", default = 'KEY_BSPLINE')
    
            seg_u: IntProperty( name = "Lattice U", default = 2, soft_min = 2)
            seg_v: IntProperty( name = "Lattice V", default = 2, soft_min = 2 )
            seg_w: IntProperty( name = "Lattice W", default = 2, soft_min = 2 )
    
            def execute(self, context):
    
    
                    apply_rot = not self.apply_rot # Global vs Local
    
                    parent_to = self.parent_to # Parents all the objects to the Lattice
                    move_first = self.move_first # moves the lattice modifier to be first in the stack
                    interpolation = self.interpolation
    
                    # check if there exists an active object
    
                    if bpy.context.view_layer.objects.active:
                        active_obj = bpy.context.view_layer.objects.active.name
    
                    else:
                        for x in bpy.context.selected_objects:
                            if bpy.data.objects[x.name].type == 'MESH':
    
                                bpy.context.view_layer.objects.active = bpy.data.objects[x.name]
                                active_obj = bpy.context.view_layer.objects.active.name
    
                    if bpy.data.objects[active_obj].type != 'MESH':
                        self.report({'ERROR'}, "Make sure the active object is a Mesh")
                        return {'CANCELLED'}
    
                    mode = bpy.context.active_object.mode
    
                    if mode == 'OBJECT':
    
                        # check if object type is not MESH and then deselect it
                        for x in bpy.context.selected_objects:
                            if bpy.data.objects[x.name].type != 'MESH':
    
                                bpy.data.objects[x.name].select_set(False)
    
                        org_objs = bpy.context.selected_objects
    
                        bpy.ops.object.duplicate()
    
                        # remove any modifiers
                        if bpy.context.object.modifiers:
                            for x in bpy.context.object.modifiers:
                                bpy.ops.object.modifier_remove(modifier=x.name)
    
                        if len(bpy.context.selected_objects) > 1:
                            bpy.ops.object.join()
    
                        # create tmp:object and store its location, rotation and dimensions
                        bpy.ops.object.transform_apply(location=False, rotation=apply_rot, scale=True)
                        bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
    
                        lattice_loc = bpy.context.object.location
                        lattice_rot = bpy.context.object.rotation_euler
                        bbox_size = bpy.context.object.dimensions
                        tmp_obj = bpy.context.object.name
    
                        # create the lattice object with the lattice_loc and rot
                        bpy.ops.object.add(radius=1, type='LATTICE', view_align=False, enter_editmode=False, location=lattice_loc, rotation=lattice_rot)
    
                        lattice_obj = bpy.context.object
    
                        # set dimensions / bounding box size
                        bpy.context.object.scale = bbox_size
    
                        bpy.ops.object.select_all(action='DESELECT')
    
                        # select and delete the tmp_object
    
                        bpy.data.objects[tmp_obj].select_set(True)
    
                        bpy.ops.object.delete(use_global=False)
    
    
                        # select all the original objects and assign the lattice deformer
    
                        for i in org_objs:
                           if bpy.data.objects[i.name].type == 'MESH' :
    
                               bpy.context.view_layer.objects.active = bpy.data.objects[i.name]
    
                               bpy.data.objects[i.name].select_set(True)
    
                               bpy.ops.object.modifier_add(type='LATTICE')
                               lattice_name = bpy.context.object.modifiers[len(bpy.context.object.modifiers)-1].name
                               bpy.context.object.modifiers[lattice_name].object = lattice_obj
                               if move_first == True:
                                   for x in bpy.context.object.modifiers:
                                       bpy.ops.object.modifier_move_up(modifier=lattice_name)
                           else:
    
                               bpy.data.objects[i.name].select_set(True)
    
                        if parent_to:
    
                            bpy.data.objects[lattice_obj.name].select_set(True)
    
                            bpy.context.view_layer.objects.active = bpy.data.objects[lattice_obj.name]
    
                            bpy.ops.object.parent_set(type='OBJECT', keep_transform=True)
                        else:
    
                            bpy.ops.object.select_all(action='DESELECT')
    
                            bpy.data.objects[lattice_obj.name].select_set(True)
    
                            bpy.context.view_layer.objects.active = bpy.data.objects[lattice_obj.name]
    
    
                        bpy.context.object.data.interpolation_type_u = interpolation
                        bpy.context.object.data.interpolation_type_v = interpolation
                        bpy.context.object.data.interpolation_type_w = interpolation
    
                        bpy.context.object.data.points_u = self.seg_u
                        bpy.context.object.data.points_v = self.seg_v
                        bpy.context.object.data.points_w = self.seg_w
    
                    elif mode == 'EDIT':
    
                        org_objs = bpy.context.selected_objects
    
                        # Add vertex group and store its name in a variable
                        bpy.ops.object.vertex_group_assign_new()
                        v_id = len(bpy.context.object.vertex_groups)-1
                        bpy.context.object.vertex_groups[v_id].name = 'tmp_lattice_to_selection'
                        v_group = bpy.context.object.vertex_groups[v_id].name
    
    
                        bpy.ops.mesh.duplicate()
                        bpy.ops.mesh.separate(type='SELECTED')
    
                        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                        for x in bpy.context.selected_objects:
                            if x not in org_objs:
                                tmp_obj = x.name
                                print(tmp_obj)
    
                        bpy.ops.object.select_all(action='DESELECT')
    
                        bpy.context.view_layer.objects.active = bpy.data.objects[tmp_obj]
    
                        bpy.data.objects[tmp_obj].select_set(True)
    
                        if bpy.context.object.modifiers:
                            for x in bpy.context.object.modifiers:
                                bpy.ops.object.modifier_remove(modifier=x.name)
    
    
                        bpy.ops.object.transform_apply(location=False, rotation=apply_rot, scale=True)
                        bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
    
                        lattice_loc = bpy.context.object.location
                        lattice_rot = bpy.context.object.rotation_euler
                        bbox_size = bpy.context.object.dimensions
                        tmp_obj = bpy.context.object.name
    
    
                        bpy.ops.object.add(radius=1, type='LATTICE', view_align=False, enter_editmode=False, location=lattice_loc, rotation=lattice_rot)
    
                        lattice_obj = bpy.context.object
    
                        bpy.context.object.scale = bbox_size
    
                        bpy.ops.object.select_all(action='DESELECT')
    
    
    
                        bpy.data.objects[tmp_obj].select_set(True)
    
    
                        bpy.ops.object.delete(use_global=False)
    
    
                        bpy.context.view_layer.objects.active = bpy.data.objects[active_obj]
    
                        bpy.data.objects[active_obj].select_set(True)
    
                        bpy.ops.object.modifier_add(type='LATTICE')
                        lattice_name = bpy.context.object.modifiers[len(bpy.context.object.modifiers)-1].name
                        bpy.context.object.modifiers[lattice_name].object = lattice_obj
                        bpy.context.object.modifiers[lattice_name].vertex_group = v_group
    
                        if move_first == True:
                            for x in bpy.context.object.modifiers:
                                bpy.ops.object.modifier_move_up(modifier=lattice_name)
    
    
                        bpy.ops.object.select_all(action='DESELECT')
    
                        bpy.data.objects[lattice_obj.name].select_set(True)
    
                        bpy.context.view_layer.objects.active = bpy.data.objects[lattice_obj.name]
    
    
                        bpy.context.object.data.interpolation_type_u = interpolation
                        bpy.context.object.data.interpolation_type_v = interpolation
                        bpy.context.object.data.interpolation_type_w = interpolation
    
                        bpy.context.object.data.points_u = self.seg_u
                        bpy.context.object.data.points_v = self.seg_v
                        bpy.context.object.data.points_w = self.seg_w
    
    
    
    
                    return {'FINISHED'}
    
    
            def invoke( self, context, event ):
                wm = context.window_manager
                return wm.invoke_props_dialog( self )
    
    
    
    
    #Adds Calculate Normals and Smooth to the Addon
    
    class calc_normals(bpy.types.Operator):
    
            """Calculates and smooths normals."""
            bl_idname = "mesh.calc_normals"
            bl_label = "Calculate Normals"
            bl_options = {'REGISTER', 'UNDO'}
    
    
            invert: BoolProperty(name = "Invert Normals", description = "Inverts the normals.", default = False)
    
    
            def execute(self, context):
    
                    invert = self.invert
                    mode = bpy.context.active_object.mode
    
                    if mode == 'OBJECT':
    
                            sel = bpy.context.selected_objects
    
                            active = bpy.context.view_layer.objects.active.name
    
    
                            bpy.ops.object.shade_smooth()
    
    
                            for ob in sel:
                                    ob = ob.name
    
                                    bpy.context.view_layer.objects.active = bpy.data.objects[ob]
    
                                    bpy.ops.object.editmode_toggle()
                                    bpy.ops.mesh.select_all(action='SELECT')
                                    bpy.ops.mesh.normals_make_consistent(inside=invert)
                                    bpy.ops.object.editmode_toggle()
    
    
                            bpy.context.view_layer.objects.active = bpy.data.objects[active]
    
                    elif mode == 'EDIT':
                            bpy.ops.mesh.normals_make_consistent(inside=invert)
    
    
    
    
                    return {'FINISHED'}
    
    
    
    #Adds SnapToAxis to the Addon
    
    class snaptoaxis(bpy.types.Operator):
    
            """Snaps selected vertices to zero on the selected axis."""
            bl_idname = "mesh.snaptoaxis"
            bl_label = "Snap to Axis"
            bl_options = {'REGISTER', 'UNDO'}
    
            #worldspace = bpy.props.EnumProperty(items= (('OBJECT', 'Object Space', 'Snap to the object axis'),
    
            #                                                                                         ('WORLD', 'World Space', 'Snap to the global axis')),
            #                                                                                         name = "Object/World", default = 'OBJECT')
    
            snap_x: BoolProperty(name = "Snap to X", description = "Snaps to zero in X. Also sets the axis for the mirror modifier if that button is turned on", default = True)
            snap_y: BoolProperty(name = "Snap to Y", description = "Snaps to zero in Y. Also sets the axis for the mirror modifier if that button is turned on", default = False)
            snap_z: BoolProperty(name = "Snap to Z", description = "Snaps to zero in Z. Also sets the axis for the mirror modifier if that button is turned on", default = False)
    
            mirror_add: BoolProperty(name = "Add Mirror Modifier", description = "Adds a mirror modifer", default = False)
    
            mirror_x: BoolProperty(name = "Mirror on X", description = "Sets the modifier to mirror on X", default = True)
            mirror_y: BoolProperty(name = "Mirror on Y", description = "Sets the modifier to mirror on Y", default = False)
            mirror_z: BoolProperty(name = "Mirror on Z", description = "Sets the modifier to mirror on Z", default = False)
            clipping: BoolProperty(name = "Enable Clipping", description = "Prevents vertices from going through the mirror during transform", default = True)
    
    
    
    
            def draw(self, context):
                layout = self.layout
                col = layout.column()
    
                col_move = col.column(align=True)
                row = col_move.row(align=True)
                if self.snap_x:
                    row.prop(self, "snap_x", text = "X", icon='CHECKBOX_HLT')
                else:
                    row.prop(self, "snap_x", text = "X", icon='CHECKBOX_DEHLT')
                if self.snap_y:
                    row.prop(self, "snap_y", text = "Y", icon='CHECKBOX_HLT')
                else:
                    row.prop(self, "snap_y", text = "Y", icon='CHECKBOX_DEHLT')
                if self.snap_z:
                    row.prop(self, "snap_z", text = "Z", icon='CHECKBOX_HLT')
                else:
                    row.prop(self, "snap_z", text = "Z", icon='CHECKBOX_DEHLT')
    
                col.separator()
    
                col_move = col.column(align=True)
    
                col_move.prop(self, "mirror_add", icon = 'MODIFIER')
    
                row = col_move.row(align=True)
    
                row = col_move.row(align=True)
                row.active = self.mirror_add
                if self.mirror_x:
                    row.prop(self, "mirror_x", text = "X", icon='CHECKBOX_HLT')
                else:
                    row.prop(self, "mirror_x", text = "X", icon='CHECKBOX_DEHLT')
                if self.mirror_y:
                    row.prop(self, "mirror_y", text = "Y", icon='CHECKBOX_HLT')
                else:
                    row.prop(self, "mirror_y", text = "Y", icon='CHECKBOX_DEHLT')
                if self.mirror_z:
                    row.prop(self, "mirror_z", text = "Z", icon='CHECKBOX_HLT')
                else:
                    row.prop(self, "mirror_z", text = "Z", icon='CHECKBOX_DEHLT')
    
                col = col.column()
                col.active = self.mirror_add
    
                col.prop(self, "clipping")
    
    
    
            def execute(self, context):
    
                    mode = bpy.context.active_object.mode
                    mirror_find = bpy.context.object.modifiers.find('Mirror')
                    run = True
    
    
                    if mode == 'EDIT':
                        loc = bpy.context.object.location
    
                        me = bpy.context.object.data
                        bm = bmesh.from_edit_mesh(me)
    
                        for v in bm.verts:
                                if v.select:
                                    if self.snap_x == True:
                                        v.co.x = 0
                                    if self.snap_y == True:
                                        v.co.y = 0
                                    if self.snap_z == True:
                                        v.co.z = 0
    
                        bmesh.update_edit_mesh(me, True, False)
    
                    if self.mirror_add == True:
    
                        if mirror_find <= -1:
                            bpy.ops.object.modifier_add(type='MIRROR')
    
                            bpy.context.object.modifiers['Mirror'].show_viewport = True
    
                        bpy.context.object.modifiers["Mirror"].use_clip = self.clipping
                        bpy.context.object.modifiers["Mirror"].use_x = self.mirror_x
                        bpy.context.object.modifiers["Mirror"].use_y = self.mirror_y
                        bpy.context.object.modifiers["Mirror"].use_z = self.mirror_z
    
    
    
    
    
                    return {'FINISHED'}
    
    
    
    #Adds QuickBool to the Addon
    
    class quickbool(bpy.types.Operator):
    
            """Quickly carves out the selected polygons. Works best with manifold meshes."""
            bl_idname = "mesh.quickbool"
            bl_label = "Quick Bool"
            bl_options = {'REGISTER', 'UNDO'}
    
    
            del_bool: BoolProperty(name="Delete BoolMesh", description="Deletes the objects used for the boolean operation.", default= True)
            move_to: BoolProperty(name="Move to layer 10", description="Moves the objects used for the boolean operation to layer 10", default= False)
            operation: EnumProperty(items= (('UNION', 'Union', 'Combines'),
    
                                                                                                     ('INTERSECT', 'Intersect', 'Keep the part that overlaps'),
    
                                                                                                     ('DIFFERENCE', 'Difference', 'Cuts out')),
    
                                                                                                     name = "Operation", default = 'DIFFERENCE')
    
    
            def draw(self, context):
                layout = self.layout
                col = layout.column()
                col.prop(self, "del_bool")
    
                col = col.column()
                col.active = self.del_bool == False
    
                col.prop(self, "move_to")
    
    
                col = layout.column()
                col.prop(self, "operation")
    
    
            def execute(self, context):
    
                    del_bool = self.del_bool
                    move_to = self.move_to
                    mode = bpy.context.active_object.mode
    
    
                    if mode == 'EDIT':
    
                        #Boolean From Edit mode
                        bpy.ops.mesh.select_linked()
                        bpy.ops.mesh.separate(type='SELECTED')
                        bpy.ops.object.editmode_toggle()
    
                        #get name of Original+Bool object
                        original = bpy.context.selected_objects[1].name
                        bool = bpy.context.selected_objects[0].name
    
                        #perform boolean
                        bpy.ops.object.modifier_add(type='BOOLEAN')
                        bpy.context.object.modifiers["Boolean"].object = bpy.data.objects[bool]
                        bpy.context.object.modifiers["Boolean"].operation = self.operation
                        bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
    
                        #delete Bool object
                        bpy.ops.object.select_all(action='DESELECT')
                        bpy.ops.object.select_pattern(pattern=bool)
    
    
                        bpy.context.view_layer.objects.active = bpy.data.objects[bool]
    
    
                        #Delete all geo inside Shrink_Object
                        bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
                        bpy.ops.mesh.select_all(action='SELECT')
                        bpy.ops.mesh.delete(type='VERT')
                        bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
    
                        bpy.ops.object.delete()
    
                        #re-enter edit mode on Original object
    
                        bpy.context.view_layer.objects.active = bpy.data.objects[original]
    
                        bpy.ops.object.select_pattern(pattern=original)
                        bpy.ops.object.editmode_toggle()
    
    
                    else:
    
                            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                            original = bpy.context.active_object.name
                            bool = bpy.context.selected_objects
    
                            for x in bool:
                                    x = x.name
                                    if x != original:
                                            list.append(x)
    
                            for name in list:
                                    #Perform Boolean
                                    bpy.ops.object.modifier_add(type='BOOLEAN')
                                    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects[name]
                                    bpy.context.object.modifiers["Boolean"].operation = self.operation
                                    bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")
    
                                    if del_bool == True:
    
                                            bpy.ops.object.select_all(action='DESELECT')
                                            bpy.ops.object.select_pattern(pattern=name)
    
                                            bpy.context.view_layer.objects.active = bpy.data.objects[name]
    
    
                                #Delete all geo inside Shrink_Object
                                            bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
                                            bpy.ops.mesh.select_all(action='SELECT')
                                            bpy.ops.mesh.delete(type='VERT')
                                            bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
    
                                            bpy.ops.object.delete(use_global=False)
    
                                            bpy.context.view_layer.objects.active = bpy.data.objects[original]
    
                                    else:
    
                                            bpy.ops.object.select_all(action='DESELECT')
                                            bpy.ops.object.select_pattern(pattern=name)
    
                                            bpy.context.view_layer.objects.active = bpy.data.objects[name]
    
                                            bpy.context.object.display_type = 'WIRE'
    
                                            # Move to garbage layer
                                            if move_to == True:
                                                    bpy.ops.object.move_to_layer(layers=(False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False))
    
                                            bpy.context.view_layer.objects.active = bpy.data.objects[original]
    
    
                            bpy.ops.object.mode_set(mode=mode, toggle=False)
    
    
    
                    return {'FINISHED'}
    
    #Adds Autotubes to the Addon
    
    class autotubes(bpy.types.Operator):
    
            """Creates a spline tube based on selected edges"""
            bl_idname = "mesh.autotubes"
            bl_label = "Auto Tubes"
            bl_options = {'REGISTER', 'UNDO'}
    
            bevel: FloatProperty(name="Tube Width", description="Change width of the tube.", default=0.1, min = 0)
            res: IntProperty(name="Tube Resolution", description="Change resolution of the tube.", default=2, min = 0, max = 20)
    
    
            def execute(self, context):
    
                    mode = bpy.context.active_object.mode
                    type = bpy.context.active_object.type
    
                    bevel = self.bevel
    
                    res = self.res
    
    
                    if mode == 'EDIT' and type == 'MESH':
                            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                            bpy.ops.object.duplicate()
    
                            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
                            bpy.ops.mesh.select_all(action='INVERT')
                            bpy.ops.mesh.delete(type='EDGE')
    
                            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                            bpy.ops.object.subdivision_set(level=0)
                            bpy.ops.object.convert(target='CURVE')
                            bpy.context.object.data.fill_mode = 'FULL'
                            bpy.context.object.data.bevel_depth = 0.1
                            bpy.context.object.data.splines[0].use_smooth = True
                            bpy.context.object.data.bevel_resolution = 2
                            bpy.ops.object.shade_smooth()
    
                            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
                            bpy.ops.curve.spline_type_set(type='BEZIER')
    
                            bpy.context.object.data.bevel_depth = bevel
                            bpy.context.object.data.bevel_resolution = res
    
                            #bpy.ops.transform.transform(('INVOKE_DEFAULT'), mode='CURVE_SHRINKFATTEN')
    
                    elif type == 'CURVE':
    
                            bpy.context.object.data.bevel_depth = bevel
                            bpy.context.object.data.bevel_resolution = res
    
                    elif mode != 'EDIT' and type == 'MESH':
                            self.report({'ERROR'}, "This one only works in Edit mode")
                            return {'CANCELLED'}
    
    
    
                    return {'FINISHED'}
    
    #Adds basicRename to the Addon
    
    
    class basicRename(bpy.types.Operator):
    
            """Renames everything to Banana"""
            bl_idname = "object.basic_rename"
            bl_label = "Basic Renamer"
            bl_options = {'REGISTER', 'UNDO'}
    
            name: StringProperty(name="Rename", description="Rename selected objects", default="banana")
            padding: IntProperty(name = "Number Padding", description = "Adds how many padded numbers", default = 3, min = 1, max = 8)
            prefix:    StringProperty(name="Pre Fix", description="Adds a Prefix to the name", default="")
            post_ob: StringProperty(name="Post Fix Object", description="Adds ending to object name", default="_MDL")
            post_data: StringProperty(name="Post Fix Data", description="Adds ending to data name", default="_DATA")
    
            def execute(self, context):
    
    
    
                    # The original script
                    obj = bpy.context.selected_objects
                    name = self.name
                    padding = self.padding
                    prefix = self.prefix
                    post_ob = self.post_ob
                    post_data = self.post_data
                    number = 0
                    for item in obj:
                            number += 1
                            item.name = "%s%s_%s%s" %(str(prefix), str(name), str(number).zfill(padding), str(post_ob))
    
                            item.data.name = "%s%s_%s%s" %(str(prefix), str(name), str(number).zfill(padding), str(post_data))
    
    
    
                    return {'FINISHED'}
    
    
    
    class cut_tool(bpy.types.Operator):
    
            """Context sensitive cut tool"""
            bl_idname = "mesh.cut_tool"
            bl_label = "Cut Tool"
            bl_options = {'REGISTER', 'UNDO'}
    
            cuts: IntProperty(name="Number of Cuts", description="Change the number of cuts.", default=1, min = 1, soft_max = 10)
            loopcut: BoolProperty(name="Insert LoopCut", description="Makes a loop cut based on the selected edges", default= False)
            smoothness: FloatProperty(name="Smoothness", description="Change the smoothness.", default=0, min = 0, soft_max = 1)
            quad_corners: bpy.props.EnumProperty(items= (('INNERVERT', 'Inner Vert', 'How to subdivide quad corners'),
    
                                                                                                     ('PATH', 'Path', 'How to subdivide quad corners'),
    
                                                                                                     ('STRAIGHT_CUT', 'Straight Cut', 'How to subdivide quad corners'),
    
                                                                                                     ('FAN', 'Fan', 'How to subdivide quad corners')),
    
                                                                                                     name = "Quad Corner Type", default = 'STRAIGHT_CUT')
    
    
            def execute(self, context):
    
                    quad_corners = self.quad_corners
                    cuts = self.cuts
                    loopcut = self.loopcut
                    smoothness = self.smoothness
                    mode = bpy.context.active_object.mode
    
                    if mode == 'EDIT':
    
                            sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
    
                                                            #Checks and stores if any Vert, Edge or Face is selected.
                            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                            me = bpy.context.object.data
                            bm = bmesh.new()     # create an empty BMesh
                            bm.from_mesh(me)     # fill it in from a Mesh
                            sel = []
                            edge_sel = []
                            vert_sel = []
    
                            for v in bm.faces:
                                    if v.select:
                                            sel.append(v.index)
                            for v in bm.edges:
                                    if v.select:
                                            edge_sel.append(v.index)
                            for v in bm.verts:
                                    if v.select:
                                            vert_sel.append(v.index)
    
                            bm.to_mesh(me)
                            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
                            if len(sel) == 0 and len(edge_sel) == 0 and len(vert_sel) == 0 :
                                    bpy.ops.mesh.knife_tool("INVOKE_DEFAULT")
    
                            if sel_mode[2] == True and len(sel) > 1:
    
                                    vgrp = bpy.context.object.vertex_groups.active_index
    
    
                                    #Store the Hidden Polygons
                                    bpy.ops.mesh.select_all(action='SELECT')
                                    bpy.ops.object.vertex_group_assign_new()
                                    tmp_hidden = bpy.context.object.vertex_groups.active_index
                                    bpy.ops.mesh.select_all(action='DESELECT')
    
                                    #Select faces to be cut
                                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                                    mesh = bpy.context.active_object.data.polygons
    
                                    for f in sel:
                                            mesh[f].select = True
    
                                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
                                    bpy.ops.mesh.hide(unselected=True)
                                    bpy.ops.mesh.select_all(action='SELECT')
                                    bpy.ops.mesh.region_to_loop()
    
                                    #Store Boundry Edges
                                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                                    me = bpy.context.object.data
    
                                    bm = bmesh.new()
                                    bm.from_mesh(me)
    
                                    boundry_edge = []
    
                                    for v in bm.edges:
                                            if v.select:
                                                    boundry_edge.append(v.index)
    
                                    bm.to_mesh(me)
    
                                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
                                    #Store Cut Edges
                                    bpy.ops.mesh.select_all(action='INVERT')
                                    bpy.ops.mesh.loop_multi_select(ring=True)
    
                                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                                    me = bpy.context.object.data
    
                                    bm = bmesh.new()
                                    bm.from_mesh(me)
    
                                    cut_edges = []
    
                                    for v in bm.edges:
                                            if v.select:
                                                    cut_edges.append(v.index)
    
                                    bm.to_mesh(me)
    
                                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
                                    #Store Intersection edges
                                    bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
                                    bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
    
                                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                                    me = bpy.context.object.data
    
                                    bm = bmesh.new()
                                    bm.from_mesh(me)
    
                                    int_edges = []
    
                                    for v in bm.edges:
                                            if v.select:
                                                    int_edges.append(v.index)
    
                                    bm.to_mesh(me)
    
                                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
                                    #Modify Lists
                                    for x in int_edges:
                                            if x in boundry_edge:
                                                    cut_edges.remove(x)
    
                                    bpy.ops.mesh.select_all(action='DESELECT')
    
                                    #Select the new edges to cut
                                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                                    mesh = bpy.context.active_object.data.edges
    
                                    for f in cut_edges:
                                            mesh[f].select = True
    
                                    #Perform cut and select the cut line.
                                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
                                    bpy.ops.mesh.subdivide(number_cuts = cuts, smoothness = smoothness, quadcorner = quad_corners)
                                    bpy.ops.mesh.select_all(action='SELECT')
                                    bpy.ops.mesh.region_to_loop()
                                    bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
                                    bpy.ops.mesh.select_all(action='INVERT')
                                    bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
                                    bpy.ops.mesh.loop_multi_select(ring=False)
    
                                    #Store cut line.
                                    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                                    me = bpy.context.object.data
    
                                    bm = bmesh.new()
                                    bm.from_mesh(me)
    
                                    cut_line = []
    
                                    for v in bm.edges:
                                            if v.select:
                                                    cut_line.append(v.index)
    
                                    bm.to_mesh(me)
    
                                    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
                                    bpy.ops.mesh.reveal()
                                    bpy.ops.mesh.select_all(action='DESELECT')
    
                                    bpy.context.object.vertex_groups.active_index = tmp_hidden
                                    bpy.ops.object.vertex_group_select()
                                    bpy.ops.mesh.hide(unselected=True)
    
    
                                    bpy.ops.mesh.select_all(action='DESELECT')
    
    
                                    #Select Cutline
                                    if cuts <= 1:
                                            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
                                            mesh = bpy.context.active_object.data.edges
    
                                            for f in cut_line:
                                                    mesh[f].select = True
    
                                            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    
                                    bpy.ops.object.vertex_group_remove(all=False)
                                    bpy.ops.mesh.select_mode(use_extend=True, use_expand=False, type='FACE')
    
                            elif sel_mode[0] == True and len(vert_sel) >= 2:
                                    bpy.ops.mesh.vert_connect_path()
    
                            elif sel_mode[1] == True and loopcut == False and len(edge_sel) != 0:
                                    bpy.ops.mesh.subdivide(number_cuts = cuts, smoothness = smoothness, quadcorner = quad_corners)
    
                            elif sel_mode[1] == True and loopcut == True and len(edge_sel) != 0:
                                    bpy.ops.mesh.loop_multi_select(ring=True)
                                    bpy.ops.mesh.subdivide(number_cuts = cuts, smoothness = smoothness, quadcorner = quad_corners)
                            else:
                                bpy.ops.mesh.select_all(action='DESELECT')
                                bpy.ops.mesh.knife_tool("INVOKE_DEFAULT")
    
                    else:
                            self.report({'ERROR'}, "This one only works in Edit mode")
    
    
                    return {'FINISHED'}
    
    #Adds customAutoSmooth to the Addon
    
    
    class customAutoSmooth(bpy.types.Operator):
    
            """Set AutoSmooth angle"""
            bl_idname = "object.custom_autosmooth"
            bl_label = "Autosmooth"
            bl_options = {'REGISTER', 'UNDO'}
    
            angle: FloatProperty(name="AutoSmooth Angle", description="Set AutoSmooth angle", default= 30.0, min = 0.0, max = 180.0)
    
    
            def execute(self, context):
    
    
                    mode = bpy.context.active_object.mode
    
                    if mode != 'OBJECT':
                            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    
                    ob = bpy.context.selected_objects
                    angle = self.angle
                    angle = angle * (3.14159265359/180)
    
                    bpy.ops.object.shade_smooth()
    
                    for x in ob:
                            x = x.name
                            bpy.data.objects[x].data.use_auto_smooth = True
                            bpy.data.objects[x].data.auto_smooth_angle = angle
    
    
                    bpy.ops.object.mode_set(mode=mode, toggle=False)
    
    #Adds shrinkwrapSmooth to the Addon
    
    
    class shrinkwrapSmooth(bpy.types.Operator):
    
            """Smooths the selected vertices while trying to keep the original shape with a shrinkwrap modifier. """
            bl_idname = "mesh.shrinkwrap_smooth"
            bl_label = "Shrinkwrap Smooth"
            bl_options = {'REGISTER', 'UNDO'}
    
            pin: BoolProperty(name="Pin Selection Border", description="Pins the outer edge of the selection.", default = True)
            subsurf: IntProperty(name="Subsurf Levels", description="More reliable, but slower results", default = 0, min = 0, soft_max = 4)
    
    
    
            def execute(self, context):
    
                    iterate = 6
                    pin = self.pin
                    data = bpy.context.object.data.name
    
                    # Set up for vertex weight
                    bpy.context.scene.tool_settings.vertex_group_weight = 1
                    v_grps = len(bpy.context.object.vertex_groups.items())
    
                    bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
                    org_ob = bpy.context.object.name
    
                    # Create intermediate object
                    bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
                    bpy.ops.mesh.primitive_plane_add(radius=1, view_align=False, enter_editmode=False)
                    bpy.context.object.data = bpy.data.meshes[data]
                    tmp_ob = bpy.context.object.name
    
    
                    bpy.ops.object.duplicate(linked=False)
                    shrink_ob = bpy.context.object.name
    
                    bpy.ops.object.select_all(action='DESELECT')
                    bpy.ops.object.select_pattern(pattern=tmp_ob)
    
                    bpy.context.view_layer.objects.active = bpy.data.objects[tmp_ob]
    
    
                    bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
                    bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
    
                    if v_grps >= 1:
                        for x in range(v_grps):
                            bpy.ops.object.vertex_group_add()
    
    
                    if pin == True:
                            bpy.ops.object.vertex_group_assign_new()
                            org_id = bpy.context.object.vertex_groups.active_index
    
                            bpy.ops.object.vertex_group_assign_new()
                            sel = bpy.context.object.vertex_groups.active.name
                            sel_id = bpy.context.object.vertex_groups.active_index
    
                            bpy.ops.mesh.region_to_loop()
                            bpy.ops.object.vertex_group_remove_from(use_all_groups=False, use_all_verts=False)
    
                            bpy.ops.mesh.select_all(action='SELECT')
                            bpy.ops.mesh.region_to_loop()
                            bpy.ops.object.vertex_group_remove_from(use_all_groups=False, use_all_verts=False)
    
                            bpy.ops.mesh.select_all(action='DESELECT')
                            bpy.ops.object.vertex_group_select(sel_id)
    
                    else:
                            bpy.ops.object.vertex_group_assign_new()
    
                            sel = bpy.context.object.vertex_groups.active.name