mesh edit tools: remove from contrib T63750
authormeta-androcto <meta.androcto1@gmail.com>
Wed, 5 Jun 2019 23:57:01 +0000 (09:57 +1000)
committermeta-androcto <meta.androcto1@gmail.com>
Wed, 5 Jun 2019 23:57:01 +0000 (09:57 +1000)
33 files changed:
mesh_extra_tools/__init__.py [deleted file]
mesh_extra_tools/face_inset_fillet.py [deleted file]
mesh_extra_tools/icons/icons.py [deleted file]
mesh_extra_tools/icons/ngon.png [deleted file]
mesh_extra_tools/icons/triangle.png [deleted file]
mesh_extra_tools/mesh_check.py [deleted file]
mesh_extra_tools/mesh_cut_faces.py [deleted file]
mesh_extra_tools/mesh_edge_roundifier.py [deleted file]
mesh_extra_tools/mesh_edges_floor_plan.py [deleted file]
mesh_extra_tools/mesh_edges_length.py [deleted file]
mesh_extra_tools/mesh_edgetools.py [deleted file]
mesh_extra_tools/mesh_extrude_and_reshape.py [deleted file]
mesh_extra_tools/mesh_fastloop.py [deleted file]
mesh_extra_tools/mesh_filletplus.py [deleted file]
mesh_extra_tools/mesh_help.py [deleted file]
mesh_extra_tools/mesh_mextrude_plus.py [deleted file]
mesh_extra_tools/mesh_offset_edges.py [deleted file]
mesh_extra_tools/mesh_pen_tool.py [deleted file]
mesh_extra_tools/mesh_select_tools/__init__.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_index_select.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_info_select.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_select_by_direction.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_select_by_edge_length.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_select_by_pi.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_select_by_type.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_select_connected_faces.py [deleted file]
mesh_extra_tools/mesh_select_tools/mesh_selection_topokit.py [deleted file]
mesh_extra_tools/mesh_vertex_chamfer.py [deleted file]
mesh_extra_tools/pkhg_faces.py [deleted file]
mesh_extra_tools/random_vertices.py [deleted file]
mesh_extra_tools/split_solidify.py [deleted file]
mesh_extra_tools/vertex_align.py [deleted file]
mesh_extra_tools/vfe_specials.py [deleted file]

diff --git a/mesh_extra_tools/__init__.py b/mesh_extra_tools/__init__.py
deleted file mode 100644 (file)
index 669d22f..0000000
+++ /dev/null
@@ -1,905 +0,0 @@
-# ##### 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 #####
-
-# Contributed to by:
-# meta-androcto,  Hidesato Ikeya, zmj100, Gert De Roost, TrumanBlending, PKHG, #
-# Oscurart, Greg, Stanislav Blinov, komi3D, BlenderLab, Paul Marshall (brikbot), #
-# metalliandy, macouno, CoDEmanX, dustractor, Liero, lijenstina, Germano Cavalcante #
-# Pistiwique, Jimmy Hazevoet #
-
-bl_info = {
-    "name": "Edit Tools 2",
-    "author": "meta-androcto",
-    "version": (0, 3, 4),
-    "blender": (2, 78, 0),
-    "location": "View3D > Toolshelf > Tools and Specials (W-key)",
-    "description": "Extra mesh edit tools - modifying meshes and selection",
-    "warning": "",
-    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
-                "Py/Scripts/Modeling/Extra_Tools",
-    "category": "Mesh"}
-
-
-# Import From Files
-if "bpy" in locals():
-    import importlib
-    importlib.reload(face_inset_fillet)
-    importlib.reload(mesh_filletplus)
-    importlib.reload(mesh_vertex_chamfer)
-    importlib.reload(mesh_mextrude_plus)
-    importlib.reload(mesh_offset_edges)
-    importlib.reload(pkhg_faces)
-    importlib.reload(mesh_edge_roundifier)
-    importlib.reload(mesh_cut_faces)
-    importlib.reload(split_solidify)
-    importlib.reload(mesh_edges_floor_plan)
-    importlib.reload(mesh_edges_length)
-    importlib.reload(random_vertices)
-    importlib.reload(mesh_fastloop)
-    importlib.reload(mesh_edgetools)
-    importlib.reload(mesh_pen_tool)
-    importlib.reload(vfe_context_menu)
-    importlib.reload(mesh_help)
-    importlib.reload(mesh_select_by_direction)
-    importlib.reload(mesh_select_by_edge_length)
-    importlib.reload(mesh_select_by_pi)
-    importlib.reload(mesh_select_by_type)
-    importlib.reload(mesh_select_connected_faces)
-    importlib.reload(mesh_index_select)
-    importlib.reload(mesh_selection_topokit)
-    importlib.reload(mesh_info_select)
-    importlib.reload(mesh_extrude_and_reshape)
-    importlib.reload(mesh_check)
-    importlib.reload(vertex_align)
-
-else:
-    from . import face_inset_fillet
-    from . import mesh_filletplus
-    from . import mesh_vertex_chamfer
-    from . import mesh_mextrude_plus
-    from . import mesh_offset_edges
-    from . import pkhg_faces
-    from . import mesh_edge_roundifier
-    from . import mesh_cut_faces
-    from . import split_solidify
-    from . import mesh_edges_floor_plan
-    from . import mesh_edges_length
-    from . import random_vertices
-    from . import mesh_fastloop
-    from . import mesh_edgetools
-    from . import mesh_pen_tool
-    from . import vfe_context_menu
-    from . import mesh_help
-    from . import mesh_extrude_and_reshape
-    from . import mesh_check
-    from . import vertex_align
-
-    from .mesh_select_tools import mesh_select_by_direction
-    from .mesh_select_tools import mesh_select_by_edge_length
-    from .mesh_select_tools import mesh_select_by_pi
-    from .mesh_select_tools import mesh_select_by_type
-    from .mesh_select_tools import mesh_select_connected_faces
-    from .mesh_select_tools import mesh_index_select
-    from .mesh_select_tools import mesh_selection_topokit
-    from .mesh_select_tools import mesh_info_select
-
-    from . icons.icons import load_icons
-
-import bpy
-import bpy_extras.keyconfig_utils
-from bpy.types import (
-        Menu,
-        Panel,
-        PropertyGroup,
-        AddonPreferences,
-        )
-from bpy.props import (
-        BoolProperty,
-        BoolVectorProperty,
-        EnumProperty,
-        FloatProperty,
-        FloatVectorProperty,
-        IntVectorProperty,
-        PointerProperty,
-        )
-
-
-# ------ MENUS ------ #
-
-# Define the "Extras" menu
-class VIEW3D_MT_edit_mesh_extras(Menu):
-    bl_idname = "VIEW3D_MT_edit_mesh_extras"
-    bl_label = "Edit Tools"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-        mode = context.tool_settings.mesh_select_mode
-
-        if mode[0]:
-            split = layout.split()
-            col = split.column()
-
-            col.label(text="Vertex", icon="VERTEXSEL")
-            col.separator()
-
-            col.operator("mesh.vertex_chamfer", text="Vertex Chamfer")
-            col.operator("mesh.random_vertices", text="Random Vertices")
-
-            col = split.column()
-            col.label(text="Utilities", icon="SCRIPTWIN")
-            col.separator()
-
-            col.operator("object_ot.fastloop", text="Fast loop")
-            col.operator("mesh.flip_normals", text="Normals Flip")
-            col.operator("mesh.remove_doubles", text="Remove Doubles")
-            col.operator("mesh.subdivide", text="Subdivide")
-            col.operator("mesh.dissolve_limited", text="Dissolve Limited")
-
-        elif mode[1]:
-            split = layout.split()
-            col = split.column()
-            col.label(text="Edge", icon="EDGESEL")
-            col.separator()
-
-            col.operator("mesh.fillet_plus", text="Edge Fillet Plus")
-            col.operator("mesh.offset_edges", text="Offset Edges")
-            col.operator("mesh.edge_roundifier", text="Edge Roundify")
-            col.operator("object.mesh_edge_length_set", text="Set Edge Length")
-            col.operator("mesh.edges_floor_plan")
-
-            col = split.column()
-            col.label(text="Utilities", icon="SCRIPTWIN")
-            col.separator()
-
-            col.operator("object_ot.fastloop", text="Fast loop")
-            col.operator("mesh.flip_normals", text="Normals Flip")
-            col.operator("mesh.remove_doubles", text="Remove Doubles")
-
-            col.operator("mesh.subdivide", text="Subdivide")
-            col.operator("mesh.dissolve_limited", text="Dissolve Limited")
-
-        elif mode[2]:
-            split = layout.split()
-            col = split.column()
-            col.label(text="Face", icon="FACESEL")
-            col.separator()
-
-            col.operator("object.mextrude", text="Multi Extrude")
-            col.operator("mesh.face_inset_fillet", text="Face Inset Fillet")
-            col.operator("mesh.extrude_reshape", text="Push/Pull")
-            col.operator("mesh.add_faces_to_object", text="PKHG Faces")
-            col.operator("mesh.ext_cut_faces", text="Cut Faces")
-            col.operator("mesh.split_solidify", text="Split Solidify")
-
-            col = split.column()
-            col.label(text="Utilities", icon="SCRIPTWIN")
-            col.separator()
-
-            col.operator("object_ot.fastloop", text="Fast loop")
-            col.operator("mesh.flip_normals", text="Normals Flip")
-            col.operator("mesh.remove_doubles", text="Remove Doubles")
-            col.operator("mesh.subdivide", text="Subdivide")
-            col.operator("mesh.dissolve_limited", text="Dissolve Limited")
-
-
-class EditToolsPanel(Panel):
-    bl_label = "Mesh Edit Tools"
-    bl_space_type = "VIEW_3D"
-    bl_region_type = "TOOLS"
-    bl_context = "mesh_edit"
-    bl_category = "Tools"
-    bl_options = {"DEFAULT_CLOSED"}
-
-    def draw(self, context):
-        scene = context.scene
-        VERTDROP = scene.mesh_extra_tools.UiTabDrop[0]
-        EDGEDROP = scene.mesh_extra_tools.UiTabDrop[1]
-        FACEDROP = scene.mesh_extra_tools.UiTabDrop[2]
-        UTILSDROP = scene.mesh_extra_tools.UiTabDrop[3]
-        # Change icons depending on the bool state (compliant with the rest of the UI)
-        icon_active_0 = "TRIA_RIGHT" if not VERTDROP else "TRIA_DOWN"
-        icon_active_1 = "TRIA_RIGHT" if not EDGEDROP else "TRIA_DOWN"
-        icon_active_2 = "TRIA_RIGHT" if not FACEDROP else "TRIA_DOWN"
-        icon_active_3 = "TRIA_RIGHT" if not UTILSDROP else "TRIA_DOWN"
-
-        layout = self.layout
-
-        # Vert options
-        box1 = self.layout.box()
-        col = box1.column(align=True)
-        row = col.row(align=True)
-        row.prop(scene.mesh_extra_tools, "UiTabDrop", text="Vertex", index=0, icon=icon_active_0)
-        if not VERTDROP:
-            row.menu("mesh.vert_select_tools", icon="RESTRICT_SELECT_OFF", text="")
-            row.menu("VIEW3D_MT_Select_Vert", icon="VERTEXSEL", text="")
-        else:
-            layout = self.layout
-
-            row = layout.row()
-            row.label(text="Vertex Tools:", icon="VERTEXSEL")
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.vertex_chamfer", text="Chamfer")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_vertex_chamfer"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.random_vertices", text="Random Vertices")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "random_vertices"
-
-            # Vertex Align Properties And Menu
-            cen0 = scene.mesh_extra_tools.vert_align_to
-
-            layout = self.layout
-            layout.label(text="Vertex Align:", icon="UV_VERTEXSEL")
-
-            # Draw the menu with 2 options
-            layout.prop(scene.mesh_extra_tools, "vert_align_to", expand=False)
-            if cen0 == 'vertex':
-                row = layout.row(align=True)
-                row.operator("vertex_align.store_id", text="Store Selected Vertex")
-
-                row = layout.split(0.8, align=True)
-                row.operator("vertex_align.align_original", text="Align to Axis")
-                props = row.operator("mesh.extra_tools_help", icon="LAYER_USED")
-                props.help_ids = "vertex_align"
-                props.popup_size = 400
-            elif cen0 == "coordinates":
-                layout.prop(scene.mesh_extra_tools, "vert_align_use_stored", toggle=True)
-
-                if scene.mesh_extra_tools.vert_align_use_stored:
-                    col = layout.column(align=True)
-                    col.prop(scene.mesh_extra_tools, "vert_align_store_axis", expand=True)
-
-                row = layout.split(0.8, align=True)
-                row.operator("vertex_align.coord_list_id", text="Align Coordinates")
-                row.operator("mesh.extra_tools_help",
-                            icon="LAYER_USED").help_ids = "vertex_align"
-
-        # Edge options
-        box1 = self.layout.box()
-        col = box1.column(align=True)
-        row = col.row(align=True)
-        row.prop(scene.mesh_extra_tools, "UiTabDrop", text="Edge", index=1, icon=icon_active_1)
-
-        if not EDGEDROP:
-            row.menu("mesh.edge_select_tools", icon="RESTRICT_SELECT_OFF", text="")
-            row.menu("VIEW3D_MT_Select_Edge", icon="EDGESEL", text="")
-        else:
-            layout = self.layout
-
-            row = layout.row()
-            row.label(text="Edge Tools:", icon="EDGESEL")
-            row.menu("VIEW3D_MT_edit_mesh_edgetools", icon="GRID")
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.fillet_plus", text="Fillet plus")
-
-            props = row.operator("mesh.extra_tools_help", icon="LAYER_USED")
-            props.help_ids = "mesh_filletplus"
-            props.popup_size = 400
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.offset_edges", text="Offset Edges")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_offset_edges"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.edge_roundifier", text="Roundify")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_edge_roundifier"
-
-            row = layout.split(0.8, align=True)
-            row.operator("object.mesh_edge_length_set", text="Set Edge Length")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_edges_length"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.edges_floor_plan")
-
-            props = row.operator("mesh.extra_tools_help", icon="LAYER_USED")
-            props.help_ids = "mesh_edges_floor_plan"
-            props.popup_size = 400
-
-        # Face options
-        box1 = self.layout.box()
-        col = box1.column(align=True)
-        row = col.row(align=True)
-        row.prop(scene.mesh_extra_tools, "UiTabDrop", text="Face", index=2, icon=icon_active_2)
-
-        if not FACEDROP:
-            row.menu("mesh.face_select_tools", icon="RESTRICT_SELECT_OFF", text="")
-            row.menu("VIEW3D_MT_Select_Face", icon="FACESEL", text="")
-        else:
-            layout = self.layout
-
-            row = layout.row()
-            row.label(text="Face Tools:", icon="FACESEL")
-
-            row = layout.split(0.8, align=True)
-            row.operator("object.mextrude", text="Multi Extrude")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_mextrude_plus"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.extrude_reshape", text="Push/Pull")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_extrude_and_reshape"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.face_inset_fillet", text="Inset Fillet")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "face_inset_fillet"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.ext_cut_faces", text="Cut Faces")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "mesh_cut_faces"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.split_solidify", text="Split Solidify")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "split_solidify"
-
-            row = layout.split(0.8, align=True)
-            row.operator("mesh.add_faces_to_object", "Shape Extrude")
-            row.operator("mesh.extra_tools_help",
-                        icon="LAYER_USED").help_ids = "pkhg_faces"
-
-        # Utils options
-        box1 = self.layout.box()
-        col = box1.column(align=True)
-        row = col.row(align=True)
-        row.prop(scene.mesh_extra_tools, "UiTabDrop", text="Utils", index=3, icon=icon_active_3)
-
-        if not UTILSDROP:
-            row.menu("mesh.utils specials", icon="SOLO_OFF", text="")
-            row.menu("VIEW3D_MT_Edit_MultiMET", icon="LOOPSEL", text="")
-        else:
-            layout = self.layout
-
-            row = layout.row()
-            row.label(text="Utilities:")
-
-            row = layout.row()
-            row = layout.split(0.8, align=True)
-            row.operator("object_ot.fastloop", text="Fast Loop")
-
-            props = row.operator("mesh.extra_tools_help", icon="LAYER_USED")
-            props.help_ids = "mesh_fastloop"
-            props.popup_size = 400
-
-            col = layout.column(align=True)
-            col.operator("mesh.flip_normals", text="Normals Flip")
-            col.operator("mesh.remove_doubles", text="Remove Doubles")
-            col.operator("mesh.subdivide", text="Subdivide")
-            col.operator("mesh.dissolve_limited", text="Dissolve Limited")
-
-            row = layout.row(align=True)
-            row.operator("mesh.select_vert_edge_face_index",
-                          icon="VERTEXSEL", text="Select By Index").select_type = 'VERT'
-
-            # Mesh Check
-            layout = self.layout
-            icons = load_icons()
-            tris = icons.get("triangles")
-            ngons = icons.get("ngons")
-
-            mesh_check = context.window_manager.mesh_check
-            icon_active_4 = "TRIA_RIGHT" if not mesh_check.mesh_check_use else "TRIA_DOWN"
-
-            row = layout.row()
-            row = layout.split(0.8, align=True)
-            row.prop(mesh_check, "mesh_check_use", toggle=True, icon=icon_active_4)
-            row.operator("mesh.extra_tools_help", icon="LAYER_USED").help_ids = "mesh_check"
-
-            if mesh_check.mesh_check_use:
-                layout = self.layout
-
-                row = layout.row(align=True)
-                row.operator("object.face_type_select", text="Tris",
-                             icon_value=tris.icon_id).face_type = 'tris'
-                row.operator("object.face_type_select", text="Ngons",
-                             icon_value=ngons.icon_id).face_type = 'ngons'
-
-                row = layout.row()
-                row.prop(mesh_check, "display_faces", text="Display Faces")
-
-                if mesh_check.display_faces:
-                    col = layout.column(align=True)
-                    col.prop(mesh_check, "edge_width")
-                    col.prop(mesh_check, "face_opacity")
-
-                    row = layout.row()
-                    row.label(text="Custom Colors:", icon="COLOR")
-
-                    col = layout.column().split(factor=0.1, align=True)
-                    col.label(text="", icon_value=tris.icon_id)
-                    col.prop(mesh_check, "custom_tri_color", text="")
-
-                    col = layout.column().split(factor=0.1, align=True)
-                    col.label(text="", icon_value=ngons.icon_id)
-                    col.prop(mesh_check, "custom_ngons_color", text="")
-
-                    layout.separator()
-
-                    row = layout.row(align=True)
-                    if bpy.app.debug:
-                        obj_data = getattr(context.active_object, "data", None)
-                        if obj_data:
-                            row.prop(obj_data, "show_extra_indices",
-                                     icon="LINENUMBERS_ON", toggle=True)
-
-                    if context.mode == 'EDIT_MESH' and not context.space_data.use_occlude_geometry:
-                        row.prop(mesh_check, "finer_lines_behind_use", icon="ORTHO")
-
-
-# ********** Edit Multiselect **********
-class VIEW3D_MT_Edit_MultiMET(Menu):
-    bl_label = "Multi Select"
-    bl_description = "Multi Select Modes"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex Select",
-                               icon='VERTEXSEL')
-        prop.value = "(True, False, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Edge Select",
-                               icon='EDGESEL')
-        prop.value = "(False, True, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Face Select",
-                               icon='FACESEL')
-        prop.value = "(False, False, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        layout.separator()
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex and Edge Select",
-                               icon='EDITMODE_HLT')
-        prop.value = "(True, True, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex and Face Select",
-                               icon='ORTHO')
-        prop.value = "(True, False, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Edge and Face Select",
-                               icon='SNAP_FACE')
-        prop.value = "(False, True, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex, Edge and Face Select",
-                               icon='SNAP_VOLUME')
-        prop.value = "(True, True, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-
-# Select Tools
-class VIEW3D_MT_Select_Vert(Menu):
-    bl_label = "Select Vert"
-    bl_description = "Vertex Selection Modes"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex Select",
-                               icon='VERTEXSEL')
-        prop.value = "(True, False, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex and Edge Select",
-                               icon='EDITMODE_HLT')
-        prop.value = "(True, True, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex and Face Select",
-                               icon='ORTHO')
-        prop.value = "(True, False, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-
-class VIEW3D_MT_Select_Edge(Menu):
-    bl_label = "Select Edge"
-    bl_description = "Edge Selection Modes"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Edge Select",
-                               icon='EDGESEL')
-        prop.value = "(False, True, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex and Edge Select",
-                               icon='EDITMODE_HLT')
-        prop.value = "(True, True, False)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Edge and Face Select",
-                               icon='SNAP_FACE')
-        prop.value = "(False, True, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-
-class VIEW3D_MT_Select_Face(Menu):
-    bl_label = "Select Face"
-    bl_description = "Face Selection Modes"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Face Select",
-                               icon='FACESEL')
-        prop.value = "(False, False, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Vertex and Face Select",
-                               icon='ORTHO')
-        prop.value = "(True, False, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-        prop = layout.operator("wm.context_set_value",
-                               text="Edge and Face Select",
-                               icon='SNAP_FACE')
-        prop.value = "(False, True, True)"
-        prop.data_path = "tool_settings.mesh_select_mode"
-
-
-class VIEW3D_MT_selectface_edit_mesh_add(Menu):
-    bl_label = "Select by Face"
-    bl_idname = "mesh.face_select_tools"
-    bl_description = "Face Selection Tools"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        layout.label(text="Face Selection Tools", icon="RESTRICT_SELECT_OFF")
-        layout.separator()
-
-        layout.operator("mesh.select_all").action = 'TOGGLE'
-        layout.operator("mesh.select_all", text="Inverse").action = 'INVERT'
-        layout.operator("mesh.ext_deselect_boundary", text="Deselect Boundary")
-        layout.separator()
-
-        layout.operator("data.facetype_select", text="Triangles").face_type = "3"
-        layout.operator("data.facetype_select", text="Quads").face_type = "4"
-        layout.operator("data.facetype_select", text="Ngons").face_type = "5"
-        layout.separator()
-
-        layout.operator("mesh.select_vert_edge_face_index",
-                        text="By Face Index").select_type = 'FACE'
-        layout.operator("mesh.select_by_direction", text="By Direction")
-        layout.operator("mesh.select_by_pi", text="By Pi or e")
-        layout.operator("mesh.select_connected_faces", text="By Connected Faces")
-        layout.operator("mesh.conway", text="By Conway's game of life")
-        layout.separator()
-
-        layout.operator("mesh.e2e_efe", text="Neighbors by Face")
-        layout.operator("mesh.f2f_fvnef", text="Neighbors by Vert not Edge")
-
-
-class VIEW3D_MT_selectedge_edit_mesh_add(Menu):
-    bl_label = "Select by Edge"
-    bl_idname = "mesh.edge_select_tools"
-    bl_description = "Edge Selection Tools"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        layout.label(text="Edge Selection Tools", icon="RESTRICT_SELECT_OFF")
-        layout.separator()
-
-        layout.operator("mesh.select_all").action = 'TOGGLE'
-        layout.operator("mesh.select_all", text="Inverse").action = 'INVERT'
-        layout.separator()
-
-        layout.operator("mesh.select_vert_edge_face_index",
-                        text="By Edge Index").select_type = 'EDGE'
-        layout.operator("mesh.select_by_direction", text="By Direction")
-        layout.operator("mesh.select_by_pi", text="By Pi or e")
-        layout.operator("mesh.select_by_edge_length", text="By Edge Length")
-        layout.separator()
-
-        layout.operator("mesh.e2e_eve", text="Neighbors by Vertex")
-        layout.operator("mesh.e2e_evfe", text="Neighbors by Vertex and Face")
-        layout.operator("mesh.e2e_efnve", text="Lateral Neighbors")
-        layout.operator("mesh.e2e_evnfe", text="Longitudinal Edges")
-
-
-class VIEW3D_MT_selectvert_edit_mesh_add(Menu):
-    bl_label = "Select by Vert"
-    bl_idname = "mesh.vert_select_tools"
-    bl_description = "Vertex Selection Tools"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        layout.label(text="Vertex Selection Tools", icon="RESTRICT_SELECT_OFF")
-        layout.separator()
-
-        layout.operator("mesh.select_all").action = 'TOGGLE'
-        layout.operator("mesh.select_all", text="Inverse").action = 'INVERT'
-        layout.separator()
-
-        layout.operator("mesh.select_vert_edge_face_index",
-                        text="By Vert Index").select_type = 'VERT'
-        layout.operator("mesh.select_by_direction", text="By Direction")
-        layout.operator("mesh.select_by_pi", text="By Pi or e")
-        layout.separator()
-
-        layout.operator("mesh.v2v_by_edge", text="Neighbors by Edge")
-        layout.operator("mesh.e2e_eve", text="Neighbors by Vertex")
-        layout.operator("mesh.e2e_efe", text="Neighbors by Face")
-        layout.operator("mesh.v2v_facewise", text="Neighbors by Face - Edge")
-
-
-class VIEW3D_MT_utils_context_menu(Menu):
-    bl_label = "Specials Menu"
-    bl_idname = "mesh.utils specials"
-    bl_description = "Utils Quick Specials"
-
-    def draw(self, context):
-        layout = self.layout
-        layout.operator_context = 'INVOKE_REGION_WIN'
-
-        layout.label(text="Fast Specials")
-        layout.separator()
-
-        layout.menu("VIEW3D_MT_edit_mesh_clean")
-        layout.separator()
-
-        layout.operator("mesh.subdivide", text="Subdivide").smoothness = 0.0
-        layout.operator("mesh.merge", text="Merge...")
-        layout.operator("mesh.remove_doubles")
-        layout.operator("mesh.inset")
-        layout.operator("mesh.bevel", text="Bevel")
-        layout.operator("mesh.bridge_edge_loops")
-        layout.separator()
-
-        layout.operator("mesh.normals_make_consistent",
-                        text="Recalculate Outside").inside = False
-        layout.operator("mesh.normals_make_consistent",
-                        text="Recalculate Inside").inside = True
-        layout.operator("mesh.flip_normals")
-
-
-# Define the "Extras" Menu append
-class VIEW3D_MT_edit_mesh_all(Menu):
-    bl_idname = "VIEW3D_MT_edit_mesh_all"
-    bl_label = "Mesh Edit Tools"
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.menu("VIEW3D_MT_edit_mesh_extras")
-        layout.menu("VIEW3D_MT_edit_mesh_edgetools")
-
-
-def menu_func(self, context):
-    self.layout.menu("VIEW3D_MT_edit_mesh_extras")
-    self.layout.menu("VIEW3D_MT_edit_mesh_edgetools")
-
-
-# Define "Select" Menu append
-def menu_select(self, context):
-    if context.tool_settings.mesh_select_mode[2]:
-        self.layout.menu("mesh.face_select_tools", icon="FACESEL")
-    if context.tool_settings.mesh_select_mode[1]:
-        self.layout.menu("mesh.edge_select_tools", icon="EDGESEL")
-    if context.tool_settings.mesh_select_mode[0]:
-        self.layout.menu("mesh.vert_select_tools", icon="VERTEXSEL")
-
-
-# Scene Properties
-class MeshExtraToolsSceneProps(PropertyGroup):
-    # Define the UI drop down prop
-    UiTabDrop = BoolVectorProperty(
-            name="Tab",
-            description="Expand/Collapse UI elements",
-            default=(False,) * 4,
-            size=4,
-            )
-    # Vertex align
-    vert_align_store_axis: FloatVectorProperty(
-            name="Define Custom Coordinates",
-            description="Store the values of coordinates, for repeated use\n"
-                        "as a starting point",
-            default=(0.0, 0.0, 0.0),
-            min=-100.0, max=100.0,
-            step=1, size=3,
-            subtype='XYZ',
-            precision=3
-            )
-    vert_align_use_stored: BoolProperty(
-            name="Use Stored Coordinates",
-            description="Use starting point coordinates for alignment",
-            default=False
-            )
-    vert_align_to: EnumProperty(
-            items=(('vertex', "Original vertex",
-                    "Use the stored vertex coordinates for aligning"),
-                   ('coordinates', "Custom coordinates",
-                    "Use defined custom coordinates for aligning")),
-            name="Align to",
-            default='vertex'
-            )
-    vert_align_axis = BoolVectorProperty(
-            name="Axis",
-            description="Align to a specific Axis",
-            default=(True, False, False),
-            size=3,
-            )
-    # Mesh Info select
-    mesh_info_show: BoolProperty(
-            name="Show Face Info",
-            description="Display the Object's Face Count information\n"
-                        "Note: it can have some performance impact on dense meshes\n"
-                        "Leave it closed if not needed or set the Delay to a higher value",
-            default=False
-            )
-    mesh_info_delay: FloatProperty(
-            name="Delay",
-            description="Set the Update time Delay in seconds\n"
-                        "Set to zero to update with the UI refresh\n"
-                        "Higher values will sometimes need to hover over the cursor",
-            default=2.0,
-            min=0.0, max=20.0,
-            step=100,
-            subtype='TIME',
-            precision=1
-            )
-
-
-# Add-on Preferences
-class mesh_extra_tools_pref(AddonPreferences):
-    bl_idname = __name__
-
-    show_info: BoolProperty(
-            name="Info",
-            default=False,
-            description="Some general information about the add-on",
-            )
-    show_shortcuts: BoolProperty(
-            name="Hot Keys",
-            default=False,
-            description="List of the shortcuts used for the included various tools",
-            )
-
-    def draw(self, context):
-        layout = self.layout
-        box = layout.box()
-
-        box.prop(self, "show_info", icon="INFO")
-        if self.show_info:
-            box.label(text="Collection of various extra Mesh Edit Functions",
-                      icon="LAYER_ACTIVE")
-            box.label(text="The majority of the tools can be found in"
-                      "Mesh Edit Mode Toolshelf or W key Specials Menu",
-                      icon="LAYER_USED")
-            box.label(text="The Pen tool is a separate Panel in the Toolshelf",
-                      icon="LAYER_USED")
-            box.label(text="The Face Extrude tool is only available in Object Mode "
-                      "as a separate panel in the Toolshelf",
-                      icon="LAYER_USED")
-            box.label(text="Face Info / Select is a separate Panel located in Properties > Data Editor",
-                      icon="LAYER_USED")
-
-        box.prop(self, "show_shortcuts", icon="KEYINGSET")
-        if self.show_shortcuts:
-            col = box.column()
-            col.label(text="Double Right Click in Edit mode in the 3D Viewport",
-                      icon="LAYER_ACTIVE")
-            col.label(text="Used for quick access to the Vertex, Edge and Face context menus",
-                      icon="LAYER_USED")
-            col.separator()
-            col.label(text="W-key in Edit Mode in the 3D Viewport",
-                      icon="LAYER_ACTIVE")
-            col.label(text="Tools are grouped into menus prepended to the Specials Menu",
-                      icon="LAYER_USED")
-            col.separator()
-            col.label(text="Ctrl+D in Edit Mode in the 3D Viewport",
-                      icon="LAYER_ACTIVE")
-            col.label(text="Used by the Pen Tool to start drawing. When activated:",
-                      icon="LAYER_USED")
-            col.label(text="Shift + Mouse Move is used to draw along the X axis",
-                      icon="LAYER_USED")
-            col.label(text="Alt + Mouse Move is used to draw along the Y axis",
-                      icon="LAYER_USED")
-            col.separator()
-            col.label(text="Note: when using Fast Loop operator, press Esc twice to finish",
-                      icon="LAYER_ACTIVE")
-
-
-def register():
-    mesh_pen_tool.register()
-    vfe_context_menu.register()
-    mesh_extrude_and_reshape.register()
-    mesh_check.register()
-
-    bpy.utils.register_module(__name__)
-
-    # Register Scene Properties
-    bpy.types.Scene.mesh_extra_tools = PointerProperty(
-                                            type=MeshExtraToolsSceneProps
-                                            )
-    # Used in mesh_selection_topokit to store cache selection data
-    bpy.types.Object.tkkey = IntVectorProperty(size=4)
-
-    # Add "Extras" menu to the "W-key Specials" menu
-    bpy.types.VIEW3D_MT_edit_mesh_context_menu.prepend(menu_func)
-    bpy.types.VIEW3D_MT_select_edit_mesh.prepend(menu_select)
-
-    try:
-        bpy.types.VIEW3D_MT_Select_Edit_Mesh.prepend(menu_select)
-    except:
-        pass
-
-
-def unregister():
-    mesh_pen_tool.unregister()
-    vfe_context_menu.unregister()
-    mesh_extrude_and_reshape.unregister()
-    mesh_check.unregister()
-
-    del bpy.types.Scene.mesh_extra_tools
-    del bpy.types.Object.tkkey
-
-    bpy.utils.unregister_module(__name__)
-
-    # Remove "Extras" menu from the "" menu.
-    bpy.types.VIEW3D_MT_edit_mesh_context_menu.remove(menu_func)
-    bpy.types.VIEW3D_MT_select_edit_mesh.remove(menu_select)
-
-    try:
-        bpy.types.VIEW3D_MT_Select_Edit_Mesh.remove(menu_select)
-    except:
-        pass
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/face_inset_fillet.py b/mesh_extra_tools/face_inset_fillet.py
deleted file mode 100644 (file)
index 8af709c..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ##### 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 #####
-
-# based completely on addon by zmj100
-# added some distance limits to prevent overlap - max12345
-
-
-import bpy
-import bmesh
-from bpy.types import Operator
-from bpy.props import (
-        FloatProperty,
-        IntProperty,
-        BoolProperty,
-        EnumProperty,
-        )
-from math import (
-        sin, cos, tan,
-        degrees, radians,
-        )
-from mathutils import Matrix
-
-
-def edit_mode_out():
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-
-def edit_mode_in():
-    bpy.ops.object.mode_set(mode='EDIT')
-
-
-def angle_rotation(rp, q, axis, angle):
-    # returns the vector made by the rotation of the vector q
-    # rp by angle around axis and then adds rp
-
-    return (Matrix.Rotation(angle, 3, axis) * (q - rp)) + rp
-
-
-def face_inset_fillet(bme, face_index_list, inset_amount, distance,
-                      number_of_sides, out, radius, type_enum, kp):
-    list_del = []
-
-    for faceindex in face_index_list:
-
-        bme.faces.ensure_lookup_table()
-        # loops through the faces...
-        f = bme.faces[faceindex]
-        f.select_set(False)
-        list_del.append(f)
-        f.normal_update()
-        vertex_index_list = [v.index for v in f.verts]
-        dict_0 = {}
-        orientation_vertex_list = []
-        n = len(vertex_index_list)
-        for i in range(n):
-            # loops through the vertices
-            dict_0[i] = []
-            bme.verts.ensure_lookup_table()
-            p = (bme.verts[vertex_index_list[i]].co).copy()
-            p1 = (bme.verts[vertex_index_list[(i - 1) % n]].co).copy()
-            p2 = (bme.verts[vertex_index_list[(i + 1) % n]].co).copy()
-            # copies some vert coordinates, always the 3 around i
-            dict_0[i].append(bme.verts[vertex_index_list[i]])
-            # appends the bmesh vert of the appropriate index to the dict
-            vec1 = p - p1
-            vec2 = p - p2
-            # vectors for the other corner points to the cornerpoint
-            # corresponding to i / p
-            angle = vec1.angle(vec2)
-
-            adj = inset_amount / tan(angle * 0.5)
-            h = (adj ** 2 + inset_amount ** 2) ** 0.5
-            if round(degrees(angle)) == 180 or round(degrees(angle)) == 0.0:
-                # if the corner is a straight line...
-                # I think this creates some new points...
-                if out is True:
-                    val = ((f.normal).normalized() * inset_amount)
-                else:
-                    val = -((f.normal).normalized() * inset_amount)
-                p6 = angle_rotation(p, p + val, vec1, radians(90))
-            else:
-                # if the corner is an actual corner
-                val = ((f.normal).normalized() * h)
-                if out is True:
-                    # this -(p - (vec2.normalized() * adj))) is just the freaking axis afaik...
-                    p6 = angle_rotation(
-                                p, p + val,
-                                -(p - (vec2.normalized() * adj)),
-                                -radians(90)
-                                )
-                else:
-                    p6 = angle_rotation(
-                                p, p - val,
-                                ((p - (vec1.normalized() * adj)) - (p - (vec2.normalized() * adj))),
-                                -radians(90)
-                                )
-
-                orientation_vertex_list.append(p6)
-
-        new_inner_face = []
-        orientation_vertex_list_length = len(orientation_vertex_list)
-        ovll = orientation_vertex_list_length
-
-        for j in range(ovll):
-            q = orientation_vertex_list[j]
-            q1 = orientation_vertex_list[(j - 1) % ovll]
-            q2 = orientation_vertex_list[(j + 1) % ovll]
-            # again, these are just vectors between somewhat displaced corner vertices
-            vec1_ = q - q1
-            vec2_ = q - q2
-            ang_ = vec1_.angle(vec2_)
-
-            # the angle between them
-            if round(degrees(ang_)) == 180 or round(degrees(ang_)) == 0.0:
-                # again... if it's really a line...
-                v = bme.verts.new(q)
-                new_inner_face.append(v)
-                dict_0[j].append(v)
-            else:
-                # s.a.
-                if radius is False:
-                    h_ = distance * (1 / cos(ang_ * 0.5))
-                    d = distance
-                elif radius is True:
-                    h_ = distance / sin(ang_ * 0.5)
-                    d = distance / tan(ang_ * 0.5)
-                # max(d) is vec1_.magnitude * 0.5
-                # or vec2_.magnitude * 0.5 respectively
-
-                # only functional difference v
-                if d > vec1_.magnitude * 0.5:
-                    d = vec1_.magnitude * 0.5
-
-                if d > vec2_.magnitude * 0.5:
-                    d = vec2_.magnitude * 0.5
-                # only functional difference ^
-
-                q3 = q - (vec1_.normalized() * d)
-                q4 = q - (vec2_.normalized() * d)
-                # these are new verts somewhat offset from the corners
-                rp_ = q - ((q - ((q3 + q4) * 0.5)).normalized() * h_)
-                # reference point inside the curvature
-                axis_ = vec1_.cross(vec2_)
-                # this should really be just the face normal
-                vec3_ = rp_ - q3
-                vec4_ = rp_ - q4
-                rot_ang = vec3_.angle(vec4_)
-                cornerverts = []
-
-                for o in range(number_of_sides + 1):
-                    # this calculates the actual new vertices
-                    q5 = angle_rotation(rp_, q4, axis_, rot_ang * o / number_of_sides)
-                    v = bme.verts.new(q5)
-
-                    # creates new bmesh vertices from it
-                    bme.verts.index_update()
-
-                    dict_0[j].append(v)
-                    cornerverts.append(v)
-
-                cornerverts.reverse()
-                new_inner_face.extend(cornerverts)
-
-        if out is False:
-            f = bme.faces.new(new_inner_face)
-            f.select_set(True)
-        elif out is True and kp is True:
-            f = bme.faces.new(new_inner_face)
-            f.select_set(True)
-
-        n2_ = len(dict_0)
-        # these are the new side faces, those that don't depend on cornertype
-        for o in range(n2_):
-            list_a = dict_0[o]
-            list_b = dict_0[(o + 1) % n2_]
-            bme.faces.new([list_a[0], list_b[0], list_b[-1], list_a[1]])
-            bme.faces.index_update()
-        # cornertype 1 - ngon faces
-        if type_enum == 'opt0':
-            for k in dict_0:
-                if len(dict_0[k]) > 2:
-                    bme.faces.new(dict_0[k])
-                    bme.faces.index_update()
-        # cornertype 2 - triangulated faces
-        if type_enum == 'opt1':
-            for k_ in dict_0:
-                q_ = dict_0[k_][0]
-                dict_0[k_].pop(0)
-                n3_ = len(dict_0[k_])
-                for kk in range(n3_ - 1):
-                    bme.faces.new([dict_0[k_][kk], dict_0[k_][(kk + 1) % n3_], q_])
-                    bme.faces.index_update()
-
-    del_ = [bme.faces.remove(f) for f in list_del]
-
-    if del_:
-        del del_
-
-
-# Operator
-
-class MESH_OT_face_inset_fillet(Operator):
-    bl_idname = "mesh.face_inset_fillet"
-    bl_label = "Face Inset Fillet"
-    bl_description = ("Inset selected and Fillet (make round) the corners \n"
-                     "of the newly created Faces")
-    bl_options = {"REGISTER", "UNDO"}
-
-    # inset amount
-    inset_amount: FloatProperty(
-            name="Inset amount",
-            description="Define the size of the Inset relative to the selection",
-            default=0.04,
-            min=0, max=100.0,
-            step=1,
-            precision=3
-            )
-    # number of sides
-    number_of_sides: IntProperty(
-            name="Number of sides",
-            description="Define the roundness of the corners by specifying\n"
-                        "the subdivision count",
-            default=4,
-            min=1, max=100,
-            step=1
-            )
-    distance: FloatProperty(
-            name="",
-            description="Use distance or radius for corners' size calculation",
-            default=0.04,
-            min=0.00001, max=100.0,
-            step=1,
-            precision=3
-            )
-    out: BoolProperty(
-            name="Outside",
-            description="Inset the Faces outwards in relation to the selection\n"
-                        "Note: depending on the geometry, can give unsatisfactory results",
-            default=False
-            )
-    radius: BoolProperty(
-            name="Radius",
-            description="Use radius for corners' size calculation",
-            default=False
-            )
-    type_enum: EnumProperty(
-            items=(('opt0', "N-gon", "N-gon corners - Keep the corner Faces uncut"),
-                   ('opt1', "Triangle", "Triangulate corners")),
-            name="Corner Type",
-            default="opt0"
-            )
-    kp: BoolProperty(
-            name="Keep faces",
-            description="Do not delete the inside Faces\n"
-                        "Only available if the Out option is checked",
-            default=False
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.label(text="Corner Type:")
-
-        row = layout.row()
-        row.prop(self, "type_enum", text="")
-
-        row = layout.row(align=True)
-        row.prop(self, "out")
-
-        if self.out is True:
-            row.prop(self, "kp")
-
-        row = layout.row()
-        row.prop(self, "inset_amount")
-
-        row = layout.row()
-        row.prop(self, "number_of_sides")
-
-        row = layout.row()
-        row.prop(self, "radius")
-
-        row = layout.row()
-        dist_rad = "Radius" if self.radius else "Distance"
-        row.prop(self, "distance", text=dist_rad)
-
-    def execute(self, context):
-        # this really just prepares everything for the main function
-        inset_amount = self.inset_amount
-        number_of_sides = self.number_of_sides
-        distance = self.distance
-        out = self.out
-        radius = self.radius
-        type_enum = self.type_enum
-        kp = self.kp
-
-        edit_mode_out()
-        ob_act = context.active_object
-        bme = bmesh.new()
-        bme.from_mesh(ob_act.data)
-        # this
-        face_index_list = [f.index for f in bme.faces if f.select and f.is_valid]
-
-        if len(face_index_list) == 0:
-            self.report({'WARNING'},
-                        "No suitable Face selection found. Operation cancelled")
-            edit_mode_in()
-
-            return {'CANCELLED'}
-
-        elif len(face_index_list) != 0:
-            face_inset_fillet(bme, face_index_list,
-                              inset_amount, distance, number_of_sides,
-                              out, radius, type_enum, kp)
-
-        bme.to_mesh(ob_act.data)
-        edit_mode_in()
-
-        return {'FINISHED'}
diff --git a/mesh_extra_tools/icons/icons.py b/mesh_extra_tools/icons/icons.py
deleted file mode 100644 (file)
index d98c8c0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-import os
-import bpy
-import bpy.utils.previews
-
-mesh_check_icon_collections = {}
-mesh_check_icons_loaded = False
-
-
-def load_icons():
-    global mesh_check_icon_collections
-    global mesh_check_icons_loaded
-
-    if mesh_check_icons_loaded:
-        return mesh_check_icon_collections["main"]
-
-    custom_icons = bpy.utils.previews.new()
-
-    icons_dir = os.path.join(os.path.dirname(__file__))
-
-    custom_icons.load("ngons", os.path.join(icons_dir, "ngon.png"), 'IMAGE')
-    custom_icons.load("triangles", os.path.join(icons_dir, "triangle.png"), 'IMAGE')
-
-    mesh_check_icon_collections["main"] = custom_icons
-    mesh_check_icons_loaded = True
-
-    return mesh_check_icon_collections["main"]
-
-
-def clear_icons():
-    global mesh_check_icons_loaded
-    for icon in mesh_check_icon_collections.values():
-        bpy.utils.previews.remove(icon)
-    mesh_check_icon_collections.clear()
-    mesh_check_icons_loaded = False
diff --git a/mesh_extra_tools/icons/ngon.png b/mesh_extra_tools/icons/ngon.png
deleted file mode 100644 (file)
index b1a79b9..0000000
Binary files a/mesh_extra_tools/icons/ngon.png and /dev/null differ
diff --git a/mesh_extra_tools/icons/triangle.png b/mesh_extra_tools/icons/triangle.png
deleted file mode 100644 (file)
index 05f3a8d..0000000
Binary files a/mesh_extra_tools/icons/triangle.png and /dev/null differ
diff --git a/mesh_extra_tools/mesh_check.py b/mesh_extra_tools/mesh_check.py
deleted file mode 100644 (file)
index 2acfe18..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-# gpl author: Pistiwique
-
-bl_info = {
-    "name": "Mesh Check BGL edition",
-    "description": "Display the triangles and ngons of the mesh",
-    "author": "Pistiwique",
-    "version": (1, 0, 1),
-    "blender": (2, 75, 0),
-    "location": "3D View(s) > Properties > Shading",
-    "category": "3D View"
-    }
-
-import bpy
-import bmesh
-from bgl import (
-        glBegin,
-        glLineWidth,
-        glColor4f,
-        glVertex3f,
-        glEnd,
-        GL_LINES,
-        glEnable,
-        glDisable,
-        GL_DEPTH_TEST,
-        GL_BLEND,
-        GL_POLYGON
-        )
-from mathutils.geometry import tessellate_polygon as tessellate
-from bpy.types import (
-        Operator,
-        PropertyGroup,
-        )
-from bpy.props import (
-        BoolProperty,
-        EnumProperty,
-        FloatProperty,
-        FloatVectorProperty,
-        PointerProperty,
-        )
-
-# -- Globals -- #
-mesh_check_handle = []
-draw_enabled = [False]
-edge_width = [1.0]
-face_opacity = [0.2]
-edges_tri_color = [(1.0, 1.0, 0.0, 1)]
-faces_tri_color = [(1.0, 1.0, 0.0, face_opacity[0])]
-edges_ngons_color = [(1.0, 0.0, 0.0, 1.0)]
-faces_ngons_color = [(1.0, 0.0, 0.0, face_opacity[0])]
-bm_old = [None]
-finer_lines = [False]
-
-
-def draw_poly(points):
-    for i in range(len(points)):
-        glVertex3f(points[i][0], points[i][1], points[i][2])
-
-
-def mesh_check_draw_callback():
-    obj = bpy.context.object
-    if obj and obj.type == 'MESH':
-        if draw_enabled[0]:
-            mesh = obj.data
-            matrix_world = obj.matrix_world
-
-            glLineWidth(edge_width[0])
-
-            if bpy.context.mode == 'EDIT_MESH':
-                use_occlude = True
-
-                if bm_old[0] is None or not bm_old[0].is_valid:
-                    bm = bm_old[0] = bmesh.from_edit_mesh(mesh)
-                else:
-                    bm = bm_old[0]
-
-                no_depth = not bpy.context.space_data.use_occlude_geometry
-
-                if no_depth:
-                    glDisable(GL_DEPTH_TEST)
-
-                    use_occlude = False
-
-                    if finer_lines[0]:
-                        glLineWidth(edge_width[0] / 4.0)
-                        use_occlude = True
-
-                    for face in bm.faces:
-                        if len([verts for verts in face.verts]) == 3:
-                            faces = [matrix_world * vert.co for vert in face.verts]
-                            glColor4f(*faces_tri_color[0])
-                            glEnable(GL_BLEND)
-                            glBegin(GL_POLYGON)
-                            draw_poly(faces)
-                            glEnd()
-
-                            for edge in face.edges:
-                                if edge.is_valid:
-                                    edges = [matrix_world * vert.co for vert in edge.verts]
-                                    glColor4f(*edges_tri_color[0])
-                                    glBegin(GL_LINES)
-                                    draw_poly(edges)
-                                    glEnd()
-
-                        elif len([verts for verts in face.verts]) > 4:
-                            new_faces = []
-                            faces = []
-                            coords = [v.co for v in face.verts]
-                            indices = [v.index for v in face.verts]
-                            for pol in tessellate([coords]):
-                                new_faces.append([indices[i] for i in pol])
-
-                            for f in new_faces:
-                                faces.append(
-                                        [((matrix_world * bm.verts[i].co)[0] + face.normal.x * 0.001,
-                                        (matrix_world * bm.verts[i].co)[1] + face.normal.y * 0.001,
-                                        (matrix_world * bm.verts[i].co)[2] + face.normal.z * 0.001)
-                                        for i in f]
-                                        )
-
-                            for f in faces:
-                                glColor4f(*faces_ngons_color[0])
-                                glEnable(GL_BLEND)
-                                glBegin(GL_POLYGON)
-                                draw_poly(f)
-                                glEnd()
-
-                            for edge in face.edges:
-                                if edge.is_valid:
-                                    edges = [matrix_world * vert.co for vert in edge.verts]
-                                    glColor4f(*edges_ngons_color[0])
-                                    glBegin(GL_LINES)
-                                    draw_poly(edges)
-                                    glEnd()
-
-                    glDisable(GL_BLEND)
-                    glColor4f(0.0, 0.0, 0.0, 1.0)
-                    glLineWidth(edge_width[0])
-                    glEnable(GL_DEPTH_TEST)
-
-                if use_occlude:
-
-                    for face in bm.faces:
-                        if len([verts for verts in face.verts]) == 3:
-                            faces = []
-                            for vert in face.verts:
-                                vert_face = matrix_world * vert.co
-                                faces.append(
-                                        (vert_face[0] + face.normal.x * 0.001,
-                                        vert_face[1] + face.normal.y * 0.001,
-                                        vert_face[2] + face.normal.z * 0.001)
-                                        )
-
-                            glColor4f(*faces_tri_color[0])
-                            glEnable(GL_BLEND)
-                            glBegin(GL_POLYGON)
-                            draw_poly(faces)
-                            glEnd()
-
-                            for edge in face.edges:
-                                if edge.is_valid:
-                                    edges = []
-                                    for vert in edge.verts:
-                                        vert_edge = matrix_world * vert.co
-                                        edges.append(
-                                            (vert_edge[0] + face.normal.x * 0.001,
-                                            vert_edge[1] + face.normal.y * 0.001,
-                                            vert_edge[2] + face.normal.z * 0.001)
-                                            )
-                                    glColor4f(*edges_tri_color[0])
-                                    glBegin(GL_LINES)
-                                    draw_poly(edges)
-                                    glEnd()
-
-                        elif len([verts for verts in face.verts]) > 4:
-                            new_faces = []
-                            faces = []
-                            coords = [v.co for v in face.verts]
-                            indices = [v.index for v in face.verts]
-                            for pol in tessellate([coords]):
-                                new_faces.append([indices[i] for i in pol])
-
-                            for f in new_faces:
-                                faces.append([
-                                        ((matrix_world * bm.verts[i].co)[0] + face.normal.x * 0.001,
-                                         (matrix_world * bm.verts[i].co)[1] + face.normal.y * 0.001,
-                                         (matrix_world * bm.verts[i].co)[2] + face.normal.z * 0.001)
-                                        for i in f]
-                                        )
-
-                            for f in faces:
-                                glColor4f(*faces_ngons_color[0])
-                                glEnable(GL_BLEND)
-                                glBegin(GL_POLYGON)
-                                draw_poly(f)
-                                glEnd()
-
-                            for edge in face.edges:
-                                if edge.is_valid:
-                                    edges = []
-                                    for vert in edge.verts:
-                                        vert_edge = matrix_world * vert.co
-                                        edges.append(
-                                                (vert_edge[0] + face.normal.x * 0.001,
-                                                vert_edge[1] + face.normal.y * 0.001,
-                                                vert_edge[2] + face.normal.z * 0.001)
-                                                )
-                                    glColor4f(*edges_ngons_color[0])
-                                    glBegin(GL_LINES)
-                                    draw_poly(edges)
-                                    glEnd()
-
-                    glDisable(GL_BLEND)
-                    glColor4f(0.0, 0.0, 0.0, 1.0)
-
-
-def updateBGLData(self, context):
-    if self.mesh_check_use and self.display_faces:
-        bpy.ops.object.mode_set(mode='EDIT')
-        draw_enabled[0] = True
-        edge_width[0] = self.edge_width
-        finer_lines[0] = self.finer_lines_behind_use
-        face_opacity[0] = self.face_opacity
-        edges_tri_color[0] = (
-                self.custom_tri_color[0],
-                self.custom_tri_color[1],
-                self.custom_tri_color[2],
-                1)
-        faces_tri_color[0] = (
-                self.custom_tri_color[0],
-                self.custom_tri_color[1],
-                self.custom_tri_color[2],
-                self.face_opacity
-                )
-        edges_ngons_color[0] = (
-                self.custom_ngons_color[0],
-                self.custom_ngons_color[1],
-                self.custom_ngons_color[2],
-                1)
-        faces_ngons_color[0] = (
-                self.custom_ngons_color[0],
-                self.custom_ngons_color[1],
-                self.custom_ngons_color[2],
-                self.face_opacity
-                )
-        return
-
-    draw_enabled[0] = False
-
-
-class FaceTypeSelect(Operator):
-    bl_idname = "object.face_type_select"
-    bl_label = "Face type select"
-    bl_description = "Select Triangles and / or Ngons on the Active Object"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    face_type: EnumProperty(
-            name="Face Type",
-            items=(('tris', "Tris", "Colorize Triangles in the Mesh"),
-                   ('ngons', "Ngons", "Colorize Ngons in the Mesh")),
-            default='ngons'
-            )
-
-    @classmethod
-    def poll(cls, context):
-        return context.active_object is not None and context.active_object.type == 'MESH'
-
-    def execute(self, context):
-        bpy.ops.object.mode_set(mode='EDIT')
-        bpy.ops.mesh.select_all(action='DESELECT')
-        context.tool_settings.mesh_select_mode = (False, False, True)
-
-        if self.face_type == "tris":
-            bpy.ops.mesh.select_face_by_sides(number=3, type='EQUAL')
-        else:
-            bpy.ops.mesh.select_face_by_sides(number=4, type='GREATER')
-
-        return {'FINISHED'}
-
-
-class MeshCheckCollectionGroup(PropertyGroup):
-    mesh_check_use: BoolProperty(
-            name="Mesh Check",
-            description="Display Mesh Check options",
-            default=False,
-            update=updateBGLData
-            )
-    display_faces: BoolProperty(
-            name="Display Faces",
-            description="Use BGL to display Ngons and Tris of the mesh",
-            default=False,
-            update=updateBGLData
-            )
-    edge_width: FloatProperty(
-            name="Width",
-            description="Drawn Edges width in pixels",
-            min=1.0,
-            max=10.0,
-            default=3.0,
-            subtype='PIXEL',
-            update=updateBGLData
-            )
-    finer_lines_behind_use: BoolProperty(
-            name="Finer Lines behind",
-            description="Display partially hidden edges finer in non-occlude mode",
-            default=True,
-            update=updateBGLData
-            )
-    custom_tri_color: FloatVectorProperty(
-            name="Tri Color",
-            description="Custom color for the Triangles",
-            min=0.0,
-            max=1.0,
-            default=(1.0, 1.0, 0.0),
-            size=3,
-            subtype='COLOR',
-            update=updateBGLData
-            )
-    custom_ngons_color: FloatVectorProperty(
-            name="Ngons Color",
-            description="Custom color for the Ngons",
-            min=0.0,
-            max=1.0,
-            default=(1.0, 0.0, 0.0),
-            size=3,
-            subtype='COLOR',
-            update=updateBGLData
-            )
-    face_opacity: FloatProperty(
-            name="Face Opacity",
-            description="Opacity of the color for the face",
-            min=0.0,
-            max=1.0,
-            default=0.2,
-            subtype='FACTOR',
-            update=updateBGLData
-            )
-
-
-# Register
-classes = (
-    FaceTypeSelect,
-    MeshCheckCollectionGroup,
-    )
-
-
-def register():
-    for cls in classes:
-        bpy.utils.register_class(cls)
-
-    bpy.types.WindowManager.mesh_check = PointerProperty(
-                                                type=MeshCheckCollectionGroup
-                                                )
-    if mesh_check_handle:
-        bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
-    mesh_check_handle[:] = [bpy.types.SpaceView3D.draw_handler_add(mesh_check_draw_callback,
-                            (), 'WINDOW', 'POST_VIEW')]
-
-
-def unregister():
-    del bpy.types.WindowManager.mesh_check
-    if mesh_check_handle:
-        bpy.types.SpaceView3D.draw_handler_remove(mesh_check_handle[0], 'WINDOW')
-        mesh_check_handle[:] = []
-
-    for cls in classes:
-        bpy.utils.unregister_class(cls)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_cut_faces.py b/mesh_extra_tools/mesh_cut_faces.py
deleted file mode 100644 (file)
index 1522b15..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-# gpl author: Stanislav Blinov
-
-bl_info = {
-    "name": "Cut Faces",
-    "author": "Stanislav Blinov",
-    "version": (1, 0, 0),
-    "blender": (2, 72, 0),
-    "description": "Cut Faces and Deselect Boundary operators",
-    "category": "Mesh", }
-
-import bpy
-import bmesh
-from bpy.types import Operator
-from bpy.props import (
-        BoolProperty,
-        IntProperty,
-        EnumProperty,
-        )
-
-
-def bmesh_from_object(object):
-    mesh = object.data
-    if object.mode == 'EDIT':
-        bm = bmesh.from_edit_mesh(mesh)
-    else:
-        bm = bmesh.new()
-        bm.from_mesh(mesh)
-    return bm
-
-
-def bmesh_release(bm, object):
-    mesh = object.data
-    bm.select_flush_mode()
-    if object.mode == 'EDIT':
-        bmesh.update_edit_mesh(mesh, True)
-    else:
-        bm.to_mesh(mesh)
-        bm.free()
-
-
-def calc_face(face, keep_caps=True):
-
-    assert face.tag
-
-    def radial_loops(loop):
-        next = loop.link_loop_radial_next
-        while next != loop:
-            result, next = next, next.link_loop_radial_next
-            yield result
-
-    result = []
-
-    face.tag = False
-    selected = []
-    to_select = []
-    for loop in face.loops:
-        self_selected = False
-        # Iterate over selected adjacent faces
-        for radial_loop in filter(lambda l: l.face.select, radial_loops(loop)):
-            # Tag the edge if no other face done so already
-            if not loop.edge.tag:
-                loop.edge.tag = True
-                self_selected = True
-
-            adjacent_face = radial_loop.face
-            # Only walk adjacent face if current face tagged the edge
-            if adjacent_face.tag and self_selected:
-                result += calc_face(adjacent_face, keep_caps)
-
-        if loop.edge.tag:
-            (selected, to_select)[self_selected].append(loop)
-
-    for loop in to_select:
-        result.append(loop.edge)
-        selected.append(loop)
-
-    # Select opposite edge in quads
-    if keep_caps and len(selected) == 1 and len(face.verts) == 4:
-        result.append(selected[0].link_loop_next.link_loop_next.edge)
-
-    return result
-
-
-def get_edge_rings(bm, keep_caps=True):
-
-    def tag_face(face):
-        if face.select:
-            face.tag = True
-            for edge in face.edges:
-                edge.tag = False
-        return face.select
-
-    # fetch selected faces while setting up tags
-    selected_faces = [f for f in bm.faces if tag_face(f)]
-
-    edges = []
-
-    try:
-        # generate a list of edges to select:
-        # traversing only tagged faces, since calc_face can walk and untag islands
-        for face in filter(lambda f: f.tag, selected_faces):
-            edges += calc_face(face, keep_caps)
-    finally:
-        # housekeeping: clear tags
-        for face in selected_faces:
-            face.tag = False
-            for edge in face.edges:
-                edge.tag = False
-
-    return edges
-
-
-class MESH_xOT_deselect_boundary(Operator):
-    bl_idname = "mesh.ext_deselect_boundary"
-    bl_label = "Deselect Boundary"
-    bl_description = ("Deselect boundary edges of selected faces\n"
-                      "Note: if all Faces are selected there is no boundary,\n"
-                      "so the tool will not have results")
-    bl_options = {'REGISTER', 'UNDO'}
-
-    keep_cap_edges: BoolProperty(
-                        name="Keep Cap Edges",
-                        description="Keep quad strip cap edges selected",
-                        default=False
-                        )
-
-    @classmethod
-    def poll(cls, context):
-        active_object = context.active_object
-        return active_object and active_object.type == 'MESH' and active_object.mode == 'EDIT'
-
-    def execute(self, context):
-        object = context.active_object
-        bm = bmesh_from_object(object)
-
-        try:
-            edges = get_edge_rings(bm, keep_caps=self.keep_cap_edges)
-            if not edges:
-                self.report({'WARNING'}, "No suitable Face selection found. Operation cancelled")
-                return {'CANCELLED'}
-
-            bpy.ops.mesh.select_all(action='DESELECT')
-            bm.select_mode = {'EDGE'}
-
-            for edge in edges:
-                edge.select = True
-            context.tool_settings.mesh_select_mode[:] = False, True, False
-
-        finally:
-            bmesh_release(bm, object)
-
-        return {'FINISHED'}
-
-
-class MESH_xOT_cut_faces(Operator):
-    bl_idname = "mesh.ext_cut_faces"
-    bl_label = "Cut Faces"
-    bl_description = "Cut selected faces, connected through their adjacent edges"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    # from bmesh_operators.h
-    SUBD_INNERVERT = 0
-    SUBD_PATH = 1
-    SUBD_FAN = 2
-    SUBD_STRAIGHT_CUT = 3
-
-    num_cuts: IntProperty(
-            name="Number of Cuts",
-            default=1,
-            min=1,
-            max=100,
-            subtype='UNSIGNED'
-            )
-    use_single_edge: BoolProperty(
-            name="Quad/Tri Mode",
-            description="Cut boundary faces",
-            default=False
-            )
-    corner_type: EnumProperty(
-            items=[('SUBD_INNERVERT', "Inner Vert", ""),
-                   ('SUBD_PATH', "Path", ""),
-                   ('SUBD_FAN', "Fan", ""),
-                   ('SUBD_STRAIGHT_CUT', "Straight Cut", ""),
-                   ],
-            name="Quad Corner Type",
-            description="How to subdivide quad corners",
-            default='SUBD_STRAIGHT_CUT'
-            )
-    use_grid_fill: BoolProperty(
-            name="Use Grid Fill",
-            description="Fill fully enclosed faces with a grid",
-            default=True
-            )
-
-    @classmethod
-    def poll(cls, context):
-        active_object = context.active_object
-        return active_object and active_object.type == 'MESH' and active_object.mode == 'EDIT'
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.label(text="Number of Cuts:")
-        layout.prop(self, "num_cuts", text="")
-
-        layout.prop(self, "use_single_edge")
-        layout.prop(self, "use_grid_fill")
-
-        layout.label(text="Quad Corner Type:")
-        layout.prop(self, "corner_type", text="")
-
-    def cut_edges(self, context):
-        object = context.active_object
-        bm = bmesh_from_object(object)
-
-        try:
-            edges = get_edge_rings(bm, keep_caps=True)
-            if not edges:
-                self.report({'WARNING'},
-                            "No suitable Face selection found. Operation cancelled")
-                return False
-
-            result = bmesh.ops.subdivide_edges(
-                            bm,
-                            edges=edges,
-                            cuts=int(self.num_cuts),
-                            use_grid_fill=bool(self.use_grid_fill),
-                            use_single_edge=bool(self.use_single_edge),
-                            quad_corner_type=eval("self." + self.corner_type)
-                            )
-            bpy.ops.mesh.select_all(action='DESELECT')
-            bm.select_mode = {'EDGE'}
-
-            inner = result['geom_inner']
-            for edge in filter(lambda e: isinstance(e, bmesh.types.BMEdge), inner):
-                edge.select = True
-
-        finally:
-            bmesh_release(bm, object)
-
-        return True
-
-    def execute(self, context):
-
-        if not self.cut_edges(context):
-            return {'CANCELLED'}
-
-        context.tool_settings.mesh_select_mode[:] = False, True, False
-        # Try to select all possible loops
-        bpy.ops.mesh.loop_multi_select(ring=False)
-
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_class(MESH_xOT_deselect_boundary)
-    bpy.utils.register_class(MESH_xOT_cut_faces)
-
-
-def unregister():
-    bpy.utils.unregister_class(MESH_xOT_deselect_boundary)
-    bpy.utils.unregister_class(MESH_xOT_cut_faces)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_edge_roundifier.py b/mesh_extra_tools/mesh_edge_roundifier.py
deleted file mode 100644 (file)
index f216b1d..0000000
+++ /dev/null
@@ -1,1380 +0,0 @@
-# ##### 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": "Edge Roundifier",
-    "category": "Mesh",
-    "author": "Piotr Komisarczyk (komi3D), PKHG",
-    "version": (1, 0, 1),
-    "blender": (2, 73, 0),
-    "location": "SPACE > Edge Roundifier or CTRL-E > "
-                "Edge Roundifier or Tools > Addons > Edge Roundifier",
-    "description": "Mesh editing script allowing edge rounding",
-    "wiki_url": "",
-    "category": "Mesh"
-}
-
-import bpy
-import bmesh
-from bpy.types import Operator
-from bpy.props import (
-        BoolProperty,
-        FloatProperty,
-        EnumProperty,
-        IntProperty,
-        )
-from math import (
-        sqrt, acos, pi,
-        radians, degrees, sin,
-        )
-from mathutils import (
-        Vector, Euler,
-        Quaternion,
-        )
-
-# CONSTANTS
-two_pi = 2 * pi
-XY = "XY"
-XZ = "XZ"
-YZ = "YZ"
-SPIN_END_THRESHOLD = 0.001
-LINE_TOLERANCE = 0.0001
-d_XABS_YABS = False
-d_Edge_Info = False
-d_Plane = False
-d_Radius_Angle = False
-d_Roots = False
-d_RefObject = False
-d_LineAB = False
-d_Selected_edges = False
-d_Rotate_Around_Spin_Center = False
-
-# Enable debug prints
-DEBUG = False
-
-
-# for debugging PKHG #
-def debugPrintNew(debugs, *text):
-    if DEBUG and debugs:
-        tmp = [el for el in text]
-        for row in tmp:
-            print(row)
-
-
-# Geometry and math calculation methods #
-
-class CalculationHelper:
-
-    def __init__(self):
-        """
-        Constructor
-        """
-    def getLineCoefficientsPerpendicularToVectorInPoint(self, point, vector, plane):
-        x, y, z = point
-        xVector, yVector, zVector = vector
-        destinationPoint = (x + yVector, y - xVector, z)
-        if plane == 'YZ':
-            destinationPoint = (x, y + zVector, z - yVector)
-        if plane == 'XZ':
-            destinationPoint = (x + zVector, y, z - xVector)
-        return self.getCoefficientsForLineThrough2Points(point, destinationPoint, plane)
-
-    def getQuadraticRoots(self, coef):
-        if len(coef) != 3:
-            return None  # Replaced NaN with None
-        else:
-            a, b, c = coef
-            delta = b ** 2 - 4 * a * c
-            if delta == 0:
-                x = -b / (2 * a)
-                return (x, x)
-            elif delta < 0:
-                return None
-            else:
-                x1 = (-b - sqrt(delta)) / (2 * a)
-                x2 = (-b + sqrt(delta)) / (2 * a)
-                return (x1, x2)
-
-    def getCoefficientsForLineThrough2Points(self, point1, point2, plane):
-        x1, y1, z1 = point1
-        x2, y2, z2 = point2
-
-        # mapping x1,x2, y1,y2 to proper values based on plane
-        if plane == YZ:
-            x1 = y1
-            x2 = y2
-            y1 = z1
-            y2 = z2
-        if plane == XZ:
-            y1 = z1
-            y2 = z2
-
-        # Further calculations the same as for XY plane
-        xabs = abs(x2 - x1)
-        yabs = abs(y2 - y1)
-        debugPrintNew(d_XABS_YABS, "XABS = " + str(xabs) + " YABS = " + str(yabs))
-
-        if xabs <= LINE_TOLERANCE:
-            return None  # this means line x = edgeCenterX
-        if yabs <= LINE_TOLERANCE:
-            A = 0
-            B = y1
-            return A, B
-        A = (y2 - y1) / (x2 - x1)
-        B = y1 - (A * x1)
-        return (A, B)
-
-    def getLineCircleIntersections(self, lineAB, circleMidPoint, radius):
-        # (x - a)**2 + (y - b)**2 = r**2 - circle equation
-        # y = A*x + B - line equation
-        # f * x**2 + g * x + h = 0 - quadratic equation
-        A, B = lineAB
-        a, b = circleMidPoint
-        f = 1 + (A ** 2)
-        g = -2 * a + 2 * A * B - 2 * A * b
-        h = (B ** 2) - 2 * b * B - (radius ** 2) + (a ** 2) + (b ** 2)
-        coef = [f, g, h]
-        roots = self.getQuadraticRoots(coef)
-        if roots is not None:
-            x1 = roots[0]
-            x2 = roots[1]
-            point1 = [x1, A * x1 + B]
-            point2 = [x2, A * x2 + B]
-            return [point1, point2]
-        else:
-            return None
-
-    def getLineCircleIntersectionsWhenXPerpendicular(self, edgeCenter,
-                                                     circleMidPoint, radius, plane):
-        # (x - a)**2 + (y - b)**2 = r**2 - circle equation
-        # x = xValue - line equation
-        # f * x**2 + g * x + h = 0 - quadratic equation
-        xValue = edgeCenter[0]
-        if plane == YZ:
-            xValue = edgeCenter[1]
-        if plane == XZ:
-            xValue = edgeCenter[0]
-
-        a, b = circleMidPoint
-        f = 1
-        g = -2 * b
-        h = (a ** 2) + (b ** 2) + (xValue ** 2) - 2 * a * xValue - (radius ** 2)
-        coef = [f, g, h]
-        roots = self.getQuadraticRoots(coef)
-        if roots is not None:
-            y1 = roots[0]
-            y2 = roots[1]
-            point1 = [xValue, y1]
-            point2 = [xValue, y2]
-            return [point1, point2]
-        else:
-            return None
-
-    # point1 is the point near 90 deg angle
-    def getAngle(self, point1, point2, point3):
-        distance1 = (Vector(point1) - Vector(point2)).length
-        distance2 = (Vector(point2) - Vector(point3)).length
-        cos = distance1 / distance2
-
-        if abs(cos) > 1:  # prevents Domain Error
-            cos = round(cos)
-
-        alpha = acos(cos)
-        return (alpha, degrees(alpha))
-
-    # get two of three coordinates used for further calculation of spin center
-    # PKHG>nice if rescriction to these 3 types or planes is to be done
-    # komi3D> from 0.0.2 there is a restriction. In future I would like Edge
-    # komi3D> Roundifier to work on Normal and View coordinate systems
-    def getCircleMidPointOnPlane(self, V1, plane):
-        X = V1[0]
-        Y = V1[1]
-        if plane == 'XZ':
-            X = V1[0]
-            Y = V1[2]
-        elif plane == 'YZ':
-            X = V1[1]
-            Y = V1[2]
-        return [X, Y]
-
-    def getEdgeReference(self, edge, edgeCenter, plane):
-        vert1 = edge.verts[1].co
-        V = vert1 - edgeCenter
-        orthoVector = Vector((V[1], -V[0], V[2]))
-        if plane == 'XZ':
-            orthoVector = Vector((V[2], V[1], -V[0]))
-        elif plane == 'YZ':
-            orthoVector = Vector((V[0], V[2], -V[1]))
-        refPoint = edgeCenter + orthoVector
-        return refPoint
-
-
-# Selection Methods #
-
-class SelectionHelper:
-
-    def selectVertexInMesh(self, mesh, vertex):
-        bpy.ops.object.mode_set(mode="OBJECT")
-        for v in mesh.vertices:
-            if v.co == vertex:
-                v.select = True
-                break
-
-        bpy.ops.object.mode_set(mode="EDIT")
-
-    def getSelectedVertex(self, mesh):
-        bpy.ops.object.mode_set(mode="OBJECT")
-        for v in mesh.vertices:
-            if v.select is True:
-                bpy.ops.object.mode_set(mode="EDIT")
-                return v
-
-        bpy.ops.object.mode_set(mode="EDIT")
-        return None
-
-    def refreshMesh(self, bm, mesh):
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bm.to_mesh(mesh)
-        bpy.ops.object.mode_set(mode='EDIT')
-
-
-# Operator
-
-class EdgeRoundifier(Operator):
-    bl_idname = "mesh.edge_roundifier"
-    bl_label = "Edge Roundifier"
-    bl_description = "Mesh modeling tool for building arcs on selected Edges"
-    bl_options = {'REGISTER', 'UNDO', 'PRESET'}
-
-    threshold = 0.0005
-    obj = None
-
-    edgeScaleFactor: FloatProperty(
-            name="",
-            description="Set the Factor of scaling",
-            default=1.0,
-            min=0.00001, max=100000.0,
-            step=0.5,
-            precision=5
-            )
-    r: FloatProperty(
-            name="",
-            description="User Defined arc steepness by a Radius\n"
-                        "Enabled only if Entry mode is set to Radius\n",
-            default=1,
-            min=0.00001, max=1000.0,
-            step=0.1,
-            precision=3
-            )
-    a: FloatProperty(
-            name="",
-            description="User defined arc steepness calculated from an Angle\n"
-                        "Enabled only if Entry mode is set to Angle and\n"
-                        "Angle presets is set Other",
-            default=180.0,
-            min=0.1, max=180.0,
-            step=0.5,
-            precision=1
-            )
-    n: IntProperty(
-            name="",
-            description="Arc subdivision level",
-            default=4,
-            min=1, max=100,
-            step=1
-            )
-    flip: BoolProperty(
-            name="Flip",
-            description="If True, flip the side of the selected edges where the arcs are drawn",
-            default=False
-            )
-    invertAngle: BoolProperty(
-            name="Invert",
-            description="If True, uses an inverted angle to draw the arc (360 degrees - angle)",
-            default=False
-            )
-    fullCircles: BoolProperty(
-            name="Circles",
-            description="If True, uses an angle of 360 degrees to draw the arcs",
-            default=False
-            )
-    bothSides: BoolProperty(
-            name="Both sides",
-            description="If True, draw arcs on both sides of the selected edges",
-            default=False
-            )
-    drawArcCenters: BoolProperty(
-            name="Centers",
-            description="If True, draws a vertex for each spin center",
-            default=False
-            )
-    removeEdges: BoolProperty(
-            name="Edges",
-            description="If True removes the Original selected edges",
-            default=False
-            )
-    removeScaledEdges: BoolProperty(
-            name="Scaled edges",
-            description="If True removes the Scaled edges (not part of the arcs)",
-            default=False
-            )
-    connectArcWithEdge: BoolProperty(
-            name="Arc - Edge",
-            description="Connect Arcs to Edges",
-            default=False
-            )
-    connectArcs: BoolProperty(
-            name="Arcs",
-            description="Connect subsequent Arcs",
-            default=False
-            )
-    connectScaledAndBase: BoolProperty(
-            name="Scaled - Base Edge",
-            description="Connect Scaled to Base Edge",
-            default=False
-            )
-    connectArcsFlip: BoolProperty(
-            name="Flip Arcs",
-            description="Flip the connection of subsequent Arcs",
-            default=False
-            )
-    connectArcWithEdgeFlip: BoolProperty(
-            name="Flip Arc - Edge",
-            description="Flip the connection of the Arcs to Edges",
-            default=False
-            )
-    axisAngle: FloatProperty(
-            name="",
-            description="Rotate Arc around the perpendicular axis",
-            default=0.0,
-            min=-180.0, max=180.0,
-            step=0.5,
-            precision=1
-            )
-    edgeAngle: FloatProperty(
-            name="",
-            description="Rotate Arc around the Edge (Edge acts like as the axis)",
-            default=0.0,
-            min=-180.0, max=180.0,
-            step=0.5,
-            precision=1
-            )
-    offset: FloatProperty(
-            name="",
-            description="Offset Arc perpendicular the Edge",
-            default=0.0,
-            min=-1000000.0, max=1000000.0,
-            step=0.1,
-            precision=5
-            )
-    offset2: FloatProperty(
-            name="",
-            description="Offset Arc in parallel to the Edge",
-            default=0.0,
-            min=-1000000.0, max=1000000.0,
-            step=0.1,
-            precision=5
-            )
-    ellipticFactor: FloatProperty(
-            name="",
-            description="Make Arc elliptic",
-            default=0.0,
-            min=-1000000.0, max=1000000.0,
-            step=0.1,
-            precision=5
-            )
-    workModeItems = [("Normal", "Normal", ""), ("Reset", "Reset", "")]
-    workMode: EnumProperty(
-            items=workModeItems,
-            name="",
-            default='Normal',
-            description="Normal work with the current given parameters set by the user\n"
-                        "Reset - changes back the parameters to their default values"
-            )
-    entryModeItems = [("Radius", "Radius", ""), ("Angle", "Angle", "")]
-    entryMode: EnumProperty(
-            items=entryModeItems,
-            name="",
-            default='Angle',
-            description="Entry mode switch between Angle and Radius\n"
-                        "If Angle is selected, arc radius is calculated from it"
-            )
-    rotateCenterItems = [
-            ("Spin", "Spin", ""), ("V1", "V1", ""),
-            ("Edge", "Edge", ""), ("V2", "V2", "")
-            ]
-    rotateCenter: EnumProperty(
-            items=rotateCenterItems,
-            name="",
-            default='Edge',
-            description="Rotate center for spin axis rotate"
-            )
-    arcModeItems = [("FullEdgeArc", "Full", "Full"), ('HalfEdgeArc', "Half", "Half")]
-    arcMode: EnumProperty(
-            items=arcModeItems,
-            name="",
-            default='FullEdgeArc',
-            description="Arc mode - switch between Full and Half arcs"
-            )
-    angleItems = [
-            ('Other', "Other", "User defined angle"), ('180', "180", "HemiCircle (2 sides)"),
-            ('120', "120", "TriangleCircle (3 sides)"), ('90', "90", "QuadCircle (4 sides)"),
-            ('72', "72", "PentagonCircle (5 sides)"), ('60', "60", "HexagonCircle (6 sides)"),
-            ('45', "45", "OctagonCircle (8 sides)"), ('30', "30", "DodecagonCircle (12 sides)")
-            ]
-    angleEnum: EnumProperty(
-            items=angleItems,
-            name="",
-            default='180',
-            description="Presets prepare standard angles and calculate proper ray"
-            )
-    refItems = [('ORG', "Origin", "Use Origin Location"), ('CUR', "3D Cursor", "Use 3DCursor Location"),
-                ('EDG', "Edge", "Use Individual Edge Reference")]
-    referenceLocation: EnumProperty(
-            items=refItems,
-            name="",
-            default='ORG',
-            description="Reference location used to calculate initial centers of drawn arcs"
-            )
-    planeItems = [
-            (XY, "XY", "XY Plane (Z=0)"),
-            (YZ, "YZ", "YZ Plane (X=0)"),
-            (XZ, "XZ", "XZ Plane (Y=0)")
-            ]
-    planeEnum: EnumProperty(
-            items=planeItems,
-            name="",
-            default='XY',
-            description="Plane used to calculate spin plane of drawn arcs"
-            )
-    edgeScaleCenterItems = [
-            ('V1', "V1", "v1 - First Edge's Vertex"),
-            ('CENTER', "Center", "Center of the Edge"),
-            ('V2', "V2", "v2 - Second Edge's Vertex")
-            ]
-    edgeScaleCenterEnum: EnumProperty(
-            items=edgeScaleCenterItems,
-            name="Edge scale center",
-            default='CENTER',
-            description="Center used for scaling the initial edge"
-            )
-
-    calc = CalculationHelper()
-    sel = SelectionHelper()
-
-    @classmethod
-    def poll(cls, context):
-        obj = context.active_object
-        return (obj and obj.type == 'MESH' and
-                obj.mode == 'EDIT')
-
-    def prepareMesh(self, context):
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.mode_set(mode='EDIT')
-
-        mesh = context.view_layer.objects.active.data
-        bm = bmesh.new()
-        bm.from_mesh(mesh)
-
-        edges = [ele for ele in bm.edges if ele.select]
-        return edges, mesh, bm
-
-    def prepareParameters(self):
-        parameters = {"a": "a"}
-        parameters["arcMode"] = self.arcMode
-        parameters["edgeScaleFactor"] = self.edgeScaleFactor
-        parameters["edgeScaleCenterEnum"] = self.edgeScaleCenterEnum
-        parameters["plane"] = self.planeEnum
-        parameters["radius"] = self.r
-        parameters["angle"] = self.a
-        parameters["segments"] = self.n
-        parameters["fullCircles"] = self.fullCircles
-        parameters["invertAngle"] = self.invertAngle
-        parameters["bothSides"] = self.bothSides
-        parameters["angleEnum"] = self.angleEnum
-        parameters["entryMode"] = self.entryMode
-        parameters["workMode"] = self.workMode
-        parameters["refObject"] = self.referenceLocation
-        parameters["flip"] = self.flip
-        parameters["drawArcCenters"] = self.drawArcCenters
-        parameters["removeEdges"] = self.removeEdges
-        parameters["removeScaledEdges"] = self.removeScaledEdges
-        parameters["connectArcWithEdge"] = self.connectArcWithEdge
-        parameters["connectScaledAndBase"] = self.connectScaledAndBase
-        parameters["connectArcs"] = self.connectArcs
-        parameters["connectArcsFlip"] = self.connectArcsFlip
-        parameters["connectArcWithEdgeFlip"] = self.connectArcWithEdgeFlip
-        parameters["axisAngle"] = self.axisAngle
-        parameters["edgeAngle"] = self.edgeAngle
-        parameters["offset"] = self.offset
-        parameters["offset2"] = self.offset2
-        parameters["ellipticFactor"] = self.ellipticFactor
-        parameters["rotateCenter"] = self.rotateCenter
-        return parameters
-
-    def draw(self, context):
-        layout = self.layout
-        box = layout.box()
-        uiPercentage = 0.333
-
-        self.addEnumParameterToUI(box, False, uiPercentage, 'Mode:', 'workMode')
-        self.addEnumParameterToUI(box, False, uiPercentage, 'Plane:', 'planeEnum')
-        self.addEnumParameterToUI(box, False, uiPercentage, 'Reference:', 'referenceLocation')
-
-        box = layout.box()
-        self.addEnumParameterToUI(box, False, uiPercentage, 'Scale base:', 'edgeScaleCenterEnum')
-        self.addParameterToUI(box, False, uiPercentage, 'Scale factor:', 'edgeScaleFactor')
-
-        box = layout.box()
-        self.addEnumParameterToUI(box, False, uiPercentage, 'Entry mode:', 'entryMode')
-
-        row = box.row(align=False)
-        row.prop(self, 'angleEnum', expand=True, text="Angle presets")
-
-        disable_a = bool(self.entryMode == 'Angle' and self.angleEnum == 'Other')
-        disable_r = bool(self.entryMode == 'Radius')
-
-        self.addParameterToUI(box, False, uiPercentage, 'Angle:', 'a', disable_a)
-        self.addParameterToUI(box, False, uiPercentage, 'Radius:', 'r', disable_r)
-        self.addParameterToUI(box, False, uiPercentage, 'Segments:', 'n')
-
-        box = layout.box()
-        self.addCheckboxToUI(box, True, 'Options:', 'flip', 'invertAngle')
-        self.addCheckboxToUI(box, True, '', 'bothSides', 'fullCircles')
-        self.addCheckboxToUI(box, True, '', 'drawArcCenters')
-
-        box = layout.box()
-        self.addCheckboxToUI(box, True, 'Remove:', 'removeEdges', 'removeScaledEdges')
-
-        box = layout.box()
-        self.addCheckboxToUI(box, True, 'Connect:', 'connectArcs', 'connectArcsFlip')
-        self.addCheckboxToUI(box, True, '', 'connectArcWithEdge', 'connectArcWithEdgeFlip')
-        self.addCheckboxToUI(box, True, '', 'connectScaledAndBase')
-
-        box = layout.box()
-        self.addParameterToUI(box, False, uiPercentage, 'Orhto offset:', 'offset')
-        self.addParameterToUI(box, False, uiPercentage, 'Parallel offset:', 'offset2')
-
-        box = layout.box()
-        self.addParameterToUI(box, False, uiPercentage, 'Edge rotate :', 'edgeAngle')
-        self.addEnumParameterToUI(box, False, uiPercentage, 'Axis rotate center:', 'rotateCenter')
-        self.addParameterToUI(box, False, uiPercentage, 'Axis rotate:', 'axisAngle')
-
-        box = layout.box()
-        self.addParameterToUI(box, False, uiPercentage, 'Elliptic factor:', 'ellipticFactor')
-
-    def addParameterToUI(self, layout, alignment, percent, label, properties, disable=True):
-        row = layout.row(align=alignment)
-        split = row.split(factor=percent)
-        col = split.column()
-
-        col.label(label)
-        col2 = split.column()
-        row = col2.row(align=alignment)
-        row.enabled = disable
-        row.prop(self, properties)
-
-    def addCheckboxToUI(self, layout, alignment, label, property1, property2=None):
-        if label not in (""):
-            row = layout.row()
-            row.label(label)
-        row2 = layout.row(align=alignment)
-        if property2:
-            split = row2.split(factor=0.5)
-            split.prop(self, property1, toggle=True)
-            split.prop(self, property2, toggle=True)
-        else:
-            row2.prop(self, property1, toggle=True)
-            layout.separator()
-
-    def addEnumParameterToUI(self, layout, alignment, percent, label, properties):
-        row = layout.row(align=alignment)
-        split = row.split(factor=percent)
-        col = split.column()
-
-        col.label(label)
-        col2 = split.column()
-        row = col2.row(align=alignment)
-        row.prop(self, properties, expand=True, text="a")
-
-    def execute(self, context):
-
-        edges, mesh, bm = self.prepareMesh(context)
-        parameters = self.prepareParameters()
-
-        self.resetValues(parameters["workMode"])
-
-        self.obj = context.view_layer.objects.active
-        scaledEdges = self.scaleDuplicatedEdges(bm, edges, parameters)
-
-        if len(scaledEdges) > 0:
-            self.roundifyEdges(scaledEdges, parameters, bm, mesh)
-
-            if parameters["connectScaledAndBase"]:
-                self.connectScaledEdgesWithBaseEdge(scaledEdges, edges, bm, mesh)
-
-            self.sel.refreshMesh(bm, mesh)
-            self.selectEdgesAfterRoundifier(context, scaledEdges)
-        else:
-            debugPrintNew(True, "No edges selected!")
-
-        if parameters["removeEdges"]:
-            bmesh.ops.delete(bm, geom=edges, context=2)
-
-        if parameters["removeScaledEdges"] and self.edgeScaleFactor != 1.0:
-            bmesh.ops.delete(bm, geom=scaledEdges, context=2)
-
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bm.to_mesh(mesh)
-        bpy.ops.object.mode_set(mode='EDIT')
-        bpy.ops.mesh.select_all(action='SELECT')
-        bpy.ops.mesh.remove_doubles()
-
-        bm.free()
-
-        return {'FINISHED'}
-
-    def resetValues(self, workMode):
-        if workMode == "Reset":
-            self.setAllParamsToDefaults()
-
-    def setAllParamsToDefaults(self):
-        try:
-            self.edgeScaleFactor = 1.0
-            self.r = 1
-            self.a = 180.0
-            self.n = 4
-            self.flip = False
-            self.invertAngle = False
-            self.fullCircles = False
-            self.bothSides = False
-            self.drawArcCenters = False
-            self.removeEdges = False
-            self.removeScaledEdges = False
-
-            self.connectArcWithEdge = False
-            self.connectArcs = False
-            self.connectScaledAndBase = False
-            self.connectArcsFlip = False
-            self.connectArcWithEdgeFlip = False
-
-            self.axisAngle = 0.0
-            self.edgeAngle = 0.0
-            self.offset = 0.0
-            self.offset2 = 0.0
-            self.ellipticFactor = 0.0
-
-            self.workMode = 'Normal'
-            self.entryMode = 'Angle'
-            self.angleEnum = '180'
-            self.referenceLocation = 'ORG'
-            self.planeEnum = 'XY'
-            self.edgeScaleCenterEnum = 'CENTER'
-            self.rotateCenter = 'Edge'
-
-            self.report({'INFO'}, "The parameters have been reset to default values")
-        except Exception as e:
-            self.report({'WARNING'}, "The parameters could not be reset")
-            debugPrintNew(True, "\n[setAllParamsToDefaults]\n parameter reset error\n" + e)
-
-    def scaleDuplicatedEdges(self, bm, edges, parameters):
-        scaleCenter = parameters["edgeScaleCenterEnum"]
-        factor = parameters["edgeScaleFactor"]
-        # this code is based on Zeffi's answer to my question
-        duplicateEdges = []
-        if factor == 1:
-            duplicateEdges = edges
-        else:
-            for e in edges:
-                v1 = e.verts[0].co
-                v2 = e.verts[1].co
-                origin = None
-                if scaleCenter == 'CENTER':
-                    origin = (v1 + v2) * 0.5
-                elif scaleCenter == 'V1':
-                    origin = v1
-                elif scaleCenter == 'V2':
-                    origin = v2
-
-                bmv1 = bm.verts.new(((v1 - origin) * factor) + origin)
-                bmv2 = bm.verts.new(((v2 - origin) * factor) + origin)
-                bme = bm.edges.new([bmv1, bmv2])
-                duplicateEdges.append(bme)
-        return duplicateEdges
-
-    def roundifyEdges(self, edges, parameters, bm, mesh):
-        arcs = []
-        for e in edges:
-            arcVerts = self.roundify(e, parameters, bm, mesh)
-            arcs.append(arcVerts)
-
-        if parameters["connectArcs"]:
-            self.connectArcsTogether(arcs, bm, mesh, parameters)
-
-    def getNormalizedEdgeVector(self, edge):
-        V1 = edge.verts[0].co
-        V2 = edge.verts[1].co
-        edgeVector = V2 - V1
-        normEdge = edgeVector.normalized()
-        return normEdge
-
-    def getEdgePerpendicularVector(self, edge, plane):
-        normEdge = self.getNormalizedEdgeVector(edge)
-
-        edgePerpendicularVector = Vector((normEdge[1], -normEdge[0], 0))
-        if plane == YZ:
-            edgePerpendicularVector = Vector((0, normEdge[2], -normEdge[1]))
-        if plane == XZ:
-            edgePerpendicularVector = Vector((normEdge[2], 0, -normEdge[0]))
-        return edgePerpendicularVector
-
-    def getEdgeInfo(self, edge):
-        V1 = edge.verts[0].co
-        V2 = edge.verts[1].co
-        edgeVector = V2 - V1
-        edgeLength = edgeVector.length
-        edgeCenter = (V2 + V1) * 0.5
-        return V1, V2, edgeVector, edgeLength, edgeCenter
-
-    def roundify(self, edge, parameters, bm, mesh):
-        V1, V2, edgeVector, edgeLength, edgeCenter = self.getEdgeInfo(edge)
-        if self.skipThisEdge(V1, V2, parameters["plane"]):
-            return
-
-        roundifyParams = None
-        arcVerts = None
-        roundifyParams = self.calculateRoundifyParams(edge, parameters, bm, mesh)
-        if roundifyParams is None:
-            return
-
-        arcVerts = self.spinAndPostprocess(edge, parameters, bm, mesh, edgeCenter, roundifyParams)
-        return arcVerts
-
-    def spinAndPostprocess(self, edge, parameters, bm, mesh, edgeCenter, roundifyParams):
-        spinnedVerts, roundifyParamsUpdated = self.drawSpin(
-                                                edge, edgeCenter,
-                                                roundifyParams,
-                                                parameters, bm, mesh
-                                                )
-        postProcessedArcVerts = self.arcPostprocessing(
-                                                edge, parameters, bm, mesh,
-                                                roundifyParamsUpdated,
-                                                spinnedVerts, edgeCenter
-                                                )
-        return postProcessedArcVerts
-
-    def rotateArcAroundEdge(self, bm, mesh, arcVerts, parameters):
-        angle = parameters["edgeAngle"]
-        if angle != 0:
-            self.arc_rotator(arcVerts, angle, parameters)
-
-    # arc_rotator method was created by PKHG, I (komi3D) adjusted it to fit the rest
-    def arc_rotator(self, arcVerts, extra_rotation, parameters):
-        bpy.ops.object.mode_set(mode='OBJECT')
-        old_location = self.obj.location.copy()
-        bpy.ops.transform.translate(
-            value=-old_location,
-            constraint_axis=(False, False, False),
-            orient_type='GLOBAL',
-            mirror=False,
-            use_proportional_edit=False,
-        )
-        bpy.ops.object.mode_set(mode='EDIT')
-        adjust_matrix = self.obj.matrix_parent_inverse
-        bm = bmesh.from_edit_mesh(self.obj.data)
-        lastVert = len(arcVerts) - 1
-        if parameters["drawArcCenters"]:
-            lastVert = lastVert - 1  # center gets added as last vert of arc
-        v0_old = adjust_matrix * arcVerts[0].co.copy()
-
-        # PKHG>INFO move if necessary v0 to origin such that the axis gos through origin and v1
-        if v0_old != Vector((0, 0, 0)):
-            for i, ele in enumerate(arcVerts):
-                arcVerts[i].co += - v0_old
-
-        axis = arcVerts[0].co - arcVerts[lastVert].co
-        a_mat = Quaternion(axis, radians(extra_rotation)).normalized().to_matrix()
-
-        for ele in arcVerts:
-            ele.co = a_mat * ele.co
-
-        # PKHG>INFO move back if needed
-        if v0_old != Vector((0, 0, 0)):
-            for i, ele in enumerate(arcVerts):
-                arcVerts[i].co += + v0_old
-
-        bpy.ops.object.mode_set(mode='OBJECT')
-        # PKHG>INFO move origin object back print("old location = " , old_location)
-        bpy.ops.transform.translate(
-            value=old_location,
-            constraint_axis=(False, False, False),
-            orient_type='GLOBAL',
-            mirror=False,
-            use_proportional_edit=False,
-        )
-        bpy.ops.object.mode_set(mode='EDIT')
-
-    def makeElliptic(self, bm, mesh, arcVertices, parameters):
-        if parameters["ellipticFactor"] != 0:  # if 0 then nothing has to be done
-            lastVert = len(arcVertices) - 1
-            if parameters["drawArcCenters"]:
-                lastVert = lastVert - 1  # center gets added as last vert of arc
-            v0co = arcVertices[0].co
-            v1co = arcVertices[lastVert].co
-
-            for vertex in arcVertices:  # range(len(res_list)):
-                # PKHg>INFO compute the base on the edge  of the height-vector
-                top = vertex.co  # res_list[nr].co
-                t = 0
-                if v1co - v0co != 0:
-                    t = (v1co - v0co).dot(top - v0co) / (v1co - v0co).length ** 2
-                h_bottom = v0co + t * (v1co - v0co)
-                height = (h_bottom - top)
-                vertex.co = top + parameters["ellipticFactor"] * height
-
-        return arcVertices
-
-    def arcPostprocessing(self, edge, parameters, bm, mesh, roundifyParams, spinnedVerts, edgeCenter):
-        [chosenSpinCenter, otherSpinCenter, spinAxis, angle, steps, refObjectLocation] = roundifyParams
-        rotatedVerts = []
-        if parameters["rotateCenter"] == 'Edge':
-            rotatedVerts = self.rotateArcAroundSpinAxis(
-                                bm, mesh, spinnedVerts, parameters, edgeCenter
-                                )
-        elif parameters["rotateCenter"] == 'Spin':
-            rotatedVerts = self.rotateArcAroundSpinAxis(
-                                bm, mesh, spinnedVerts, parameters, chosenSpinCenter
-                                )
-        elif parameters["rotateCenter"] == 'V1':
-            rotatedVerts = self.rotateArcAroundSpinAxis(
-                                bm, mesh, spinnedVerts, parameters, edge.verts[0].co
-                                )
-        elif parameters["rotateCenter"] == 'V2':
-            rotatedVerts = self.rotateArcAroundSpinAxis(
-                                bm, mesh, spinnedVerts, parameters, edge.verts[1].co
-                                )
-
-        offsetVerts = self.offsetArcPerpendicular(
-                                bm, mesh, rotatedVerts, edge, parameters
-                                )
-        offsetVerts2 = self.offsetArcParallel(
-                                bm, mesh, offsetVerts, edge, parameters
-                                )
-        ellipticVerts = self.makeElliptic(
-                                bm, mesh, offsetVerts2, parameters
-                                )
-        self.rotateArcAroundEdge(bm, mesh, ellipticVerts, parameters)
-
-        if parameters["connectArcWithEdge"]:
-            self.connectArcTogetherWithEdge(
-                                edge, offsetVerts2, bm, mesh, parameters
-                                )
-        return offsetVerts2
-
-    def connectArcTogetherWithEdge(self, edge, arcVertices, bm, mesh, parameters):
-        lastVert = len(arcVertices) - 1
-        if parameters["drawArcCenters"]:
-            lastVert = lastVert - 1  # center gets added as last vert of arc
-        edgeV1 = edge.verts[0].co
-        edgeV2 = edge.verts[1].co
-        arcV1 = arcVertices[0].co
-        arcV2 = arcVertices[lastVert].co
-
-        bmv1 = bm.verts.new(edgeV1)
-        bmv2 = bm.verts.new(arcV1)
-
-        bmv3 = bm.verts.new(edgeV2)
-        bmv4 = bm.verts.new(arcV2)
-
-        if parameters["connectArcWithEdgeFlip"] is False:
-            bme = bm.edges.new([bmv1, bmv2])
-            bme2 = bm.edges.new([bmv3, bmv4])
-        else:
-            bme = bm.edges.new([bmv1, bmv4])
-            bme2 = bm.edges.new([bmv3, bmv2])
-        self.sel.refreshMesh(bm, mesh)
-
-    def connectScaledEdgesWithBaseEdge(self, scaledEdges, baseEdges, bm, mesh):
-        for i in range(0, len(scaledEdges)):
-            scaledEdgeV1 = scaledEdges[i].verts[0].co
-            baseEdgeV1 = baseEdges[i].verts[0].co
-            scaledEdgeV2 = scaledEdges[i].verts[1].co
-            baseEdgeV2 = baseEdges[i].verts[1].co
-
-            bmv1 = bm.verts.new(baseEdgeV1)
-            bmv2 = bm.verts.new(scaledEdgeV1)
-            bme = bm.edges.new([bmv1, bmv2])
-
-            bmv3 = bm.verts.new(scaledEdgeV2)
-            bmv4 = bm.verts.new(baseEdgeV2)
-            bme = bm.edges.new([bmv3, bmv4])
-        self.sel.refreshMesh(bm, mesh)
-
-    def connectArcsTogether(self, arcs, bm, mesh, parameters):
-        for i in range(0, len(arcs) - 1):
-            # in case on XZ or YZ there are no arcs drawn
-            if arcs[i] is None or arcs[i + 1] is None:
-                return
-
-            lastVert = len(arcs[i]) - 1
-            if parameters["drawArcCenters"]:
-                lastVert = lastVert - 1  # center gets added as last vert of arc
-            # take last vert of arc i and first vert of arc i+1
-
-            V1 = arcs[i][lastVert].co
-            V2 = arcs[i + 1][0].co
-
-            if parameters["connectArcsFlip"]:
-                V1 = arcs[i][0].co
-                V2 = arcs[i + 1][lastVert].co
-
-            bmv1 = bm.verts.new(V1)
-            bmv2 = bm.verts.new(V2)
-            bme = bm.edges.new([bmv1, bmv2])
-
-        # connect last arc and first one
-        lastArcId = len(arcs) - 1
-        lastVertIdOfLastArc = len(arcs[lastArcId]) - 1
-        if parameters["drawArcCenters"]:
-            # center gets added as last vert of arc
-            lastVertIdOfLastArc = lastVertIdOfLastArc - 1
-
-        V1 = arcs[lastArcId][lastVertIdOfLastArc].co
-        V2 = arcs[0][0].co
-        if parameters["connectArcsFlip"]:
-            V1 = arcs[lastArcId][0].co
-            V2 = arcs[0][lastVertIdOfLastArc].co
-
-        bmv1 = bm.verts.new(V1)
-        bmv2 = bm.verts.new(V2)
-        bme = bm.edges.new([bmv1, bmv2])
-
-        self.sel.refreshMesh(bm, mesh)
-
-    def offsetArcPerpendicular(self, bm, mesh, Verts, edge, parameters):
-        perpendicularVector = self.getEdgePerpendicularVector(edge, parameters["plane"])
-        offset = parameters["offset"]
-        translation = offset * perpendicularVector
-
-        try:
-            bmesh.ops.translate(bm, verts=Verts, vec=translation)
-        except ValueError:
-            print("[Edge Roundifier]: Perpendicular translate value error - "
-                  "multiple vertices in list - try unchecking 'Centers'")
-
-        indexes = [v.index for v in Verts]
-        self.sel.refreshMesh(bm, mesh)
-        offsetVertices = [bm.verts[i] for i in indexes]
-        return offsetVertices
-
-    def offsetArcParallel(self, bm, mesh, Verts, edge, parameters):
-        edgeVector = self.getNormalizedEdgeVector(edge)
-        offset = parameters["offset2"]
-        translation = offset * edgeVector
-
-        try:
-            bmesh.ops.translate(bm, verts=Verts, vec=translation)
-        except ValueError:
-            print("[Edge Roundifier]: Parallel translate value error - "
-                  "multiple vertices in list - try unchecking 'Centers'")
-
-        indexes = [v.index for v in Verts]
-        self.sel.refreshMesh(bm, mesh)
-        offsetVertices = [bm.verts[i] for i in indexes]
-        return offsetVertices
-
-    def skipThisEdge(self, V1, V2, plane):
-        # Check If It is possible to spin selected verts on this plane if not exit roundifier
-        if(plane == XY):
-            if (V1[0] == V2[0] and V1[1] == V2[1]):
-                return True
-        elif(plane == YZ):
-            if (V1[1] == V2[1] and V1[2] == V2[2]):
-                return True
-        elif(plane == XZ):
-            if (V1[0] == V2[0] and V1[2] == V2[2]):
-                return True
-        return False
-
-    def calculateRoundifyParams(self, edge, parameters, bm, mesh):
-        # Because all data from mesh is in local coordinates
-        # and spin operator works on global coordinates
-        # We first need to translate all input data by vector equal
-        # to origin position and then perform calculations
-        # At least that is my understanding :) <komi3D>
-
-        # V1 V2 stores Local Coordinates
-        V1, V2, edgeVector, edgeLength, edgeCenter = self.getEdgeInfo(edge)
-
-        debugPrintNew(d_Plane, "PLANE: " + parameters["plane"])
-        lineAB = self.calc.getLineCoefficientsPerpendicularToVectorInPoint(
-                                                edgeCenter, edgeVector,
-                                                parameters["plane"]
-                                                )
-        circleMidPoint = V1
-        circleMidPointOnPlane = self.calc.getCircleMidPointOnPlane(
-                                                V1, parameters["plane"]
-                                                )
-        radius = parameters["radius"]
-
-        angle = 0
-        if (parameters["entryMode"] == 'Angle'):
-            if (parameters["angleEnum"] != 'Other'):
-                radius, angle = self.CalculateRadiusAndAngleForAnglePresets(
-                                                parameters["angleEnum"], radius,
-                                                angle, edgeLength
-                                                )
-            else:
-                radius, angle = self.CalculateRadiusAndAngle(edgeLength)
-        debugPrintNew(d_Radius_Angle, "RADIUS = " + str(radius) + "  ANGLE = " + str(angle))
-        roots = None
-        if angle != pi:  # mode other than 180
-            if lineAB is None:
-                roots = self.calc.getLineCircleIntersectionsWhenXPerpendicular(
-                                                edgeCenter, circleMidPointOnPlane,
-                                                radius, parameters["plane"]
-                                                )
-            else:
-                roots = self.calc.getLineCircleIntersections(
-                                                lineAB, circleMidPointOnPlane, radius
-                                                )
-
-            if roots is None:
-                debugPrintNew(True,
-                             "[Edge Roundifier]: No centers were found. Change radius to higher value")
-                return None
-            roots = self.addMissingCoordinate(roots, V1, parameters["plane"])  # adds X, Y or Z coordinate
-        else:
-            roots = [edgeCenter, edgeCenter]
-        debugPrintNew(d_Roots, "roots=" + str(roots))
-
-        refObjectLocation = None
-        objectLocation = bpy.context.active_object.location  # Origin Location
-
-        if parameters["refObject"] == "ORG":
-            refObjectLocation = [0, 0, 0]
-        elif parameters["refObject"] == "CUR":
-            refObjectLocation = bpy.context.scene.cursor.location - objectLocation
-        else:
-            refObjectLocation = self.calc.getEdgeReference(edge, edgeCenter, parameters["plane"])
-
-        debugPrintNew(d_RefObject, parameters["refObject"], refObjectLocation)
-        chosenSpinCenter, otherSpinCenter = self.getSpinCenterClosestToRefCenter(
-                                                            refObjectLocation, roots
-                                                            )
-
-        if (parameters["entryMode"] == "Radius"):
-            halfAngle = self.calc.getAngle(edgeCenter, chosenSpinCenter, circleMidPoint)
-            angle = 2 * halfAngle[0]  # in radians
-            self.a = degrees(angle)   # in degrees
-
-        spinAxis = self.getSpinAxis(parameters["plane"])
-        steps = parameters["segments"]
-        angle = -angle  # rotate clockwise by default
-
-        return [chosenSpinCenter, otherSpinCenter, spinAxis, angle, steps, refObjectLocation]
-
-    def drawSpin(self, edge, edgeCenter, roundifyParams, parameters, bm, mesh):
-        [chosenSpinCenter, otherSpinCenter, spinAxis, angle, steps, refObjectLocation] = roundifyParams
-
-        v0org, v1org = (edge.verts[0], edge.verts[1])
-
-        if parameters["flip"]:
-            angle = -angle
-            spinCenterTemp = chosenSpinCenter
-            chosenSpinCenter = otherSpinCenter
-            otherSpinCenter = spinCenterTemp
-
-        if(parameters["invertAngle"]):
-            if angle < 0:
-                angle = two_pi + angle
-            elif angle > 0:
-                angle = -two_pi + angle
-            else:
-                angle = two_pi
-
-        if(parameters["fullCircles"]):
-            angle = two_pi
-
-        v0 = bm.verts.new(v0org.co)
-
-        result = bmesh.ops.spin(
-                        bm, geom=[v0], cent=chosenSpinCenter, axis=spinAxis,
-                        angle=angle, steps=steps, use_duplicate=False
-                        )
-
-        # it seems there is something wrong with last index of this spin
-        # I need to calculate the last index manually here
-        vertsLength = len(bm.verts)
-        bm.verts.ensure_lookup_table()
-        lastVertIndex = bm.verts[vertsLength - 1].index
-        lastSpinVertIndices = self.getLastSpinVertIndices(steps, lastVertIndex)
-
-        self.sel.refreshMesh(bm, mesh)
-
-        alternativeLastSpinVertIndices = []
-        bothSpinVertices = []
-        spinVertices = []
-        alternate = False
-
-        if ((angle == pi or angle == -pi) and not parameters["bothSides"]):
-
-            midVertexIndex = lastVertIndex - round(steps / 2)
-            bm.verts.ensure_lookup_table()
-            midVert = bm.verts[midVertexIndex].co
-
-            midVertexDistance = (Vector(refObjectLocation) - Vector(midVert)).length
-            midEdgeDistance = (Vector(refObjectLocation) - Vector(edgeCenter)).length
-
-            if ((parameters["invertAngle"]) or (parameters["flip"])):
-                if (midVertexDistance > midEdgeDistance):
-                    alternativeLastSpinVertIndices = self.alternateSpin(
-                                                        bm, mesh, angle, chosenSpinCenter,
-                                                        spinAxis, steps, v0, v1org, lastSpinVertIndices
-                                                        )
-            else:
-                if (midVertexDistance < midEdgeDistance):
-                    alternativeLastSpinVertIndices = self.alternateSpin(
-                                                        bm, mesh, angle, chosenSpinCenter,
-                                                        spinAxis, steps, v0, v1org, lastSpinVertIndices
-                                                        )
-        elif (angle != two_pi):  # to allow full circles
-            if (result['geom_last'][0].co - v1org.co).length > SPIN_END_THRESHOLD:
-                alternativeLastSpinVertIndices = self.alternateSpin(
-                                                        bm, mesh, angle, chosenSpinCenter,
-                                                        spinAxis, steps, v0, v1org, lastSpinVertIndices
-                                                        )
-                alternate = True
-
-        self.sel.refreshMesh(bm, mesh)
-        if alternativeLastSpinVertIndices != []:
-            lastSpinVertIndices = alternativeLastSpinVertIndices
-
-        if lastSpinVertIndices.stop <= len(bm.verts):  # make sure arc was added to bmesh
-            spinVertices = [bm.verts[i] for i in lastSpinVertIndices]
-            if alternativeLastSpinVertIndices != []:
-                spinVertices = spinVertices + [v0]
-            else:
-                spinVertices = [v0] + spinVertices
-
-        if (parameters["bothSides"]):
-            # do some more testing here!!!
-            if (angle == pi or angle == -pi):
-                alternativeLastSpinVertIndices = self.alternateSpinNoDelete(
-                                                        bm, mesh, -angle, chosenSpinCenter,
-                                                        spinAxis, steps, v0, v1org, []
-                                                        )
-            elif alternate:
-                alternativeLastSpinVertIndices = self.alternateSpinNoDelete(
-                                                        bm, mesh, angle, otherSpinCenter,
-                                                        spinAxis, steps, v0, v1org, []
-                                                        )
-            elif not alternate:
-                alternativeLastSpinVertIndices = self.alternateSpinNoDelete(
-                                                        bm, mesh, -angle, otherSpinCenter,
-                                                        spinAxis, steps, v0, v1org, []
-                                                        )
-            bothSpinVertices = [bm.verts[i] for i in lastSpinVertIndices]
-            alternativeSpinVertices = [bm.verts[i] for i in alternativeLastSpinVertIndices]
-            bothSpinVertices = [v0] + bothSpinVertices + alternativeSpinVertices
-            spinVertices = bothSpinVertices
-
-        if (parameters["fullCircles"]):
-            v1 = bm.verts.new(v1org.co)
-            spinVertices = spinVertices + [v1]
-
-        if (parameters['drawArcCenters']):
-            centerVert = bm.verts.new(chosenSpinCenter)
-            spinVertices.append(centerVert)
-
-        return spinVertices, [chosenSpinCenter, otherSpinCenter, spinAxis, angle, steps, refObjectLocation]
-
-    def deleteSpinVertices(self, bm, mesh, lastSpinVertIndices):
-        verticesForDeletion = []
-        bm.verts.ensure_lookup_table()
-        for i in lastSpinVertIndices:
-            vi = bm.verts[i]
-            vi.select = True
-            debugPrintNew(True, str(i) + ") " + str(vi))
-            verticesForDeletion.append(vi)
-
-        bmesh.ops.delete(bm, geom=verticesForDeletion, context=1)
-        bmesh.update_edit_mesh(mesh, True)
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.mode_set(mode='EDIT')
-
-    def alternateSpinNoDelete(self, bm, mesh, angle, chosenSpinCenter,
-                              spinAxis, steps, v0, v1org, lastSpinVertIndices):
-        v0prim = v0
-
-        result2 = bmesh.ops.spin(bm, geom=[v0prim], cent=chosenSpinCenter, axis=spinAxis,
-                                 angle=angle, steps=steps, use_duplicate=False)
-        vertsLength = len(bm.verts)
-        bm.verts.ensure_lookup_table()
-        lastVertIndex2 = bm.verts[vertsLength - 1].index
-
-        lastSpinVertIndices2 = self.getLastSpinVertIndices(steps, lastVertIndex2)
-        return lastSpinVertIndices2
-
-    def alternateSpin(self, bm, mesh, angle, chosenSpinCenter,
-                      spinAxis, steps, v0, v1org, lastSpinVertIndices):
-
-        self.deleteSpinVertices(bm, mesh, lastSpinVertIndices)
-        v0prim = v0
-
-        result2 = bmesh.ops.spin(
-                        bm, geom=[v0prim], cent=chosenSpinCenter, axis=spinAxis,
-                        angle=-angle, steps=steps, use_duplicate=False
-                        )
-        # it seems there is something wrong with last index of this spin
-        # I need to calculate the last index manually here
-        vertsLength = len(bm.verts)
-        bm.verts.ensure_lookup_table()
-        lastVertIndex2 = bm.verts[vertsLength - 1].index
-
-        lastSpinVertIndices2 = self.getLastSpinVertIndices(steps, lastVertIndex2)
-        # second spin also does not hit the v1org
-        if (result2['geom_last'][0].co - v1org.co).length > SPIN_END_THRESHOLD:
-
-            self.deleteSpinVertices(bm, mesh, lastSpinVertIndices2)
-            self.deleteSpinVertices(bm, mesh, range(v0.index, v0.index + 1))
-            return []
-        else:
-            return lastSpinVertIndices2
-
-    def getLastSpinVertIndices(self, steps, lastVertIndex):
-        arcfirstVertexIndex = lastVertIndex - steps + 1
-        lastSpinVertIndices = range(arcfirstVertexIndex, lastVertIndex + 1)
-        return lastSpinVertIndices
-
-    def rotateArcAroundSpinAxis(self, bm, mesh, vertices, parameters, edgeCenter):
-        axisAngle = parameters["axisAngle"]
-        plane = parameters["plane"]
-        # compensate rotation center
-        objectLocation = bpy.context.active_object.location
-        center = objectLocation + edgeCenter
-
-        rot = Euler((0.0, 0.0, radians(axisAngle)), 'XYZ').to_matrix()
-        if plane == YZ:
-            rot = Euler((radians(axisAngle), 0.0, 0.0), 'XYZ').to_matrix()
-        if plane == XZ:
-            rot = Euler((0.0, radians(axisAngle), 0.0), 'XYZ').to_matrix()
-
-        indexes = [v.index for v in vertices]
-
-        bmesh.ops.rotate(
-            bm,
-            cent=center,
-            matrix=rot,
-            verts=vertices,
-            space=bpy.context.edit_object.matrix_world
-        )
-        self.sel.refreshMesh(bm, mesh)
-        bm.verts.ensure_lookup_table()
-        rotatedVertices = [bm.verts[i] for i in indexes]
-
-        return rotatedVertices
-
-    def CalculateRadiusAndAngle(self, edgeLength):
-        degAngle = self.a
-        angle = radians(degAngle)
-        self.r = radius = edgeLength / (2 * sin(angle / 2))
-        return radius, angle
-
-    def CalculateRadiusAndAngleForAnglePresets(self, angleEnum, initR, initA, edgeLength):
-        radius = initR
-        angle = initA
-        try:
-            # Note - define an integer string in the angleEnum
-            angle_convert = int(angleEnum)
-            self.a = angle_convert
-        except:
-            self.a = 180  # fallback
-            debugPrintNew(True,
-                          "CalculateRadiusAndAngleForAnglePresets problem with int conversion")
-
-        return self.CalculateRadiusAndAngle(edgeLength)
-
-    def getSpinCenterClosestToRefCenter(self, objLocation, roots):
-        root0Distance = (Vector(objLocation) - Vector(roots[0])).length
-        root1Distance = (Vector(objLocation) - Vector(roots[1])).length
-
-        chosenId = 0
-        rejectedId = 1
-        if (root0Distance > root1Distance):
-            chosenId = 1
-            rejectedId = 0
-        return roots[chosenId], roots[rejectedId]
-
-    def addMissingCoordinate(self, roots, startVertex, plane):
-        if roots is not None:
-            a, b = roots[0]
-            c, d = roots[1]
-            if plane == XY:
-                roots[0] = Vector((a, b, startVertex[2]))
-                roots[1] = Vector((c, d, startVertex[2]))
-            if plane == YZ:
-                roots[0] = Vector((startVertex[0], a, b))
-                roots[1] = Vector((startVertex[0], c, d))
-            if plane == XZ:
-                roots[0] = Vector((a, startVertex[1], b))
-                roots[1] = Vector((c, startVertex[1], d))
-        return roots
-
-    def selectEdgesAfterRoundifier(self, context, edges):
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.mode_set(mode='EDIT')
-        mesh = context.view_layer.objects.active.data
-        bmnew = bmesh.new()
-        bmnew.from_mesh(mesh)
-
-        self.deselectEdges(bmnew)
-        for selectedEdge in edges:
-            for e in bmnew.edges:
-                if (e.verts[0].co - selectedEdge.verts[0].co).length <= self.threshold \
-                   and (e.verts[1].co - selectedEdge.verts[1].co).length <= self.threshold:
-                    e.select_set(True)
-
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bmnew.to_mesh(mesh)
-        bmnew.free()
-        bpy.ops.object.mode_set(mode='EDIT')
-
-    def deselectEdges(self, bm):
-        for edge in bm.edges:
-            edge.select_set(False)
-
-    def getSpinAxis(self, plane):
-        axis = (0, 0, 1)
-        if plane == YZ:
-            axis = (1, 0, 0)
-        if plane == XZ:
-            axis = (0, 1, 0)
-        return axis
-
-
-def register():
-    bpy.utils.register_class(EdgeRoundifier)
-
-
-def unregister():
-    bpy.utils.unregister_class(EdgeRoundifier)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_edges_floor_plan.py b/mesh_extra_tools/mesh_edges_floor_plan.py
deleted file mode 100644 (file)
index 1804c79..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-# ##### 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; version 2
-#  of the License.
-#
-#  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 #####
-
-# based upon the functionality of Mesh to wall by luxuy_BlenderCN
-# thanks to meta-androcto
-
-bl_info = {
-    "name": "Edge Floor Plan",
-    "author": "lijenstina",
-    "version": (0, 2),
-    "blender": (2, 78, 0),
-    "location": "View3D > EditMode > Mesh",
-    "description": "Make a Floor Plan from Edges",
-    "wiki_url": "",
-    "category": "Mesh"}
-
-import bpy
-import bmesh
-from bpy.types import Operator
-from bpy.props import (
-        BoolProperty,
-        EnumProperty,
-        FloatProperty,
-        FloatVectorProperty,
-        IntProperty,
-        )
-
-
-# Handle error notifications
-def error_handlers(self, error, reports="ERROR"):
-    if self and reports:
-        self.report({'WARNING'}, reports + " (See Console for more info)")
-
-    print("\n[mesh.edges_floor_plan]\nError: {}\n".format(error))
-
-
-class MESH_OT_edges_floor_plan(Operator):
-    bl_idname = "mesh.edges_floor_plan"
-    bl_label = "Edges Floor Plan"
-    bl_description = "Top View, Extrude Flat Along Edges"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    wid: FloatProperty(
-            name="Wall width:",
-            description="Set the width of the generated walls\n",
-            default=0.1,
-            min=0.001, max=30000
-            )
-    depth: FloatProperty(
-            name="Inner height:",
-            description="Set the height of the inner wall edges",
-            default=0.0,
-            min=0, max=10
-            )
-    connect_ends: BoolProperty(
-            name="Connect Ends",
-            description="Connect the ends of the boundary Edge loops",
-            default=False
-            )
-    repeat_cleanup: IntProperty(
-            name="Recursive Prepare",
-            description="Number of times that the preparation phase runs\n"
-                        "at the start of the script\n"
-                        "If parts of the mesh are not modified, increase this value",
-            min=1, max=20,
-            default=1
-            )
-    fill_items = [
-            ('EDGE_NET', "Edge Net",
-             "Edge Net Method for mesh preparation - Initial Fill\n"
-             "The filled in faces will be Inset individually\n"
-             "Supports simple 3D objects"),
-            ('SINGLE_FACE', "Single Face",
-             "Single Face Method for mesh preparation - Initial Fill\n"
-             "The produced face will be Triangulated before Inset Region\n"
-             "Good for edges forming a circle, avoid 3D objects"),
-            ('SOLIDIFY', "Solidify",
-             "Extrude and Solidify Method\n"
-             "Useful for complex meshes, however works best on flat surfaces\n"
-             "as the extrude direction has to be defined")
-            ]
-    fill_type: EnumProperty(
-            name="Fill Type",
-            items=fill_items,
-            description="Choose the method for creating geometry",
-            default='SOLIDIFY'
-            )
-    keep_faces: BoolProperty(
-            name="Keep Faces",
-            description="Keep or not the fill faces\n"
-                        "Can depend on Remove Ngons state",
-            default=False
-            )
-    tri_faces: BoolProperty(
-            name="Triangulate Faces",
-            description="Triangulate the created fill faces\n"
-                        "Sometimes can lead to unsatisfactory results",
-            default=False
-            )
-    initial_extrude: FloatVectorProperty(
-            name="Initial Extrude",
-            description="",
-            default=(0.0, 0.0, 0.1),
-            min=-20.0, max=20.0,
-            subtype='XYZ',
-            precision=3,
-            size=3
-            )
-    remove_ngons: BoolProperty(
-            name="Remove Ngons",
-            description="Keep or not the Ngon Faces\n"
-                        "Note about limitations:\n"
-                        "Sometimes the kept Faces could be Ngons\n"
-                        "Removing the Ngons can lead to no geometry created",
-            default=True
-            )
-    offset: FloatProperty(
-            name="Wall Offset:",
-            description="Set the offset for the Solidify modifier",
-            default=0.0,
-            min=-1.0, max=1.0
-            )
-    only_rim: BoolProperty(
-            name="Rim Only",
-            description="Solidify Fill Rim only option",
-            default=False
-            )
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return (ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def check_edge(self, context):
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.mode_set(mode='EDIT')
-        obj = bpy.context.object
-        me_check = obj.data
-        if len(me_check.edges) < 1:
-            return False
-
-        return True
-
-    @staticmethod
-    def ensure(bm):
-        if bm:
-            bm.verts.ensure_lookup_table()
-            bm.edges.ensure_lookup_table()
-            bm.faces.ensure_lookup_table()
-
-    def solidify_mod(self, context, ob, wid, offset, only_rim):
-        try:
-            mods = ob.modifiers.new(
-                        name="_Mesh_Solidify_Wall", type='SOLIDIFY'
-                        )
-            mods.thickness = wid
-            mods.use_quality_normals = True
-            mods.offset = offset
-            mods.use_even_offset = True
-            mods.use_rim = True
-            mods.use_rim_only = only_rim
-            mods.show_on_cage = True
-
-            bpy.ops.object.modifier_apply(
-                        modifier="_Mesh_Solidify_Wall"
-                        )
-        except Exception as e:
-            error_handlers(self, e,
-                           reports="Adding a Solidify Modifier failed")
-            pass
-
-    def draw(self, context):
-        layout = self.layout
-
-        box = layout.box()
-        box.label(text="Choose Method:", icon="SCRIPTWIN")
-        box.prop(self, "fill_type")
-
-        col = box.column(align=True)
-
-        if self.fill_type == 'EDGE_NET':
-            col.prop(self, "repeat_cleanup")
-            col.prop(self, "remove_ngons", toggle=True)
-
-        elif self.fill_type == 'SOLIDIFY':
-            col.prop(self, "offset", slider=True)
-            col.prop(self, "initial_extrude")
-
-        else:
-            col.prop(self, "remove_ngons", toggle=True)
-            col.prop(self, "tri_faces", toggle=True)
-
-        box = layout.box()
-        box.label(text="Settings:", icon="MOD_BUILD")
-
-        col = box.column(align=True)
-        col.prop(self, "wid")
-
-        if self.fill_type != 'SOLIDIFY':
-            col.prop(self, "depth")
-            col.prop(self, "connect_ends", toggle=True)
-            col.prop(self, "keep_faces", toggle=True)
-        else:
-            col.prop(self, "only_rim", toggle=True)
-
-    def execute(self, context):
-        if not self.check_edge(context):
-            self.report({'WARNING'},
-                        "Operation Cancelled. Needs a Mesh with at least one edge")
-            return {'CANCELLED'}
-
-        wid = self.wid * 0.1
-        depth = self.depth * 0.1
-        offset = self.offset * 0.1
-        store_selection_mode = context.tool_settings.mesh_select_mode
-        # Note: the remove_doubles called after bmesh creation would make
-        # blender crash with certain meshes - keep it in mind for the future
-        bpy.ops.mesh.remove_doubles(threshold=0.003)
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.mode_set(mode='EDIT')
-        ob = bpy.context.object
-
-        me = ob.data
-        bm = bmesh.from_edit_mesh(me)
-
-        bmesh.ops.delete(bm, geom=bm.faces, context=3)
-        self.ensure(bm)
-        context.tool_settings.mesh_select_mode = (False, True, False)
-        original_edges = [edge.index for edge in bm.edges]
-        original_verts = [vert.index for vert in bm.verts]
-        self.ensure(bm)
-        bpy.ops.mesh.select_all(action='DESELECT')
-
-        if self.fill_type == 'EDGE_NET':
-            for i in range(self.repeat_cleanup):
-                bmesh.ops.edgenet_prepare(bm, edges=bm.edges)
-                self.ensure(bm)
-            bmesh.ops.edgenet_fill(bm, edges=bm.edges, mat_nr=0, use_smooth=True, sides=0)
-            self.ensure(bm)
-            if self.remove_ngons:
-                ngons = [face for face in bm.faces if len(face.edges) > 4]
-                self.ensure(bm)
-                bmesh.ops.delete(bm, geom=ngons, context=5)  # 5 - delete faces
-                del ngons
-                self.ensure(bm)
-
-        elif self.fill_type == 'SOLIDIFY':
-            for vert in bm.verts:
-                vert.normal_update()
-            self.ensure(bm)
-            bmesh.ops.extrude_edge_only(
-                    bm, edges=bm.edges, use_select_history=False
-                    )
-            self.ensure(bm)
-            verts_extrude = [vert for vert in bm.verts if vert.index in original_verts]
-            self.ensure(bm)
-            bmesh.ops.translate(
-                bm,
-                verts=verts_extrude,
-                vec=(self.initial_extrude)
-                )
-            self.ensure(bm)
-            del verts_extrude
-            self.ensure(bm)
-
-            for edge in bm.edges:
-                if edge.is_boundary:
-                    edge.select = True
-
-            bm = bmesh.update_edit_mesh(ob.data, 1, 1)
-
-            bpy.ops.object.mode_set(mode='OBJECT')
-            self.solidify_mod(context, ob, wid, offset, self.only_rim)
-
-            bpy.ops.object.mode_set(mode='EDIT')
-
-            context.tool_settings.mesh_select_mode = store_selection_mode
-
-            return {'FINISHED'}
-
-        else:
-            bm.faces.new(bm.verts)
-            self.ensure(bm)
-
-            if self.tri_faces:
-                bmesh.ops.triangle_fill(
-                        bm, use_beauty=True, use_dissolve=False, edges=bm.edges
-                        )
-                self.ensure(bm)
-
-        if self.remove_ngons and self.fill_type != 'EDGE_NET':
-            ngons = [face for face in bm.faces if len(face.edges) > 4]
-            self.ensure(bm)
-            bmesh.ops.delete(bm, geom=ngons, context=5)  # 5 - delete faces
-            del ngons
-            self.ensure(bm)
-
-        del_boundary = [edge for edge in bm.edges if edge.index not in original_edges]
-        self.ensure(bm)
-
-        del original_edges
-        self.ensure(bm)
-
-        if self.fill_type == 'EDGE_NET':
-            extrude_inner = bmesh.ops.inset_individual(
-                    bm, faces=bm.faces, thickness=wid, depth=depth,
-                    use_even_offset=True, use_interpolate=False,
-                    use_relative_offset=False
-                    )
-        else:
-            extrude_inner = bmesh.ops.inset_region(
-                    bm, faces=bm.faces, faces_exclude=[], use_boundary=True,
-                    use_even_offset=True, use_interpolate=False,
-                    use_relative_offset=False, use_edge_rail=False,
-                    thickness=wid, depth=depth, use_outset=False
-                    )
-        self.ensure(bm)
-
-        del_faces = [faces for faces in bm.faces if faces not in extrude_inner["faces"]]
-        self.ensure(bm)
-        del extrude_inner
-        self.ensure(bm)
-
-        if not self.keep_faces:
-            bmesh.ops.delete(bm, geom=del_faces, context=5)  # 5 delete faces
-        del del_faces
-        self.ensure(bm)
-
-        face_del = set()
-        for face in bm.faces:
-            for edge in del_boundary:
-                if isinstance(edge, bmesh.types.BMEdge):
-                    if edge in face.edges:
-                        face_del.add(face)
-        self.ensure(bm)
-        face_del = list(face_del)
-        self.ensure(bm)
-
-        del del_boundary
-        self.ensure(bm)
-
-        if not self.connect_ends:
-            bmesh.ops.delete(bm, geom=face_del, context=5)
-            self.ensure(bm)
-
-        del face_del
-        self.ensure(bm)
-
-        for edge in bm.edges:
-            if edge.is_boundary:
-                edge.select = True
-
-        bm = bmesh.update_edit_mesh(ob.data, 1, 1)
-
-        context.tool_settings.mesh_select_mode = store_selection_mode
-
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_class(MESH_OT_edges_floor_plan)
-
-
-def unregister():
-    bpy.utils.unregister_class(MESH_OT_edges_floor_plan)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_edges_length.py b/mesh_extra_tools/mesh_edges_length.py
deleted file mode 100644 (file)
index d8c3ec5..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-# gpl author: Giuseppe De Marco [BlenderLab] inspired by NirenYang
-
-bl_info = {
-    "name": "Set edges length",
-    "description": "Edges length",
-    "author": "Giuseppe De Marco [BlenderLab] inspired by NirenYang",
-    "version": (0, 1, 0),
-    "blender": (2, 71, 0),
-    "location": "Toolbar > Tools > Mesh Tools: set Length(Shit+Alt+E)",
-    "warning": "",
-    "wiki_url": "",
-    "category": "Mesh",
-    }
-
-import bpy
-import bmesh
-from mathutils import Vector
-from bpy.types import Operator
-from bpy.props import (
-        FloatProperty,
-        EnumProperty,
-        )
-
-# GLOBALS
-edge_length_debug = False
-_error_message = "Please select at least one edge to fill select history"
-_error_message_2 = "Edges with shared vertices are not allowed. Please, use scale instead"
-
-# Note : Refactor - removed all the operators apart from LengthSet
-#        and merged the other ones as options of length (lijenstina)
-
-
-def get_edge_vector(edge):
-    verts = (edge.verts[0].co, edge.verts[1].co)
-    vector = verts[1] - verts[0]
-
-    return vector
-
-
-def get_selected(bmesh_obj, geometry_type):
-    # geometry type should be edges, verts or faces
-    selected = []
-
-    for i in getattr(bmesh_obj, geometry_type):
-        if i.select:
-            selected.append(i)
-    return tuple(selected)
-
-
-def get_center_vector(verts):
-    # verts = [Vector((x,y,z)), Vector((x,y,z))]
-
-    center_vector = Vector((((verts[1][0] + verts[0][0]) / 2.),
-                           ((verts[1][1] + verts[0][1]) / 2.),
-                           ((verts[1][2] + verts[0][2]) / 2.)))
-    return center_vector
-
-
-class LengthSet(Operator):
-    bl_idname = "object.mesh_edge_length_set"
-    bl_label = "Set edge length"
-    bl_description = ("Change one selected edge length by a specified target,\n"
-                      "existing length and different modes\n"
-                      "Note: works only with Edges that not share a vertex")
-    bl_options = {'REGISTER', 'UNDO'}
-
-    old_length: FloatProperty(
-            name="Original length",
-            options={'HIDDEN'},
-            )
-    set_length_type: EnumProperty(
-            items=[
-                ('manual', "Manual",
-                 "Input manually the desired Target Length"),
-                ('existing', "Existing Length",
-                 "Use existing geometry Edges' characteristics"),
-            ],
-            name="Set Type of Input",
-            )
-    target_length: FloatProperty(
-            name="Target Length",
-            description="Input a value for an Edges Length target",
-            default=1.00,
-            unit='LENGTH',
-            precision=5
-            )
-    existing_length: EnumProperty(
-            items=[
-                ('min', "Shortest",
-                 "Set all to shortest Edge of selection"),
-                ('max', "Longest",
-                 "Set all to the longest Edge of selection"),
-                ('average', "Average",
-                 "Set all to the average Edge length of selection"),
-                ('active', "Active",
-                 "Set all to the active Edge's one\n"
-                 "Needs a selection to be done in Edge Select mode"),
-            ],
-            name="Existing length"
-            )
-    mode: EnumProperty(
-            items=[
-                ('fixed', "Fixed", "Fixed"),
-                ('increment', "Increment", "Increment"),
-                ('decrement', "Decrement", "Decrement"),
-            ],
-            name="Mode"
-            )
-    behaviour: EnumProperty(
-            items=[
-                ('proportional', "Proportional",
-                 "Move vertex locations proportionally to the center of the Edge"),
-                ('clockwise', "Clockwise",
-                "Compute the Edges' vertex locations in a clockwise fashion"),
-                ('unclockwise', "Counterclockwise",
-                "Compute the Edges' vertex locations in a counterclockwise fashion"),
-            ],
-            name="Resize behavior"
-            )
-
-    originary_edge_length_dict = {}
-    edge_lengths = []
-    selected_edges = ()
-
-    @classmethod
-    def poll(cls, context):
-        return (context.edit_object and context.object.type == 'MESH')
-
-    def check(self, context):
-        return True
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.label(text="Original Active length is: {:.3f}".format(self.old_length))
-
-        layout.label(text="Input Mode:")
-        layout.prop(self, "set_length_type", expand=True)
-        if self.set_length_type == 'manual':
-            layout.prop(self, "target_length")
-        else:
-            layout.prop(self, "existing_length", text="")
-
-        layout.label(text="Mode:")
-        layout.prop(self, "mode", text="")
-
-        layout.label(text="Resize Behavior:")
-        layout.prop(self, "behaviour", text="")
-
-    def get_existing_edge_length(self, bm):
-        if self.existing_length != "active":
-            if self.existing_length == "min":
-                return min(self.edge_lengths)
-            if self.existing_length == "max":
-                return max(self.edge_lengths)
-            elif self.existing_length == "average":
-                return sum(self.edge_lengths) / float(len(self.selected_edges))
-        else:
-            bm.edges.ensure_lookup_table()
-            active_edge_length = None
-
-            for elem in reversed(bm.select_history):
-                if isinstance(elem, bmesh.types.BMEdge):
-                    active_edge_length = elem.calc_length()
-                    break
-            return active_edge_length
-
-        return 0.0
-
-    def invoke(self, context, event):
-        wm = context.window_managerlength
-
-        obj = context.edit_object
-        bm = bmesh.from_edit_mesh(obj.data)
-
-        bpy.ops.mesh.select_mode(type="EDGE")
-        self.selected_edges = get_selected(bm, 'edges')
-
-        if self.selected_edges:
-            vertex_set = []
-
-            for edge in self.selected_edges:
-                vector = get_edge_vector(edge)
-
-                if edge.verts[0].index not in vertex_set:
-                    vertex_set.append(edge.verts[0].index)
-                else:
-                    self.report({'ERROR_INVALID_INPUT'}, _error_message_2)
-                    return {'CANCELLED'}
-
-                if edge.verts[1].index not in vertex_set:
-                    vertex_set.append(edge.verts[1].index)
-                else:
-                    self.report({'ERROR_INVALID_INPUT'}, _error_message_2)
-                    return {'CANCELLED'}
-
-                # warning, it's a constant !
-                verts_index = ''.join((str(edge.verts[0].index), str(edge.verts[1].index)))
-                self.originary_edge_length_dict[verts_index] = vector
-                self.edge_lengths.append(vector.length)
-                self.old_length = vector.length
-        else:
-            self.report({'ERROR'}, _error_message)
-            return {'CANCELLED'}
-
-        if edge_length_debug:
-            self.report({'INFO'}, str(self.originary_edge_length_dict))
-
-        if bpy.context.scene.unit_settings.system == 'IMPERIAL':
-            # imperial to metric conversion
-            vector.length = (0.9144 * vector.length) / 3
-
-        self.target_length = vector.length
-
-        return wm.invoke_props_dialog(self)
-
-    def execute(self, context):
-
-        bpy.ops.mesh.select_mode(type="EDGE")
-        self.context = context
-
-        obj = context.edit_object
-        bm = bmesh.from_edit_mesh(obj.data)
-
-        self.selected_edges = get_selected(bm, 'edges')
-
-        if not self.selected_edges:
-            self.report({'ERROR'}, _error_message)
-            return {'CANCELLED'}
-
-        for edge in self.selected_edges:
-            vector = get_edge_vector(edge)
-            # what we should see in original length dialog field
-            self.old_length = vector.length
-
-            if self.set_length_type == 'manual':
-                vector.length = abs(self.target_length)
-            else:
-                get_lengths = self.get_existing_edge_length(bm)
-                # check for edit mode
-                if not get_lengths:
-                    self.report({'WARNING'},
-                                "Operation Cancelled. "
-                                "Active Edge could not be determined (needs selection in Edit Mode)")
-                    return {'CANCELLED'}
-
-                vector.length = get_lengths
-
-            if vector.length == 0.0:
-                self.report({'ERROR'}, "Operation cancelled. Target length is set to zero")
-                return {'CANCELLED'}
-
-            center_vector = get_center_vector((edge.verts[0].co, edge.verts[1].co))
-
-            verts_index = ''.join((str(edge.verts[0].index), str(edge.verts[1].index)))
-
-            if edge_length_debug:
-                self.report({'INFO'},
-                            ' - '.join(('vector ' + str(vector),
-                                        'originary_vector ' +
-                                        str(self.originary_edge_length_dict[verts_index])
-                                        )))
-            verts = (edge.verts[0].co, edge.verts[1].co)
-
-            if edge_length_debug:
-                self.report({'INFO'},
-                            '\n edge.verts[0].co ' + str(verts[0]) +
-                            '\n edge.verts[1].co ' + str(verts[1]) +
-                            '\n vector.length' + str(vector.length))
-
-            # the clockwise direction have v1 -> v0, unclockwise v0 -> v1
-            if self.target_length >= 0:
-                if self.behaviour == 'proportional':
-                    edge.verts[1].co = center_vector + vector / 2
-                    edge.verts[0].co = center_vector - vector / 2
-
-                    if self.mode == 'decrement':
-                        edge.verts[0].co = (center_vector + vector / 2) - \
-                                            (self.originary_edge_length_dict[verts_index] / 2)
-                        edge.verts[1].co = (center_vector - vector / 2) + \
-                                            (self.originary_edge_length_dict[verts_index] / 2)
-
-                    elif self.mode == 'increment':
-                        edge.verts[1].co = (center_vector + vector / 2) + \
-                                            self.originary_edge_length_dict[verts_index] / 2
-                        edge.verts[0].co = (center_vector - vector / 2) - \
-                                            self.originary_edge_length_dict[verts_index] / 2
-
-                elif self.behaviour == 'unclockwise':
-                    if self.mode == 'increment':
-                        edge.verts[1].co = \
-                                verts[0] + (self.originary_edge_length_dict[verts_index] + vector)
-                    elif self.mode == 'decrement':
-                        edge.verts[0].co = \
-                                verts[1] - (self.originary_edge_length_dict[verts_index] - vector)
-                    else:
-                        edge.verts[1].co = verts[0] + vector
-
-                else:
-                    # clockwise
-                    if self.mode == 'increment':
-                        edge.verts[0].co = \
-                                verts[1] - (self.originary_edge_length_dict[verts_index] + vector)
-                    elif self.mode == 'decrement':
-                        edge.verts[1].co = \
-                                verts[0] + (self.originary_edge_length_dict[verts_index] - vector)
-                    else:
-                        edge.verts[0].co = verts[1] - vector
-
-            if bpy.context.scene.unit_settings.system == 'IMPERIAL':
-                """
-                # yards to metric conversion
-                vector.length = ( 3. * vector.length ) / 0.9144
-                # metric to yards conversion
-                vector.length = ( 0.9144 * vector.length ) / 3.
-                """
-                for mvert in edge.verts:
-                    # school time: 0.9144 : 3 = X : mvert
-                    mvert.co = (0.9144 * mvert.co) / 3
-
-            if edge_length_debug:
-                self.report({'INFO'},
-                            '\n edge.verts[0].co' + str(verts[0]) +
-                            '\n edge.verts[1].co' + str(verts[1]) +
-                            '\n vector' + str(vector) + '\n v1 > v0:' + str((verts[1] >= verts[0]))
-                            )
-            bmesh.update_edit_mesh(obj.data, True)
-
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_class(LengthSet)
-
-
-def unregister():
-    bpy.utils.unregister_class(LengthSet)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_edgetools.py b/mesh_extra_tools/mesh_edgetools.py
deleted file mode 100644 (file)
index 0547e91..0000000
+++ /dev/null
@@ -1,1878 +0,0 @@
-#  The Blender Edgetools is to bring CAD tools to Blender.
-#  Copyright (C) 2012  Paul Marshall
-
-# ##### 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 3 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, see <http://www.gnu.org/licenses/>.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-
-bl_info = {
-    "name": "EdgeTools",
-    "author": "Paul Marshall",
-    "version": (0, 9, 2),
-    "blender": (2, 68, 0),
-    "location": "View3D > Toolbar and View3D > Specials (W-key)",
-    "warning": "",
-    "description": "CAD style edge manipulation tools",
-    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/"
-                "Scripts/Modeling/EdgeTools",
-    "category": "Mesh"}
-
-
-import bpy
-import bmesh
-from bpy.types import (
-        Operator,
-        Menu,
-        )
-from math import acos, pi, radians, sqrt
-from mathutils import Matrix, Vector
-from mathutils.geometry import (
-        distance_point_to_plane,
-        interpolate_bezier,
-        intersect_point_line,
-        intersect_line_line,
-        intersect_line_plane,
-        )
-from bpy.props import (
-        BoolProperty,
-        IntProperty,
-        FloatProperty,
-        EnumProperty,
-       )
-
-"""
-Blender EdgeTools
-This is a toolkit for edge manipulation based on mesh manipulation
-abilities of several CAD/CAE packages, notably CATIA's Geometric Workbench
-from which most of these tools have a functional basis.
-
-The GUI and Blender add-on structure shamelessly coded in imitation of the
-LoopTools addon.
-
-Examples:
-- "Ortho" inspired from CATIA's line creation tool which creates a line of a
-   user specified length at a user specified angle to a curve at a chosen
-   point.  The user then selects the plane the line is to be created in.
-- "Shaft" is inspired from CATIA's tool of the same name.  However, instead
-   of a curve around an axis, this will instead shaft a line, a point, or
-   a fixed radius about the selected axis.
-- "Slice" is from CATIA's ability to split a curve on a plane.  When
-   completed this be a Python equivalent with all the same basic
-   functionality, though it will sadly be a little clumsier to use due
-   to Blender's selection limitations.
-
-Notes:
-- Fillet operator and related functions removed as they didn't work
-- Buggy parts have been hidden behind ENABLE_DEBUG global (set it to True)
-   Example: Shaft with more than two edges selected
-
-Paul "BrikBot" Marshall
-Created: January 28, 2012
-Last Modified: October 6, 2012
-
-Coded in IDLE, tested in Blender 2.6.
-Search for "@todo" to quickly find sections that need work
-
-Note: lijenstina - modified this script in preparation for merging
-fixed the needless jumping to object mode for bmesh creation
-causing the crash with the Slice > Rip operator
-Removed the test operator since version 0.9.2
-added general error handling
-"""
-
-# Enable debug
-# Set to True to have the debug prints available
-ENABLE_DEBUG = False
-
-
-# Quick an dirty method for getting the sign of a number:
-def sign(number):
-    return (number > 0) - (number < 0)
-
-
-# is_parallel
-# Checks to see if two lines are parallel
-
-def is_parallel(v1, v2, v3, v4):
-    result = intersect_line_line(v1, v2, v3, v4)
-    return result is None
-
-
-# Handle error notifications
-def error_handlers(self, op_name, error, reports="ERROR", func=False):
-    if self and reports:
-        self.report({'WARNING'}, reports + " (See Console for more info)")
-
-    is_func = "Function" if func else "Operator"
-    print("\n[Mesh EdgeTools]\n{}: {}\nError: {}\n".format(is_func, op_name, error))
-
-
-def flip_edit_mode():
-    bpy.ops.object.editmode_toggle()
-    bpy.ops.object.editmode_toggle()
-
-
-# check the appropriate selection condition
-# to prevent crashes with the index out of range errors
-# pass the bEdges and bVerts based selection tables here
-# types: Edge, Vertex, All
-def is_selected_enough(self, bEdges, bVerts, edges_n=1, verts_n=0, types="Edge"):
-    check = False
-    try:
-        if bEdges and types == "Edge":
-            check = (len(bEdges) >= edges_n)
-        elif bVerts and types == "Vertex":
-            check = (len(bVerts) >= verts_n)
-        elif bEdges and bVerts and types == "All":
-            check = (len(bEdges) >= edges_n and len(bVerts) >= verts_n)
-
-        if check is False:
-            strings = "%s Vertices and / or " % verts_n if verts_n != 0 else ""
-            self.report({'WARNING'},
-                        "Needs at least " + strings + "%s Edge(s) selected. "
-                        "Operation Cancelled" % edges_n)
-            flip_edit_mode()
-
-        return check
-
-    except Exception as e:
-        error_handlers(self, "is_selected_enough", e,
-                      "No appropriate selection. Operation Cancelled", func=True)
-        return False
-
-    return False
-
-
-# is_axial
-# This is for the special case where the edge is parallel to an axis.
-# The projection onto the XY plane will fail so it will have to be handled differently
-
-def is_axial(v1, v2, error=0.000002):
-    vector = v2 - v1
-    # Don't need to store, but is easier to read:
-    vec0 = vector[0] > -error and vector[0] < error
-    vec1 = vector[1] > -error and vector[1] < error
-    vec2 = vector[2] > -error and vector[2] < error
-    if (vec0 or vec1) and vec2:
-        return 'Z'
-    elif vec0 and vec1:
-        return 'Y'
-    return None
-
-
-# is_same_co
-# For some reason "Vector = Vector" does not seem to look at the actual coordinates
-
-def is_same_co(v1, v2):
-    if len(v1) != len(v2):
-        return False
-    else:
-        for co1, co2 in zip(v1, v2):
-            if co1 != co2:
-                return False
-    return True
-
-
-def is_face_planar(face, error=0.0005):
-    for v in face.verts:
-        d = distance_point_to_plane(v.co, face.verts[0].co, face.normal)
-        if ENABLE_DEBUG:
-            print("Distance: " + str(d))
-        if d < -error or d > error:
-            return False
-    return True
-
-
-# other_joined_edges
-# Starts with an edge. Then scans for linked, selected edges and builds a
-# list with them in "order", starting at one end and moving towards the other
-
-def order_joined_edges(edge, edges=[], direction=1):
-    if len(edges) == 0:
-        edges.append(edge)
-        edges[0] = edge
-
-    if ENABLE_DEBUG:
-        print(edge, end=", ")
-        print(edges, end=", ")
-        print(direction, end="; ")
-
-    # Robustness check: direction cannot be zero
-    if direction == 0:
-        direction = 1
-
-    newList = []
-    for e in edge.verts[0].link_edges:
-        if e.select and edges.count(e) == 0:
-            if direction > 0:
-                edges.insert(0, e)
-                newList.extend(order_joined_edges(e, edges, direction + 1))
-                newList.extend(edges)
-            else:
-                edges.append(e)
-                newList.extend(edges)
-                newList.extend(order_joined_edges(e, edges, direction - 1))
-
-    # This will only matter at the first level:
-    direction = direction * -1
-
-    for e in edge.verts[1].link_edges:
-        if e.select and edges.count(e) == 0:
-            if direction > 0:
-                edges.insert(0, e)
-                newList.extend(order_joined_edges(e, edges, direction + 2))
-                newList.extend(edges)
-            else:
-                edges.append(e)
-                newList.extend(edges)
-                newList.extend(order_joined_edges(e, edges, direction))
-
-    if ENABLE_DEBUG:
-        print(newList, end=", ")
-        print(direction)
-
-    return newList
-
-
-# --------------- GEOMETRY CALCULATION METHODS --------------
-
-# distance_point_line
-# I don't know why the mathutils.geometry API does not already have this, but
-# it is trivial to code using the structures already in place. Instead of
-# returning a float, I also want to know the direction vector defining the
-# distance. Distance can be found with "Vector.length"
-
-def distance_point_line(pt, line_p1, line_p2):
-    int_co = intersect_point_line(pt, line_p1, line_p2)
-    distance_vector = int_co[0] - pt
-    return distance_vector
-
-
-# interpolate_line_line
-# This is an experiment into a cubic Hermite spline (c-spline) for connecting
-# two edges with edges that obey the general equation.
-# This will return a set of point coordinates (Vectors)
-#
-# A good, easy to read background on the mathematics can be found at:
-# http://cubic.org/docs/hermite.htm
-#
-# Right now this is . . . less than functional :P
-# @todo
-#   - C-Spline and Bezier curves do not end on p2_co as they are supposed to.
-#   - B-Spline just fails.  Epically.
-#   - Add more methods as I come across them.  Who said flexibility was bad?
-
-def interpolate_line_line(p1_co, p1_dir, p2_co, p2_dir, segments, tension=1,
-                          typ='BEZIER', include_ends=False):
-    pieces = []
-    fraction = 1 / segments
-
-    # Form: p1, tangent 1, p2, tangent 2
-    if typ == 'HERMITE':
-        poly = [[2, -3, 0, 1], [1, -2, 1, 0],
-                [-2, 3, 0, 0], [1, -1, 0, 0]]
-    elif typ == 'BEZIER':
-        poly = [[-1, 3, -3, 1], [3, -6, 3, 0],
-                [1, 0, 0, 0], [-3, 3, 0, 0]]
-        p1_dir = p1_dir + p1_co
-        p2_dir = -p2_dir + p2_co
-    elif typ == 'BSPLINE':
-        # Supposed poly matrix for a cubic b-spline:
-        # poly = [[-1, 3, -3, 1], [3, -6, 3, 0],
-        #         [-3, 0, 3, 0], [1, 4, 1, 0]]
-        # My own invention to try to get something that somewhat acts right
-        # This is semi-quadratic rather than fully cubic:
-        poly = [[0, -1, 0, 1], [1, -2, 1, 0],
-                [0, -1, 2, 0], [1, -1, 0, 0]]
-
-    if include_ends:
-        pieces.append(p1_co)
-
-    # Generate each point:
-    for i in range(segments - 1):
-        t = fraction * (i + 1)
-        if ENABLE_DEBUG:
-            print(t)
-        s = [t ** 3, t ** 2, t, 1]
-        h00 = (poly[0][0] * s[0]) + (poly[0][1] * s[1]) + (poly[0][2] * s[2]) + (poly[0][3] * s[3])
-        h01 = (poly[1][0] * s[0]) + (poly[1][1] * s[1]) + (poly[1][2] * s[2]) + (poly[1][3] * s[3])
-        h10 = (poly[2][0] * s[0]) + (poly[2][1] * s[1]) + (poly[2][2] * s[2]) + (poly[2][3] * s[3])
-        h11 = (poly[3][0] * s[0]) + (poly[3][1] * s[1]) + (poly[3][2] * s[2]) + (poly[3][3] * s[3])
-        pieces.append((h00 * p1_co) + (h01 * p1_dir) + (h10 * p2_co) + (h11 * p2_dir))
-    if include_ends:
-        pieces.append(p2_co)
-
-    # Return:
-    if len(pieces) == 0:
-        return None
-    else:
-        if ENABLE_DEBUG:
-            print(pieces)
-        return pieces
-
-
-# intersect_line_face
-
-# Calculates the coordinate of intersection of a line with a face.  It returns
-# the coordinate if one exists, otherwise None.  It can only deal with tris or
-# quads for a face. A quad does NOT have to be planar
-"""
-Quad math and theory:
-A quad may not be planar. Therefore the treated definition of the surface is
-that the surface is composed of all lines bridging two other lines defined by
-the given four points. The lines do not "cross"
-
-The two lines in 3-space can defined as:
-┌  ┐         ┌   ┐     ┌   ┐  ┌  ┐         ┌   ┐     ┌   ┐
-│x1│         │a11│     │b11│  │x2│         │a21│     │b21│
-│y1│ = (1-t1)│a12│ + t1│b12│, │y2│ = (1-t2)│a22│ + t2│b22│
-│z1│         │a13│     │b13│  │z2│         │a23│     │b23│
-└  ┘         └   ┘     └   ┘  └  ┘         └   ┘     └   ┘
-Therefore, the surface is the lines defined by every point alone the two
-lines with a same "t" value (t1 = t2). This is basically R = V1 + tQ, where
-Q = V2 - V1 therefore R = V1 + t(V2 - V1) -> R = (1 - t)V1 + tV2:
-┌   ┐            ┌                  ┐      ┌                  ┐
-│x12│            │(1-t)a11 + t * b11│      │(1-t)a21 + t * b21│
-│y12│ = (1 - t12)│(1-t)a12 + t * b12│ + t12│(1-t)a22 + t * b22│
-│z12│            │(1-t)a13 + t * b13│      │(1-t)a23 + t * b23│
-└   ┘            └                  ┘      └                  ┘
-Now, the equation of our line can be likewise defined:
-┌  ┐   ┌   ┐     ┌   ┐
-│x3│   │a31│     │b31│
-│y3│ = │a32│ + t3│b32│
-│z3│   │a33│     │b33│
-└  ┘   └   ┘     └   ┘
-Now we just have to find a valid solution for the two equations.  This should
-be our point of intersection. Therefore, x12 = x3 -> x, y12 = y3 -> y,
-z12 = z3 -> z.  Thus, to find that point we set the equation defining the
-surface as equal to the equation for the line:
-        ┌                  ┐      ┌                  ┐   ┌   ┐     ┌   ┐
-        │(1-t)a11 + t * b11│      │(1-t)a21 + t * b21│   │a31│     │b31│
-(1 - t12)│(1-t)a12 + t * b12│ + t12│(1-t)a22 + t * b22│ = │a32│ + t3│b32│
-        │(1-t)a13 + t * b13│      │(1-t)a23 + t * b23│   │a33│     │b33│
-        └                  ┘      └                  ┘   └   ┘     └   ┘
-This leaves us with three equations, three unknowns.  Solving the system by
-hand is practically impossible, but using Mathematica we are given an insane
-series of three equations (not reproduced here for the sake of space: see
-http://www.mediafire.com/file/cc6m6ba3sz2b96m/intersect_line_surface.nb and
-http://www.mediafire.com/file/0egbr5ahg14talm/intersect_line_surface2.nb for
-Mathematica computation).
-
-Additionally, the resulting series of equations may result in a div by zero
-exception if the line in question if parallel to one of the axis or if the
-quad is planar and parallel to either the XY, XZ, or YZ planes. However, the
-system is still solvable but must be dealt with a little differently to avaid
-these special cases. Because the resulting equations are a little different,
-we have to code them differently. 00Hence the special cases.
-
-Tri math and theory:
-A triangle must be planar (three points define a plane). So we just
-have to make sure that the line intersects inside the triangle.
-
-If the point is within the triangle, then the angle between the lines that
-connect the point to the each individual point of the triangle will be
-equal to 2 * PI. Otherwise, if the point is outside the triangle, then the
-sum of the angles will be less.
-"""
-# @todo
-# - Figure out how to deal with n-gons
-# How the heck is a face with 8 verts defined mathematically?
-# How do I then find the intersection point of a line with said vert?
-# How do I know if that point is "inside" all the verts?
-# I have no clue, and haven't been able to find anything on it so far
-# Maybe if someone (actually reads this and) who knows could note?
-
-
-def intersect_line_face(edge, face, is_infinite=False, error=0.000002):
-    int_co = None
-
-    # If we are dealing with a non-planar quad:
-    if len(face.verts) == 4 and not is_face_planar(face):
-        edgeA = face.edges[0]
-        edgeB = None
-        flipB = False
-
-        for i in range(len(face.edges)):
-            if face.edges[i].verts[0] not in edgeA.verts and \
-               face.edges[i].verts[1] not in edgeA.verts:
-
-                edgeB = face.edges[i]
-                break
-
-        # I haven't figured out a way to mix this in with the above. Doing so might remove a
-        # few extra instructions from having to be executed saving a few clock cycles:
-        for i in range(len(face.edges)):
-            if face.edges[i] == edgeA or face.edges[i] == edgeB:
-                continue
-            if ((edgeA.verts[0] in face.edges[i].verts and
-               edgeB.verts[1] in face.edges[i].verts) or
-               (edgeA.verts[1] in face.edges[i].verts and edgeB.verts[0] in face.edges[i].verts)):
-
-                flipB = True
-                break
-
-        # Define calculation coefficient constants:
-        # "xx1" is the x coordinate, "xx2" is the y coordinate, and "xx3" is the z coordinate
-        a11, a12, a13 = edgeA.verts[0].co[0], edgeA.verts[0].co[1], edgeA.verts[0].co[2]
-        b11, b12, b13 = edgeA.verts[1].co[0], edgeA.verts[1].co[1], edgeA.verts[1].co[2]
-
-        if flipB:
-            a21, a22, a23 = edgeB.verts[1].co[0], edgeB.verts[1].co[1], edgeB.verts[1].co[2]
-            b21, b22, b23 = edgeB.verts[0].co[0], edgeB.verts[0].co[1], edgeB.verts[0].co[2]
-        else:
-            a21, a22, a23 = edgeB.verts[0].co[0], edgeB.verts[0].co[1], edgeB.verts[0].co[2]
-            b21, b22, b23 = edgeB.verts[1].co[0], edgeB.verts[1].co[1], edgeB.verts[1].co[2]
-        a31, a32, a33 = edge.verts[0].co[0], edge.verts[0].co[1], edge.verts[0].co[2]
-        b31, b32, b33 = edge.verts[1].co[0], edge.verts[1].co[1], edge.verts[1].co[2]
-
-        # There are a bunch of duplicate "sub-calculations" inside the resulting
-        # equations for t, t12, and t3.  Calculate them once and store them to
-        # reduce computational time:
-        m01 = a13 * a22 * a31
-        m02 = a12 * a23 * a31
-        m03 = a13 * a21 * a32
-        m04 = a11 * a23 * a32
-        m05 = a12 * a21 * a33
-        m06 = a11 * a22 * a33
-        m07 = a23 * a32 * b11
-        m08 = a22 * a33 * b11
-        m09 = a23 * a31 * b12
-        m10 = a21 * a33 * b12
-        m11 = a22 * a31 * b13
-        m12 = a21 * a32 * b13
-        m13 = a13 * a32 * b21
-        m14 = a12 * a33 * b21
-        m15 = a13 * a31 * b22
-        m16 = a11 * a33 * b22
-        m17 = a12 * a31 * b23
-        m18 = a11 * a32 * b23
-        m19 = a13 * a22 * b31
-        m20 = a12 * a23 * b31
-        m21 = a13 * a32 * b31
-        m22 = a23 * a32 * b31
-        m23 = a12 * a33 * b31
-        m24 = a22 * a33 * b31
-        m25 = a23 * b12 * b31
-        m26 = a33 * b12 * b31
-        m27 = a22 * b13 * b31
-        m28 = a32 * b13 * b31
-        m29 = a13 * b22 * b31
-        m30 = a33 * b22 * b31
-        m31 = a12 * b23 * b31
-        m32 = a32 * b23 * b31
-        m33 = a13 * a21 * b32
-        m34 = a11 * a23 * b32
-        m35 = a13 * a31 * b32
-        m36 = a23 * a31 * b32
-        m37 = a11 * a33 * b32
-        m38 = a21 * a33 * b32
-        m39 = a23 * b11 * b32
-        m40 = a33 * b11 * b32
-        m41 = a21 * b13 * b32
-        m42 = a31 * b13 * b32
-        m43 = a13 * b21 * b32
-        m44 = a33 * b21 * b32
-        m45 = a11 * b23 * b32
-        m46 = a31 * b23 * b32
-        m47 = a12 * a21 * b33
-        m48 = a11 * a22 * b33
-        m49 = a12 * a31 * b33
-        m50 = a22 * a31 * b33
-        m51 = a11 * a32 * b33
-        m52 = a21 * a32 * b33
-        m53 = a22 * b11 * b33
-        m54 = a32 * b11 * b33
-        m55 = a21 * b12 * b33
-        m56 = a31 * b12 * b33
-        m57 = a12 * b21 * b33
-        m58 = a32 * b21 * b33
-        m59 = a11 * b22 * b33
-        m60 = a31 * b22 * b33
-        m61 = a33 * b12 * b21
-        m62 = a32 * b13 * b21
-        m63 = a33 * b11 * b22
-        m64 = a31 * b13 * b22
-        m65 = a32 * b11 * b23
-        m66 = a31 * b12 * b23
-        m67 = b13 * b22 * b31
-        m68 = b12 * b23 * b31
-        m69 = b13 * b21 * b32
-        m70 = b11 * b23 * b32
-        m71 = b12 * b21 * b33
-        m72 = b11 * b22 * b33
-        n01 = m01 - m02 - m03 + m04 + m05 - m06
-        n02 = -m07 + m08 + m09 - m10 - m11 + m12 + m13 - m14 - m15 + m16 + m17 - m18 - \
-              m25 + m27 + m29 - m31 + m39 - m41 - m43 + m45 - m53 + m55 + m57 - m59
-        n03 = -m19 + m20 + m33 - m34 - m47 + m48
-        n04 = m21 - m22 - m23 + m24 - m35 + m36 + m37 - m38 + m49 - m50 - m51 + m52
-        n05 = m26 - m28 - m30 + m32 - m40 + m42 + m44 - m46 + m54 - m56 - m58 + m60
-        n06 = m61 - m62 - m63 + m64 + m65 - m66 - m67 + m68 + m69 - m70 - m71 + m72
-        n07 = 2 * n01 + n02 + 2 * n03 + n04 + n05
-        n08 = n01 + n02 + n03 + n06
-
-        # Calculate t, t12, and t3:
-        t = (n07 - sqrt(pow(-n07, 2) - 4 * (n01 + n03 + n04) * n08)) / (2 * n08)
-
-        # t12 can be greatly simplified by defining it with t in it:
-        # If block used to help prevent any div by zero error.
-        t12 = 0
-
-        if a31 == b31:
-            # The line is parallel to the z-axis:
-            if a32 == b32:
-                t12 = ((a11 - a31) + (b11 - a11) * t) / ((a21 - a11) + (a11 - a21 - b11 + b21) * t)
-            # The line is parallel to the y-axis:
-            elif a33 == b33:
-                t12 = ((a11 - a31) + (b11 - a11) * t) / ((a21 - a11) + (a11 - a21 - b11 + b21) * t)
-            # The line is along the y/z-axis but is not parallel to either:
-            else:
-                t12 = -(-(a33 - b33) * (-a32 + a12 * (1 - t) + b12 * t) + (a32 - b32) *
-                        (-a33 + a13 * (1 - t) + b13 * t)) / (-(a33 - b33) *
-                        ((a22 - a12) * (1 - t) + (b22 - b12) * t) + (a32 - b32) *
-                        ((a23 - a13) * (1 - t) + (b23 - b13) * t))
-        elif a32 == b32:
-            # The line is parallel to the x-axis:
-            if a33 == b33:
-                t12 = ((a12 - a32) + (b12 - a12) * t) / ((a22 - a12) + (a12 - a22 - b12 + b22) * t)
-            # The line is along the x/z-axis but is not parallel to either:
-            else:
-                t12 = -(-(a33 - b33) * (-a31 + a11 * (1 - t) + b11 * t) + (a31 - b31) * (-a33 + a13 *
-                      (1 - t) + b13 * t)) / (-(a33 - b33) * ((a21 - a11) * (1 - t) + (b21 - b11) * t) +
-                      (a31 - b31) * ((a23 - a13) * (1 - t) + (b23 - b13) * t))
-        # The line is along the x/y-axis but is not parallel to either:
-        else:
-            t12 = -(-(a32 - b32) * (-a31 + a11 * (1 - t) + b11 * t) + (a31 - b31) * (-a32 + a12 *
-                  (1 - t) + b12 * t)) / (-(a32 - b32) * ((a21 - a11) * (1 - t) + (b21 - b11) * t) +
-                  (a31 - b31) * ((a22 - a21) * (1 - t) + (b22 - b12) * t))
-
-        # Likewise, t3 is greatly simplified by defining it in terms of t and t12:
-        # If block used to prevent a div by zero error.
-        t3 = 0
-        if a31 != b31:
-            t3 = (-a11 + a31 + (a11 - b11) * t + (a11 - a21) *
-                t12 + (a21 - a11 + b11 - b21) * t * t12) / (a31 - b31)
-        elif a32 != b32:
-            t3 = (-a12 + a32 + (a12 - b12) * t + (a12 - a22) *
-                t12 + (a22 - a12 + b12 - b22) * t * t12) / (a32 - b32)
-        elif a33 != b33:
-            t3 = (-a13 + a33 + (a13 - b13) * t + (a13 - a23) *
-                t12 + (a23 - a13 + b13 - b23) * t * t12) / (a33 - b33)
-        else:
-            if ENABLE_DEBUG:
-                print("The second edge is a zero-length edge")
-            return None
-
-        # Calculate the point of intersection:
-        x = (1 - t3) * a31 + t3 * b31
-        y = (1 - t3) * a32 + t3 * b32
-        z = (1 - t3) * a33 + t3 * b33
-        int_co = Vector((x, y, z))
-
-        if ENABLE_DEBUG:
-            print(int_co)
-
-        # If the line does not intersect the quad, we return "None":
-        if (t < -1 or t > 1 or t12 < -1 or t12 > 1) and not is_infinite:
-            int_co = None
-
-    elif len(face.verts) == 3:
-        p1, p2, p3 = face.verts[0].co, face.verts[1].co, face.verts[2].co
-        int_co = intersect_line_plane(edge.verts[0].co, edge.verts[1].co, p1, face.normal)
-
-        # Only check if the triangle is not being treated as an infinite plane:
-        # Math based from http://paulbourke.net/geometry/linefacet/
-        if int_co is not None and not is_infinite:
-            pA = p1 - int_co
-            pB = p2 - int_co
-            pC = p3 - int_co
-            # These must be unit vectors, else we risk a domain error:
-            pA.length = 1
-            pB.length = 1
-            pC.length = 1
-            aAB = acos(pA.dot(pB))
-            aBC = acos(pB.dot(pC))
-            aCA = acos(pC.dot(pA))
-            sumA = aAB + aBC + aCA
-
-            # If the point is outside the triangle:
-            if (sumA > (pi + error) and sumA < (pi - error)):
-                int_co = None
-
-    # This is the default case where we either have a planar quad or an n-gon
-    else:
-        int_co = intersect_line_plane(edge.verts[0].co, edge.verts[1].co,
-                                      face.verts[0].co, face.normal)
-    return int_co
-
-
-# project_point_plane
-# Projects a point onto a plane. Returns a tuple of the projection vector
-# and the projected coordinate
-
-def project_point_plane(pt, plane_co, plane_no):
-    if ENABLE_DEBUG:
-        print("project_point_plane was called")
-    proj_co = intersect_line_plane(pt, pt + plane_no, plane_co, plane_no)
-    proj_ve = proj_co - pt
-    if ENABLE_DEBUG:
-        print("project_point_plane: proj_co is {}\nproj_ve is {}".format(proj_co, proj_ve))
-    return (proj_ve, proj_co)
-
-
-# ------------ CHAMPHER HELPER METHODS -------------
-
-def is_planar_edge(edge, error=0.000002):
-    angle = edge.calc_face_angle()
-    return ((angle < error and angle > -error) or
-            (angle < (180 + error) and angle > (180 - error)))
-
-
-# ------------- EDGE TOOL METHODS -------------------
-
-# Extends an "edge" in two directions:
-#   - Requires two vertices to be selected. They do not have to form an edge
-#   - Extends "length" in both directions
-
-class Extend(Operator):
-    bl_idname = "mesh.edgetools_extend"
-    bl_label = "Extend"
-    bl_description = "Extend the selected edges of vertex pairs"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    di1: BoolProperty(
-            name="Forwards",
-            description="Extend the edge forwards",
-            default=True
-            )
-    di2: BoolProperty(
-            name="Backwards",
-            description="Extend the edge backwards",
-            default=False
-            )
-    length: FloatProperty(
-            name="Length",
-            description="Length to extend the edge",
-            min=0.0, max=1024.0,
-            default=1.0
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        row = layout.row(align=True)
-        row.prop(self, "di1", toggle=True)
-        row.prop(self, "di2", toggle=True)
-
-        layout.prop(self, "length")
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return(ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bEdges = bm.edges
-            bVerts = bm.verts
-
-            edges = [e for e in bEdges if e.select]
-            verts = [v for v in bVerts if v.select]
-
-            if not is_selected_enough(self, edges, 0, edges_n=1, verts_n=0, types="Edge"):
-                return {'CANCELLED'}
-
-            if len(edges) > 0:
-                for e in edges:
-                    vector = e.verts[0].co - e.verts[1].co
-                    vector.length = self.length
-
-                    if self.di1:
-                        v = bVerts.new()
-                        if (vector[0] + vector[1] + vector[2]) < 0:
-                            v.co = e.verts[1].co - vector
-                            newE = bEdges.new((e.verts[1], v))
-                            bEdges.ensure_lookup_table()
-                        else:
-                            v.co = e.verts[0].co + vector
-                            newE = bEdges.new((e.verts[0], v))
-                            bEdges.ensure_lookup_table()
-                    if self.di2:
-                        v = bVerts.new()
-                        if (vector[0] + vector[1] + vector[2]) < 0:
-                            v.co = e.verts[0].co + vector
-                            newE = bEdges.new((e.verts[0], v))
-                            bEdges.ensure_lookup_table()
-                        else:
-                            v.co = e.verts[1].co - vector
-                            newE = bEdges.new((e.verts[1], v))
-                            bEdges.ensure_lookup_table()
-            else:
-                vector = verts[0].co - verts[1].co
-                vector.length = self.length
-
-                if self.di1:
-                    v = bVerts.new()
-                    if (vector[0] + vector[1] + vector[2]) < 0:
-                        v.co = verts[1].co - vector
-                        e = bEdges.new((verts[1], v))
-                        bEdges.ensure_lookup_table()
-                    else:
-                        v.co = verts[0].co + vector
-                        e = bEdges.new((verts[0], v))
-                        bEdges.ensure_lookup_table()
-                if self.di2:
-                    v = bVerts.new()
-                    if (vector[0] + vector[1] + vector[2]) < 0:
-                        v.co = verts[0].co + vector
-                        e = bEdges.new((verts[0], v))
-                        bEdges.ensure_lookup_table()
-                    else:
-                        v.co = verts[1].co - vector
-                        e = bEdges.new((verts[1], v))
-                        bEdges.ensure_lookup_table()
-
-            bmesh.update_edit_mesh(me)
-
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_extend", e,
-                           reports="Extend Operator failed", func=False)
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-# Creates a series of edges between two edges using spline interpolation.
-# This basically just exposes existing functionality in addition to some
-# other common methods: Hermite (c-spline), Bezier, and b-spline. These
-# alternates I coded myself after some extensive research into spline theory
-#
-# @todo Figure out what's wrong with the Blender bezier interpolation
-
-class Spline(Operator):
-    bl_idname = "mesh.edgetools_spline"
-    bl_label = "Spline"
-    bl_description = "Create a spline interplopation between two edges"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    alg: EnumProperty(
-            name="Spline Algorithm",
-            items=[('Blender', "Blender", "Interpolation provided through mathutils.geometry"),
-                    ('Hermite', "C-Spline", "C-spline interpolation"),
-                    ('Bezier', "Bezier", "Bezier interpolation"),
-                    ('B-Spline', "B-Spline", "B-Spline interpolation")],
-            default='Bezier'
-            )
-    segments: IntProperty(
-            name="Segments",
-            description="Number of segments to use in the interpolation",
-            min=2, max=4096,
-            soft_max=1024,
-            default=32
-            )
-    flip1: BoolProperty(
-            name="Flip Edge",
-            description="Flip the direction of the spline on Edge 1",
-            default=False
-            )
-    flip2: BoolProperty(
-            name="Flip Edge",
-            description="Flip the direction of the spline on Edge 2",
-            default=False
-            )
-    ten1: FloatProperty(
-            name="Tension",
-            description="Tension on Edge 1",
-            min=-4096.0, max=4096.0,
-            soft_min=-8.0, soft_max=8.0,
-            default=1.0
-            )
-    ten2: FloatProperty(
-            name="Tension",
-            description="Tension on Edge 2",
-            min=-4096.0, max=4096.0,
-            soft_min=-8.0, soft_max=8.0,
-            default=1.0
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.prop(self, "alg")
-        layout.prop(self, "segments")
-
-        layout.label(text="Edge 1:")
-        split = layout.split(factor=0.8, align=True)
-        split.prop(self, "ten1")
-        split.prop(self, "flip1", text="", icon="ALIGN", toggle=True)
-
-        layout.label(text="Edge 2:")
-        split = layout.split(factor=0.8, align=True)
-        split.prop(self, "ten2")
-        split.prop(self, "flip2", text="", icon="ALIGN", toggle=True)
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return(ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bEdges = bm.edges
-            bVerts = bm.verts
-
-            seg = self.segments
-            edges = [e for e in bEdges if e.select]
-
-            if not is_selected_enough(self, edges, 0, edges_n=2, verts_n=0, types="Edge"):
-                return {'CANCELLED'}
-
-            verts = [edges[v // 2].verts[v % 2] for v in range(4)]
-
-            if self.flip1:
-                v1 = verts[1]
-                p1_co = verts[1].co
-                p1_dir = verts[1].co - verts[0].co
-            else:
-                v1 = verts[0]
-                p1_co = verts[0].co
-                p1_dir = verts[0].co - verts[1].co
-            if self.ten1 < 0:
-                p1_dir = -1 * p1_dir
-                p1_dir.length = -self.ten1
-            else:
-                p1_dir.length = self.ten1
-
-            if self.flip2:
-                v2 = verts[3]
-                p2_co = verts[3].co
-                p2_dir = verts[2].co - verts[3].co
-            else:
-                v2 = verts[2]
-                p2_co = verts[2].co
-                p2_dir = verts[3].co - verts[2].co
-            if self.ten2 < 0:
-                p2_dir = -1 * p2_dir
-                p2_dir.length = -self.ten2
-            else:
-                p2_dir.length = self.ten2
-
-            # Get the interploted coordinates:
-            if self.alg == 'Blender':
-                pieces = interpolate_bezier(
-                                p1_co, p1_dir, p2_dir, p2_co, self.segments
-                                )
-            elif self.alg == 'Hermite':
-                pieces = interpolate_line_line(
-                                p1_co, p1_dir, p2_co, p2_dir, self.segments, 1, 'HERMITE'
-                                )
-            elif self.alg == 'Bezier':
-                pieces = interpolate_line_line(
-                                p1_co, p1_dir, p2_co, p2_dir, self.segments, 1, 'BEZIER'
-                                )
-            elif self.alg == 'B-Spline':
-                pieces = interpolate_line_line(
-                                p1_co, p1_dir, p2_co, p2_dir, self.segments, 1, 'BSPLINE'
-                                )
-
-            verts = []
-            verts.append(v1)
-            # Add vertices and set the points:
-            for i in range(seg - 1):
-                v = bVerts.new()
-                v.co = pieces[i]
-                bVerts.ensure_lookup_table()
-                verts.append(v)
-            verts.append(v2)
-            # Connect vertices:
-            for i in range(seg):
-                e = bEdges.new((verts[i], verts[i + 1]))
-                bEdges.ensure_lookup_table()
-
-            bmesh.update_edit_mesh(me)
-
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_spline", e,
-                           reports="Spline Operator failed", func=False)
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-# Creates edges normal to planes defined between each of two edges and the
-# normal or the plane defined by those two edges.
-#   - Select two edges.  The must form a plane.
-#   - On running the script, eight edges will be created.  Delete the
-#     extras that you don't need.
-#   - The length of those edges is defined by the variable "length"
-#
-# @todo Change method from a cross product to a rotation matrix to make the
-#   angle part work.
-#   --- todo completed 2/4/2012, but still needs work ---
-# @todo Figure out a way to make +/- predictable
-#   - Maybe use angle between edges and vector direction definition?
-#   --- TODO COMPLETED ON 2/9/2012 ---
-
-class Ortho(Operator):
-    bl_idname = "mesh.edgetools_ortho"
-    bl_label = "Angle Off Edge"
-    bl_description = "Creates new edges within an angle from vertices of selected edges"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    vert1: BoolProperty(
-            name="Vertice 1",
-            description="Enable edge creation for Vertice 1",
-            default=True
-            )
-    vert2: BoolProperty(
-            name="Vertice 2",
-            description="Enable edge creation for Vertice 2",
-            default=True
-            )
-    vert3: BoolProperty(
-            name="Vertice 3",
-            description="Enable edge creation for Vertice 3",
-            default=True
-            )
-    vert4: BoolProperty(
-            name="Vertice 4",
-            description="Enable edge creation for Vertice 4",
-            default=True
-            )
-    pos: BoolProperty(
-            name="Positive",
-            description="Enable creation of positive direction edges",
-            default=True
-            )
-    neg: BoolProperty(
-            name="Negative",
-            description="Enable creation of negative direction edges",
-            default=True
-            )
-    angle: FloatProperty(
-            name="Angle",
-            description="Define the angle off of the originating edge",
-            min=0.0, max=180.0,
-            default=90.0
-            )
-    length: FloatProperty(
-            name="Length",
-            description="Length of created edges",
-            min=0.0, max=1024.0,
-            default=1.0
-            )
-    # For when only one edge is selected (Possible feature to be testd):
-    plane: EnumProperty(
-            name="Plane",
-            items=[("XY", "X-Y Plane", "Use the X-Y plane as the plane of creation"),
-                   ("XZ", "X-Z Plane", "Use the X-Z plane as the plane of creation"),
-                   ("YZ", "Y-Z Plane", "Use the Y-Z plane as the plane of creation")],
-            default="XY"
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.label(text="Creation:")
-        split = layout.split()
-        col = split.column()
-
-        col.prop(self, "vert1", toggle=True)
-        col.prop(self, "vert2", toggle=True)
-
-        col = split.column()
-        col.prop(self, "vert3", toggle=True)
-        col.prop(self, "vert4", toggle=True)
-
-        layout.label(text="Direction:")
-        row = layout.row(align=False)
-        row.alignment = 'EXPAND'
-        row.prop(self, "pos")
-        row.prop(self, "neg")
-
-        layout.separator()
-
-        col = layout.column(align=True)
-        col.prop(self, "angle")
-        col.prop(self, "length")
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return(ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bVerts = bm.verts
-            bEdges = bm.edges
-            edges = [e for e in bEdges if e.select]
-            vectors = []
-
-            if not is_selected_enough(self, edges, 0, edges_n=2, verts_n=0, types="Edge"):
-                return {'CANCELLED'}
-
-            verts = [edges[0].verts[0],
-                     edges[0].verts[1],
-                     edges[1].verts[0],
-                     edges[1].verts[1]]
-
-            cos = intersect_line_line(verts[0].co, verts[1].co, verts[2].co, verts[3].co)
-
-            # If the two edges are parallel:
-            if cos is None:
-                self.report({'WARNING'},
-                            "Selected lines are parallel: results may be unpredictable")
-                vectors.append(verts[0].co - verts[1].co)
-                vectors.append(verts[0].co - verts[2].co)
-                vectors.append(vectors[0].cross(vectors[1]))
-                vectors.append(vectors[2].cross(vectors[0]))
-                vectors.append(-vectors[3])
-            else:
-                # Warn the user if they have not chosen two planar edges:
-                if not is_same_co(cos[0], cos[1]):
-                    self.report({'WARNING'},
-                                "Selected lines are not planar: results may be unpredictable")
-
-                # This makes the +/- behavior predictable:
-                if (verts[0].co - cos[0]).length < (verts[1].co - cos[0]).length:
-                    verts[0], verts[1] = verts[1], verts[0]
-                if (verts[2].co - cos[0]).length < (verts[3].co - cos[0]).length:
-                    verts[2], verts[3] = verts[3], verts[2]
-
-                vectors.append(verts[0].co - verts[1].co)
-                vectors.append(verts[2].co - verts[3].co)
-
-                # Normal of the plane formed by vector1 and vector2:
-                vectors.append(vectors[0].cross(vectors[1]))
-
-                # Possible directions:
-                vectors.append(vectors[2].cross(vectors[0]))
-                vectors.append(vectors[1].cross(vectors[2]))
-
-            # Set the length:
-            vectors[3].length = self.length
-            vectors[4].length = self.length
-
-            # Perform any additional rotations:
-            matrix = Matrix.Rotation(radians(90 + self.angle), 3, vectors[2])
-            vectors.append(matrix * -vectors[3])    # vectors[5]
-            matrix = Matrix.Rotation(radians(90 - self.angle), 3, vectors[2])
-            vectors.append(matrix * vectors[4])     # vectors[6]
-            vectors.append(matrix * vectors[3])     # vectors[7]
-            matrix = Matrix.Rotation(radians(90 + self.angle), 3, vectors[2])
-            vectors.append(matrix * -vectors[4])    # vectors[8]
-
-            # Perform extrusions and displacements:
-            # There will be a total of 8 extrusions.  One for each vert of each edge.
-            # It looks like an extrusion will add the new vert to the end of the verts
-            # list and leave the rest in the same location.
-            # -- EDIT --
-            # It looks like I might be able to do this within "bpy.data" with the ".add" function
-
-            for v in range(len(verts)):
-                vert = verts[v]
-                if ((v == 0 and self.vert1) or (v == 1 and self.vert2) or
-                   (v == 2 and self.vert3) or (v == 3 and self.vert4)):
-
-                    if self.pos:
-                        new = bVerts.new()
-                        new.co = vert.co - vectors[5 + (v // 2) + ((v % 2) * 2)]
-                        bVerts.ensure_lookup_table()
-                        bEdges.new((vert, new))
-                        bEdges.ensure_lookup_table()
-                    if self.neg:
-                        new = bVerts.new()
-                        new.co = vert.co + vectors[5 + (v // 2) + ((v % 2) * 2)]
-                        bVerts.ensure_lookup_table()
-                        bEdges.new((vert, new))
-                        bEdges.ensure_lookup_table()
-
-            bmesh.update_edit_mesh(me)
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_ortho", e,
-                           reports="Angle Off Edge Operator failed", func=False)
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-# Usage:
-# Select an edge and a point or an edge and specify the radius (default is 1 BU)
-# You can select two edges but it might be unpredictable which edge it revolves
-# around so you might have to play with the switch
-
-class Shaft(Operator):
-    bl_idname = "mesh.edgetools_shaft"
-    bl_label = "Shaft"
-    bl_description = "Create a shaft mesh around an axis"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    # Selection defaults:
-    shaftType = 0
-
-    # For tracking if the user has changed selection:
-    last_edge: IntProperty(
-            name="Last Edge",
-            description="Tracks if user has changed selected edges",
-            min=0, max=1,
-            default=0
-            )
-    last_flip = False
-
-    edge: IntProperty(
-            name="Edge",
-            description="Edge to shaft around",
-            min=0, max=1,
-            default=0
-            )
-    flip: BoolProperty(
-            name="Flip Second Edge",
-            description="Flip the perceived direction of the second edge",
-            default=False
-            )
-    radius: FloatProperty(
-            name="Radius",
-            description="Shaft Radius",
-            min=0.0, max=1024.0,
-            default=1.0
-            )
-    start: FloatProperty(
-            name="Starting Angle",
-            description="Angle to start the shaft at",
-            min=-360.0, max=360.0,
-            default=0.0
-            )
-    finish: FloatProperty(
-            name="Ending Angle",
-            description="Angle to end the shaft at",
-            min=-360.0, max=360.0,
-            default=360.0
-            )
-    segments: IntProperty(
-            name="Shaft Segments",
-            description="Number of segments to use in the shaft",
-            min=1, max=4096,
-            soft_max=512,
-            default=32
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        if self.shaftType == 0:
-            layout.prop(self, "edge")
-            layout.prop(self, "flip")
-        elif self.shaftType == 3:
-            layout.prop(self, "radius")
-
-        layout.prop(self, "segments")
-        layout.prop(self, "start")
-        layout.prop(self, "finish")
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return(ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        # Make sure these get reset each time we run:
-        self.last_edge = 0
-        self.edge = 0
-
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bFaces = bm.faces
-            bEdges = bm.edges
-            bVerts = bm.verts
-
-            active = None
-            edges, verts = [], []
-
-            # Pre-caclulated values:
-            rotRange = [radians(self.start), radians(self.finish)]
-            rads = radians((self.finish - self.start) / self.segments)
-
-            numV = self.segments + 1
-            numE = self.segments
-
-            edges = [e for e in bEdges if e.select]
-
-            # Robustness check: there should at least be one edge selected
-            if not is_selected_enough(self, edges, 0, edges_n=1, verts_n=0, types="Edge"):
-                return {'CANCELLED'}
-
-            # If two edges are selected:
-            if len(edges) == 2:
-                # default:
-                edge = [0, 1]
-                vert = [0, 1]
-
-                # By default, we want to shaft around the last selected edge (it
-                # will be the active edge). We know we are using the default if
-                # the user has not changed which edge is being shafted around (as
-                # is tracked by self.last_edge). When they are not the same, then
-                # the user has changed selection.
-                # We then need to make sure that the active object really is an edge
-                # (robustness check)
-                # Finally, if the active edge is not the initial one, we flip them
-                # and have the GUI reflect that
-                if self.last_edge == self.edge:
-                    if isinstance(bm.select_history.active, bmesh.types.BMEdge):
-                        if bm.select_history.active != edges[edge[0]]:
-                            self.last_edge, self.edge = edge[1], edge[1]
-                            edge = [edge[1], edge[0]]
-                    else:
-                        flip_edit_mode()
-                        self.report({'WARNING'},
-                                    "Active geometry is not an edge. Operation Cancelled")
-                        return {'CANCELLED'}
-                elif self.edge == 1:
-                    edge = [1, 0]
-
-                verts.append(edges[edge[0]].verts[0])
-                verts.append(edges[edge[0]].verts[1])
-
-                if self.flip:
-                    verts = [1, 0]
-
-                verts.append(edges[edge[1]].verts[vert[0]])
-                verts.append(edges[edge[1]].verts[vert[1]])
-
-                self.shaftType = 0
-            # If there is more than one edge selected:
-            # There are some issues with it ATM, so don't expose is it to normal users
-            # @todo Fix edge connection ordering issue
-            elif ENABLE_DEBUG and len(edges) > 2:
-                if isinstance(bm.select_history.active, bmesh.types.BMEdge):
-                    active = bm.select_history.active
-                    edges.remove(active)
-                    # Get all the verts:
-                    # edges = order_joined_edges(edges[0])
-                    verts = []
-                    for e in edges:
-                        if verts.count(e.verts[0]) == 0:
-                            verts.append(e.verts[0])
-                        if verts.count(e.verts[1]) == 0:
-                            verts.append(e.verts[1])
-                else:
-                    flip_edit_mode()
-                    self.report({'WARNING'},
-                                "Active geometry is not an edge. Operation Cancelled")
-                    return {'CANCELLED'}
-                self.shaftType = 1
-            else:
-                verts.append(edges[0].verts[0])
-                verts.append(edges[0].verts[1])
-
-                for v in bVerts:
-                    if v.select and verts.count(v) == 0:
-                        verts.append(v)
-                    v.select = False
-                if len(verts) == 2:
-                    self.shaftType = 3
-                else:
-                    self.shaftType = 2
-
-            # The vector denoting the axis of rotation:
-            if self.shaftType == 1:
-                axis = active.verts[1].co - active.verts[0].co
-            else:
-                axis = verts[1].co - verts[0].co
-
-            # We will need a series of rotation matrices. We could use one which
-            # would be faster but also might cause propagation of error
-            # matrices = []
-            # for i in range(numV):
-            #    matrices.append(Matrix.Rotation((rads * i) + rotRange[0], 3, axis))
-            matrices = [Matrix.Rotation((rads * i) + rotRange[0], 3, axis) for i in range(numV)]
-
-            # New vertice coordinates:
-            verts_out = []
-
-            # If two edges were selected:
-            #  - If the lines are not parallel, then it will create a cone-like shaft
-            if self.shaftType == 0:
-                for i in range(len(verts) - 2):
-                    init_vec = distance_point_line(verts[i + 2].co, verts[0].co, verts[1].co)
-                    co = init_vec + verts[i + 2].co
-                    # These will be rotated about the origin so will need to be shifted:
-                    for j in range(numV):
-                        verts_out.append(co - (matrices[j] * init_vec))
-            elif self.shaftType == 1:
-                for i in verts:
-                    init_vec = distance_point_line(i.co, active.verts[0].co, active.verts[1].co)
-                    co = init_vec + i.co
-                    # These will be rotated about the origin so will need to be shifted:
-                    for j in range(numV):
-                        verts_out.append(co - (matrices[j] * init_vec))
-            # Else if a line and a point was selected:
-            elif self.shaftType == 2:
-                init_vec = distance_point_line(verts[2].co, verts[0].co, verts[1].co)
-                # These will be rotated about the origin so will need to be shifted:
-                verts_out = [
-                    (verts[i].co - (matrices[j] * init_vec)) for i in range(2) for j in range(numV)
-                    ]
-            else:
-                # Else the above are not possible, so we will just use the edge:
-                #  - The vector defined by the edge is the normal of the plane for the shaft
-                #  - The shaft will have radius "radius"
-                if is_axial(verts[0].co, verts[1].co) is None:
-                    proj = (verts[1].co - verts[0].co)
-                    proj[2] = 0
-                    norm = proj.cross(verts[1].co - verts[0].co)
-                    vec = norm.cross(verts[1].co - verts[0].co)
-                    vec.length = self.radius
-                elif is_axial(verts[0].co, verts[1].co) == 'Z':
-                    vec = verts[0].co + Vector((0, 0, self.radius))
-                else:
-                    vec = verts[0].co + Vector((0, self.radius, 0))
-                init_vec = distance_point_line(vec, verts[0].co, verts[1].co)
-                # These will be rotated about the origin so will need to be shifted:
-                verts_out = [
-                    (verts[i].co - (matrices[j] * init_vec)) for i in range(2) for j in range(numV)
-                    ]
-
-            # We should have the coordinates for a bunch of new verts
-            # Now add the verts and build the edges and then the faces
-
-            newVerts = []
-
-            if self.shaftType == 1:
-                # Vertices:
-                for i in range(numV * len(verts)):
-                    new = bVerts.new()
-                    new.co = verts_out[i]
-                    bVerts.ensure_lookup_table()
-                    new.select = True
-                    newVerts.append(new)
-                # Edges:
-                for i in range(numE):
-                    for j in range(len(verts)):
-                        e = bEdges.new((newVerts[i + (numV * j)], newVerts[i + (numV * j) + 1]))
-                        bEdges.ensure_lookup_table()
-                        e.select = True
-                for i in range(numV):
-                    for j in range(len(verts) - 1):
-                        e = bEdges.new((newVerts[i + (numV * j)], newVerts[i + (numV * (j + 1))]))
-                        bEdges.ensure_lookup_table()
-                        e.select = True
-
-                # Faces: There is a problem with this right now
-                """
-                for i in range(len(edges)):
-                    for j in range(numE):
-                        f = bFaces.new((newVerts[i], newVerts[i + 1],
-                                       newVerts[i + (numV * j) + 1], newVerts[i + (numV * j)]))
-                        f.normal_update()
-                """
-            else:
-                # Vertices:
-                for i in range(numV * 2):
-                    new = bVerts.new()
-                    new.co = verts_out[i]
-                    new.select = True
-                    bVerts.ensure_lookup_table()
-                    newVerts.append(new)
-                # Edges:
-                for i in range(numE):
-                    e = bEdges.new((newVerts[i], newVerts[i + 1]))
-                    e.select = True
-                    bEdges.ensure_lookup_table()
-                    e = bEdges.new((newVerts[i + numV], newVerts[i + numV + 1]))
-                    e.select = True
-                    bEdges.ensure_lookup_table()
-                for i in range(numV):
-                    e = bEdges.new((newVerts[i], newVerts[i + numV]))
-                    e.select = True
-                    bEdges.ensure_lookup_table()
-                # Faces:
-                for i in range(numE):
-                    f = bFaces.new((newVerts[i], newVerts[i + 1],
-                                    newVerts[i + numV + 1], newVerts[i + numV]))
-                    bFaces.ensure_lookup_table()
-                    f.normal_update()
-
-            bmesh.update_edit_mesh(me)
-
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_shaft", e,
-                           reports="Shaft Operator failed", func=False)
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-# "Slices" edges crossing a plane defined by a face
-
-class Slice(Operator):
-    bl_idname = "mesh.edgetools_slice"
-    bl_label = "Slice"
-    bl_description = "Cut edges at the plane defined by a selected face"
-    bl_options = {'REGISTER', 'UNDO'}
-
-    make_copy: BoolProperty(
-            name="Make Copy",
-            description="Make new vertices at intersection points instead of splitting the edge",
-            default=False
-            )
-    rip: BoolProperty(
-            name="Rip",
-            description="Split into two edges that DO NOT share an intersection vertex",
-            default=True
-            )
-    pos: BoolProperty(
-            name="Positive",
-            description="Remove the portion on the side of the face normal",
-            default=False
-            )
-    neg: BoolProperty(
-            name="Negative",
-            description="Remove the portion on the side opposite of the face normal",
-            default=False
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.prop(self, "make_copy")
-        if not self.make_copy:
-            layout.prop(self, "rip")
-            layout.label(text="Remove Side:")
-            layout.prop(self, "pos")
-            layout.prop(self, "neg")
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return(ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bVerts = bm.verts
-            bEdges = bm.edges
-            bFaces = bm.faces
-
-            face, normal = None, None
-
-            # Find the selected face. This will provide the plane to project onto:
-            #  - First check to use the active face. Allows users to just
-            #    select a bunch of faces with the last being the cutting plane
-            #  - If that fails, then use the first found selected face in the BMesh face list
-            if isinstance(bm.select_history.active, bmesh.types.BMFace):
-                face = bm.select_history.active
-                normal = bm.select_history.active.normal
-                bm.select_history.active.select = False
-            else:
-                for f in bFaces:
-                    if f.select:
-                        face = f
-                        normal = f.normal
-                        f.select = False
-                        break
-
-            # If we don't find a selected face exit:
-            if face is None:
-                flip_edit_mode()
-                self.report({'WARNING'},
-                            "Please select a face as the cutting plane. Operation Cancelled")
-                return {'CANCELLED'}
-
-            # Warn the user if they are using an n-gon might lead to some odd results
-            elif len(face.verts) > 4 and not is_face_planar(face):
-                self.report({'WARNING'},
-                            "Selected face is an N-gon.  Results may be unpredictable")
-
-            if ENABLE_DEBUG:
-                dbg = 0
-                print("Number of Edges: ", len(bEdges))
-
-            for e in bEdges:
-                if ENABLE_DEBUG:
-                    print("Looping through Edges - ", dbg)
-                    dbg = dbg + 1
-
-                # Get the end verts on the edge:
-                v1 = e.verts[0]
-                v2 = e.verts[1]
-
-                # Make sure that verts are not a part of the cutting plane:
-                if e.select and (v1 not in face.verts and v2 not in face.verts):
-                    if len(face.verts) < 5:  # Not an n-gon
-                        intersection = intersect_line_face(e, face, True)
-                    else:
-                        intersection = intersect_line_plane(v1.co, v2.co, face.verts[0].co, normal)
-
-                    if ENABLE_DEBUG:
-                        print("Intersection: ", intersection)
-
-                    # If an intersection exists find the distance of each of the end
-                    # points from the plane, with "positive" being in the direction
-                    # of the cutting plane's normal. If the points are on opposite
-                    # side of the plane, then it intersects and we need to cut it
-                    if intersection is not None:
-                        bVerts.ensure_lookup_table()
-                        bEdges.ensure_lookup_table()
-                        bFaces.ensure_lookup_table()
-
-                        d1 = distance_point_to_plane(v1.co, face.verts[0].co, normal)
-                        d2 = distance_point_to_plane(v2.co, face.verts[0].co, normal)
-                        # If they have different signs, then the edge crosses the cutting plane:
-                        if abs(d1 + d2) < abs(d1 - d2):
-                            # Make the first vertex the positive one:
-                            if d1 < d2:
-                                v2, v1 = v1, v2
-
-                            if self.make_copy:
-                                new = bVerts.new()
-                                new.co = intersection
-                                new.select = True
-                                bVerts.ensure_lookup_table()
-                            elif self.rip:
-                                if ENABLE_DEBUG:
-                                    print("Branch rip engaged")
-                                newV1 = bVerts.new()
-                                newV1.co = intersection
-                                bVerts.ensure_lookup_table()
-                                if ENABLE_DEBUG:
-                                    print("newV1 created", end='; ')
-
-                                newV2 = bVerts.new()
-                                newV2.co = intersection
-                                bVerts.ensure_lookup_table()
-
-                                if ENABLE_DEBUG:
-                                    print("newV2 created", end='; ')
-
-                                newE1 = bEdges.new((v1, newV1))
-                                newE2 = bEdges.new((v2, newV2))
-                                bEdges.ensure_lookup_table()
-
-                                if ENABLE_DEBUG:
-                                    print("new edges created", end='; ')
-
-                                if e.is_valid:
-                                    bEdges.remove(e)
-
-                                bEdges.ensure_lookup_table()
-
-                                if ENABLE_DEBUG:
-                                    print("Old edge removed.\nWe're done with this edge")
-                            else:
-                                new = list(bmesh.utils.edge_split(e, v1, 0.5))
-                                bEdges.ensure_lookup_table()
-                                new[1].co = intersection
-                                e.select = False
-                                new[0].select = False
-                                if self.pos:
-                                    bEdges.remove(new[0])
-                                if self.neg:
-                                    bEdges.remove(e)
-                                bEdges.ensure_lookup_table()
-
-            if ENABLE_DEBUG:
-                print("The Edge Loop has exited. Now to update the bmesh")
-                dbg = 0
-
-            bmesh.update_edit_mesh(me)
-
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_slice", e,
-                           reports="Slice Operator failed", func=False)
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-# This projects the selected edges onto the selected plane
-# and/or both points on the selected edge
-
-class Project(Operator):
-    bl_idname = "mesh.edgetools_project"
-    bl_label = "Project"
-    bl_description = ("Projects the selected Vertices/Edges onto a selected plane\n"
-                      "(Active is projected onto the rest)")
-    bl_options = {'REGISTER', 'UNDO'}
-
-    make_copy: BoolProperty(
-            name="Make Copy",
-            description="Make duplicates of the vertices instead of altering them",
-            default=False
-            )
-
-    def draw(self, context):
-        layout = self.layout
-        layout.prop(self, "make_copy")
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return (ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bFaces = bm.faces
-            bVerts = bm.verts
-
-            fVerts = []
-
-            # Find the selected face.  This will provide the plane to project onto:
-            # @todo Check first for an active face
-            for f in bFaces:
-                if f.select:
-                    for v in f.verts:
-                        fVerts.append(v)
-                    normal = f.normal
-                    f.select = False
-                    break
-
-            for v in bVerts:
-                if v.select:
-                    if v in fVerts:
-                        v.select = False
-                        continue
-                    d = distance_point_to_plane(v.co, fVerts[0].co, normal)
-                    if self.make_copy:
-                        temp = v
-                        v = bVerts.new()
-                        v.co = temp.co
-                        bVerts.ensure_lookup_table()
-                    vector = normal
-                    vector.length = abs(d)
-                    v.co = v.co - (vector * sign(d))
-                    v.select = False
-
-            bmesh.update_edit_mesh(me)
-
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_project", e,
-                           reports="Project Operator failed", func=False)
-
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-# Project_End is for projecting/extending an edge to meet a plane
-# This is used be selecting a face to define the plane then all the edges
-# Then move the vertices in the edge that is closest to the
-# plane to the coordinates of the intersection of the edge and the plane
-
-class Project_End(Operator):
-    bl_idname = "mesh.edgetools_project_end"
-    bl_label = "Project (End Point)"
-    bl_description = ("Projects the vertices of the selected\n"
-                      "edges closest to a plane onto that plane")
-    bl_options = {'REGISTER', 'UNDO'}
-
-    make_copy: BoolProperty(
-            name="Make Copy",
-            description="Make a duplicate of the vertice instead of moving it",
-            default=False
-            )
-    keep_length: BoolProperty(
-            name="Keep Edge Length",
-            description="Maintain edge lengths",
-            default=False
-            )
-    use_force: BoolProperty(
-            name="Use opposite vertices",
-            description="Force the usage of the vertices at the other end of the edge",
-            default=False
-            )
-    use_normal: BoolProperty(
-            name="Project along normal",
-            description="Use the plane's normal as the projection direction",
-            default=False
-            )
-
-    def draw(self, context):
-        layout = self.layout
-
-        if not self.keep_length:
-            layout.prop(self, "use_normal")
-        layout.prop(self, "make_copy")
-        layout.prop(self, "use_force")
-
-    @classmethod
-    def poll(cls, context):
-        ob = context.active_object
-        return(ob and ob.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def invoke(self, context, event):
-        return self.execute(context)
-
-    def execute(self, context):
-        try:
-            me = context.object.data
-            bm = bmesh.from_edit_mesh(me)
-            bm.normal_update()
-
-            bFaces = bm.faces
-            bEdges = bm.edges
-            bVerts = bm.verts
-
-            fVerts = []
-
-            # Find the selected face. This will provide the plane to project onto:
-            for f in bFaces:
-                if f.select:
-                    for v in f.verts:
-                        fVerts.append(v)
-                    normal = f.normal
-                    f.select = False
-                    break
-
-            for e in bEdges:
-                if e.select:
-                    v1 = e.verts[0]
-                    v2 = e.verts[1]
-                    if v1 in fVerts or v2 in fVerts:
-                        e.select = False
-                        continue
-                    intersection = intersect_line_plane(v1.co, v2.co, fVerts[0].co, normal)
-                    if intersection is not None:
-                        # Use abs because we don't care what side of plane we're on:
-                        d1 = distance_point_to_plane(v1.co, fVerts[0].co, normal)
-                        d2 = distance_point_to_plane(v2.co, fVerts[0].co, normal)
-                        # If d1 is closer than we use v1 as our vertice:
-                        # "xor" with 'use_force':
-                        if (abs(d1) < abs(d2)) is not self.use_force:
-                            if self.make_copy:
-                                v1 = bVerts.new()
-                                v1.co = e.verts[0].co
-                                bVerts.ensure_lookup_table()
-                                bEdges.ensure_lookup_table()
-                            if self.keep_length:
-                                v1.co = intersection
-                            elif self.use_normal:
-                                vector = normal
-                                vector.length = abs(d1)
-                                v1.co = v1.co - (vector * sign(d1))
-                            else:
-                                v1.co = intersection
-                        else:
-                            if self.make_copy:
-                                v2 = bVerts.new()
-                                v2.co = e.verts[1].co
-                                bVerts.ensure_lookup_table()
-                                bEdges.ensure_lookup_table()
-                            if self.keep_length:
-                                v2.co = intersection
-                            elif self.use_normal:
-                                vector = normal
-                                vector.length = abs(d2)
-                                v2.co = v2.co - (vector * sign(d2))
-                            else:
-                                v2.co = intersection
-                    e.select = False
-
-            bmesh.update_edit_mesh(me)
-
-        except Exception as e:
-            error_handlers(self, "mesh.edgetools_project_end", e,
-                           reports="Project (End Point) Operator failed", func=False)
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-class VIEW3D_MT_edit_mesh_edgetools(Menu):
-    bl_label = "Edge Tools"
-    bl_description = "Various tools for manipulating edges"
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.operator("mesh.edgetools_extend")
-        layout.operator("mesh.edgetools_spline")
-        layout.operator("mesh.edgetools_ortho")
-        layout.operator("mesh.edgetools_shaft")
-        layout.operator("mesh.edgetools_slice")
-        layout.separator()
-
-        layout.operator("mesh.edgetools_project")
-        layout.operator("mesh.edgetools_project_end")
-
-
-# define classes for registration
-classes = (
-    VIEW3D_MT_edit_mesh_edgetools,
-    Extend,
-    Spline,
-    Ortho,
-    Shaft,
-    Slice,
-    Project,
-    Project_End,
-    )
-
-
-# registering and menu integration
-def register():
-    for cls in classes:
-        bpy.utils.register_class(cls)
-
-
-# unregistering and removing menus
-def unregister():
-    for cls in classes:
-        bpy.utils.unregister_class(cls)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_extrude_and_reshape.py b/mesh_extra_tools/mesh_extrude_and_reshape.py
deleted file mode 100644 (file)
index ec7b969..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-# ##### 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 3
-#  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, see <http://www.gnu.org/licenses/>.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# Contact for more information about the Addon:
-# Email:    germano.costa@ig.com.br
-# Twitter:  wii_mano @mano_wii
-
-bl_info = {
-    "name": "Extrude and Reshape",
-    "author": "Germano Cavalcante",
-    "version": (0, 8, 1),
-    "blender": (2, 76, 5),
-    "location": "View3D > TOOLS > Tools > Mesh Tools > Add: > Extrude Menu (Alt + E)",
-    "description": "Extrude face and merge edge intersections "
-                   "between the mesh and the new edges",
-    "wiki_url": "http://blenderartists.org/forum/"
-                "showthread.php?376618-Addon-Push-Pull-Face",
-    "category": "Mesh"}
-
-import bpy
-import bmesh
-from mathutils.geometry import intersect_line_line
-from bpy.types import Operator
-
-
-class BVHco():
-    i = 0
-    c1x = 0.0
-    c1y = 0.0
-    c1z = 0.0
-    c2x = 0.0
-    c2y = 0.0
-    c2z = 0.0
-
-
-def edges_BVH_overlap(bm, edges, epsilon=0.0001):
-    bco = set()
-    for e in edges:
-        bvh = BVHco()
-        bvh.i = e.index
-        b1 = e.verts[0]
-        b2 = e.verts[1]
-        co1 = b1.co.x
-        co2 = b2.co.x
-        if co1 <= co2:
-            bvh.c1x = co1 - epsilon
-            bvh.c2x = co2 + epsilon
-        else:
-            bvh.c1x = co2 - epsilon
-            bvh.c2x = co1 + epsilon
-        co1 = b1.co.y
-        co2 = b2.co.y
-        if co1 <= co2:
-            bvh.c1y = co1 - epsilon
-            bvh.c2y = co2 + epsilon
-        else:
-            bvh.c1y = co2 - epsilon
-            bvh.c2y = co1 + epsilon
-        co1 = b1.co.z
-        co2 = b2.co.z
-        if co1 <= co2:
-            bvh.c1z = co1 - epsilon
-            bvh.c2z = co2 + epsilon
-        else:
-            bvh.c1z = co2 - epsilon
-            bvh.c2z = co1 + epsilon
-        bco.add(bvh)
-    del edges
-    overlap = {}
-    oget = overlap.get
-    for e1 in bm.edges:
-        by = bz = True
-        a1 = e1.verts[0]
-        a2 = e1.verts[1]
-        c1x = a1.co.x
-        c2x = a2.co.x
-        if c1x > c2x:
-            tm = c1x
-            c1x = c2x
-            c2x = tm
-        for bvh in bco:
-            if c1x <= bvh.c2x and c2x >= bvh.c1x:
-                if by:
-                    by = False
-                    c1y = a1.co.y
-                    c2y = a2.co.y
-                    if c1y > c2y:
-                        tm = c1y
-                        c1y = c2y
-                        c2y = tm
-                if c1y <= bvh.c2y and c2y >= bvh.c1y:
-                    if bz:
-                        bz = False
-                        c1z = a1.co.z
-                        c2z = a2.co.z
-                        if c1z > c2z:
-                            tm = c1z
-                            c1z = c2z
-                            c2z = tm
-                    if c1z <= bvh.c2z and c2z >= bvh.c1z:
-                        e2 = bm.edges[bvh.i]
-                        if e1 != e2:
-                            overlap[e1] = oget(e1, set()).union({e2})
-    return overlap
-
-
-def intersect_edges_edges(overlap, precision=4):
-    epsilon = .1**precision
-    fpre_min = -epsilon
-    fpre_max = 1 + epsilon
-    splits = {}
-    sp_get = splits.get
-    new_edges1 = set()
-    new_edges2 = set()
-    targetmap = {}
-    for edg1 in overlap:
-        # print("***", ed1.index, "***")
-        for edg2 in overlap[edg1]:
-            a1 = edg1.verts[0]
-            a2 = edg1.verts[1]
-            b1 = edg2.verts[0]
-            b2 = edg2.verts[1]
-
-            # test if are linked
-            if a1 in {b1, b2} or a2 in {b1, b2}:
-                # print('linked')
-                continue
-
-            aco1, aco2 = a1.co, a2.co
-            bco1, bco2 = b1.co, b2.co
-            tp = intersect_line_line(aco1, aco2, bco1, bco2)
-            if tp:
-                p1, p2 = tp
-                if (p1 - p2).to_tuple(precision) == (0, 0, 0):
-                    v = aco2 - aco1
-                    f = p1 - aco1
-                    x, y, z = abs(v.x), abs(v.y), abs(v.z)
-                    max1 = 0 if x >= y and x >= z else\
-                           1 if y >= x and y >= z else 2
-                    fac1 = f[max1] / v[max1]
-
-                    v = bco2 - bco1
-                    f = p2 - bco1
-                    x, y, z = abs(v.x), abs(v.y), abs(v.z)
-                    max2 = 0 if x >= y and x >= z else\
-                           1 if y >= x and y >= z else 2
-                    fac2 = f[max2] / v[max2]
-
-                    if fpre_min <= fac1 <= fpre_max:
-                        # print(edg1.index, 'can intersect', edg2.index)
-                        ed1 = edg1
-
-                    elif edg1 in splits:
-                        for ed1 in splits[edg1]:
-                            a1 = ed1.verts[0]
-                            a2 = ed1.verts[1]
-
-                            vco1 = a1.co
-                            vco2 = a2.co
-
-                            v = vco2 - vco1
-                            f = p1 - vco1
-                            fac1 = f[max1] / v[max1]
-                            if fpre_min <= fac1 <= fpre_max:
-                                # print(e.index, 'can intersect', edg2.index)
-                                break
-                        else:
-                            # print(edg1.index, 'really does not intersect', edg2.index)
-                            continue
-                    else:
-                        # print(edg1.index, 'not intersect', edg2.index)
-                        continue
-
-                    if fpre_min <= fac2 <= fpre_max:
-                        # print(ed1.index, 'actually intersect', edg2.index)
-                        ed2 = edg2
-
-                    elif edg2 in splits:
-                        for ed2 in splits[edg2]:
-                            b1 = ed2.verts[0]
-                            b2 = ed2.verts[1]
-
-                            vco1 = b1.co
-                            vco2 = b2.co
-
-                            v = vco2 - vco1
-                            f = p2 - vco1
-                            fac2 = f[max2] / v[max2]
-                            if fpre_min <= fac2 <= fpre_max:
-                                # print(ed1.index, 'actually intersect', e.index)
-                                break
-                        else:
-                            # print(ed1.index, 'really does not intersect', ed2.index)
-                            continue
-                    else:
-                        # print(ed1.index, 'not intersect', edg2.index)
-                        continue
-
-                    new_edges1.add(ed1)
-                    new_edges2.add(ed2)
-
-                    if abs(fac1) <= epsilon:
-                        nv1 = a1
-                    elif fac1 + epsilon >= 1:
-                        nv1 = a2
-                    else:
-                        ne1, nv1 = bmesh.utils.edge_split(ed1, a1, fac1)
-                        new_edges1.add(ne1)
-                        splits[edg1] = sp_get(edg1, set()).union({ne1})
-
-                    if abs(fac2) <= epsilon:
-                        nv2 = b1
-                    elif fac2 + epsilon >= 1:
-                        nv2 = b2
-                    else:
-                        ne2, nv2 = bmesh.utils.edge_split(ed2, b1, fac2)
-                        new_edges2.add(ne2)
-                        splits[edg2] = sp_get(edg2, set()).union({ne2})
-
-                    if nv1 != nv2:  # necessary?
-                        targetmap[nv1] = nv2
-
-    return new_edges1, new_edges2, targetmap
-
-
-class Extrude_and_Reshape(Operator):
-    bl_idname = "mesh.extrude_reshape"
-    bl_label = "Extrude and Reshape"
-    bl_description = "Push and pull face entities to sculpt 3d models"
-    bl_options = {'REGISTER', 'GRAB_CURSOR', 'BLOCKING'}
-
-    @classmethod
-    def poll(cls, context):
-        return context.mode != 'EDIT_MESH'
-
-    def modal(self, context, event):
-        if self.confirm:
-            sface = self.bm.faces.active
-            if not sface:
-                for face in self.bm.faces:
-                    if face.select is True:
-                        sface = face
-                        break
-                else:
-                    return {'FINISHED'}
-            # edges to intersect
-            edges = set()
-            [[edges.add(ed) for ed in v.link_edges] for v in sface.verts]
-
-            overlap = edges_BVH_overlap(self.bm, edges, epsilon=0.0001)
-            overlap = {k: v for k, v in overlap.items() if k not in edges}  # remove repetition
-            """
-            print([e.index for e in edges])
-            for a, b in overlap.items():
-                print(a.index, [e.index for e in b])
-            """
-            new_edges1, new_edges2, targetmap = intersect_edges_edges(overlap)
-            pos_weld = set()
-            for e in new_edges1:
-                v1, v2 = e.verts
-                if v1 in targetmap and v2 in targetmap:
-                    pos_weld.add((targetmap[v1], targetmap[v2]))
-            if targetmap:
-                bmesh.ops.weld_verts(self.bm, targetmap=targetmap)
-            """
-            print([e.is_valid for e in new_edges1])
-            print([e.is_valid for e in new_edges2])
-            sp_faces1 = set()
-            """
-            for e in pos_weld:
-                v1, v2 = e
-                lf1 = set(v1.link_faces)
-                lf2 = set(v2.link_faces)
-                rlfe = lf1.intersection(lf2)
-                for f in rlfe:
-                    try:
-                        nf = bmesh.utils.face_split(f, v1, v2)
-                        # sp_faces1.update({f, nf[0]})
-                    except:
-                        pass
-
-            # sp_faces2 = set()
-            for e in new_edges2:
-                lfe = set(e.link_faces)
-                v1, v2 = e.verts
-                lf1 = set(v1.link_faces)
-                lf2 = set(v2.link_faces)
-                rlfe = lf1.intersection(lf2)
-                for f in rlfe.difference(lfe):
-                    nf = bmesh.utils.face_split(f, v1, v2)
-                    # sp_faces2.update({f, nf[0]})
-
-            bmesh.update_edit_mesh(self.mesh, loop_triangles=True, destructive=True)
-            return {'FINISHED'}
-        if self.cancel:
-            return {'FINISHED'}
-        self.cancel = event.type in {'ESC', 'NDOF_BUTTON_ESC'}
-        self.confirm = event.type in {'LEFTMOUSE', 'RET', 'NUMPAD_ENTER'}
-        return {'PASS_THROUGH'}
-
-    def execute(self, context):
-        self.mesh = context.object.data
-        self.bm = bmesh.from_edit_mesh(self.mesh)
-        try:
-            selection = self.bm.select_history[-1]
-        except:
-            for face in self.bm.faces:
-                if face.select is True:
-                    selection = face
-                    break
-            else:
-                return {'FINISHED'}
-        if not isinstance(selection, bmesh.types.BMFace):
-            bpy.ops.mesh.extrude_region_move('INVOKE_DEFAULT')
-            return {'FINISHED'}
-        else:
-            face = selection
-            # face.select = False
-            bpy.ops.mesh.select_all(action='DESELECT')
-            geom = []
-            for edge in face.edges:
-                if abs(edge.calc_face_angle(0) - 1.5707963267948966) < 0.01:  # self.angle_tolerance:
-                    geom.append(edge)
-
-            ret_dict = bmesh.ops.extrude_discrete_faces(self.bm, faces=[face])
-
-            for face in ret_dict['faces']:
-                self.bm.faces.active = face
-                face.select = True
-                sface = face
-            dfaces = bmesh.ops.dissolve_edges(
-                        self.bm, edges=geom, use_verts=True, use_face_split=False
-                        )
-            bmesh.update_edit_mesh(self.mesh, loop_triangles=True, destructive=True)
-            bpy.ops.transform.translate(
-                        'INVOKE_DEFAULT', constraint_axis=(False, False, True),
-                        orient_type='NORMAL', release_confirm=True
-                        )
-
-        context.window_manager.modal_handler_add(self)
-
-        self.cancel = False
-        self.confirm = False
-        return {'RUNNING_MODAL'}
-
-
-def operator_draw(self, context):
-    layout = self.layout
-    col = layout.column(align=True)
-    col.operator("mesh.extrude_reshape", text="Extrude and Reshape")
-
-
-def register():
-    bpy.utils.register_class(Extrude_and_Reshape)
-    bpy.types.VIEW3D_MT_edit_mesh_extrude.append(operator_draw)
-
-
-def unregister():
-    bpy.types.VIEW3D_MT_edit_mesh_extrude.remove(operator_draw)
-    bpy.utils.unregister_class(Extrude_and_Reshape)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_fastloop.py b/mesh_extra_tools/mesh_fastloop.py
deleted file mode 100644 (file)
index b52a350..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-# ##### 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": "Fast Loop",
-    "description": "Add loops fast",
-    "author": "Andy Davies (metalliandy)",
-    "version": (0, 1, 7),
-    "blender": (2, 56, 0),
-    "location": "Tool Shelf",
-    "warning": "",
-    "wiki_url": "",
-    "category": "Mesh"
-    }
-
-"""
-About this script:-
-This script enables the fast creation of multiple loops on a mesh
-
-Usage:-
-1)Click the FastLoop button on the Tool Shelf to activate the tool
-2)Hover over the mesh in the general area where you would like a loop to be added
-  (shown by a highlight on the mesh)
-3)Click once to confirm the loop placement
-4)place the loop and then slide to fine tune its position
-5)Repeat 1-4 if needed
-6)Press Esc. twice to exit the tool
-
-Related Links:-
-http://blenderartists.org/forum/showthread.php?t=206989
-http://www.metalliandy.com
-
-Thanks to:-
-Bartius Crouch (Crouch) - http://sites.google.com/site/bartiuscrouch/
-Dealga McArdle (zeffii) - http://www.digitalaphasia.com
-
-Version history:-
-v0.16 - Amended script for compatibility with recent API changes
-v0.15 - Amended script meta information and button rendering code for
-        compatibility with recent API changes
-v0.14 - Modal operator
-v0.13 - Initial revision
-"""
-
-import bpy
-from bpy.types import Operator
-from bpy.props import BoolProperty
-
-
-class OBJECT_OT_FastLoop(Operator):
-    bl_idname = "object_ot.fastloop"
-    bl_label = "FastLoop"
-    bl_description = ("Create multiple edge loops in succession\n"
-                      "Runs modal until ESC is pressed twice")
-
-    active: BoolProperty(
-                name="active",
-                default=False
-                )
-
-    @classmethod
-    def poll(cls, context):
-        return bpy.ops.mesh.loopcut_slide.poll()
-
-    def modal(self, context, event):
-        if event.type == 'ESC':
-            context.area.header_text_set(None)
-            return {'CANCELLED'}
-
-        elif event.type == 'LEFTMOUSE' and event.value == 'RELEASE':
-            self.active = False
-
-        if not self.active:
-            self.active = True
-            bpy.ops.mesh.loopcut_slide('INVOKE_DEFAULT')
-            context.area.header_text_set("Press ESC twice to stop FastLoop")
-
-        return {'RUNNING_MODAL'}
-
-    def invoke(self, context, event):
-        context.window_manager.modal_handler_add(self)
-
-        return {'RUNNING_MODAL'}
-
-
-def register():
-    bpy.utils.register_module(__name__)
-    pass
-
-
-def unregister():
-    bpy.utils.unregister_module(__name__)
-    pass
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_filletplus.py b/mesh_extra_tools/mesh_filletplus.py
deleted file mode 100644 (file)
index a54eba7..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ##### END 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": "FilletPlus",
-    "author": "Gert De Roost - original by zmj100",
-    "version": (0, 4, 3),
-    "blender": (2, 61, 0),
-    "location": "View3D > Tool Shelf",
-    "description": "",
-    "warning": "",
-    "wiki_url": "",
-    "category": "Mesh"}
-
-
-import bpy
-from bpy.props import (
-        FloatProperty,
-        IntProperty,
-        BoolProperty,
-        )
-from bpy.types import Operator
-import bmesh
-from mathutils import Matrix
-from math import (
-        cos, pi, sin,
-        degrees, tan,
-        )
-
-
-def list_clear_(l):
-    if l:
-        del l[:]
-    return l
-
-
-def get_adj_v_(list_):
-    tmp = {}
-    for i in list_:
-        try:
-            tmp[i[0]].append(i[1])
-        except KeyError:
-            tmp[i[0]] = [i[1]]
-        try:
-            tmp[i[1]].append(i[0])
-        except KeyError:
-            tmp[i[1]] = [i[0]]
-    return tmp
-
-
-class f_buf():
-    # one of the angles was not 0 or 180
-    check = False
-
-
-def fillets(list_0, startv, vertlist, face, adj, n, out, flip, radius):
-    try:
-        dict_0 = get_adj_v_(list_0)
-        list_1 = [[dict_0[i][0], i, dict_0[i][1]] for i in dict_0 if (len(dict_0[i]) == 2)][0]
-        list_3 = []
-        for elem in list_1:
-            list_3.append(bm.verts[elem])
-        list_2 = []
-
-        p_ = list_3[1]
-        p = (list_3[1].co).copy()
-        p1 = (list_3[0].co).copy()
-        p2 = (list_3[2].co).copy()
-
-        vec1 = p - p1
-        vec2 = p - p2
-
-        ang = vec1.angle(vec2, any)
-        check_angle = round(degrees(ang))
-
-        if check_angle == 180 or check_angle == 0.0:
-            return False
-        else:
-            f_buf.check = True
-
-        opp = adj
-
-        if radius is False:
-            h = adj * (1 / cos(ang * 0.5))
-            adj_ = adj
-        elif radius is True:
-            h = opp / sin(ang * 0.5)
-            adj_ = opp / tan(ang * 0.5)
-
-        p3 = p - (vec1.normalized() * adj_)
-        p4 = p - (vec2.normalized() * adj_)
-        rp = p - ((p - ((p3 + p4) * 0.5)).normalized() * h)
-
-        vec3 = rp - p3
-        vec4 = rp - p4
-
-        axis = vec1.cross(vec2)
-
-        if out is False:
-            if flip is False:
-                rot_ang = vec3.angle(vec4)
-            elif flip is True:
-                rot_ang = vec1.angle(vec2)
-        elif out is True:
-            rot_ang = (2 * pi) - vec1.angle(vec2)
-
-        for j in range(n + 1):
-            new_angle = rot_ang * j / n
-            mtrx = Matrix.Rotation(new_angle, 3, axis)
-            if out is False:
-                if flip is False:
-                    tmp = p4 - rp
-                    tmp1 = mtrx * tmp
-                    tmp2 = tmp1 + rp
-                elif flip is True:
-                    p3 = p - (vec1.normalized() * opp)
-                    tmp = p3 - p
-                    tmp1 = mtrx * tmp
-                    tmp2 = tmp1 + p
-            elif out is True:
-                p4 = p - (vec2.normalized() * opp)
-                tmp = p4 - p
-                tmp1 = mtrx * tmp
-                tmp2 = tmp1 + p
-
-            v = bm.verts.new(tmp2)
-            list_2.append(v)
-
-        if flip is True:
-            list_3[1:2] = list_2
-        else:
-            list_2.reverse()
-            list_3[1:2] = list_2
-
-        list_clear_(list_2)
-
-        n1 = len(list_3)
-
-        for t in range(n1 - 1):
-            bm.edges.new([list_3[t], list_3[(t + 1) % n1]])
-
-            v = bm.verts.new(p)
-            bm.edges.new([v, p_])
-
-        bm.edges.ensure_lookup_table()
-
-        if face is not None:
-            for l in face.loops:
-                if l.vert == list_3[0]:
-                    startl = l
-                    break
-            vertlist2 = []
-
-            if startl.link_loop_next.vert == startv:
-                l = startl.link_loop_prev
-                while len(vertlist) > 0:
-                    vertlist2.insert(0, l.vert)
-                    vertlist.pop(vertlist.index(l.vert))
-                    l = l.link_loop_prev
-            else:
-                l = startl.link_loop_next
-                while len(vertlist) > 0:
-                    vertlist2.insert(0, l.vert)
-                    vertlist.pop(vertlist.index(l.vert))
-                    l = l.link_loop_next
-
-            for v in list_3:
-                vertlist2.append(v)
-            bm.faces.new(vertlist2)
-        if startv.is_valid:
-            bm.verts.remove(startv)
-        else:
-            print("\n[Function fillets Error]\n"
-                  "Starting vertex (startv var) couldn't be removed\n")
-            return False
-        bm.verts.ensure_lookup_table()
-        bm.edges.ensure_lookup_table()
-        bm.faces.ensure_lookup_table()
-        list_3[1].select = 1
-        list_3[-2].select = 1
-        bm.edges.get([list_3[0], list_3[1]]).select = 1
-        bm.edges.get([list_3[-1], list_3[-2]]).select = 1
-        bm.verts.index_update()
-        bm.edges.index_update()
-        bm.faces.index_update()
-
-        me.update(calc_edges=True, calc_loop_triangles=True)
-        bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
-
-    except Exception as e:
-        print("\n[Function fillets Error]\n{}\n".format(e))
-        return False
-
-
-def do_filletplus(self, pair):
-    is_finished = True
-    try:
-        startv = None
-        global inaction
-        global flip
-        list_0 = [list([e.verts[0].index, e.verts[1].index]) for e in pair]
-
-        vertset = set([])
-        bm.verts.ensure_lookup_table()
-        bm.edges.ensure_lookup_table()
-        bm.faces.ensure_lookup_table()
-        vertset.add(bm.verts[list_0[0][0]])
-        vertset.add(bm.verts[list_0[0][1]])
-        vertset.add(bm.verts[list_0[1][0]])
-        vertset.add(bm.verts[list_0[1][1]])
-
-        v1, v2, v3 = vertset
-
-        if len(list_0) != 2:
-            self.report({'WARNING'}, "Two adjacent edges must be selected")
-            is_finished = False
-        else:
-            inaction = 1
-            vertlist = []
-            found = 0
-            for f in v1.link_faces:
-                if v2 in f.verts and v3 in f.verts:
-                    found = 1
-            if not found:
-                for v in [v1, v2, v3]:
-                    if v.index in list_0[0] and v.index in list_0[1]:
-                        startv = v
-                face = None
-            else:
-                for f in v1.link_faces:
-                    if v2 in f.verts and v3 in f.verts:
-                        for v in f.verts:
-                            if not(v in vertset):
-                                vertlist.append(v)
-                            if (v in vertset and v.link_loops[0].link_loop_prev.vert in vertset and
-                               v.link_loops[0].link_loop_next.vert in vertset):
-                                startv = v
-                        face = f
-            if out is True:
-                flip = False
-            if startv:
-                fills = fillets(list_0, startv, vertlist, face, adj, n, out, flip, radius)
-                if not fills:
-                    is_finished = False
-            else:
-                is_finished = False
-    except Exception as e:
-        print("\n[Function do_filletplus Error]\n{}\n".format(e))
-        is_finished = False
-    return is_finished
-
-
-def check_is_not_coplanar(bm_data):
-    from mathutils import Vector
-    check = False
-    angles, norm_angle = 0, 0
-    z_vec = Vector((0, 0, 1))
-    try:
-        bm_data.faces.ensure_lookup_table()
-
-        for f in bm_data.faces:
-            norm_angle = f.normal.angle(z_vec)
-            if angles == 0:
-                angles = norm_angle
-            if angles != norm_angle:
-                check = True
-                break
-    except Exception as e:
-        print("\n[Function check_is_not_coplanar Error]\n{}\n".format(e))
-        check = True
-    return check
-
-
-#  Operator
-
-class MESH_OT_fillet_plus(Operator):
-    bl_idname = "mesh.fillet_plus"
-    bl_label = "Fillet Plus"
-    bl_description = ("Fillet adjoining edges\n"
-                      "Note: Works on a mesh whose all faces share the same normal")
-    bl_options = {"REGISTER", "UNDO"}
-
-    adj: FloatProperty(
-            name="",
-            description="Size of the filleted corners",
-            default=0.1,
-            min=0.00001, max=100.0,
-            step=1,
-            precision=3
-            )
-    n: IntProperty(
-            name="",
-            description="Subdivision of the filleted corners",
-            default=3,
-            min=1, max=50,
-            step=1
-            )
-    out: BoolProperty(
-            name="Outside",
-            description="Fillet towards outside",
-            default=False
-            )
-    flip: BoolProperty(
-            name="Flip",
-            description="Flip the direction of the Fillet\n"
-                        "Only available if Outside option is not active",
-            default=False
-            )
-    radius: BoolProperty(
-            name="Radius",
-            description="Use radius for the size of the filleted corners",
-            default=False
-            )
-
-    @classmethod
-    def poll(cls, context):
-        obj = context.active_object
-        return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
-
-    def draw(self, context):
-        layout = self.layout
-
-        if f_buf.check is False:
-            layout.label(text="Angle is equal to 0 or 180", icon="INFO")
-            layout.label(text="Can not fillet", icon="BLANK1")
-        else:
-            layout.prop(self, "radius")
-            if self.radius is True:
-                layout.label(text="Radius:")
-            elif self.radius is False:
-                layout.label(text="Distance:")
-            layout.prop(self, "adj")
-            layout.label(text="Number of sides:")
-            layout.prop(self, "n")
-
-            if self.n > 1:
-                row = layout.row(align=False)
-                row.prop(self, "out")
-                if self.out is False:
-                    row.prop(self, "flip")
-
-    def execute(self, context):
-        global inaction
-        global bm, me, adj, n, out, flip, radius
-
-        adj = self.adj
-        n = self.n
-        out = self.out
-        flip = self.flip
-        radius = self.radius
-
-        inaction = 0
-        f_buf.check = False
-
-        ob_act = context.active_object
-        try:
-            me = ob_act.data
-            bm = bmesh.from_edit_mesh(me)
-            warn_obj = bool(check_is_not_coplanar(bm))
-            if warn_obj is False:
-                tempset = set([])
-                bm.verts.ensure_lookup_table()
-                bm.edges.ensure_lookup_table()
-                bm.faces.ensure_lookup_table()
-                for v in bm.verts:
-                    if v.select and v.is_boundary:
-                        tempset.add(v)
-                for v in tempset:
-                    edgeset = set([])
-                    for e in v.link_edges:
-                        if e.select and e.is_boundary:
-                            edgeset.add(e)
-                        if len(edgeset) == 2:
-                            is_finished = do_filletplus(self, edgeset)
-                            if not is_finished:
-                                break
-
-                if inaction == 1:
-                    bpy.ops.mesh.select_all(action="DESELECT")
-                    for v in bm.verts:
-                        if len(v.link_edges) == 0:
-                            bm.verts.remove(v)
-                    bpy.ops.object.editmode_toggle()
-                    bpy.ops.object.editmode_toggle()
-                else:
-                    self.report({'WARNING'}, "Filletplus operation could not be performed")
-                    return {'CANCELLED'}
-            else:
-                self.report({'WARNING'}, "Mesh is not a coplanar surface. Operation cancelled")
-                return {'CANCELLED'}
-        except:
-            self.report({'WARNING'}, "Filletplus operation could not be performed")
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
diff --git a/mesh_extra_tools/mesh_help.py b/mesh_extra_tools/mesh_help.py
deleted file mode 100644 (file)
index 30047a8..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-# gpl authors: lijenstina, meta-androcto
-
-# Note:  this script contains the Help Operator used by the various functions
-# Usage: add a key string to the dictionary in this file with the list of strings to pass to labels
-#        and call the operator from the add-on UI draw function by passing the help_ids parameter
-#        If the size of the pop-up if needed, define popup_size in the call by using variables
-#        Example (with using the variable props):
-#        props = layout.row("mesh.extra_tools_help")
-#        props.help_ids = "default"
-#        props.popup_size = 400
-
-
-import bpy
-from bpy.types import Operator
-from bpy.props import (
-        StringProperty,
-        IntProperty,
-        )
-
-
-class MESH_OT_extra_tools_help(Operator):
-    bl_idname = "mesh.extra_tools_help"
-    bl_label = ""
-    bl_description = "Tool Help - click to read some basic information"
-    bl_options = {'REGISTER'}
-
-    help_ids: StringProperty(
-            name="ID of the Operator to display",
-            options={'HIDDEN'},
-            default="default"
-            )
-    popup_size: IntProperty(
-            name="Size of the Help Pop-up Menu",
-            default=350,
-            min=100,
-            max=600,
-            )
-
-    def draw(self, context):
-        layout = self.layout
-        pick_help = help_custom_draw(self.help_ids)
-
-        for line_text in pick_help:
-            layout.label(line_text)
-
-    def execute(self, context):
-        return {'FINISHED'}
-
-    def invoke(self, context, event):
-        return context.window_manager.invoke_popup(self, width=self.popup_size)
-
-
-def help_custom_draw(identifier="default"):
-    # A table of lists containing the help text under an index key that is the script name
-    # If several returns are needed per file, add some suffix after the script name
-    # and call them separately
-    # In case nothing is passed from the UI call, the returned list is default
-    # If undefined one is passed, it will return a warning message
-    help_text = {
-        "default": [
-                "This is a placeholder text",
-                "Please fill up the entries in the " + __name__ + " script",
-                ],
-        "random_vertices": [
-                "To use:",
-                "Make a selection or selection of Vertices",
-                "Randomize displaced positions",
-                "Note:",
-                "There is an option to use Vertex Weights for displacement",
-                "Prior to use, don't forget to assign after updating the Group Weight",
-                ],
-        "mesh_vertex_chamfer": [
-                "To use:",
-                "Make a selection or selection of vertices",
-                "Result is a triangle Chamfer, works on a single vertex",
-                "Note:",
-                "The difference to the vertex Bevel is that original geometry",
-                "(selected vertices) can optionally be kept and displaced",
-                "Limitation:",
-                "In some cases, may need to press F to fill the result",
-                ],
-        "mesh_filletplus": [
-                "To use:",
-                "Select two adjacent edges and press Fillet button",
-                "Limitation:",
-                "Works on a mesh with all faces sharing the same normal",
-                "(Flat Surface - faces have the same direction)",
-                "Planes with already round corners can produce unsatisfactory results",
-                "Only boundary edges will be evaluated",
-                ],
-        "mesh_offset_edges": [
-                "To use:",
-                "Make a selection or selection of Edges",
-                "Extrude, rotate extrusions and more",
-                "Limitation:",
-                "Operates only on separate Edge loops selections",
-                "(i.e. Edge loops that are not connected by a selected edge)",
-                ],
-        "mesh_edge_roundifier": [
-                "To use:",
-                "Select a single or multiple Edges",
-                "Make Arcs with various parameters",
-                "Reference, Rotation, Scaling, Connection and Offset",
-                "Note:",
-                "The Mode - Reset button restores the default values",
-                ],
-        "mesh_edges_length": [
-                "To use:",
-                "Select a single or multiple Edges",
-                "Change length with various parameters",
-                "Limitation:",
-                "Does not operate on edges that share a vertex",
-                "If the selection wasn't done in Edge Selection mode,",
-                "the option Active will not work (due to Blender's limitation)",
-                ],
-        "mesh_edges_floor_plan": [
-                "To use:",
-                "Starting edges will be flat extruded forming faces strips",
-                "on the inside. Similar to using Face fill inset select outer",
-                "Methods:",
-                "Edge Net: Fills the edge grid with faces then Inset",
-                "Single Face: Single Face fill (all Edges) then Inset",
-                "Solidify: Extrude along defined axis, apply a Solidify modifier",
-                "Note:",
-                "Grid Fill and Single Face sometimes need tweaking with the options",
-                "Limitation:",
-                "Depending on the input geometry, Keep Ngons sometimes needs to be",
-                "enabled to produce any results",
-                "Edge Net and Single Face depend on bmesh face fill and inset",
-                "that sometimes can fail to produce good results",
-                "Avoid using Single Face Method on Edges that define a Volume - like Suzanne",
-                "Solidify method works best for flat surfaces and complex geometry",
-                ],
-        "mesh_mextrude_plus": [
-                "To use:",
-                "Make a selection of Faces",
-                "Extrude with Rotation, Scaling, Variation,",
-                "Randomization and Offset parameters",
-                "Limitation:",
-                "Works only with selections that enclose Faces",
-                "(i.e. all Edges or Vertices of a Face selected)",
-                ],
-        "mesh_extrude_and_reshape": [
-                "To use:",
-                "Extrude Face and merge Edge intersections,",
-                "between the mesh and the new Edges",
-                "Note:",
-                "If selected Vertices don't form Face they will be",
-                "still extruded in the same direction",
-                "Limitation:",
-                "Works only with the last selected face",
-                "(or all Edges or Vertices of a Face selected)",
-                ],
-        "face_inset_fillet": [
-                "To use:",
-                "Select one or multiple faces and inset",
-                "Inset square, circle or outside",
-                "Note:",
-                "Radius: use remove doubles to tidy joins",
-                "Out: select and use normals flip before extruding",
-                "Limitation:",
-                "Using the Out option, sometimes can lead to unsatisfactory results",
-                ],
-        "mesh_cut_faces": [
-                "To use:",
-                "Make a selection or selection of Faces",
-                "Some Functions work on a plane only",
-                "Limitation:",
-                "The selection must include at least two Faces with adjacent edges",
-                "(Selections not sharing edges will not work)",
-                ],
-        "split_solidify": [
-                "To use:",
-                "Make a selection or selection of Faces",
-                "Split Faces and Extrude results",
-                "Similar to a shatter/explode effect",
-                ],
-        "mesh_fastloop": [
-                "To use:",
-                "Activate the tool and hover over the mesh in the general area",
-                "for the loop and left click once to confirm the loop placement",
-                "Slide using the mouse to fine tune its position, left click to confirm",
-                "Repeat the operations if needed for new loops",
-                "Press Esc. twice to exit the tool",
-                "Limitation:",
-                "The tool has the same limitations as Loop Cut and Slide",
-                "In the Operator Panel, only the last loop can be tweaked",
-                ],
-        "mesh_pen_tool": [
-                "To use:",
-                "Press Ctrl + D key or click Draw button",
-                "To draw along x use SHIFT + MOUSEMOVE",
-                "To draw along y use ALT + MOUSEMOVE",
-                "Press Ctrl to toggle Extrude at Cursor tool",
-                "Right click to finish drawing or",
-                "Press Esc to cancel",
-                ],
-        "pkhg_faces": [
-                "To use:",
-                "Needs a Face Selection in Edit Mode",
-                "Select an option from Face Types drop down list",
-                "Extrude, rotate extrusions and more",
-                "Toggle Edit Mode after use",
-                "Note:",
-                "After using the operator, normals could need repair,",
-                "or Removing Doubles",
-                ],
-        "vertex_align": [
-                "To use:",
-                "Select vertices that you want to align and click Align button",
-                "Options include aligning to defined Custom coordinates or",
-                "Stored vertex - (a single selected one with Store Selected Vertex)",
-                "Note:",
-                "Use Stored Coordinates - allows to save a set of coordinates",
-                "as a starting point that can be tweaked on during operation",
-                ],
-        "mesh_check": [
-                "To use:",
-                "Tris and Ngons will select Faces by corensponding type",
-                "Display faces will color the faces depending on the",
-                "defined Colors, Edges' width and Face Opacity",
-                "Note:",
-                "The Faces' type count is already included elsewhere:",
-                "In the Properties Editor > Data > Face / Info Select Panel",
-                ],
-        }
-
-    if identifier in help_text:
-        return help_text[identifier]
-
-    return ["ERROR:", "Help Operator", "Undefined call to the Dictionary"]
-
-
-# register
-def register():
-    bpy.utils.register_class(MESH_OT_extra_tools_help)
-
-
-def unregister():
-    bpy.utils.unregister_class(MESH_OT_extra_tools_help)
-
-
-if __name__ == "__main__":
-    register()
diff --git a/mesh_extra_tools/mesh_mextrude_plus.py b/mesh_extra_tools/mesh_mextrude_plus.py
deleted file mode 100644 (file)
index 5fa2aa2..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-# ##### 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 #####
-
-# Repeats extrusion + rotation + scale for one or more faces
-# Original code by liero
-# Update by Jimmy Hazevoet 03/2017 for Blender 2.79
-# normal rotation, probability, scaled offset, object coords, initial and per step noise
-
-
-bl_info = {
-    "name": "MExtrude Plus1",
-    "author": "liero, Jimmy Hazevoet",
-    "version": (1, 3, 0),
-    "blender": (2, 77, 0),
-    "location": "View3D > Tool Shelf",
-    "description": "Repeat extrusions from faces to create organic shapes",
-    "warning": "",
-    "wiki_url": "",
-    "category": "Mesh"}
-
-
-import bpy
-import bmesh
-import random
-from bpy.types import Operator
-from random import gauss
-from math import radians
-from mathutils import (
-        Euler, Vector,
-        )
-from bpy.props import (
-        FloatProperty,
-        IntProperty,
-        BoolProperty,
-        )
-
-
-def gloc(self, r):
-    return Vector((self.offx, self.offy, self.offz))
-
-
-def vloc(self, r):
-    random.seed(self.ran + r)
-    return self.off * (1 + gauss(0, self.var1 / 3))
-
-
-def nrot(self, n):
-    return Euler((radians(self.nrotx) * n[0],
-                  radians(self.nroty) * n[1],
-                  radians(self.nrotz) * n[2]), 'XYZ')
-
-
-def vrot(self, r):
-    random.seed(self.ran + r)
-    return Euler((radians(self.rotx) + gauss(0, self.var2 / 3),
-                  radians(self.roty) + gauss(0, self.var2 / 3),
-                  radians(self.rotz) + gauss(0, self.var2 / 3)), 'XYZ')
-
-
-def vsca(self, r):
-    random.seed(self.ran + r)
-    return self.sca * (1 + gauss(0, self.var3 / 3))
-
-
-class MExtrude(Operator):
-    bl_idname = "object.mextrude"
-    bl_label = "Multi Extrude"
-    bl_description = ("Extrude selected Faces with Rotation,\n"
-                      "Scaling, Variation, Randomization")
-    bl_options = {"REGISTER", "UNDO", "PRESET"}
-
-    off: FloatProperty(
-            name="Offset",
-            soft_min=0.001, soft_max=10,
-            min=-100, max=100,
-            default=1.0,
-            description="Translation"
-            )
-    offx: FloatProperty(
-            name="Loc X",
-            soft_min=-10.0, soft_max=10.0,
-            min=-100.0, max=100.0,
-            default=0.0,
-            description="Global Translation X"
-            )
-    offy: FloatProperty(
-            name="Loc Y",
-            soft_min=-10.0, soft_max=10.0,
-            min=-100.0, max=100.0,
-            default=0.0,
-            description="Global Translation Y"
-            )
-    offz: FloatProperty(
-            name="Loc Z",
-            soft_min=-10.0, soft_max=10.0,
-            min=-100.0, max=100.0,
-            default=0.0,
-            description="Global Translation Z"
-            )
-    rotx: FloatProperty(
-            name="Rot X",
-            min=-85, max=85,
-            soft_min=-30, soft_max=30,
-            default=0,
-            description="X Rotation"
-            )
-    roty: FloatProperty(
-            name="Rot Y",
-            min=-85, max=85,
-            soft_min=-30,
-            soft_max=30,
-            default=0,
-            description="Y Rotation"
-            )
-    rotz: FloatProperty(
-            name="Rot Z",
-            min=-85, max=85,
-            soft_min=-30, soft_max=30,
-            default=-0,
-            description="Z Rotation"
-            )
-    nrotx: FloatProperty(
-            name="N Rot X",
-            min=-85, max=85,
-            soft_min=-30, soft_max=30,
-            default=0,
-            description="Normal X Rotation"
-            )
-    nroty: FloatProperty(
-            name="N Rot Y",
-            min=-85, max=85,
-            soft_min=-30, soft_max=30,
-            default=0,
-            description="Normal Y Rotation"
-            )
-    nrotz: FloatProperty(
-            name="N Rot Z",
-            min=-85, max=85,
-            soft_min=-30, soft_max=30,
-            default=-0,
-            description="Normal Z Rotation"
-            )
-    sca: FloatProperty(
-            name="Scale",
-            min=0.01, max=10,
-            soft_min=0.5, soft_max=1.5,
-            default=1.0,
-            description="Scaling of the selected faces after extrusion"
-            )
-    var1: FloatProperty(
-            name="Offset Var", min=-10, max=10,
-            soft_min=-1, soft_max=1,
-            default=0,
-            description="Offset variation"
-            )
-    var2: FloatProperty(
-            name="Rotation Var",
-            min=-10, max=10,
-            soft_min=-1, soft_max=1,
-            default=0,
-            description="Rotation variation"
-            )
-    var3: FloatProperty(
-            name="Scale Noise",
-            min=-10, max=10,
-            soft_min=-1, soft_max=1,
-            default=0,
-            description="Scaling noise"
-            )
-    var4: IntProperty(
-            name="Probability",
-            min=0, max=100,
-            default=100,
-            description="Probability, chance of extruding a face"
-            )
-    num: IntProperty(
-            name="Repeat",
-            min=1, max=500,
-            soft_max=100,
-            default=5,
-            description="Repetitions"
-            )
-    ran: IntProperty(
-            name="Seed",
-            min=-9999, max=9999,
-            default=0,
-            description="Seed to feed random values"
-            )
-    opt1: BoolProperty(
-            name="Polygon coordinates",
-            default=True,
-            description="Polygon coordinates, Object coordinates"
-            )
-    opt2: BoolProperty(
-            name="Proportional offset",
-            default=False,
-            description="Scale * Offset"
-            )
-    opt3: BoolProperty(
-            name="Per step rotation noise",
-            default=False,
-            description="Per step rotation noise, Initial rotation noise"
-            )
-    opt4: BoolProperty(
-            name="Per step scale noise",
-            default=False,
-            description="Per step scale noise, Initial scale noise"
-            )
-
-    @classmethod
-    def poll(cls, context):
-        obj = context.object
-        return (obj and obj.type == 'MESH')
-
-    def draw(self, context):
-        layout = self.layout
-        col = layout.column(align=True)
-        col.label(text="Transformations:")
-        col.prop(self, "off", slider=True)
-        col.prop(self, "offx", slider=True)
-        col.prop(self, "offy", slider=True)
-        col.prop(self, "offz", slider=True)
-
-        col = layout.column(align=True)
-        col.prop(self, "rotx", slider=True)
-        col.prop(self, "roty", slider=True)
-        col.prop(self, "rotz", slider=True)
-        col.prop(self, "nrotx", slider=True)
-        col.prop(self, "nroty", slider=True)
-        col.prop(self, "nrotz", slider=True)
-        col = layout.column(align=True)
-        col.prop(self, "sca", slider=True)
-
-        col = layout.column(align=True)
-        col.label(text="Variation settings:")
-        col.prop(self, "var1", slider=True)
-        col.prop(self, "var2", slider=True)
-        col.prop(self, "var3", slider=True)
-        col.prop(self, "var4", slider=True)
-        col.prop(self, "ran")
-        col = layout.column(align=False)
-        col.prop(self, 'num')
-
-        col = layout.column(align=True)
-        col.label(text="Options:")
-        col.prop(self, "opt1")
-        col.prop(self, "opt2")
-        col.prop(self, "opt3")
-        col.prop(self, "opt4")
-
-    def execute(self, context):
-        obj = bpy.context.object
-        om = obj.mode
-        bpy.context.tool_settings.mesh_select_mode = [False, False, True]
-        origin = Vector([0.0, 0.0, 0.0])
-
-        # bmesh operations
-        bpy.ops.object.mode_set()
-        bm = bmesh.new()
-        bm.from_mesh(obj.data)
-        sel = [f for f in bm.faces if f.select]
-
-        after = []
-
-        # faces loop
-        for i, of in enumerate(sel):
-            nro = nrot(self, of.normal)
-            off = vloc(self, i)
-            loc = gloc(self, i)
-            of.normal_update()
-
-            # initial rotation noise
-            if self.opt3 is False:
-                rot = vrot(self, i)
-            # initial scale noise
-            if self.opt4 is False:
-                s = vsca(self, i)
-
-            # extrusion loop
-            for r in range(self.num):
-                # random probability % for extrusions
-                if self.var4 > int(random.random() * 100):
-                    nf = of.copy()
-                    nf.normal_update()
-                    no = nf.normal.copy()
-
-                    # face/obj coördinates
-                    if self.opt1 is True:
-                        ce = nf.calc_center_bounds()
-                    else:
-                        ce = origin
-
-                    # per step rotation noise
-                    if self.opt3 is True:
-                        rot = vrot(self, i + r)
-                    # per step scale noise
-                    if self.opt4 is True:
-                        s = vsca(self, i + r)
-
-                    # proportional, scale * offset
-                    if self.opt2 is True:
-                        off = s * off
-
-                    for v in nf.verts:
-                        v.co -= ce
-                        v.co.rotate(nro)
-                        v.co.rotate(rot)
-                        v.co += ce + loc + no * off
-                        v.co = v.co.lerp(ce, 1 - s)
-
-                    # extrude code from TrumanBlending
-                    for a, b in zip(of.loops, nf.loops):
-                        sf = bm.faces.new((a.vert, a.link_loop_next.vert,
-                                           b.link_loop_next.vert, b.vert))
-                        sf.normal_update()
-                    bm.faces.remove(of)
-                    of = nf
-
-            after.append(of)
-
-        for v in bm.verts:
-            v.select = False
-        for e in bm.edges:
-            e.select = False
-
-        for f in after:
-            if f not in sel:
-                f.select = True
-            else:
-                f.select = False
-
-        bm.to_mesh(obj.data)
-        obj.data.update()
-
-        # restore user settings
-        bpy.ops.object.mode_set(mode=om)
-
-        if not len(sel):
-            self.report({"WARNING"},
-                        "No suitable Face selection found. Operation cancelled")
-            return {'CANCELLED'}
-
-        return {'FINISHED'}
-
-
-def register():
-    bpy.utils.register_module(__name__)
-
-
-def unregister():
-    bpy.utils.unregister_module(__name__)
-
-
-if __name__ == '__main__':
-    register()
diff --git a/mesh_extra_tools/mesh_offset_edges.py b/mesh_extra_tools/mesh_offset_edges.py
deleted file mode 100644 (file)
index b6d760b..0000000
+++ /dev/null
@@ -1,823 +0,0 @@
-# ##### 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": "Offset Edges",
-    "author": "Hidesato Ikeya",
-    "version": (0, 2, 6),
-    "blender": (2, 70, 0),
-    "location": "VIEW3D > Edge menu(CTRL-E) > Offset Edges",
-    "description": "Offset Edges",
-    "warning": "",
-    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
-                "Py/Scripts/Modeling/offset_edges",
-    "category": "Mesh"}
-
-import bpy
-import bmesh
-from bpy.types import Operator
-from math import sin, cos, pi, radians
-from mathutils import Vector
-from time import perf_counter
-
-from bpy.props import (
-        BoolProperty,
-        FloatProperty,
-        EnumProperty,
-        )
-
-# Globals
-X_UP = Vector((1.0, .0, .0))
-Y_UP = Vector((.0, 1.0, .0))
-Z_UP = Vector((.0, .0, 1.0))
-ZERO_VEC = Vector((.0, .0, .0))
-ANGLE_90 = pi / 2
-ANGLE_180 = pi
-ANGLE_360 = 2 * pi
-
-# switch performance logging
-ENABLE_DEBUG = False
-
-
-def calc_loop_normal(verts, fallback=Z_UP):
-    # Calculate normal from verts using Newell's method
-    normal = ZERO_VEC.copy()
-
-    if verts[0] is verts[-1]:
-        # Perfect loop
-        range_verts = range(1, len(verts))
-    else:
-        # Half loop
-        range_verts = range(0, len(verts))
-
-    for i in range_verts:
-        v1co, v2co = verts[i - 1].co, verts[i].co
-        normal.x += (v1co.y - v2co.y) * (v1co.z + v2co.z)
-        normal.y += (v1co.z - v2co.z) * (v1co.x + v2co.x)
-        normal.z += (v1co.x - v2co.x) * (v1co.y + v2co.y)
-
-    if normal != ZERO_VEC:
-        normal.normalize()
-    else:
-        normal = fallback
-
-    return normal
-
-
-def collect_edges(bm):
-    set_edges_orig = set()
-    for e in bm.edges:
-        if e.select:
-            co_faces_selected = 0
-            for f in e.link_faces:
-                if f.select:
-                    co_faces_selected += 1
-                    if co_faces_selected == 2:
-                        break
-            else:
-                set_edges_orig.add(e)
-
-    if not set_edges_orig:
-        return None
-
-    return set_edges_orig
-
-
-def collect_loops(set_edges_orig):
-    set_edges_copy = set_edges_orig.copy()
-
-    loops = []  # [v, e, v, e, ... , e, v]
-    while set_edges_copy:
-        edge_start = set_edges_copy.pop()
-        v_left, v_right = edge_start.verts
-        lp = [v_left, edge_start, v_right]
-        reverse = False
-        while True:
-            edge = None
-            for e in v_right.link_edges:
-                if e in set_edges_copy:
-                    if edge:
-                        # Overlap detected.
-                        return None
-                    edge = e
-                    set_edges_copy.remove(e)
-            if edge:
-                v_right = edge.other_vert(v_right)
-                lp.extend((edge, v_right))
-                continue
-            else:
-                if v_right is v_left:
-                    # Real loop.
-                    loops.append(lp)
-                    break
-                elif reverse is False:
-                    # Right side of half loop
-                    # Reversing the loop to operate same procedure on the left side
-                    lp.reverse()
-                    v_right, v_left = v_left, v_right
-                    reverse = True
-                    continue
-                else:
-                    # Half loop, completed
-                    loops.append(lp)
-                    break
-    return loops
-
-
-def get_adj_ix(ix_start, vec_edges, half_loop):
-    # Get adjacent edge index, skipping zero length edges
-    len_edges = len(vec_edges)
-    if half_loop:
-        range_right = range(ix_start, len_edges)
-        range_left = range(ix_start - 1, -1, -1)
-    else:
-        range_right = range(ix_start, ix_start + len_edges)
-        range_left = range(ix_start - 1, ix_start - 1 - len_edges, -1)
-
-    ix_right = ix_left = None
-    for i in range_right:
-        # Right
-        i %= len_edges
-        if vec_edges[i] != ZERO_VEC:
-            ix_right = i
-            break
-    for i in range_left:
-        # Left
-        i %= len_edges
-        if vec_edges[i] != ZERO_VEC:
-            ix_left = i
-            break
-    if half_loop:
-        # If index of one side is None, assign another index
-        if ix_right is None:
-            ix_right = ix_left
-        if ix_left is None:
-            ix_left = ix_right
-
-    return ix_right, ix_left
-
-
-def get_adj_faces(edges):
-    adj_faces = []
-    for e in edges:
-        adj_f = None
-        co_adj = 0
-        for f in e.link_faces:
-            # Search an adjacent face
-            # Selected face has precedence
-            if not f.hide and f.normal != ZERO_VEC:
-                adj_f = f
-                co_adj += 1
-                if f.select:
-                    adj_faces.append(adj_f)
-                    break
-        else:
-            if co_adj == 1:
-                adj_faces.append(adj_f)
-            else:
-                adj_faces.append(None)
-    return adj_faces
-
-
-def get_edge_rail(vert, set_edges_orig):
-    co_edges = co_edges_selected = 0
-    vec_inner = None
-    for e in vert.link_edges:
-        if (e not in set_edges_orig and
-                (e.select or (co_edges_selected == 0 and not e.hide))):
-            v_other = e.other_vert(vert)
-            vec = v_other.co - vert.co
-            if vec != ZERO_VEC:
-                vec_inner = vec
-                if e.select:
-                    co_edges_selected += 1
-                    if co_edges_selected == 2:
-                        return None
-                else:
-                    co_edges += 1
-    if co_edges_selected == 1:
-        vec_inner.normalize()
-        return vec_inner
-    elif co_edges == 1:
-        # No selected edges, one unselected edge
-        vec_inner.normalize()
-        return vec_inner
-    else:
-        return None
-
-
-def get_cross_rail(vec_tan, vec_edge_r, vec_edge_l, normal_r, normal_l):
-    # Cross rail is a cross vector between normal_r and normal_l
-    vec_cross = normal_r.cross(normal_l)
-    if vec_cross.dot(vec_tan) < .0:
-        vec_cross *= -1
-    cos_min = min(vec_tan.dot(vec_edge_r), vec_tan.dot(-vec_edge_l))
-    cos = vec_tan.dot(vec_cross)
-    if cos >= cos_min:
-        vec_cross.normalize()
-        return vec_cross
-    else:
-        return None
-
-
-def move_verts(width, depth, verts, directions, geom_ex):
-    if geom_ex:
-        geom_s = geom_ex['side']
-        verts_ex = []
-        for v in verts:
-            for e in v.link_edges:
-                if e in geom_s:
-                    verts_ex.append(e.other_vert(v))
-                    break
-        verts = verts_ex
-
-    for v, (vec_width, vec_depth) in zip(verts, directions):
-        v.co += width * vec_width + depth * vec_depth
-
-
-def extrude_edges(bm, edges_orig):
-    extruded = bmesh.ops.extrude_edge_only(bm, edges=edges_orig)['geom']
-    n_edges = n_faces = len(edges_orig)
-    n_verts = len(extruded) - n_edges - n_faces
-
-    geom = dict()
-    geom['verts'] = verts = set(extruded[:n_verts])
-    geom['edges'] = edges = set(extruded[n_verts:n_verts + n_edges])
-    geom['faces'] = set(extruded[n_verts + n_edges:])
-    geom['side'] = set(e for v in verts for e in v.link_edges if e not in edges)
-
-    return geom
-
-
-def clean(bm, mode, edges_orig, geom_ex=None):
-    for f in bm.faces:
-        f.select = False
-    if geom_ex:
-        for e in geom_ex['edges']:
-            e.select = True
-        if mode == 'offset':
-            lis_geom = list(geom_ex['side']) + list(geom_ex['faces'])
-            bmesh.ops.delete(bm, geom=lis_geom, context=2)
-    else:
-        for e in edges_orig:
-            e.select = True
-
-
-def collect_mirror_planes(edit_object):
-    mirror_planes = []
-    eob_mat_inv = edit_object.matrix_world.inverted()
-    for m in edit_object.modifiers:
-        if (m.type == 'MIRROR' and m.use_mirror_merge):
-            merge_limit = m.merge_threshold
-            if not m.mirror_object:
-                loc = ZERO_VEC
-                norm_x, norm_y, norm_z = X_UP, Y_UP, Z_UP
-            else:
-                mirror_mat_local = eob_mat_inv * m.mirror_object.matrix_world
-                loc = mirror_mat_local.to_translation()
-                norm_x, norm_y, norm_z, _ = mirror_mat_local.adjugated()
-                norm_x = norm_x.to_3d().normalized()
-                norm_y = norm_y.to_3d().normalized()
-                norm_z = norm_z.to_3d().normalized()
-            if m.use_x:
-                mirror_planes.append((loc, norm_x, merge_limit))
-            if m.use_y:
-                mirror_planes.append((loc, norm_y, merge_limit))
-            if m.use_z:
-                mirror_planes.append((loc, norm_z, merge_limit))
-    return mirror_planes
-
-
-def get_vert_mirror_pairs(set_edges_orig, mirror_planes):
-    if mirror_planes:
-        set_edges_copy = set_edges_orig.copy()
-        vert_mirror_pairs = dict()
-        for e in set_edges_orig:
-            v1, v2 = e.verts
-            for mp in mirror_planes:
-