EWOCprojects stuff
authorGert De Roost <gertderoost@telenet.be>
Tue, 10 Sep 2013 00:08:57 +0000 (00:08 +0000)
committerGert De Roost <gertderoost@telenet.be>
Tue, 10 Sep 2013 00:08:57 +0000 (00:08 +0000)
22 files changed:
EWOCprojects tools/__init__.py [new file with mode: 0644]
EWOCprojects tools/mesh_deathguppie.py [new file with mode: 0644]
EWOCprojects tools/mesh_edgegrow.py [new file with mode: 0644]
EWOCprojects tools/mesh_edgetune.py [new file with mode: 0644]
EWOCprojects tools/mesh_fanconnect.py [new file with mode: 0644]
EWOCprojects tools/mesh_filletplus.py [new file with mode: 0644]
EWOCprojects tools/mesh_floodsel.py [new file with mode: 0644]
EWOCprojects tools/mesh_innerweld.py [new file with mode: 0644]
EWOCprojects tools/mesh_laprelax.py [new file with mode: 0644]
EWOCprojects tools/mesh_paredge.py [new file with mode: 0644]
EWOCprojects tools/mesh_quadder.py [new file with mode: 0644]
EWOCprojects tools/mesh_selproject.py [new file with mode: 0644]
EWOCprojects tools/mesh_straightenplus.py [new file with mode: 0644]
EWOCprojects tools/object_fastorigin.py [new file with mode: 0644]
chromoly_ruler/__init__.py [new file with mode: 0644]
chromoly_ruler/va/__init__.py [new file with mode: 0644]
chromoly_ruler/va/gl.py [new file with mode: 0644]
chromoly_ruler/va/math.py [new file with mode: 0644]
chromoly_ruler/va/mesh.py [new file with mode: 0644]
chromoly_ruler/va/utils.py [new file with mode: 0644]
chromoly_ruler/va/view.py [new file with mode: 0644]
object_creaprim.py

diff --git a/EWOCprojects tools/__init__.py b/EWOCprojects tools/__init__.py
new file mode 100644 (file)
index 0000000..5f1a553
--- /dev/null
@@ -0,0 +1,202 @@
+# ##### 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 #
+
+bl_info = {
+       "name": "EWOCprojects tools",
+       "author": "Gert De Roost - paleajed",
+       "version": (1, 0, 0),
+       "blender": (2, 6, 3),
+       "location": "View3D > Toolbar and View3D > Specials (W-key)",
+       "description": "Edit mode tools - contrib version",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+
+if "bpy" in locals():
+       import imp
+       imp.reload(mesh_edgetune)
+       imp.reload(mesh_quadder)
+       imp.reload(mesh_paredge)
+       imp.reload(mesh_edgegrow)
+       imp.reload(mesh_fanconnect)
+       imp.reload(mesh_filletplus)
+       imp.reload(object_fastorigin)
+       imp.reload(mesh_laprelax)
+       imp.reload(mesh_innerweld)
+       imp.reload(mesh_straightenplus)
+       imp.reload(mesh_floodsel)
+       imp.reload(mesh_deathguppie)
+       imp.reload(mesh_selproject)
+
+else:
+       from . import mesh_edgetune
+       from . import mesh_quadder
+       from . import mesh_paredge
+       from . import mesh_edgegrow
+       from . import mesh_fanconnect
+       from . import mesh_filletplus
+       from . import object_fastorigin
+       from . import mesh_laprelax
+       from . import mesh_innerweld
+       from . import mesh_straightenplus
+       from . import mesh_floodsel
+       from . import mesh_deathguppie
+       from . import mesh_selproject
+
+import bpy
+
+
+
+class VIEW3D_MT_edit_mesh_paleajed(bpy.types.Menu):
+       # Define the "Extras" menu
+       bl_idname = "VIEW3D_MT_edit_mesh_paleajed"
+       bl_label = "EWOCprojects tools"
+
+       def draw(self, context):
+               layout = self.layout
+               layout.operator_context = 'INVOKE_REGION_WIN'
+               layout.operator("mesh.edgetune",
+                       text="EdgeTune")
+               layout.operator("mesh.quadder",
+                       text="Quadder") 
+               layout.operator("mesh.paredge",
+                       text="ParEdge")
+               layout.operator("mesh.edgegrow",
+                       text="EdgeGrow")
+               layout.operator("mesh.fanconnect",
+                       text="FanConnect")
+               layout.operator("f.op0_id",
+                       text="FilletPlus")
+               layout.operator("object.fastorigin",
+                       text="FastOrigin")
+               layout.operator("mesh.laprelax",
+                       text="LapRelax")
+               layout.operator("mesh.polyredux",
+                       text="PolyRedux")
+               layout.operator("mesh.innerweld",
+                       text="InnerWeld")
+               layout.operator("mesh.straightenplus",
+                       text="StraightenPlus")
+               layout.operator("mesh.floodsel",
+                       text="FloodSel")
+               layout.operator("mesh.deathguppie",
+                       text="DeathGuppie")
+               layout.operator("mesh.selproject",
+                       text="SelProject")
+
+
+class PaleajedPanel(bpy.types.Panel):
+       bl_label = 'EWOCprojects tools'
+       bl_space_type = 'VIEW_3D'
+       bl_region_type = 'TOOLS'
+
+       def draw(self, context):
+               scn = bpy.context.scene
+               layout = self.layout
+               layout.operator('mesh.edgetune')
+               layout.operator('mesh.quadder')
+               
+               layout.operator('mesh.paredge')
+               if mesh_paredge.started:
+                       layout.prop(scn, 'Distance')
+                       layout.prop(scn, 'Both')
+                       if scn.Both:
+                               layout.prop(scn, 'Cap')
+                       mesh_paredge.parchange = 1
+                       bpy.context.region.tag_redraw()
+
+               layout.operator('mesh.edgegrow')
+               layout.operator('mesh.fanconnect')
+               layout.operator('f.op0_id', text="FIlletPlus")
+               layout.operator('object.fastorigin')
+               layout.operator('mesh.laprelax')
+               layout.operator('mesh.innerweld')
+               
+               if not(mesh_straightenplus.started):
+                       layout.operator("mesh.straightenplus")
+               else:
+                       layout.label(text="ENTER or leftmouse to confirm")
+                       layout.label(text="RightMouse or ESC to cancel")
+                       layout.prop(scn, "Percentage")
+                       if mesh_straightenplus.started and scn.Percentage != mesh_straightenplus.oldperc:
+                               mesh_straightenplus.do_straighten()
+                               mesh_straightenplus.oldperc = scn.Percentage
+                       layout.prop(scn, "CancelAxis")
+               
+               layout.operator("mesh.floodsel", text="Flood Sel")
+               if mesh_floodsel.started:
+                       layout.prop(scn, "Multiple")
+                       layout.prop(scn, "Preselection")
+                       layout.prop(scn, "Diagonal")
+               
+               layout.operator('mesh.deathguppie')
+               layout.prop(scn, "Smooth")
+               layout.prop(scn, "Inner")
+               
+               if not(mesh_selproject.activated):
+                       self.layout.operator("selproject.activate", text="Activate SelProject")
+               else:
+                       if not(mesh_selproject.started):
+                               self.layout.operator("mesh.selproject", text="Start SelProject")
+                               if context.mode == "EDIT_MESH":
+                                       self.layout.prop(scn, "UseSel")
+                                       if not(scn.UseSel):
+                                               self.layout.prop(scn, "FromObject")
+                                       else:
+                                               mesh_selproject.fromobj = bpy.context.active_object.name
+                                               mesh_selproject.redomenus = 1
+                                               context.region.tag_redraw()
+                               else:
+                                       self.layout.prop(scn, "FromObject")
+                               self.layout.prop(scn, "ToObject")
+                       else:
+                               self.layout.label(text="ENTER to confirm")
+       
+               if scn.FromObject != mesh_selproject.oldfromobj:
+                       mesh_selproject.oldfromobj = scn.FromObject
+                       mesh_selproject.redomenus = 1
+                       context.region.tag_redraw()
+               mesh_selproject.redomenus = 1   
+
+
+# Register all operators and panels
+
+# Define "Extras" menu
+def menu_func(self, context):
+       self.layout.menu("VIEW3D_MT_edit_mesh_paleajed", icon="PLUGIN")
+
+
+def register():
+       bpy.utils.register_module(__name__)
+
+       # Add "Extras" menu to the "Add Mesh" menu
+       bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func)
+
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+
+       # Remove "Extras" menu from the "Add Mesh" menu.
+       bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
+
+if __name__ == "__main__":
+       register()
diff --git a/EWOCprojects tools/mesh_deathguppie.py b/EWOCprojects tools/mesh_deathguppie.py
new file mode 100644 (file)
index 0000000..11dfa1a
--- /dev/null
@@ -0,0 +1,618 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+This addon implements a subdivision scheme called deathguppie.
+It is ideal for creating more detail locally when sculpting.
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the DeathGuppie addon in the Mesh category.
+Go to EditMode, select some elements and invoke the addon (button in the Mesh Tool panel).
+The selected area will be subdivided according to the deathguppie algorithm.
+Subdivision is destructive so this is no modifier but a mesh operation.
+Selected area after operation allows for further sudividing the area.
+The smooth tickbox chooses between smooth and non-smooth subdivision.
+The Select inner only tickbox sets what is left selected after operation, only inner faces or everything.
+
+BEWARE - deathguppie will only subdivide grids of quads!
+
+If you wish to hotkey DeathGuppie:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.deathguppie'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+
+bl_info = {
+       "name": "DeathGuppie",
+       "author": "Gert De Roost",
+       "version": (0, 2, 2),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Deathguppie subdivision operation",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+import bmesh
+
+
+bpy.types.Scene.Smooth = bpy.props.BoolProperty(
+               name = "Smoothing", 
+               description = "Subdivide smooth",
+               default = True)
+
+bpy.types.Scene.Inner = bpy.props.BoolProperty(
+               name = "Select inner only", 
+               description = "After operation only inner verts selected",
+               default = True)
+
+
+class DeathGuppie(bpy.types.Operator):
+       bl_idname = "mesh.deathguppie"
+       bl_label = "DeathGuppie"
+       bl_description = "Deathguppie subdivision operation"
+       bl_options = {"REGISTER", "UNDO"}
+       
+
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               do_deathguppie(self)
+               
+               return {'FINISHED'}
+
+
+def panel_func(self, context):
+       
+       scn = bpy.context.scene
+       self.layout.label(text="DeathGuppie:")
+       self.layout.operator("mesh.deathguppie", text="Subdivide DG")
+       self.layout.prop(scn, "Smooth")
+       self.layout.prop(scn, "Inner")
+
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+def do_deathguppie(self):
+               
+       global smoothset, cornerlist, innerlist, vselset
+
+       context = bpy.context
+       region = context.region  
+       area = context.area
+       selobj = bpy.context.active_object
+
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.object.duplicate()
+       projobj = bpy.context.active_object
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.mesh.subdivide(number_cuts=5, smoothness=1.0)
+       bpy.ops.object.editmode_toggle()
+       projobj.hide = 1
+       bpy.context.scene.objects.active = selobj
+       bpy.ops.object.editmode_toggle()
+
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+       bmkeep = bm.copy()
+
+       facelist = []
+       for f1 in bm.faces:
+               if f1.select:
+                       linked = []
+                       for e in f1.edges:
+                               for f2 in e.link_faces:
+                                       if f2 != f1:
+                                               if f2.select:
+                                                       linked.append(f2.index)
+                                                       break
+                       facelist.insert(0, [])
+                       facelist[0].append(f1)
+                       facelist[0].append(linked)
+       
+
+       transfer = {}
+       holdlist = []   
+       for [f, linked] in facelist:
+               bpy.ops.mesh.select_all(action="DESELECT")
+               f.select = 1
+               transfer[f.calc_center_median()[:]] = [f.index, linked]
+               bpy.ops.mesh.split()
+                               
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.object.editmode_toggle()
+       bm = bmesh.from_edit_mesh(mesh)
+       facelist = []
+       for f in bm.faces:
+               num = 0
+               for e in f.edges:
+                       if len(e.link_faces) == 1:
+                               num += 1
+               if num == 4:
+                       if f.calc_center_median()[:] in transfer.keys():
+                               f.select = 1
+                               facelist.insert(0, [])
+                               facelist[0].append(f)
+                               facelist[0].append(transfer[f.calc_center_median()[:]])
+                               
+
+       def createinnerlists(f):
+       
+               global smoothset, cornerlist, innerlist, vselset
+               
+               for l in f.loops:
+                       cornerlist.append(l.vert)
+                       vselset.add(l.vert)
+                       v1 = l.vert
+                       vnext = l.link_loop_next.vert
+                       vprev = l.link_loop_prev.vert
+                       vnextnext = l.link_loop_next.link_loop_next.vert
+                       vprevprev = l.link_loop_prev.link_loop_prev.vert
+                       tempco1 = v1.co + (vprev.co - v1.co) / 3
+                       tempco2 = vnext.co + (vnextnext.co - vnext.co) / 3
+                       vert = bm.verts.new(tempco1 + ((tempco2 - tempco1) / 3))
+                       innerlist.append(vert)
+                       smoothset.add(vert)
+       
+       scn = bpy.context.scene
+       vselset = set([])
+       fselset = set([])
+       smoothset = set([])
+       for [f, [foldidx, linked]] in facelist:
+               fold = bmkeep.faces[foldidx]
+               linked2 = []
+               for idx in linked:
+                       linked2.append(bmkeep.faces[idx])
+               cornerlist = []
+               innerlist = []
+               if len(linked) == 4:
+                       createinnerlists(f)
+                       for e in f.edges:
+                               ne, vert1 = bmesh.utils.edge_split(e, e.verts[0], 0.66)         
+                               ne, vert2 = bmesh.utils.edge_split(ne, vert1, 0.5)
+                               vselset.add(vert1)
+                               vselset.add(vert2)
+                               smoothset.add(vert1)
+                               smoothset.add(vert2)
+                       for idx in range(len(cornerlist)):
+                               cv = cornerlist[idx]
+                               for l in f.loops:
+                                       if l.vert == cv:
+                                               fs = bm.faces.new((cv, l.link_loop_next.vert, innerlist[idx], l.link_loop_prev.vert))
+                                               fselset.add(fs)
+                                               fs = bm.faces.new((l.link_loop_prev.vert, l.link_loop_prev.link_loop_prev.vert, innerlist[idx - 1], innerlist[idx]))
+                                               fselset.add(fs)
+                       fs = bm.faces.new((innerlist[0], innerlist[1], innerlist[2], innerlist[3]))
+                       fselset.add(fs)
+                       bm.faces.remove(f)
+               elif len(linked) == 3:
+                       fedges = fold.edges[:]
+                       for e1 in fedges:
+                               for f1 in e1.link_faces:
+                                       if len(e1.link_faces) == 1 or (f1 != fold and not(f1 in linked2)):
+                                               edge = f.edges[fedges.index(e1)]
+                       createinnerlists(f)
+                       for e in f.edges:
+                               if e != edge:
+                                       ne, vert1 = bmesh.utils.edge_split(e, e.verts[0], 0.66)         
+                                       ne, vert2 = bmesh.utils.edge_split(ne, vert1, 0.5)
+                                       vselset.add(vert1)
+                                       vselset.add(vert2)
+                                       smoothset.add(vert1)
+                                       smoothset.add(vert2)
+                       for l in edge.link_loops:
+                               if l.face == f:
+                                       if l.edge == edge:
+                                               v1 = l.vert
+                                               vnext = l.link_loop_next.vert
+                                               vprev = l.link_loop_prev.vert
+                                               vnextnext = l.link_loop_next.link_loop_next.vert
+                                               vprevprev = l.link_loop_prev.link_loop_prev.vert
+                                               for idx in range(4):
+                                                       if cornerlist[idx] == v1:
+                                                               co1 = innerlist[idx].co + ((innerlist[idx].co - innerlist[idx-1].co) / 2)
+                                                               co2 = innerlist[idx-3].co + ((innerlist[idx-3].co - innerlist[idx-2].co) / 2)
+                                                               sidev1 = bm.verts.new(co1)
+                                                               sidev2 = bm.verts.new(co2)
+                                                               fs = bm.faces.new((v1, vnext, sidev2, sidev1))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((v1, sidev1, innerlist[idx], vprev))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((sidev2, vnext, vnextnext, innerlist[idx-3]))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((sidev1, sidev2, innerlist[idx-3], innerlist[idx]))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((innerlist[idx], innerlist[idx-1], vprevprev, vprev))
+                                                               fselset.add(fs)
+                                               cornerlist[cornerlist.index(v1)] = None
+                                               cornerlist[cornerlist.index(vnext)] = None
+                                               break
+                       for idx in range(len(cornerlist)):
+                               cv = cornerlist[idx]
+                               if cv != None:
+                                       for l in f.loops:
+                                               if l.vert == cv:
+                                                       fs = bm.faces.new((cv, l.link_loop_next.vert, innerlist[idx], l.link_loop_prev.vert))
+                                                       fselset.add(fs)
+                                                       fs = bm.faces.new((l.link_loop_prev.vert, l.link_loop_prev.link_loop_prev.vert, innerlist[idx - 1], innerlist[idx]))
+                                                       fselset.add(fs)
+                       fs = bm.faces.new((innerlist[0], innerlist[1], innerlist[2], innerlist[3]))
+                       fselset.add(fs)
+                       bm.faces.remove(f)
+                       smoothset.add(sidev1)
+                       smoothset.add(sidev2)
+               elif len(linked) == 2:
+                       case = "bridge"
+                       for vert in linked2[0].verts:
+                               if vert in linked2[1].verts:
+                                       case = "corner"
+                                       break
+                       if case == "corner":
+                               fedges = fold.edges[:]
+                               edges = []
+                               for e1 in fedges:
+                                       for f1 in e1.link_faces:
+                                               if len(e1.link_faces) == 1 or (f1 != fold and not(f1 in linked2)):
+                                                       edges.append(f.edges[fedges.index(e1)])
+                               for l in edges[1].link_loops:
+                                       if l.face == f:
+                                               if l.edge == edges[1] and l.link_loop_next.edge == edges[0]:
+                                                       edges.reverse()
+                                                       break
+                               createinnerlists(f)                     
+                               for e in f.edges:
+                                       if not(e in edges):
+                                               ne, vert1 = bmesh.utils.edge_split(e, e.verts[0], 0.66)         
+                                               ne, vert2 = bmesh.utils.edge_split(ne, vert1, 0.5)
+                                               vselset.add(vert1)
+                                               vselset.add(vert2)
+                                               smoothset.add(vert1)
+                                               smoothset.add(vert2)
+                               for l in edges[0].link_loops:
+                                       if l.face == f:
+                                               if l.edge == edges[0]:
+                                                       if l.link_loop_next.edge == edges[1]:
+                                                               v1 = l.vert
+                                                               vnext = l.link_loop_next.vert
+                                                               vprev = l.link_loop_prev.vert
+                                                               vnextnext = l.link_loop_next.link_loop_next.vert
+                                                               vnnn = l.link_loop_next.link_loop_next.link_loop_next.vert
+                                                               vprevprev = l.link_loop_prev.link_loop_prev.vert
+                                                               vppp = l.link_loop_prev.link_loop_prev.link_loop_prev.vert
+                                                               vpppp = l.link_loop_prev.link_loop_prev.link_loop_prev.link_loop_prev.vert
+                                                               for idx in range(4):
+                                                                       if cornerlist[idx] == v1:
+                                                                               delta1 = (innerlist[idx].co - innerlist[idx-1].co) / 2
+                                                                               co1 = innerlist[idx].co + delta1
+                                                                               delta2 = (innerlist[idx-3].co - innerlist[idx].co) / 2
+                                                                               delta3 = (innerlist[idx-3].co - innerlist[idx-2].co) / 2
+                                                                               co2 = innerlist[idx-3].co + delta1 + delta2
+                                                                               sidev1 = bm.verts.new(co1)
+                                                                               sidev2 = bm.verts.new(co2)
+                                                                               sidev3 = bm.verts.new(innerlist[idx-2].co + ((innerlist[idx-2].co - innerlist[idx-1].co) / 2))
+                                                                               
+                                                                               fs = bm.faces.new((v1, vnext, sidev2, sidev1))
+                                                                               if not(scn.Inner):
+                                                                                       fselset.add(fs)
+                                                                               fs = bm.faces.new((sidev3, sidev2, vnext, vnextnext))
+                                                                               if not(scn.Inner):
+                                                                                       fselset.add(fs)
+                                                                               fs = bm.faces.new((v1, sidev1, innerlist[idx], vprev))
+                                                                               if not(scn.Inner):
+                                                                                       fselset.add(fs)
+                                                                               fs = bm.faces.new((innerlist[idx-2], sidev3, vnextnext, vnnn))
+                                                                               if not(scn.Inner):
+                                                                                       fselset.add(fs)
+                                                                               fs = bm.faces.new((sidev1, sidev2, innerlist[idx-3], innerlist[idx]))
+                                                                               if not(scn.Inner):
+                                                                                       fselset.add(fs)
+                                                                               fs = bm.faces.new((sidev2, sidev3, innerlist[idx-2], innerlist[idx-3]))
+                                                                               if not(scn.Inner):
+                                                                                       fselset.add(fs)
+                                                                               fs = bm.faces.new((vprevprev, vprev, innerlist[idx], innerlist[idx-1]))
+                                                                               fselset.add(fs)
+                                                                               fs = bm.faces.new((vpppp, vppp, vprevprev, innerlist[idx-1]))
+                                                                               fselset.add(fs)
+                                                                               fs = bm.faces.new((vnnn, vpppp, innerlist[idx-1], innerlist[idx-2]))
+                                                                               fselset.add(fs)
+                                                                               break
+                                                               break
+                               fs = bm.faces.new((innerlist[0], innerlist[1], innerlist[2], innerlist[3]))
+                               fselset.add(fs)
+                               bm.faces.remove(f)
+                               smoothset.add(sidev1)
+                               smoothset.add(sidev2)
+                               smoothset.add(sidev3)
+                       else:
+                               fedges = fold.edges[:]
+                               edges = []
+                               for e1 in fedges:
+                                       for f1 in e1.link_faces:
+                                               if len(e1.link_faces) == 1 or (f1 != fold and not(f1 in linked2)):
+                                                       edges.append(f.edges[fedges.index(e1)])
+                               createinnerlists(f)                     
+                               for e in f.edges:
+                                       if not(e in edges):
+                                               ne, vert1 = bmesh.utils.edge_split(e, e.verts[0], 0.66)         
+                                               ne, vert2 = bmesh.utils.edge_split(ne, vert1, 0.5)
+                                               vselset.add(vert1)
+                                               vselset.add(vert2)
+                                               smoothset.add(vert1)
+                                               smoothset.add(vert2)
+                               for l in f.loops:
+                                       if l.edge == edges[0]:
+                                               v1 = l.vert
+                                               vnext = l.link_loop_next.vert
+                                               vprev = l.link_loop_prev.vert
+                                               vnextnext = l.link_loop_next.link_loop_next.vert
+                                               vnnn = l.link_loop_next.link_loop_next.link_loop_next.vert
+                                               vnnnn = l.link_loop_next.link_loop_next.link_loop_next.link_loop_next.vert
+                                               vprevprev = l.link_loop_prev.link_loop_prev.vert
+                                               vppp = l.link_loop_prev.link_loop_prev.link_loop_prev.vert
+                                               vpppp = l.link_loop_prev.link_loop_prev.link_loop_prev.link_loop_prev.vert
+                                               for idx in range(4):
+                                                       if cornerlist[idx] == v1:
+                                                               delta1 = (innerlist[idx].co - innerlist[idx-1].co) / 2
+                                                               co1 = innerlist[idx].co + delta1
+                                                               sidev1 = bm.verts.new(co1)
+                                                               delta2 = (innerlist[idx-3].co - innerlist[idx-2].co) / 2
+                                                               co2 = innerlist[idx-3].co + delta2
+                                                               sidev2 = bm.verts.new(co2)
+                                                               delta3 = (innerlist[idx-2].co - innerlist[idx-3].co) / 2
+                                                               co3 = innerlist[idx-2].co + delta3
+                                                               sidev3 = bm.verts.new(co3)
+                                                               delta4 = (innerlist[idx-1].co - innerlist[idx].co) / 2
+                                                               co4 = innerlist[idx-1].co + delta4
+                                                               sidev4 = bm.verts.new(co4)
+                                                               fs = bm.faces.new((v1, vnext, sidev2, sidev1))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((v1, sidev1, innerlist[idx], vprev))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((vnext, vnextnext, innerlist[idx-3], sidev2))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((sidev1, sidev2, innerlist[idx-3], innerlist[idx]))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((vppp, sidev4, sidev3, vnnnn))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((vppp, vprevprev, innerlist[idx-1], sidev4))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((sidev3, innerlist[idx-2], vnnn, vnnnn))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((sidev3, sidev4, innerlist[idx-1], innerlist[idx-2]))
+                                                               if not(scn.Inner):
+                                                                       fselset.add(fs)
+                                                               fs = bm.faces.new((vprevprev, vprev, innerlist[idx], innerlist[idx-1]))
+                                                               fselset.add(fs)
+                                                               fs = bm.faces.new((vnextnext, vnnn, innerlist[idx-2], innerlist[idx-3]))
+                                                               fselset.add(fs)
+                                                               
+                               fs = bm.faces.new((innerlist[0], innerlist[1], innerlist[2], innerlist[3]))
+                               fselset.add(fs)
+                               bm.faces.remove(f)
+                               smoothset.add(sidev1)
+                               smoothset.add(sidev2)
+                               smoothset.add(sidev3)
+                               smoothset.add(sidev4)
+                               
+                               
+               elif len(linked) == 1:
+                       fedges = fold.edges[:]
+                       edges = []
+                       for e1 in fedges:
+                               for f1 in e1.link_faces:
+                                       if len(e1.link_faces) == 1 or (f1 != fold and not(f1 in linked2)):
+                                               edges.append(f.edges[fedges.index(e1)])
+                       for l in f.loops:
+                               if not(l.edge in edges):
+                                       edges = [l.link_loop_next.edge, l.link_loop_next.link_loop_next.edge, l.link_loop_next.link_loop_next.link_loop_next.edge]
+                       createinnerlists(f)                     
+                       for e in f.edges:
+                               if not(e in edges):
+                                       ne, vert1 = bmesh.utils.edge_split(e, e.verts[0], 0.66)         
+                                       ne, vert2 = bmesh.utils.edge_split(ne, vert1, 0.5)
+                                       vselset.add(vert1)
+                                       vselset.add(vert2)
+                                       smoothset.add(vert1)
+                                       smoothset.add(vert2)
+                       for l in f.loops:
+                               if l.edge == edges[0]:
+                                       v1 = l.vert
+                                       vnext = l.link_loop_next.vert
+                                       vprev = l.link_loop_prev.vert
+                                       vnextnext = l.link_loop_next.link_loop_next.vert
+                                       vnnn = l.link_loop_next.link_loop_next.link_loop_next.vert
+                                       vprevprev = l.link_loop_prev.link_loop_prev.vert
+                                       vppp = l.link_loop_prev.link_loop_prev.link_loop_prev.vert
+                                       vpppp = l.link_loop_prev.link_loop_prev.link_loop_prev.link_loop_prev.vert
+                                       for idx in range(4):
+                                               if cornerlist[idx] == v1:
+                                                       delta1 = (innerlist[idx].co - innerlist[idx-1].co) / 2
+                                                       co1 = innerlist[idx].co + delta1
+                                                       delta2 = (innerlist[idx-3].co - innerlist[idx].co) / 2
+                                                       delta3 = (innerlist[idx-3].co - innerlist[idx-2].co) / 2
+                                                       co2 = innerlist[idx-3].co + delta1 + delta2
+                                                       sidev1 = bm.verts.new(co1)
+                                                       sidev2 = bm.verts.new(co2)
+                                                       delta4 = (innerlist[idx-2].co - innerlist[idx-1].co) / 2
+                                                       delta5 = (innerlist[idx-2].co - innerlist[idx-3].co) / 2
+                                                       co3 = innerlist[idx-2].co + delta4 + delta5
+                                                       sidev3 = bm.verts.new(co3)
+                                                       delta6 = (innerlist[idx-1].co - innerlist[idx].co) / 2
+                                                       co4 = innerlist[idx-1].co + delta6
+                                                       sidev4 = bm.verts.new(co4)
+                                                       fs = bm.faces.new((v1, vnext, sidev2, sidev1))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((sidev3, sidev2, vnext, vnextnext))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((v1, sidev1, innerlist[idx], vprev))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((sidev1, sidev2, innerlist[idx-3], innerlist[idx]))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((sidev2, sidev3, innerlist[idx-2], innerlist[idx-3]))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((sidev4, sidev3, vnextnext, vppp))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((innerlist[idx-2], innerlist[idx-1], sidev4, sidev3))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((vprevprev, vppp, sidev4, innerlist[idx-1]))
+                                                       if not(scn.Inner):
+                                                               fselset.add(fs)
+                                                       fs = bm.faces.new((vprev, vprevprev, innerlist[idx-1], innerlist[idx]))
+                                                       fselset.add(fs)
+                       fs = bm.faces.new((innerlist[0], innerlist[1], innerlist[2], innerlist[3]))
+                       fselset.add(fs)
+                       bm.faces.remove(f)
+                       smoothset.add(sidev1)
+                       smoothset.add(sidev2)
+                       smoothset.add(sidev3)
+                       smoothset.add(sidev4)
+                               
+               elif len(linked) == 0:
+                       createinnerlists(f)                     
+                       l = f.loops[0]
+                       v1 = l.vert
+                       vnext = l.link_loop_next.vert
+                       vprev = l.link_loop_prev.vert
+                       vnextnext = l.link_loop_next.link_loop_next.vert
+                       for idx in range(4):
+                               if cornerlist[idx] == v1:
+                                       sidev1 = bm.verts.new((cornerlist[idx].co + innerlist[idx].co) / 2)
+                                       sidev2 = bm.verts.new((cornerlist[idx-3].co + innerlist[idx-3].co) / 2)
+                                       sidev3 = bm.verts.new((cornerlist[idx-2].co + innerlist[idx-2].co) / 2)
+                                       sidev4 = bm.verts.new((cornerlist[idx-1].co + innerlist[idx-1].co) / 2)
+                                       fs = bm.faces.new((v1, vnext, sidev2, sidev1))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev3, sidev2, vnext, vnextnext))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev4, sidev3, vnextnext, vprev))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev1, sidev4, vprev, v1))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev1, sidev2, innerlist[idx-3], innerlist[idx]))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev2, sidev3, innerlist[idx-2], innerlist[idx-3]))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev3, sidev4, innerlist[idx-1], innerlist[idx-2]))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                                       fs = bm.faces.new((sidev4, sidev1, innerlist[idx], innerlist[idx-1]))
+                                       if not(scn.Inner):
+                                               fselset.add(fs)
+                       fs = bm.faces.new((innerlist[0], innerlist[1], innerlist[2], innerlist[3]))
+                       fselset.add(fs)
+                       bm.faces.remove(f)
+                       smoothset.add(sidev1)
+                       smoothset.add(sidev2)
+                       smoothset.add(sidev3)
+                       smoothset.add(sidev4)
+       
+       
+       scn = bpy.context.scene
+       if scn.Smooth:
+               for v in smoothset:
+                       v.co = projobj.closest_point_on_mesh(v.co)[0]
+               
+       bpy.ops.mesh.select_all(action="SELECT")
+       bm.normal_update()
+       bpy.ops.mesh.normals_make_consistent()
+       bpy.ops.mesh.select_all(action="DESELECT")
+       for f in fselset:
+               f.select = 1
+               for e in f.edges:
+                       e.select = 1
+               for v in f.verts:
+                       v.select = 1
+       for e in bm.edges:
+               if len(e.link_faces) == 1:
+                       e.verts[0].select = 1
+                       e.verts[1].select = 1
+       bpy.ops.mesh.remove_doubles()
+       for e in bm.edges:
+               if len(e.link_faces) == 1:
+                       e.verts[0].select = 0
+                       e.verts[1].select = 0
+                       e.select = 0
+                                       
+       mesh.update()
+       bm.free()
+       bmkeep.free()
+       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.object.select_all(action="DESELECT")
+       bpy.context.scene.objects.active = projobj
+       projobj.hide = 0
+       bpy.ops.object.delete()
+       selobj.select = 1
+       bpy.context.scene.objects.active = selobj
+       bpy.ops.object.editmode_toggle()
+       
diff --git a/EWOCprojects tools/mesh_edgegrow.py b/EWOCprojects tools/mesh_edgegrow.py
new file mode 100644 (file)
index 0000000..eb61c55
--- /dev/null
@@ -0,0 +1,788 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+This addon enables you to snakelike "grow" an edgeloop selection with arrow keys.
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the EdgeGrow addon in the Mesh category.
+Invoke it (button in the Mesh Tools panel).
+Go to EditMode, select one or more edges or connected edge-snakes (you can grow several at the same time, a bmesh mesh has a certain
+spin direction to it, so in most general non-complex situations multiple edges will grow together
+in the desired direction).  Use the left and right arrow keys to grow / ungrow the edgeloop in any direction.
+The addon will show the edges you can grow next in light blue, with the active edge(will be selected 
+when using arrow keys) highlighted in red.  Use up and down arrow keys to activate the other light blue
+edges, this way you can route your edge-snake in every possible direction; defsult is the middle one.
+You can grow multiple slices at the same time.
+
+If you wish to hotkey EdgeGrow:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.edgetune'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+
+bl_info = {
+       "name": "EdgeGrow",
+       "author": "Gert De Roost",
+       "version": (0, 3, 2),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Growing edgeloops with arrowkeys",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+from bpy_extras import *
+import bmesh
+from bgl import *
+from mathutils import *
+import time
+
+
+
+
+class EdgeGrow(bpy.types.Operator):
+       bl_idname = "mesh.edgegrow"
+       bl_label = "EdgeGrow"
+       bl_description = "Growing edgeloops with arrowkeys"
+       bl_options = {"REGISTER", "UNDO"}
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               do_edgegrow(self)
+               
+               context.window_manager.modal_handler_add(self)
+               if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                       self._handle = bpy.types.SpaceView3D.draw_handler_add(redraw, (), 'WINDOW', 'POST_PIXEL')
+               else:
+                       self._handle = context.region.callback_add(redraw, (), 'POST_PIXEL')
+               
+               return {'RUNNING_MODAL'}
+
+       def modal(self, context, event):
+               
+               global bm, mesh
+               global viewchange, state, activedir, check
+               global edgelist, cursor, counter, posn
+
+               scn = bpy.context.scene
+               
+               if event.type in ["MIDDLEMOUSE"]:
+                       # recalculate transformation matrix
+                       viewchange = 1
+                       return {"PASS_THROUGH"}
+               elif event.type in ["WHEELDOWNMOUSE", "WHEELUPMOUSE"]:
+                       # recalculate transformation matrix
+                       viewchange = 1
+                       return {"PASS_THROUGH"}
+               elif event.type == "RET" or stop:
+                       # Consolidate changes if ENTER pressed.
+                       # Free the bmesh.
+                       bm.free()
+                       if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                               bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
+                       else:
+                               context.region.callback_remove(self._handle)
+                       bpy.ops.object.editmode_toggle()
+                       bpy.ops.object.editmode_toggle()
+                       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                       return {'FINISHED'}
+               elif event.type == "LEFT_ARROW":
+                       # reinit: when user returns to begin position: display cursor edges on both sides
+                       # start: add to beginning of lists
+                       # end: add to end of lists
+                       # init: first initialization state: cursor on both sides
+                       # set cursor to correct edge
+                       for posn in range(len(edgelist)):
+                               if event.value == "PRESS":
+                                       if state[posn] == "reinit":
+                                               check[posn] = 0
+                                               if oldstate[posn] == "start":
+                                                       if activedir[posn] == "left":
+                                                               state[posn] = "start"
+                                                       else:
+                                                               state[posn] = "end"
+                                                               if cursor[posn] == startcur[posn]:
+                                                                       cursor[posn] = endcur[posn]
+                                                               else:
+                                                                       cursor[posn] = startcur[posn]
+                                               else:
+                                                       if activedir[posn] == "left":
+                                                               state[posn] = "end"
+                                                       else:
+                                                               state[posn] = "start"
+                                                               if cursor[posn] == startcur[posn]:
+                                                                       cursor[posn] = endcur[posn]
+                                                               else:
+                                                                       cursor[posn] = startcur[posn]
+                                               activedir[posn] = "left"                                                
+                                       if state[posn] == "init":                       
+                                               activedir[posn] = "left"
+                                               check[posn] = 1
+                                               state[posn] = "start"
+                                               cursor[posn] = startcur[posn]
+                                                       
+                                       # activedir: left or right absolute -> movement in x direction (when in init state)
+                                       if activedir[posn] == "left":
+                                               addedge()
+                                       else:
+                                               removeedge()
+                       return {'RUNNING_MODAL'}
+               elif event.type == "RIGHT_ARROW":
+                       # check LEFT_ARROW
+                       if event.value == "PRESS":
+                               for posn in range(len(edgelist)):
+                                       if state[posn] == "reinit":
+                                               check[posn] = 0
+                                               if oldstate[posn] == "start":
+                                                       if activedir[posn] == "right":
+                                                               state[posn] = "start"
+                                                               if cursor[posn] == startcur[posn]:
+                                                                       cursor[posn] = startcur[posn]
+                                                               else:
+                                                                       cursor[posn] = endcur[posn]
+                                                       else:
+                                                               state[posn] = "end"
+                                                               if cursor[posn] == startcur[posn]:
+                                                                       cursor[posn] = endcur[posn]
+                                                               else:
+                                                                       cursor[posn] = startcur[posn]
+                                               else:
+                                                       if activedir[posn] == "right":
+                                                               state[posn] = "end"
+                                                               if cursor[posn] == startcur[posn]:
+                                                                       cursor[posn] = startcur[posn]
+                                                               else:
+                                                                       cursor[posn] = endcur[posn]
+                                                       else:
+                                                               state[posn] = "start"
+                                                               if cursor[posn] == startcur[posn]:
+                                                                       cursor[posn] = endcur[posn]
+                                                               else:
+                                                                       cursor[posn] = startcur[posn]
+                                               activedir[posn] = "right"
+                                       if state[posn] == "init":
+                                               activedir[posn] = "right"
+                                               check[posn] = 1
+                                               state[posn] = "end"
+                                               cursor[posn] = endcur[posn]
+                                       if activedir[posn] == "right":
+                                               addedge()
+                                       else:
+                                               removeedge()
+                       return {'RUNNING_MODAL'}
+               elif event.type == "UP_ARROW":
+                       # next cursor possibility
+                       if event.value == "PRESS":
+                               counter += 1
+                               mesh.update()
+                       return {'RUNNING_MODAL'}
+               elif event.type == "DOWN_ARROW":
+                       # previous cursor possibility
+                       if event.value == "PRESS":
+                               counter -= 1
+                               mesh.update()
+                       return {'RUNNING_MODAL'}
+               
+               return {'RUNNING_MODAL'}
+
+def addedge():
+       
+       global edgelist, mesh, change
+       
+       # add edge to edgelist
+       change = 1
+       if state[posn] == "start":
+               edgelist[posn].insert(0, cursor[posn])
+       if state[posn] == "end":
+               edgelist[posn].append(cursor[posn])
+       cursor[posn].verts[0].select = 1
+       cursor[posn].verts[1].select = 1
+       cursor[posn].select = 1 
+       mesh.update()
+
+def removeedge():
+       
+       global edgelist, mesh, cursor, change
+       
+       # removve edge from edgelist
+       change = 1
+       if state[posn] == "start":
+               for vert in edgelist[posn][0].verts:
+                       if vert in cursor[posn].verts:
+                               vert.select = 0
+               cursor[posn] = edgelist[posn][0]
+               edgelist[posn].pop(0)
+       if state[posn] == "end":
+               for vert in edgelist[posn][len(edgelist[posn]) - 1].verts:
+                       if vert in cursor[posn].verts:
+                               vert.select = 0
+               cursor[posn] = edgelist[posn][len(edgelist[posn]) - 1]
+               edgelist[posn].pop(len(edgelist[posn]) - 1)
+       cursor[posn].select = 0
+       mesh.update()
+
+
+
+
+def panel_func(self, context):
+       scn = bpy.context.scene
+       self.layout.label(text="EdgeGrow:")
+       self.layout.operator("mesh.edgegrow", text="Grow Edges")
+
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+
+def unregister():
+       bpy.utils.unregister_class(EdgeGrow)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+
+
+def getscreencoords(vector):
+       
+       # calculate screen coords for given Vector
+       
+       region = bpy.context.region
+       rv3d = bpy.context.space_data.region_3d 
+       pvector = vector * matrix
+       pvector = pvector + selobj.location
+       svector = view3d_utils.location_3d_to_region_2d(region, rv3d, pvector)
+       if svector == None:
+               return [0, 0 ,0]
+       else:
+               return [svector[0], svector[1], pvector[2]]
+
+
+
+def addstart(vert):
+       
+       global selset, edgelist
+
+       # recursive: adds to initial edgelist at start
+       for e in vert.link_edges:
+               if e in selset:
+                       selset.discard(e)
+                       v = e.other_vert(vert)
+                       edgelist[posn].insert(0, e)
+                       addstart(v)
+                       break
+
+def addend(vert):
+       
+       global selset, edgelist
+
+       # recursive: adds to initial edgelist at end
+       for e in vert.link_edges:
+               if e in selset:
+                       selset.discard(e)
+                       v = e.other_vert(vert)
+                       edgelist[posn].append(e)
+                       addend(v)
+                       break
+
+
+def do_edgegrow(self):
+
+       global bm, mesh, selobj, actedge
+       global selset, edgelist, posn, startlen
+       global viewchange, check, change, stop
+       global state, oldstate, cursor, startcur, endcur, activedir, singledir
+       
+       viewchange = 0
+       change = 1
+       stop = 0
+
+       context = bpy.context
+       region = context.region  
+       area = context.area
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+       actedge = bm.select_history.active
+       # get transf matrix
+       adapt()
+
+       # vsellist, essellist: remember selection for reselecting later
+       selset = set([])
+       vsellist = []
+       esellist = []
+       for edge in bm.edges:
+               if edge.select:
+                       selset.add(edge)
+                       esellist.append(edge)           
+       for vert in bm.verts:
+               if vert.select:
+                       vsellist.append(vert)           
+
+       state = []
+       oldstate = []
+       cursor = []
+       startcur = []
+       endcur = []
+       check = []
+       activedir = []
+       posn = 0
+       singledir = {}
+       singledir[0] = None
+       startlen = []
+       edgelist = []
+       while len(selset) > 0:
+               # initialize next edgesnake
+               state.append("init")
+               oldstate.append("init")
+               cursor.append(None)
+               startcur.append(None)
+               endcur.append(None)
+               check.append(0)
+               activedir.append("")
+               
+               edgelist.append([])
+               elem = selset.pop()
+               vert = elem.verts[0]
+               selset.add(elem)
+               # add to start and end of arbitrary start vert
+               addstart(vert)
+               addend(vert)
+               startlen.append(len(edgelist[posn]))
+               posn += 1
+       if len(edgelist) == 1:
+               if len(edgelist[0]) == 1:
+                       # must store leftmost vert as startingvert when only one edge selected
+                       x1, y, z = getscreencoords(edgelist[0][0].verts[0].co)
+                       x2, y, z = getscreencoords(edgelist[0][0].verts[1].co)
+                       if x1 < x2:
+                               singledir[0] = edgelist[0][0].verts[0]
+                       else:
+                               singledir[0] = edgelist[0][0].verts[1]
+       
+       # orient first edgesnake from left(start) to right(end)
+       x1, y, z = getscreencoords(edgelist[0][0].verts[0].co)
+       x2, y, z = getscreencoords(edgelist[0][len(edgelist[0]) - 1].verts[0].co)
+       if x1 > x2:
+               edgelist[0].reverse()                           
+               
+       
+       # 
+       # orient edge and vertlists parallel - reverse if necessary
+       for i in range(len(edgelist) - 1):
+               bpy.ops.mesh.select_all(action="DESELECT")
+               # get first vert and edge for two adjacent snakes
+               for v in edgelist[i][0].verts:
+                       if len(edgelist[i]) == 1:
+                               if i == 0:
+                                       x1, y, z = getscreencoords(v.co)
+                                       x2, y, z = getscreencoords(edgelist[i][0].other_vert(v).co)
+                                       if x1 < x2:
+                                               singledir[0] = v
+                                       else:
+                                               singledir[0] = edgelist[i][0].other_vert(v)
+                               vt = singledir[i]       
+                               vt.select = 1
+                               bm.select_history.add(vt)
+                               v1 = vt
+                               e1 = edgelist[i][0]
+                               break
+                       elif not(v in edgelist[i][1].verts):
+                               v.select = 1
+                               bm.select_history.add(v)
+                               v1 = v
+                               e1 = edgelist[i][0]
+               for v in edgelist[i+1][0].verts:
+                       if len(edgelist[i+1]) == 1:
+                               v.select = 1
+                               bm.select_history.add(v)
+                               v2 = v
+                               e2 = edgelist[i+1][0]
+                               break
+                       elif not(v in edgelist[i+1][1].verts):
+                               v.select = 1
+                               bm.select_history.add(v)
+                               v2 = v
+                               e2 = edgelist[i+1][0]
+               singledir[i+1] = v2
+               bm.select_history.validate()
+               # get path between startverts for checking orientation
+               bpy.ops.mesh.shortest_path_select()
+               
+               for e in bm.edges:
+                       if e.verts[0].select and e.verts[1].select:
+                               e.select = 1
+               
+               # correct selected path when not connected neatly to vert from left or right(cant know direction)
+               def correctsel(e1, v1, lst):
+                       found = 0
+                       while not(found):
+                               found = 1
+                               for edge in e1.other_vert(v1).link_edges:
+                                       if edge.select and edge != e1:
+                                               if lst.index(e1) < len(lst) - 1:
+                                                       v1.select = 0
+                                                       e1.select = 0
+                                                       v1 = e1.other_vert(v1)
+                                                       e1 = lst[lst.index(e1) + 1]
+                                               else:
+                                                       templ = list(e1.other_vert(v1).link_faces)
+                                                       for f in e1.link_faces:
+                                                               templ.pop(templ.index(f))
+                                                       for edge in e1.other_vert(v1).link_edges:
+                                                               if edge in templ[0].edges and edge in templ[1].edges:
+                                                                       v1.select = 0
+                                                                       e1.select = 0
+                                                                       v1 = e1.other_vert(v1)
+                                                                       e1 = edge
+                                               found = 0
+                                                                       
+                       # check situation where left/right connection is on vert thats outside slice
+                       found = 0
+                       while not(found):
+                               templ = list(v1.link_faces)
+                               for f in e1.link_faces:
+                                       templ.pop(templ.index(f))
+                               found = 1
+                               for edge in v1.link_edges:
+                                       if edge in templ[0].edges and edge in templ[1].edges:
+                                               if edge.other_vert(v1).select:
+                                                       v1.select = 0
+                                                       edge.select = 0
+                                                       v1 = edge.other_vert(v1)
+                                                       e1 = edge
+                                                       found = 0
+                       return e1, v1
+                                                       
+               e1, v1 = correctsel(e1, v1, edgelist[i])
+               e2, v2 = correctsel(e2, v2, edgelist[i+1])                                      
+               
+               # do all the checking to see if the checked lists must be reversed
+               brk = 0
+               for face1 in e1.link_faces:
+                       for edge1 in face1.edges:
+                               if edge1.select:
+                                       for loop1 in face1.loops:
+                                               if loop1.vert == v1:
+                                                       if loop1.edge == e1:
+                                                               turn = loop1
+                                                       elif loop1.link_loop_next.edge == e1:
+                                                               turn = loop1.link_loop_next
+                                                       else:
+                                                               turn = loop1.link_loop_prev
+                                                       # check if turning in one direction
+                                                       if turn.link_loop_next.edge.select:
+                                                               for face2 in e2.link_faces:
+                                                                       for edge2 in face2.edges:
+                                                                               if edge2.select:
+                                                                                       for loop2 in face2.loops:
+                                                                                               if loop2.vert == v2:
+                                                                                                       if loop2.edge == e2:
+                                                                                                               turn = loop2
+                                                                                                       elif loop2.link_loop_next.edge == e2:
+                                                                                                               turn = loop2.link_loop_next
+                                                                                                       else:
+                                                                                                               turn = loop2.link_loop_prev
+                                                                                                       if turn.link_loop_next.edge.select:
+                                                                                                               singledir[i+1] = e2.other_vert(v2)
+                                                                                                               edgelist[i+1].reverse()
+                                                                                                       break
+                                                                                       brk = 1
+                                                                                       break
+                                                                       if brk == 1:
+                                                                               break
+                                                       # and the other
+                                                       elif loop1.link_loop_prev.edge.select:
+                                                               for face2 in e2.link_faces:
+                                                                       for edge2 in face2.edges:
+                                                                               if edge2.select:
+                                                                                       for loop2 in face2.loops:
+                                                                                               if loop2.vert == v2:
+                                                                                                       if loop2.edge == e2:
+                                                                                                               turn = loop2
+                                                                                                       elif loop2.link_loop_next.edge == e2:
+                                                                                                               turn = loop2.link_loop_next
+                                                                                                       else:
+                                                                                                               turn = loop2.link_loop_prev
+                                                                                                       if turn.link_loop_prev.edge.select:
+                                                                                                               singledir[i+1] = e2.other_vert(v2)
+                                                                                                               edgelist[i+1].reverse()
+                                                                                                       break
+                                                                                       brk = 1
+                                                                                       break
+                                                                       if brk == 1:
+                                                                               break
+                                                       break
+                                       break
+                                       
+       for posn in range(len(edgelist)):
+               if edgelist[posn][0] == actedge:
+                       for posn in range(len(edgelist)):
+                               edgelist[posn].reverse()
+                                       
+       bpy.ops.mesh.select_all(action="DESELECT")
+       for v in vsellist:
+               v.select = 1
+       for e in esellist:
+               e.select = 1
+
+
+       region.tag_redraw()
+
+
+
+def adapt():
+       
+       global matrix
+       global bm, mesh, selobj
+       global mbns, viewchange
+       global selobj
+       
+       # Rotating / panning / zooming 3D view is handled here.
+       # Get matrix.
+       if selobj.rotation_mode == "AXIS_ANGLE":
+               # when roataion mode is axisangle
+               angle, x, y, z =  selobj.rotation_axis_angle
+               matrix = Matrix.Rotation(-angle, 4, Vector((x, y, z)))
+       elif selobj.rotation_mode == "QUATERNION":
+               # when rotation on object is quaternion
+               w, x, y, z = selobj.rotation_quaternion
+               x = -x
+               y = -y
+               z = -z
+               quat = Quaternion([w, x, y, z])
+               matrix = quat.to_matrix()
+               matrix.resize_4x4()
+       else:
+               # when rotation of object is euler
+               ax, ay, az = selobj.rotation_euler
+               mat_rotX = Matrix.Rotation(-ax, 4, 'X')
+               mat_rotY = Matrix.Rotation(-ay, 4, 'Y')
+               mat_rotZ = Matrix.Rotation(-az, 4, 'Z')
+       if selobj.rotation_mode == "XYZ":
+               matrix = mat_rotX * mat_rotY * mat_rotZ
+       elif selobj.rotation_mode == "XZY":
+               matrix = mat_rotX * mat_rotZ * mat_rotY
+       elif selobj.rotation_mode == "YXZ":
+               matrix = mat_rotY * mat_rotX * mat_rotZ
+       elif selobj.rotation_mode == "YZX":
+               matrix = mat_rotY * mat_rotZ * mat_rotX
+       elif selobj.rotation_mode == "ZXY":
+               matrix = mat_rotZ * mat_rotX * mat_rotY
+       elif selobj.rotation_mode == "ZYX":
+               matrix = mat_rotZ * mat_rotY * mat_rotX
+
+       # handle object scaling
+       sx, sy, sz = selobj.scale
+       mat_scX = Matrix.Scale(sx, 4, Vector([1, 0, 0]))
+       mat_scY = Matrix.Scale(sy, 4, Vector([0, 1, 0]))
+       mat_scZ = Matrix.Scale(sz, 4, Vector([0, 0, 1]))
+       matrix = mat_scX * mat_scY * mat_scZ * matrix
+
+
+def getedge(vert, edge):
+       
+       global sortlist, startedge
+       
+       # get the next edge in list of edges rotating from/around vert at seelection end (for cursor choice)
+       for loop in vert.link_loops:
+               if loop.edge == edge:
+                       edge = loop.link_loop_prev.edge
+                       if edge == startedge:
+                               break
+                       sortlist.append(edge)
+                       getedge(vert, edge)
+                       break
+
+def drawedges(vert, edge):
+       
+       global sortlist, startedge, tempcur, change, counter
+       
+       # get sorted list of possible cursor choices
+       sortlist = []
+       startedge = edge
+       getedge(vert, edge)
+       if len(vert.link_edges) - len(sortlist) > 1:
+               for e in vert.link_edges:
+                       if e != startedge:
+                               if not(e in sortlist):
+                                       sortlist.append(e)
+       # calculate new cursor position in sortlist if changed                  
+       if change:
+               if len(sortlist) == 2 and (len(sortlist[0].link_faces) == 1 or len(sortlist[1].link_faces) == 1):
+                       for f in startedge.link_faces:
+                               for e in sortlist:
+                                       tel = 0
+                                       if e.verts[0] in f.verts:
+                                               tel += 1
+                                               vfound = e.verts[1]
+                                       if e.verts[1] in f.verts:
+                                               tel += 1
+                                               vfound = e.verts[0]
+                                       if tel == 1:
+                                               break
+                       for e in sortlist:
+                               if vfound in e.verts:
+                                       cnt = sortlist.index(e)
+               else:
+                       # standard middle edge is cursor
+                       cnt = int((len(sortlist) - 1) / 2)
+               counter = cnt
+       else:
+               # do revert to start when past end and other way around
+               if counter >= len(sortlist):
+                       cnt = counter - (int(counter / len(sortlist)) * len(sortlist))
+               elif counter < 0:
+                       cnt = counter
+                       while cnt < 0:
+                               cnt += len(sortlist)
+               else:
+                       cnt = counter
+       # draw cursor possibilities in blue, current in red
+       for edge in sortlist:
+               if sortlist.index(edge) == cnt:
+                       tempcur = edge
+                       glColor3f(1.0, 0, 0)
+               else:
+                       glColor3f(0.2, 0.2, 1.0)
+               glBegin(GL_LINES)
+               x, y, dummy = getscreencoords(edge.verts[0].co)
+               glVertex2f(x, y)
+               x, y, dummy = getscreencoords(edge.verts[1].co)
+               glVertex2f(x, y)
+               glEnd()
+                       
+def setcursors(v):
+       
+       global startcur, endcur, posn
+       
+       # what it says
+       if oldstate[posn] == "start":
+               if v in cursor[posn].verts:
+                       startcur[posn] = tempcur
+               else:
+                       endcur[posn] = tempcur
+       elif oldstate[posn] == "end":
+               if v in cursor[posn].verts:
+                       endcur[posn] = tempcur
+               else:
+                       startcur[posn] = tempcur
+
+
+def redraw():
+       
+       global viewchange, edgelist, state, oldstate, check
+       global cursor, startcur, endcur, tempcur, change, posn
+       
+       # user changes view
+       if viewchange:
+               viewchange = 0
+               adapt()
+       
+       # reinit if returning to initial state
+       for lst in edgelist:
+               posn = edgelist.index(lst)
+               oldstate[posn] = state[posn]
+               if len(lst) == startlen[posn]:
+                       if check[posn]:
+                               state[posn] = "reinit"
+               else:
+                       check[posn] = 1
+       
+       for lst in edgelist:
+               posn = edgelist.index(lst)
+               
+               if state[posn] == "init" or state[posn] == "reinit":
+                       if len(lst) == 1:
+                               # if snake is one edge, use singledir vert for orientation
+                               v = lst[0].verts[0]
+                               drawedges(v, lst[0])
+                               setcursors(v)
+                               if oldstate[posn] == "init":
+                                       if singledir[posn] == v:
+                                               startcur[posn] = tempcur
+                                       else:
+                                               endcur[posn] = tempcur
+                               v = lst[0].verts[1]
+                               drawedges(v, lst[0])
+                               setcursors(v)
+                               if oldstate[posn] == "init":
+                                       if singledir[posn] == v:
+                                               startcur[posn] = tempcur
+                                       else:
+                                               endcur[posn] = tempcur
+                       else:
+                               # draw and set start and end cursors
+                               edge = lst[0]
+                               edge.select = 0
+                               for vert in edge.verts:
+                                       if not(vert in lst[1].verts):
+                                               drawedges(vert, edge)
+                                               startcur[posn] = tempcur
+                               edge = lst[len(lst) - 1]
+                               edge.select = 0
+                               for vert in edge.verts:
+                                       if not(vert in lst[len(lst) - 2].verts):
+                                               drawedges(vert, edge)
+                                               endcur[posn] = tempcur
+               elif state[posn] == "start":
+                       # draw and set cursor at start
+                       edge = lst[0]
+                       for vert in edge.verts:
+                               if not(vert in lst[1].verts):
+                                       drawedges(vert, edge)
+                                       cursor[posn] = tempcur
+               elif state[posn] == "end":
+                       # draw and set cursor at end
+                       edge = lst[len(lst) - 1]
+                       for vert in edge.verts:
+                               if not(vert in lst[len(lst) - 2].verts):
+                                       drawedges(vert, edge)
+                                       cursor[posn] = tempcur
+               for e in edgelist[posn]:
+                       e.verts[0].select = 1
+                       e.verts[1].select = 1
+                       e.select = 1
+                       
+       change = 0
+       
+
+
diff --git a/EWOCprojects tools/mesh_edgetune.py b/EWOCprojects tools/mesh_edgetune.py
new file mode 100644 (file)
index 0000000..4a2725d
--- /dev/null
@@ -0,0 +1,625 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+This script is an implementation of the concept of sliding vertices around
+   on edges.  It is used to finetune/redraw edges/edgeloops through the process of sliding
+   vertices.  It can be used to slide anything anywhere.
+   To my knowledge this is a new concept in 3D modeling. Try it and you will
+   see how it can impact your modeling habits.
+   You are able to tune vertices by sliding by freehand-redrawing them on the
+   edges they are part of.
+   
+
+
+   Documentation
+   
+   
+   First install the addon by going to User Preferences-> AddOns and choosing
+   "Install from file". Locate the downloaded file and install it.
+   Enable the script in User Preferences->AddOns->Mesh.
+
+   
+   The addon will work on any vertice/edge/face-selection. 
+   Make a selection, click the EdgeTune button on the Mesh Tools panel.
+   (addon only accessible when in EditMode).   
+
+   The selection will be visualized in yellow.
+   EdgeTune will abide by the limited visibility setting.
+   Press and hold left-mouse button and draw freely across the "slide-edges",
+   visualized in red.
+   The respective selected vertices will change position on the slide-edge to
+   the new position you choose by moving over it with the left mouse-button
+   pressed.  Vertices can be made to move past the end of the edge by
+   keeping leftmouse pressed, and moving along the supporting edge and
+   further in that same direction.
+
+   Undo one step a time with Ctrl-Z.
+   Press ENTER/RETURN to finalize the operation.
+
+   Just press the right-mouse-button to cancel the addon operation.
+
+   Change orientation the standard Blender way.
+   HINT: EdgeTune is also multi-vertex-slide."""
+
+
+bl_info = {
+       "name": "EdgeTune",
+       "author": "Gert De Roost",
+       "version": (3, 4, 0),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Tuning edgeloops by redrawing them manually, sliding verts.",
+       "warning": "",
+       "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Mesh/EdgeTune",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+
+
+
+import bpy
+from bpy_extras import *
+from bgl import *
+import math
+from mathutils import *
+import bmesh
+
+
+
+
+
+
+
+class EdgeTune(bpy.types.Operator):
+       bl_idname = "mesh.edgetune"
+       bl_label = "Tune Edge"
+       bl_description = "Tuning edgeloops by redrawing them manually, sliding verts"
+       bl_options = {"REGISTER", "UNDO"}
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               
+               self.scn = context.scene
+               self.screen = context.screen
+               self.area = context.area
+               self.region = context.region  
+               self.selobj = context.active_object
+               self.init_edgetune()
+               
+               context.window_manager.modal_handler_add(self)
+               self._handle = bpy.types.SpaceView3D.draw_handler_add(self.redraw, (), 'WINDOW', 'POST_PIXEL')
+               
+               return {'RUNNING_MODAL'}
+
+
+       def modal(self, context, event):
+       
+               self.viewchange = False
+               if event.type == 'LEFTMOUSE':
+                       if event.value == 'PRESS':
+                               self.mbns = True
+                       if event.value == 'RELEASE':
+                               self.mbns = False
+                               self.contedge = None
+                               self.movedoff = True
+               if event.type == 'RIGHTMOUSE':
+                       # cancel operation, reset to bmumdo mesh
+                       bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+                       self.bm.free()
+                       bpy.ops.object.editmode_toggle()
+                       self.bmundo.to_mesh(self.mesh)
+                       bpy.ops.object.editmode_toggle()
+                       return {'CANCELLED'}
+               elif event.type == 'MIDDLEMOUSE':
+                       # recalculate view parameters
+                       self.viewchange = True
+                       return {'PASS_THROUGH'}
+               elif event.type in {'WHEELDOWNMOUSE', 'WHEELUPMOUSE'}:
+                       # recalculate view parameters
+                       self.viewchange = True          
+                       return {'PASS_THROUGH'}
+               elif event.type == 'Z':
+                       if event.value == 'PRESS':
+                               if event.ctrl:
+                                       if self.undolist != []:
+                                               # put one vert(last) back to undo coordinate, found in list
+                                               self.undolist.pop(0)
+                                               vert = self.bm.verts[self.undocolist[0][0].index]
+                                               vert.co[0] = self.undocolist[0][1]
+                                               vert.co[1] = self.undocolist[0][2]
+                                               vert.co[2] = self.undocolist[0][3]
+                                               self.undocolist.pop(0)
+                                               self.mesh.update()
+                       return {'RUNNING_MODAL'}
+                       
+               elif event.type == 'RET':
+                       # Consolidate changes.
+                       # Free the bmesh.
+                       self.bm.free()
+                       self.bmundo.free()
+                       bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
+                       return {'FINISHED'}
+                       
+               elif event.type == 'MOUSEMOVE':
+                       mxa = event.mouse_x
+                       mya = event.mouse_y
+                       self.region = None
+                       for a in context.screen.areas:
+                               if not(a.type == 'VIEW_3D'):
+                                       continue
+                               for r in a.regions:
+                                       if not(r.type == 'WINDOW'):
+                                               continue
+                                       if mxa > r.x and mya > r.y and mxa < r.x + r.width and mya < r.y + r.height:
+                                               self.region = r
+                                               break
+                                       
+                       if not(self.region):
+                               return {'RUNNING_MODAL'}
+                       mx = mxa - self.region.x
+                       my = mya - self.region.y
+
+                       hoveredge = None
+       
+                       # First check mouse is in bounding box edge of which edges.
+                       testscrl = []
+                       for edge in self.slideedges[self.region]:
+                               x1, y1, dummy = self.getscreencoords(edge.verts[0].co, self.region)
+                               x2, y2, dummy = self.getscreencoords(edge.verts[1].co, self.region)
+                               if x1 < x2:
+                                       lwpx = x1 - 5
+                                       uppx = x2 + 5
+                               else:
+                                       lwpx = x2 - 5
+                                       uppx = x1 + 5
+                               if y1 < y2:
+                                       lwpy = y1 - 5
+                                       uppy = y2 + 5
+                               else:
+                                       lwpy = y2 - 5
+                                       uppy = y1 + 5           
+                               if (((x1 < mx < x2) or (x2 < mx < x1)) and (lwpy < my < uppy)) or (((y1 < my < y2) or (y2 < my < y1)) and (lwpx < mx < uppx)):
+                                       testscrl.append(edge)
+                               if self.contedge != None:
+                                       testscrl.append(self.contedge)
+       
+                       # Then check these edges to see if mouse is on one of them.
+                       allhoveredges = []
+                       hovering = False
+                       zmin = 1e10
+                       if testscrl != []:
+                               for edge in testscrl:
+                                       x1, y1, z1 = self.getscreencoords(edge.verts[0].co, self.region)
+                                       x2, y2, z2 = self.getscreencoords(edge.verts[1].co, self.region)
+       
+                                       if x1 == x2 and y1 == y2:
+                                               dist = math.sqrt((mx - x1)**2 + (my - y1)**2)
+                                       else:
+                                               dist = ((mx - x1)*(y2 - y1) - (my - y1)*(x2 - x1)) / math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
+       
+                                       if -5 < dist < 5:
+                                               if self.movedoff or (not(self.movedoff) and edge == self.contedge):
+                                                       allhoveredges.append(edge)
+                                                       if hoveredge != None and ((z1 + z2) / 2) > zmin:
+                                                               pass
+                                                       else:
+                                                               hovering = True
+                                                               hoveredge = edge
+                                                               zmin = (z1 + z2) / 2
+                                                               self.mouseover = True
+                                                               x1, y1, dummy = self.getscreencoords(hoveredge.verts[0].co, self.region)
+                                                               x2, y2, dummy = self.getscreencoords(hoveredge.verts[1].co, self.region)
+                                                               for r in self.regions:
+                                                                       self.bx1[r], self.by1[r], dummy = self.getscreencoords(hoveredge.verts[0].co, r)
+                                                                       self.bx2[r], self.by2[r], dummy = self.getscreencoords(hoveredge.verts[1].co, r)
+                                                               self.region.tag_redraw()
+                                                               break
+                                                               
+                       if hovering == False:
+                               self.movedoff = True
+                               if self.mouseover == True:
+                                       self.highoff = True
+                                       self.region.tag_redraw()
+                               self.mouseover = False
+                               self.bx1[self.region] = -1 
+                               self.bx2[self.region] = -1
+                               self.by1[self.region] = -1
+                               self.by2[self.region] = -1, -1, -1, -1
+                       
+       
+       
+                       if hoveredge != None and self.mbns == True:
+                               self.contedge = edge
+                               self.movedoff = False
+                               # Find projection mouse perpend on edge.
+                               if x1 == x2:    x1 += 1e-6
+                               if y1 == y2:    y1 += 1e-6
+                               a = (x2 - x1) / (y2 - y1)
+                               x = ((x1 / a) + (mx * a) + my - y1) / ((1 / a) + a)
+                               y = ((mx - x) * a) + my
+                               # Calculate relative position on edge and adapt screencoords accoringly.
+                               div = (x - x1) / (x2 - x1)
+                               if hoveredge.verts[0] in self.sverts[self.region]:
+                                       vert = hoveredge.verts[0]
+                                       vert2 = hoveredge.verts[1]
+                               else:
+                                       vert = hoveredge.verts[1]
+                                       vert2 = hoveredge.verts[0]
+                                       
+                               # Update local undo info.
+                               if self.undolist == []:
+                                       self.undolist.insert(0, hoveredge)
+                                       self.undocolist.insert(0, [vert, vert.co[0], vert.co[1], vert.co[2]])
+                               if self.undolist[0] != hoveredge:
+                                       self.undolist.insert(0, hoveredge)
+                                       self.undocolist.insert(0, [vert, vert.co[0], vert.co[1], vert.co[2]])
+
+                               hx1, hy1, dummy = self.getscreencoords(hoveredge.verts[0].co, self.region)
+                               hx2, hy2, dummy = self.getscreencoords(hoveredge.verts[1].co, self.region)
+                               coords = [((hx2 - hx1) * div ) + hx1, ((hy2 - hy1) * div ) + hy1]
+                               for verts in self.selverts[self.region]:
+                                       if vert == verts[0]:
+                                               self.selcoords[self.region][self.selverts[self.region].index(verts)][0] = coords
+                                       elif vert == verts[1]:  
+                                               self.selcoords[self.region][self.selverts[self.region].index(verts)][1] = coords
+                               if vert in self.singles:
+                                       self.boxes[self.region][self.singles.index(vert)] = coords
+                               # Calculate new vert 3D coordinates.            
+                               vx1, vy1, vz1 = hoveredge.verts[0].co[:]
+                               vx2, vy2, vz2 = hoveredge.verts[1].co[:]
+                               self.vertd[vert] = [((vx2 - vx1) * div ) + vx1, ((vy2 - vy1) * div ) + vy1, ((vz2 - vz1) * div ) + vz1]
+                               vert = self.bm.verts[vert.index]
+                               vert.co[0] = ((vx2 - vx1) * div ) + vx1
+                               vert.co[1] = ((vy2 - vy1) * div ) + vy1
+                               vert.co[2] = ((vz2 - vz1) * div ) + vz1
+                               self.mesh.update()
+                               
+               return {'RUNNING_MODAL'}
+
+
+       def getmatrix(self, obj):
+               
+               # Calculate matrix.
+               if obj.rotation_mode == 'AXIS_ANGLE':
+                       # object rotationmode axisangle
+                       ang, x, y, z =  obj.rotation_axis_angle
+                       mat = Matrix.Rotation(-ang, 4, Vector((x, y, z)))
+               elif obj.rotation_mode == 'QUATERNION':
+                       # object rotationmode quaternion
+                       w, x, y, z = obj.rotation_quaternion
+                       x = -x
+                       y = -y
+                       z = -z
+                       quat = Quaternion([w, x, y, z])
+                       mat = quat.to_matrix()
+                       mat.resize_4x4()
+               else:
+                       # object rotationmode euler
+                       ax, ay, az = obj.rotation_euler
+                       mat_rotX = Matrix.Rotation(-ax, 4, 'X')
+                       mat_rotY = Matrix.Rotation(-ay, 4, 'Y')
+                       mat_rotZ = Matrix.Rotation(-az, 4, 'Z')
+               if obj.rotation_mode == 'XYZ':
+                       mat = mat_rotX * mat_rotY * mat_rotZ
+               elif obj.rotation_mode == 'XZY':
+                       mat = mat_rotX * mat_rotZ * mat_rotY
+               elif obj.rotation_mode == 'YXZ':
+                       mat = mat_rotY * mat_rotX * mat_rotZ
+               elif obj.rotation_mode == 'YZX':
+                       mat = mat_rotY * mat_rotZ * mat_rotX
+               elif obj.rotation_mode == 'ZXY':
+                       mat = mat_rotZ * mat_rotX * mat_rotY
+               elif obj.rotation_mode == 'ZYX':
+                       mat = mat_rotZ * mat_rotY * mat_rotX
+       
+               # handle object scaling
+               sx, sy, sz = obj.scale
+               mat_scX = Matrix.Scale(sx, 4, Vector([1, 0, 0]))
+               mat_scY = Matrix.Scale(sy, 4, Vector([0, 1, 0]))
+               mat_scZ = Matrix.Scale(sz, 4, Vector([0, 0, 1]))
+               mat = mat_scX * mat_scY * mat_scZ * mat
+               
+               return mat
+       
+       
+       def adapt(self):
+               
+               self.firstrun = False
+                       
+               self.regions = []
+               self.spaces = []
+               self.halfheight = {}
+               self.halfwidth = {}
+               self.perspm = {}
+               for a in self.screen.areas:
+                       if not(a.type == 'VIEW_3D'):
+                               continue
+                       for r in a.regions:
+                               if not(r.type == 'WINDOW'):
+                                       continue
+                               self.regions.append(r)
+                               self.halfwidth[r] = r.width / 2
+                               self.halfheight[r] = r.height / 2
+                               for sp in a.spaces:
+                                       if sp.type == 'VIEW_3D':
+                                               self.spaces.append(sp)
+                                               self.perspm[r] = sp.region_3d.perspective_matrix
+                                               
+               self.selcoords = {}
+               self.slidecoords = {}
+               self.boxes = {}
+               self.sverts = {}
+               self.selverts = {}
+               self.seledges = {}
+               self.slideverts = {}
+               self.slideedges = {}
+               for r in self.regions:
+                       self.selcoords[r] = []
+                       self.slidecoords[r] = []
+                       self.boxes[r] = []
+                       self.sverts[r] = []
+                       self.selverts[r] = []
+                       self.seledges[r] = []
+                       self.slideverts[r] = []
+                       self.slideedges[r] = []
+                       
+               for r in self.regions:
+
+                       self.getlayout(r)
+                       
+                       # recalculate screencoords in lists
+                       for posn in range(len(self.selverts[r])):
+                               self.selcoords[r][posn] = [self.getscreencoords(Vector(self.vertd[self.selverts[r][posn][0]]), r)[:2], self.getscreencoords(Vector(self.vertd[self.selverts[r][posn][1]]), r)[:2]]
+                       for posn in range(len(self.slideverts[r])):
+                               self.slidecoords[r][posn] = [self.getscreencoords(self.slideverts[r][posn][0].co, r)[:2],  self.getscreencoords(self.slideverts[r][posn][1].co, r)[:2]]
+                       for posn in range(len(self.singles)):
+                               self.boxes[r][posn] = self.getscreencoords(Vector(self.vertd[self.singles[posn]]), r)[:2]
+                       
+       
+       
+       def getscreencoords(self, vector, reg):
+       
+               # calculate screencoords of given Vector
+               vector = vector * self.matrix
+               vector = vector + self.selobj.location
+               prj = self.perspm[reg] * vector.to_4d()
+               return (self.halfwidth[reg] + self.halfwidth[reg] * (prj.x / prj.w), self.halfheight[reg] + self.halfheight[reg] * (prj.y / prj.w), prj.z)
+       
+       
+       
+       
+       def init_edgetune(self):
+       
+               self.mesh = self.selobj.data
+               self.bm = bmesh.from_edit_mesh(self.mesh)
+               self.bmundo = self.bm.copy()
+       
+               self.viewwidth = self.area.width
+               self.viewheight = self.area.height
+               
+               #remember initial selection
+               self.keepverts = []
+               for vert in self.bm.verts:
+                       if vert.select:
+                               self.keepverts.append(vert)
+               self.keepedges = []
+               for edge in self.bm.edges:
+                       if edge.select:
+                               self.keepedges.append(edge)
+       
+               self.firstrun = True
+               self.highoff = False
+               self.mbns = False
+               self.viewchange = False
+               self.mouseover = False  
+               self.bx1, self.bx2, self.by1, self.by2 = {}, {}, {}, {}
+               self.undolist = []
+               self.undocolist = []
+               self.contedge = None
+       
+               self.matrix = self.getmatrix(self.selobj)
+               obj = self.selobj
+               while obj.parent:
+                       self.matrix *= getmatrix(obj.parent)
+                       obj = obj.parent
+       
+               self.adapt()
+               for r in self.regions:
+                       r.tag_redraw()
+       
+       
+       
+       def getlayout(self, reg):
+               
+               # seledges: selected edges list
+               # selverts: selected verts list per edge
+               # selcoords: selected verts coordinate list per edge
+               self.sverts[reg] = []
+               self.seledges[reg] = []
+               self.selverts[reg] = []
+               self.selcoords[reg] = []
+               visible = {}
+               if self.spaces[self.regions.index(reg)].use_occlude_geometry:
+                       rv3d = self.spaces[self.regions.index(reg)].region_3d
+                       eyevec = Vector(rv3d.view_matrix[2][:3])
+                       eyevec.length = 100000
+                       eyeloc = Vector(rv3d.view_matrix.inverted().col[3][:3])
+                       for vert in self.keepverts:
+                               vno = vert.normal
+                               vno.length = 0.0001
+                               vco = (vert.co + vno) * self.matrix + self.selobj.location
+                               if rv3d.is_perspective:
+                                       hit = self.scn.ray_cast(vco, eyeloc)
+                                       if hit[0]:
+                                               vno = -vno
+                                               vco = (vert.co + vno) * self.matrix + self.selobj.location
+                                               hit = self.scn.ray_cast(vco, eyevec)
+                               else:
+                                       hit = self.scn.ray_cast(vco, vco + eyevec)
+                                       if hit[0]:
+                                               vno = -vno
+                                               vco = (vert.co + vno) * self.matrix + self.selobj.location
+                                               hit = self.scn.ray_cast(vco, vco + eyevec)
+                               if not(hit[0]):
+                                       visible[vert] = True
+                                       self.sverts[reg].append(self.bmundo.verts[vert.index])
+                               else:
+                                       visible[vert] = False
+               else:
+                       for vert in self.keepverts:
+                               visible[vert] = True
+                               self.sverts[reg].append(self.bmundo.verts[vert.index])
+                               
+               for edge in self.keepedges:
+                       if visible[edge.verts[0]] and visible[edge.verts[1]]:
+                               edge = self.bmundo.edges[edge.index]
+                               self.seledges[reg].append(edge)
+                               self.selverts[reg].append([edge.verts[0], edge.verts[1]])
+                               x1, y1, dummy = self.getscreencoords(edge.verts[0].co, reg)
+                               x2, y2, dummy = self.getscreencoords(edge.verts[1].co, reg)
+                               self.selcoords[reg].append([[x1, y1],[x2, y2]])
+       
+               # selverts: selected verts list
+               # slideedges: slideedges list
+               # slideverts: slideverts list per edge
+               # slidecoords: slideverts coordinate list per edge
+               self.vertd = {}
+               self.slideverts[reg] = []
+               self.slidecoords[reg] = []
+               self.slideedges[reg] = []
+               count = 0
+               for vert in self.sverts[reg]:
+                       self.vertd[vert] = vert.co[:]
+                       for edge in vert.link_edges:
+                               count += 1
+                               if not(edge in self.seledges[reg]):
+                                       self.slideedges[reg].append(edge)
+                                       self.slideverts[reg].append([edge.verts[0], edge.verts[1]])
+                                       x1, y1, dummy = self.getscreencoords(edge.verts[0].co, reg)
+                                       x2, y2, dummy = self.getscreencoords(edge.verts[1].co, reg)
+                                       self.slidecoords[reg].append([[x1, y1], [x2, y2]])                              
+               # Box out single vertices.
+               self.singles = []
+               self.boxes[reg] = []
+               for vert in self.sverts[reg]:
+                       single = True
+                       for edge in self.seledges[reg]:
+                               if vert == edge.verts[0] or vert == edge.verts[1]:
+                                       single = False
+                                       break
+                       if single:
+                               self.singles.append(vert)
+                               self.boxes[reg].append(self.getscreencoords(vert.co, reg)[:2])
+       
+       
+       def redraw(self):
+               
+               drawregion = bpy.context.region
+               print (drawregion)
+                                       
+               if self.viewchange:
+                       self.adapt()
+                       
+               if self.slideverts[drawregion] != []:
+                       # Draw single verts as boxes.
+                       glColor3f(1.0,1.0,0)
+                       for self.vertcoords in self.boxes[drawregion]:
+                               glBegin(GL_POLYGON)
+                               x, y = self.vertcoords
+                               glVertex2f(x-2, y-2)
+                               glVertex2f(x-2, y+2)
+                               glVertex2f(x+2, y+2)
+                               glVertex2f(x+2, y-2)
+                               glEnd()
+               
+                       # Accentuate selected edges.
+                       glColor3f(1.0, 1.0, 0)
+                       for posn in range(len(self.selcoords[drawregion])):
+                               glBegin(GL_LINES)
+                               x, y = self.selcoords[drawregion][posn][0]
+                               glVertex2f(x, y)
+                               x, y = self.selcoords[drawregion][posn][1]
+                               glVertex2f(x, y)
+                               glEnd()
+               
+                       # Draw slide-edges.
+                       glColor3f(1.0, 0, 0)
+                       for posn in range(len(self.slidecoords[drawregion])):
+                               glBegin(GL_LINES)
+                               x, y = self.slidecoords[drawregion][posn][0]
+                               glVertex2f(x, y)
+                               x, y = self.slidecoords[drawregion][posn][1]
+                               glVertex2f(x, y)
+                               glEnd()
+       
+               # Draw mouseover highlighting.
+               if self.mouseover:
+                       glColor3f(0, 0, 1.0)
+                       glBegin(GL_LINES)
+                       x,y = self.bx1[drawregion], self.by1[drawregion]
+                       if not(x == -1):
+                               glVertex2f(x,y)
+                       x,y = self.bx2[drawregion], self.by2[drawregion]
+                       if not(x == -1):
+                               glVertex2f(x,y)
+                       glEnd()
+               if self.highoff:
+                       self.highoff = 0
+                       glColor3f(1.0, 0, 0)
+                       glBegin(GL_LINES)
+                       x,y = self.bx1[drawregion], self.by1[drawregion]
+                       if not(x == -1):
+                               glVertex2f(x,y)
+                       x,y = self.bx2[drawregion], self.by2[drawregion]
+                       if not(x == -1):
+                               glVertex2f(x,y)
+                       glEnd()
+
+
+
+
+
+def panel_func(self, context):
+       self.layout.label(text="Deform:")
+       self.layout.operator("mesh.edgetune", text="EdgeTune")
+
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+def unregister():
+       bpy.utils.unregister_class(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+
+
+
+       
diff --git a/EWOCprojects tools/mesh_fanconnect.py b/EWOCprojects tools/mesh_fanconnect.py
new file mode 100644 (file)
index 0000000..dc9a2cf
--- /dev/null
@@ -0,0 +1,286 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+The FanConnect addon connects multiple selected verts to one single other vert. 
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the ParEdge addon in the Mesh category.
+Go to EditMode, select all verts (including the vert to connect to) and invoke 
+the addon (button in the Mesh Tool panel).
+Now leftclick (this will work with pre-selection highlighting) the single vert to connect to et voila...
+"""
+
+
+bl_info = {
+       "name": "FanConnect",
+       "author": "Gert De Roost",
+       "version": (0, 1, 2),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Connects multiple selected verts to one single other vert.",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+from bpy_extras import *
+from bgl import *
+import bmesh
+from mathutils import *
+
+
+
+class FanConnect(bpy.types.Operator):
+       bl_idname = "mesh.fanconnect"
+       bl_label = "Fan Connect"
+       bl_description = "Connects multiple selected verts to one single other vert"
+       bl_options = {"REGISTER", "UNDO"}
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               do_fanconnect(self)
+               
+               context.window_manager.modal_handler_add(self)
+               if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                       self._handle = bpy.types.SpaceView3D.draw_handler_add(redraw, (), 'WINDOW', 'POST_PIXEL')
+               else:
+                       self._handle = context.region.callback_add(redraw, (), 'POST_PIXEL')
+               
+               return {'RUNNING_MODAL'}
+
+       def modal(self, context, event):
+
+               global bm, mesh
+               global viewchange
+               global vertlist, hoververt
+               
+               if event.type == "LEFTMOUSE":
+                       # do connection
+                       if hoververt != None:   
+                               vertlist.pop(vertlist.index(hoververt))
+                               for v in vertlist:
+                                       for f in hoververt.link_faces:
+                                               if v in f.verts:
+                                                       # when already face: split it
+                                                       bmesh.utils.face_split(f, v, hoververt)
+                               for v in vertlist:
+                                       v2 = None
+                                       for e in v.link_edges:
+                                               vertl = e.verts[:]
+                                               vertl.pop(vertl.index(v))
+                                               if vertl[0] in vertlist:
+                                                       v2 = vertl[0]
+                                       if v2 != None:
+                                               already = 0
+                                               for f in hoververt.link_faces:
+                                                       if v in f.verts and v2 in f.verts:
+                                                               already = 1
+                                                               break
+                                               # if no face already between to first and selected vert: make it
+                                               if already == 0:
+                                                       bm.faces.new([v, hoververt, v2])
+                       bm.free()
+                       if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                               bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
+                       else:
+                               context.region.callback_remove(self._handle)
+                       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                       bpy.ops.object.editmode_toggle()
+                       bpy.ops.object.editmode_toggle()
+                       return {'FINISHED'}
+               elif event.type in ["MIDDLEMOUSE"]:
+                       # user transforms view
+                       viewchange = 1
+                       return {"PASS_THROUGH"}
+               elif event.type in ["WHEELDOWNMOUSE", "WHEELUPMOUSE"]:
+                       # user transforms view
+                       viewchange = 1          
+                       return {"PASS_THROUGH"}
+               elif event.type == "MOUSEMOVE":
+                       mx = event.mouse_region_x
+                       my = event.mouse_region_y
+                       # check for vert mouse hovers over
+                       hoververt = None
+                       for v in vertlist:
+                               x, y, dummy = getscreencoords(v.co)
+                               # max distance 5 pixels
+                               if abs(mx - x) < 5 and abs(my - y) < 5:
+                                       hoververt = v
+                                       break
+                       region.tag_redraw()
+                       return {'RUNNING_MODAL'}
+
+               
+               return {'RUNNING_MODAL'}
+
+
+def panel_func(self, context):
+       self.layout.label(text="FanConnect:")
+       self.layout.operator("mesh.fanconnect", text="Connect mult")
+
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+
+
+
+def adapt():
+       
+       global matrix, selobj
+       
+       # Rotating / panning / zooming 3D view is handled here.
+       # Creates a matrix.
+       if selobj.rotation_mode == "AXIS_ANGLE":
+               # object rotationmode axisangle
+               ang, x, y, z =  selobj.rotation_axis_angle
+               matrix = Matrix.Rotation(-ang, 4, Vector((x, y, z)))
+       elif selobj.rotation_mode == "QUATERNION":
+               # object rotationmode euler
+               w, x, y, z = selobj.rotation_quaternion
+               x = -x
+               y = -y
+               z = -z
+               quat = Quaternion([w, x, y, z])
+               matrix = quat.to_matrix()
+               matrix.resize_4x4()
+       else:
+               # object rotationmode euler
+               ax, ay, az = selobj.rotation_euler
+               mat_rotX = Matrix.Rotation(-ax, 4, 'X')
+               mat_rotY = Matrix.Rotation(-ay, 4, 'Y')
+               mat_rotZ = Matrix.Rotation(-az, 4, 'Z')
+       if selobj.rotation_mode == "XYZ":
+               matrix = mat_rotX * mat_rotY * mat_rotZ
+       elif selobj.rotation_mode == "XZY":
+               matrix = mat_rotX * mat_rotZ * mat_rotY
+       elif selobj.rotation_mode == "YXZ":
+               matrix = mat_rotY * mat_rotX * mat_rotZ
+       elif selobj.rotation_mode == "YZX":
+               matrix = mat_rotY * mat_rotZ * mat_rotX
+       elif selobj.rotation_mode == "ZXY":
+               matrix = mat_rotZ * mat_rotX * mat_rotY
+       elif selobj.rotation_mode == "ZYX":
+               matrix = mat_rotZ * mat_rotY * mat_rotX
+
+       # handle object scaling
+       sx, sy, sz = selobj.scale
+       mat_scX = Matrix.Scale(sx, 4, Vector([1, 0, 0]))
+       mat_scY = Matrix.Scale(sy, 4, Vector([0, 1, 0]))
+       mat_scZ = Matrix.Scale(sz, 4, Vector([0, 0, 1]))
+       matrix = mat_scX * mat_scY * mat_scZ * matrix
+
+
+       
+
+
+
+
+
+def getscreencoords(vector):
+       # calculate screencoords of given Vector
+       region = bpy.context.region
+       rv3d = bpy.context.space_data.region_3d 
+       pvector = vector * matrix
+       pvector = pvector + selobj.location
+       
+       svector = view3d_utils.location_3d_to_region_2d(region, rv3d, pvector)
+       if svector == None:
+               return [0, 0 ,0]
+       else:
+               return [svector[0], svector[1], pvector[2]]
+
+
+
+
+
+
+def do_fanconnect(self):
+
+       global bm, mesh, selobj, region
+       global vertlist, viewchange
+
+       # main operation
+       context = bpy.context
+       region = context.region  
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+       area = bpy.context.area
+       
+       vertlist = []
+       for v in bm.verts:
+               if v.select:
+                       vertlist.append(v)
+                       
+       adapt()
+       
+       viewchange = 0
+
+
+
+
+
+def redraw():  
+
+       global viewchange
+
+       if viewchange:
+               adapt()
+               viewchange = 0
+
+       # Draw mouseover highlighting.
+       # Draw single verts as boxes.
+       glColor3f(1.0,1.0,0)
+       if hoververt != None:
+               glBegin(GL_POLYGON)
+               x, y, dummy = getscreencoords(hoververt.co)
+               glVertex2f(x-4, y-4)
+               glVertex2f(x-4, y+4)
+               glVertex2f(x+4, y+4)
+               glVertex2f(x+4, y-4)
+               glEnd()
+
diff --git a/EWOCprojects tools/mesh_filletplus.py b/EWOCprojects tools/mesh_filletplus.py
new file mode 100644 (file)
index 0000000..c655fe3
--- /dev/null
@@ -0,0 +1,378 @@
+# -*- 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 LICENCE BLOCK *****
+
+# ------ ------
+bl_info = {
+       'name': 'FilletPlus',
+       'author': 'Gert De Roost - original by zmj100',
+       'version': (0, 4, 3),
+       'blender': (2, 6, 1),
+       'api': 43085,
+       'location': 'View3D > Tool Shelf',
+       'description': '',
+       'warning': '',
+       'wiki_url': '',
+       'tracker_url': '',
+       'category': 'Mesh' }
+
+# ------ ------
+import bpy
+from bpy.props import FloatProperty, IntProperty, BoolProperty
+import bmesh
+from mathutils import Matrix
+from math import cos, pi, degrees, sin, tan
+
+
+def list_clear_(l):
+       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 FPbuffer():
+       an = 0
+
+# ------ ------
+def f_(list_0, startv, vertlist, face, adj, n, out, flip, radius):
+
+       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)
+       FPbuffer.an = round(degrees(ang))
+
+       # -- -- -- --
+       if FPbuffer.an == 180 or FPbuffer.an == 0.0:
+               return
+
+       # -- -- -- --
+       opp = adj
+
+       if radius == False:
+               h = adj * (1 / cos(ang * 0.5))
+               adj_ = adj
+       elif radius == 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 == False:
+               if flip == False:
+                       rot_ang = vec3.angle(vec4)
+               elif flip == True:
+                       rot_ang = vec1.angle(vec2)
+       elif out == 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 == False:
+                       if flip == False:
+                               tmp = p4 - rp
+                               tmp1 = mtrx * tmp
+                               tmp2 = tmp1 + rp
+                       elif flip == True:
+                               p3 = p - (vec1.normalized() * opp)
+                               tmp = p3 - p
+                               tmp1 = mtrx * tmp
+                               tmp2 = tmp1 + p
+               elif out == 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 == 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_])
+       
+       if face != 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)
+               
+       bm.verts.remove(startv)
+       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_tessface=True)
+       
+       
+
+def do_filletplus(pair):
+       
+       global inaction
+       global flip
+       
+       
+       list_0 = [list([e.verts[0].index, e.verts[1].index]) for e in pair]
+
+       vertset = set([])
+       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({'INFO'}, 'Two adjacent edges must be selected.')
+               return
+       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 == True:
+                       flip = False
+               f_(list_0, startv, vertlist, face, adj, n, out, flip, radius)
+               
+
+
+
+# ------ panel 0 ------
+class FPpanel0(bpy.types.Panel):
+       bl_space_type = 'VIEW_3D'
+       bl_region_type = 'TOOLS'
+       #bl_idname = 'FPpanel0_id'                                                                                                
+       bl_label = 'Fillet'
+       bl_context = 'mesh_edit'
+
+       def draw(self, context):
+               layout = self.layout
+               
+               row = layout.split(0.80)
+               row.operator('f.op0_id', text = 'Fillet plus')
+               row.operator('f.op1_id', text = '?')
+
+# ------ operator 0 ------
+class FPoperartor0(bpy.types.Operator):
+       bl_idname = 'f.op0_id'
+       bl_label = 'Fillet plus'
+       bl_options = {'REGISTER', 'UNDO'}
+
+       adj = FloatProperty( name = '', default = 0.1, min = 0.00001, max = 100.0, step = 1, precision = 3 )
+       n = IntProperty( name = '', default = 3, min = 1, max = 100, step = 1 )
+       out = BoolProperty( name = 'Outside', default = False )
+       flip = BoolProperty( name = 'Flip', default = False )
+       radius = BoolProperty( name = 'Radius', 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 FPbuffer.an == 180 or FPbuffer.an == 0.0:
+                       layout.label('Info:')
+                       layout.label('Angle equal to 0 or 180,')
+                       layout.label('can not fillet.')
+               else:
+                       layout.prop(self, 'radius')
+                       if self.radius == True:
+                               layout.label('Radius:')
+                       elif self.radius == False:
+                               layout.label('Distance:')
+                       layout.prop(self, 'adj')
+                       layout.label('Number of sides:')
+                       layout.prop(self, 'n', slider = True)
+                       if self.n > 1:
+                               row = layout.row(align = False)
+                               row.prop(self, 'out')
+                               if self.out == 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
+
+               ob_act = context.active_object
+               me = ob_act.data
+               bm = bmesh.from_edit_mesh(me)
+#              e_mode = bpy.context.tool_settings.mesh_select_mode
+               
+               done = 1
+               while done:
+                       tempset = set([])
+                       for v in bm.verts:
+                               if v.select:
+                                       tempset.add(v)
+                       done = 0                
+                       for v in tempset:
+                               cnt = 0
+                               edgeset = set([])
+                               for e in v.link_edges:
+                                       if e.select:
+                                               edgeset.add(e)
+                                               cnt += 1
+                               if cnt == 2:
+                                       do_filletplus(edgeset)
+                                       done = 1
+                                       break
+                                       #return {'FINISHED'}
+                               if done:
+                                       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()
+                       return {'FINISHED'}
+               else:
+                       return {'CANCELLED'}
+
+# ------ operator 1 ------
+class FPoperartor1(bpy.types.Operator):
+       bl_idname = 'f.op1_id'
+       bl_label = ''
+
+       def draw(self, context):
+               layout = self.layout
+               layout.label('To use:')
+               layout.label('Select two adjacent edges and press Fillet button.')
+       
+       def execute(self, context):
+               return {'FINISHED'}
+
+       def invoke(self, context, event):
+               return context.window_manager.invoke_popup(self, width = 400)
+
+# ------ operator 2 ------
+class FPoperartor2(bpy.types.Operator):
+       bl_idname = 'f.op2_id'
+       bl_label = ''
+
+       def execute(self, context):
+               bpy.ops.f.op1_id('INVOKE_DEFAULT')
+               return {'FINISHED'}
+
+# ------ ------
+class_list = [ FPoperartor0, FPoperartor1, FPoperartor2, FPpanel0]
+
+# ------ register ------
+def register():
+       for c in class_list:
+               bpy.utils.register_class(c)
+
+# ------ unregister ------
+def unregister():
+       for c in class_list:
+               bpy.utils.unregister_class(c)
+
+# ------ ------
+if __name__ == "__main__":
+       register()
\ No newline at end of file
diff --git a/EWOCprojects tools/mesh_floodsel.py b/EWOCprojects tools/mesh_floodsel.py
new file mode 100644 (file)
index 0000000..441a38d
--- /dev/null
@@ -0,0 +1,443 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+This addon enables you to "flood-select" or deselect entire areas of selected/deselected elements. 
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the FloodSel addon in the Mesh category.
+Go to EditMode, select one or more areas of elements.  Invoke addon (button in Mesh Tools panel)
+Click area with leftmouse to select/deselect and rightmouse to cancel. Choose "Multiple" tickbox
+if you want to do several operations in succession, and ENTER to keep changes. Click tickbox
+"Preselection" to preview selection/deselection when hovering mouse over areas.
+View can be transformed during operation.
+
+If you wish to hotkey FloodSel:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.floodsel'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+
+bl_info = {
+       "name": "FloodSel",
+       "author": "Gert De Roost",
+       "version": (0, 1, 2),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Flood-(de)select areas.",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+       import imp
+
+
+import bpy
+from bpy_extras import *
+import bmesh
+from mathutils import *
+
+
+oldviewmat = None
+started = 0
+
+
+bpy.types.Scene.Multiple = bpy.props.BoolProperty(
+               name = "Multiple", 
+               description = "Several operations after each other",
+               default = False)
+
+bpy.types.Scene.Preselection = bpy.props.BoolProperty(
+               name = "Preselection", 
+               description = "Preview when hovering over areas",
+               default = True)
+
+bpy.types.Scene.Diagonal = bpy.props.BoolProperty(
+               name = "Diagonal is border", 
+               description = "Diagonal selections are treated as borders",
+               default = True)
+
+
+
+class FloodSel(bpy.types.Operator):
+       bl_idname = "mesh.floodsel"
+       bl_label = "FloodSel"
+       bl_description = "Flood-(de)select areas"
+       bl_options = {"REGISTER", "UNDO"}
+       
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               do_prepare()
+               
+               context.window_manager.modal_handler_add(self)
+               if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                       self._handle = bpy.types.SpaceView3D.draw_handler_add(redraw, (), 'WINDOW', 'POST_PIXEL')
+               else:
+                       self._handle = context.region.callback_add(redraw, (), 'POST_PIXEL')
+               
+               return {'RUNNING_MODAL'}
+
+       def modal(self, context, event):
+               
+               global viewchange, state, doneset, selset, started
+               
+               scn = bpy.context.scene
+               if event.type == "RIGHTMOUSE":
+                       started = 0
+                       # cancel operation, reset selection state
+                       bpy.ops.mesh.select_all(action="DESELECT")
+                       for elem in baseselset:
+                               elem.select = 1
+                       bm.free()
+                       if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                               bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
+                       else:
+                               context.region.callback_remove(self._handle)
+                       bpy.ops.object.editmode_toggle()
+                       bpy.ops.object.editmode_toggle()
+                       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                       return {'CANCELLED'}
+               elif event.type in ["MIDDLEMOUSE"]:
+                       return {"PASS_THROUGH"}
+               elif event.type in ["WHEELDOWNMOUSE", "WHEELUPMOUSE"]:
+                       return {"PASS_THROUGH"}
+               elif event.type in ["LEFTMOUSE"]:
+                       if event.mouse_region_x < 0:
+                               # this for splitting up mouse func between panel and 3d view
+                               return {"PASS_THROUGH"}
+                       if not(scn.Preselection):
+                               for elem in doneset:
+                                       elem.select = not(state)
+                       if not(scn.Multiple):
+                               bm.free()
+                               if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                                       bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
+                               else:
+                                       context.region.callback_remove(self._handle)
+                               bpy.ops.object.editmode_toggle()
+                               bpy.ops.object.editmode_toggle()
+                               bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                               return {'FINISHED'}
+                       else:
+                               if state == 0:
+                                       selset = selset.union(doneset)
+                               else:
+                                       selset = selset.difference(doneset)
+                       return {"RUNNING_MODAL"}
+               elif event.type == "RET":
+                       started = 0
+                       # Consolidate changes if ENTER pressed.
+                       # Free the bmesh.
+                       bm.free()
+                       if eval(str(bpy.app.build_revision)[2:7]) >= 53207:
+                               bpy.types.SpaceView3D.draw_handler_remove(self._handle, "WINDOW")
+                       else:
+                               context.region.callback_remove(self._handle)
+                       bpy.ops.object.editmode_toggle()
+                       bpy.ops.object.editmode_toggle()
+                       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                       return {'FINISHED'}
+               elif event.type in ["MOUSEMOVE"]:
+                       if event.mouse_region_x <= 0:
+                               # this for splitting up mouse func between panel and 3d view
+                               return {"PASS_THROUGH"}
+                               
+                       mx = event.mouse_region_x
+                       my = event.mouse_region_y
+                       
+                       hoverlist = []
+                       for [fidx, xmin, xmax, ymin, ymax] in boundlist:
+                               if xmin < mx < xmax and ymin < my < ymax:
+                                       hoverlist.append(fidx)
+                               
+                       face = None     
+                       bpy.ops.mesh.select_all(action="DESELECT")
+                       for fidx in hoverlist:
+                               f = bm.faces[fidx]
+                               pointlist = []
+                               for v in f.verts:
+                                       pointlist.append(getscreencoords(v.co))
+                               mpoint = (mx, my)
+                               if insidepoly(pointlist, len(f.verts), mpoint):
+                                       face = f
+                                       break
+                       
+                       doneset = set([])
+                       for elem in selset:
+                               elem.select = 1
+                       if face == None:
+                               return {"RUNNING_MODAL"}
+                       if "VERT" in bm.select_mode:
+                               state = 1
+                               for v in face.verts:
+                                       if not(v.select):
+                                               state = 0
+                                               break
+                               scanlist = list(face.verts[:])
+                               doneset = set(face.verts[:])
+                               while len(scanlist) > 0:
+                                       vert = scanlist.pop()
+                                       cands = []
+                                       if scn.Diagonal:
+                                               for e in vert.link_edges:
+                                                       v = e.other_vert(vert)
+                                                       cands.append(v)
+                                       else:
+                                               for f in vert.link_faces:
+                                                       cands.extend(list(f.verts))
+                                       for v in cands:
+                                               if not(v in doneset) and v.select == state:
+                                                       doneset.add(v)
+                                                       scanlist.append(v)
+                       if "EDGE" in bm.select_mode:
+                               state = 1
+                               testset = set(face.edges[:])
+                               for e in face.edges:
+                                       if not(e.select):
+                                               state = 0
+                                       else:
+                                               testset.discard(e)
+                               if state == 1:
+                                       testset = set(face.edges[:])
+                               scanlist = list(testset)
+                               doneset = testset
+                               while len(scanlist) > 0:
+                                       edge = scanlist.pop()
+                                       for l in edge.link_loops:
+                                               if l.edge == edge:
+                                                       if state == 0:
+                                                               cands = [l.link_loop_prev.edge, l.link_loop_next.edge]
+                                                       else:
+                                                               cands = l.vert.link_edges
+                                                       for e in cands:
+                                                               if e!= edge and not(e in doneset) and e.select == state:
+                                                                       doneset.add(e)
+                                                                       scanlist.append(e)
+                       if "FACE" in bm.select_mode:
+                               if face.select:
+                                       state = 1
+                               else:
+                                       state = 0
+                               scanlist = [face]
+                               doneset = set([face])
+                               while len(scanlist) > 0:
+                                       face = scanlist.pop()
+                                       cands = []
+                                       if scn.Diagonal:
+                                               for e in face.edges:
+                                                       for f in e.link_faces:
+                                                               cands.append(f)
+                                       else:
+                                               for v in face.verts:
+                                                       for f in v.link_faces:
+                                                               cands.append(f)
+                                       for f in cands:
+                                               if f != face and not(f in doneset) and f.select == state:
+                                                       doneset.add(f)
+                                                       scanlist.append(f)
+                       if scn.Preselection:
+                               for elem in doneset:
+                                       elem.select = not(state)
+                       
+                       return {"RUNNING_MODAL"}
+                       
+               return {'RUNNING_MODAL'}
+
+
+def panel_func(self, context):
+       
+       scn = bpy.context.scene
+       self.layout.label(text="FloodSel:")
+       self.layout.operator("mesh.floodsel", text="Flood SelArea")
+       self.layout.prop(scn, "Multiple")
+       self.layout.prop(scn, "Preselection")
+       self.layout.prop(scn, "Diagonal")
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+def adapt():
+       
+       global matrix, boundlist
+       
+       # Rotating / panning / zooming 3D view is handled here.
+       # Calculate matrix.
+       if selobj.rotation_mode == "AXIS_ANGLE":
+               # object rotationmode axisangle
+               ang, x, y, z =  selobj.rotation_axis_angle
+               matrix = Matrix.Rotation(-ang, 4, Vector((x, y, z)))
+       elif selobj.rotation_mode == "QUATERNION":
+               # object rotationmode quaternion
+               w, x, y, z = selobj.rotation_quaternion
+               x = -x
+               y = -y
+               z = -z
+               quat = Quaternion([w, x, y, z])
+               matrix = quat.to_matrix()
+               matrix.resize_4x4()
+       else:
+               # object rotationmode euler
+               ax, ay, az = selobj.rotation_euler
+               mat_rotX = Matrix.Rotation(-ax, 4, 'X')
+               mat_rotY = Matrix.Rotation(-ay, 4, 'Y')
+               mat_rotZ = Matrix.Rotation(-az, 4, 'Z')
+       if selobj.rotation_mode == "XYZ":
+               matrix = mat_rotX * mat_rotY * mat_rotZ
+       elif selobj.rotation_mode == "XZY":
+               matrix = mat_rotX * mat_rotZ * mat_rotY
+       elif selobj.rotation_mode == "YXZ":
+               matrix = mat_rotY * mat_rotX * mat_rotZ
+       elif selobj.rotation_mode == "YZX":
+               matrix = mat_rotY * mat_rotZ * mat_rotX
+       elif selobj.rotation_mode == "ZXY":
+               matrix = mat_rotZ * mat_rotX * mat_rotY
+       elif selobj.rotation_mode == "ZYX":
+               matrix = mat_rotZ * mat_rotY * mat_rotX
+
+       # handle object scaling
+       sx, sy, sz = selobj.scale
+       mat_scX = Matrix.Scale(sx, 4, Vector([1, 0, 0]))
+       mat_scY = Matrix.Scale(sy, 4, Vector([0, 1, 0]))
+       mat_scZ = Matrix.Scale(sz, 4, Vector([0, 0, 1]))
+       matrix = mat_scX * mat_scY * mat_scZ * matrix
+
+       boundlist = []
+       for f in bm.faces:
+               xli = []
+               yli = []
+               for v in f.verts:
+                       x, y = getscreencoords(v.co)
+                       xli.append(x)
+                       yli.append(y)
+               xmin = min(xli)
+               xmax = max(xli)
+               ymin = min(yli)
+               ymax = max(yli)
+               boundlist.append([f.index, xmin, xmax, ymin, ymax])
+
+
+
+def getscreencoords(vector):
+       # calculate screencoords of given Vector
+       region = bpy.context.region
+       rv3d = bpy.context.space_data.region_3d 
+       vector = Vector([vector[0], vector[1], vector[2]])
+       pvector = vector * matrix
+       pvector = pvector + selobj.location
+       
+       svector = view3d_utils.location_3d_to_region_2d(region, rv3d, pvector)
+       if svector == None:
+               return [0, 0]
+       else:
+               return [svector[0], svector[1]]
+
+
+
+
+def do_prepare():
+       
+       global bm, mesh, selobj, started
+       global selset, baseselset, boundlist
+
+       started = 1
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.object.editmode_toggle()
+       context = bpy.context
+       region = context.region  
+       area = context.area
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+       
+       selset = set([])
+       if "VERT" in bm.select_mode:
+               for v in bm.verts:
+                       if v.select:
+                               selset.add(v)
+       if "EDGE" in bm.select_mode:
+               for e in bm.edges:
+                       if e.select:
+                               selset.add(e)
+       if "FACE" in bm.select_mode:
+               for f in bm.faces:
+                       if f.select:
+                               selset.add(f)
+       baseselset = selset.copy()
+       
+       adapt()
+
+
+def insidepoly(polygonlist, N, p):
+
+       counter = 0
+       p1 = polygonlist[0]
+       for i in range(1, N+1, 1):
+               p2 = polygonlist[i % N]
+               if (p[1] > min(p1[1],p2[1])):
+                       if (p[1] <= max(p1[1],p2[1])):
+                               if (p[0] <= max(p1[0],p2[0])):
+                                       if (p1[1] != p2[1]):
+                                               xinters = (p[1]-p1[1])*(p2[0]-p1[0])/(p2[1]-p1[1])+p1[0]
+                                               if (p1[0] == p2[0]) or (p[0] <= xinters):
+                                                       counter += 1
+               p1 = p2
+
+       if counter % 2 == 0:
+               return False
+       else:
+               return True
+
+
+
+def redraw():
+       
+       global oldviewmat
+       
+       # user changes view
+       viewmat = bpy.context.space_data.region_3d.perspective_matrix
+       if viewmat != oldviewmat:
+               adapt()
+               oldviewmat = viewmat.copy()
+       
+
diff --git a/EWOCprojects tools/mesh_innerweld.py b/EWOCprojects tools/mesh_innerweld.py
new file mode 100644 (file)
index 0000000..65cf021
--- /dev/null
@@ -0,0 +1,192 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+InnerWeld.  This addon welds parallel connected selected edges together. 
+
+Documentation
+
+First go to User Preferences->Addons and enable the InnerWeld addon in the Mesh category.
+Go to EditMode, select some parallel edge(loop)(slices).  Handles ALL edges parallel next to each other.
+These edges will be welded together when invoking addon (button in Mesh Tools panel).
+
+If you wish to hotkey InnerWeld:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.innerweld'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+
+bl_info = {
+       "name": "InnerWeld",
+       "author": "Gert De Roost",
+       "version": (0, 1, 0),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Welding parallel edges together.",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+import bmesh
+
+
+
+
+class InnerWeld(bpy.types.Operator):
+       bl_idname = "mesh.innerweld"
+       bl_label = "InnerWeld"
+       bl_description = "Welding parallel edges together"
+       bl_options = {"REGISTER", "UNDO"}
+
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               do_innerweld()
+               
+               bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+               bm.free()
+               bpy.ops.object.editmode_toggle()
+               bpy.ops.object.editmode_toggle()
+               
+               return {'FINISHED'}
+
+
+def panel_func(self, context):
+       
+       scn = bpy.context.scene
+       self.layout.label(text="InnerWeld:")
+       self.layout.operator("mesh.innerweld", text="Weld Edges")
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+
+def addstart(vert):
+       
+       global sellist, vertlist
+
+       # recursive: adds to initial edgelist at start
+       for e in vert.link_edges:
+               if e in sellist:
+                       sellist.pop(sellist.index(e))
+                       v = e.other_vert(vert)
+                       vertlist[posn].insert(0, v)
+                       addstart(v)
+
+def addend(vert):
+       
+       global sellist, vertlist
+
+       # recursive: adds to initial edgelist at end
+       for e in vert.link_edges:
+               if e in sellist:
+                       sellist.pop(sellist.index(e))
+                       v = e.other_vert(vert)
+                       vertlist[posn].append(v)
+                       addend(v)
+
+
+def do_innerweld():
+
+       global sellist, vertlist, posn
+       global bm
+
+       context = bpy.context
+       region = context.region  
+       area = context.area
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+
+       sellist = []
+       for edge in bm.edges:
+               if edge.select:
+                       sellist.append(edge)
+
+       posn = 0
+       vertlist = []
+       while len(sellist) > 0:
+               # initialize next edgesnake             
+               vertlist.append([])
+               vert = sellist[0].verts[0]
+               vertlist[posn].append(vert)
+               # add to start and end of arbitrary start vert
+               addstart(vert)
+               addend(vert)
+               posn += 1
+               
+       found = 1       
+       posn = 0
+       mergesets = []
+       while found:
+               found = 0
+               for idx in range(len(vertlist)):
+                       if len(vertlist[idx]) > 0:
+                               found = 1
+                               vset = set([])
+                               vset.add(vertlist[idx].pop())
+                               mergesets.append(vset.copy())
+                               while len(vset) > 0:
+                                       vert = vset.pop()
+                                       for edge in vert.link_edges:
+                                               if edge.select:
+                                                       continue
+                                               v1 = edge.other_vert(vert)
+                                               for vlist in vertlist:
+                                                       if v1 in vlist and not(v1 in mergesets[posn]):
+                                                               mergesets[posn].add(v1)
+                                                               vset.add(v1)
+                                                               vertlist[vertlist.index(vlist)].pop(vlist.index(v1))
+                               posn +=1
+
+       for st in mergesets:
+               bpy.ops.mesh.select_all(action="DESELECT")
+               for vert in st:
+                       vert.select = 1
+               bpy.ops.mesh.merge(type='CENTER', uvs=True)
+       
+       
+       
+       
diff --git a/EWOCprojects tools/mesh_laprelax.py b/EWOCprojects tools/mesh_laprelax.py
new file mode 100644 (file)
index 0000000..ac27798
--- /dev/null
@@ -0,0 +1,165 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+This addon implements a smoothing algorithm for meshes based on Laplacian relaxation, but adapted
+to have no shrinkage.
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the LapRelax addon in the Mesh category.
+Go to EditMode, select some vertices and invoke the addon (button in the Mesh Tool panel).
+Set the amount of times you want the smoothing operation to be repeated.
+The mesh will be smoothed.
+
+If you wish to hotkey LapRelax:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.laprelax'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+
+bl_info = {
+       "name": "LapRelax",
+       "author": "Gert De Roost",
+       "version": (0, 1, 2),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Smoothing mesh keeping volume",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+import bmesh
+from mathutils import *
+import math
+
+bpy.types.Scene.Repeat = bpy.props.IntProperty(
+               name = "Repeat", 
+               description = "Repeat how many times",
+               default = 1,
+               min = 1,
+               max = 100)
+
+
+
+class LapRelax(bpy.types.Operator):
+       bl_idname = "mesh.laprelax"
+       bl_label = "LapRelax"
+       bl_description = "Smoothing mesh keeping volume"
+       bl_options = {"REGISTER", "UNDO"}
+       
+
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               
+               scn = bpy.context.scene
+               
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               # smooth #Repeat times
+               for i in range(scn.Repeat):
+                       do_laprelax(self)
+               
+               return {'FINISHED'}
+
+
+def panel_func(self, context):
+       
+       scn = bpy.context.scene
+       self.layout.label(text="LapRelax:")
+       self.layout.operator("mesh.laprelax", text="Laplace Relax")
+       self.layout.prop(scn, "Repeat")
+
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+def do_laprelax(self):
+
+       context = bpy.context
+       region = context.region  
+       area = context.area
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+       bmprev = bm.copy()
+
+       for v in bmprev.verts:
+               if v.select:
+                       tot = Vector((0, 0, 0))
+                       cnt = 0
+                       for e in v.link_edges:
+                               for f in e.link_faces:
+                                       if not(f.select):
+                                               cnt = 1
+                               if len(e.link_faces) == 1:
+                                       cnt = 1
+                                       break
+                       if cnt:
+                               # dont affect border edges: they cause shrinkage
+                               continue
+                               
+                       # find Laplacian mean
+                       for e in v.link_edges:
+                               tot += e.other_vert(v).co
+                       tot /= len(v.link_edges)
+                       
+                       # cancel movement in direction of vertex normal
+                       delta = (tot - v.co)
+                       if delta.length != 0:
+                               ang = delta.angle(v.normal)
+                               deltanor = math.cos(ang) * delta.length
+                               nor = v.normal
+                               nor.length = abs(deltanor)
+                               bm.verts[v.index].co = tot + nor
+               
+               
+       mesh.update()
+       bm.free()
+       bmprev.free()
+       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.object.editmode_toggle()
+       
diff --git a/EWOCprojects tools/mesh_paredge.py b/EWOCprojects tools/mesh_paredge.py
new file mode 100644 (file)
index 0000000..317dbc3
--- /dev/null
@@ -0,0 +1,1009 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+This script uses the concept of support edges, or the inserting of new edges parallel to the selected edges.
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the ParEdge addon in the Mesh category.
+Go to EditMode, select a closed edge path without corners (an edgeloop or part of an edgeloop)and invoke 
+the addon (button in the Mesh Tool panel).  Enter a distance (positive or negative) with the slider in 
+the Mesh Tools panel or leftclick-drag from left to right to
+interactively choose the parallel distance.  Select "Both Sides" on the panel to insert edges on both sides.
+Select "Endpoint quads" if you want to have edgepath endpoints "capped".
+Press the right mouse button to cancel operation or ENTER to accept changes.  
+The tool will remember the last set distance and the "Both Sides" setting for the next ParEdge operation.
+
+If you wish to hotkey ParEdge:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.paredge'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+
+bl_info = {
+       "name": "ParEdge",
+       "author": "Gert De Roost",
+       "version": (0, 4, 5),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Inserting of parallel edges",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+import bmesh
+import math
+
+
+
+parchange = 0
+started = 0
+
+
+bpy.types.Scene.Distance = bpy.props.FloatProperty(
+               name = "Distance", 
+               description = "Enter distance",
+               default = 0,
+               min = -1,
+               max = 1)
+
+bpy.types.Scene.Both = bpy.props.BoolProperty(
+               name = "Both sides", 
+               description = "Insert on both sides",
+               default = False)
+
+bpy.types.Scene.Cap = bpy.props.BoolProperty(
+               name = "Endpoint quads", 
+               description = "Create endpoint quads",
+               default = False)
+
+
+
+
+class ParEdge(bpy.types.Operator):
+       bl_idname = "mesh.paredge"
+       bl_label = "ParEdge"
+       bl_description = "Inserting of parallel edges"
+       bl_options = {"REGISTER", "UNDO"}
+       
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+
+               do_paredge(self)
+               
+               context.window_manager.modal_handler_add(self)
+               self._handle = bpy.types.SpaceView3D.draw_handler_add(redraw,(), 'WINDOW', 'POST_PIXEL')
+               
+               return {'RUNNING_MODAL'}
+
+       def modal(self, context, event):
+               
+               global bm, bmundo, mesh
+               global started, mbns, basex, basev, dist
+               global dist, olddist, distset, oldboth, negsubd, possubd
+               global dissverts1, dissedges1, railverts1, railedges1
+               global dissverts2, dissedges2, railverts2, railedges2
+
+               scn = bpy.context.scene
+               
+               if event.type == "RIGHTMOUSE" or wrongsel or stop:
+                       # right mousebutton cancels
+                       started = 0
+                       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                       bm.free()
+                       bpy.ops.object.editmode_toggle()
+                       bmundo.to_mesh(mesh)
+                       bpy.ops.object.editmode_toggle()
+                       return {'CANCELLED'}
+               elif event.type in ["LEFTMOUSE"]:
+                       if event.mouse_region_x < 0:
+                               # this for splitting up mouse func between panel and 3d view
+                               return {"PASS_THROUGH"}
+                       if event.value == "PRESS":
+                               basex = event.mouse_region_x
+                               basev = dist
+                               mbns = 1
+                       if event.value == "RELEASE":
+                               mbns = 0
+                       return {"RUNNING_MODAL"}
+               elif event.type in ["MIDDLEMOUSE", "WHEELDOWNMOUSE", "WHEELUPMOUSE"]:
+                       return {"PASS_THROUGH"}
+               elif event.type == "RET":
+                       # Consolidate changes if SPACEBAR pressed.
+                       # Free the bmesh.
+                       if event.mouse_region_x < 0:
+                               return {"PASS_THROUGH"}
+                       started = 0
+                       bpy.ops.mesh.select_all(action="DESELECT")
+                       for posn in range(len(vertlist)):
+                               if capped:
+                                       for e in capsellist:
+                                               if e == None:
+                                                       continue
+                                               e.select = 1
+                                               e.verts[0].select = 1
+                                               e.verts[1].select = 1
+                               # select only the inserted verts/edges
+                               if negsubd[posn]:
+                                       for vert in dissverts1[posn]:
+                                               vert.select = 1
+                                       for edge in dissedges1[posn]:
+                                               edge.select = 1
+                               if possubd[posn]:
+                                       for vert in dissverts2[posn]:
+                                               vert.select = 1
+                                       for edge in dissedges2[posn]:
+                                               edge.select = 1
+                               # if user resetted to zero: remove inserted edges
+                               if dist == 0:
+                                       if negsubd[posn]:
+                                               bpy.ops.mesh.select_all(action="DESELECT")
+                                               for vert in dissverts1[posn]:
+                                                       vert.select = 1
+                                               for edge in dissedges1[posn]:
+                                                       edge.select = 1
+                                               bpy.ops.mesh.dissolve_limited()
+                                               mesh.calc_tessface()
+                                               negsubd[posn] = 0
+                                               possubd[posn] = 0
+                                       if possubd[posn]:
+                                               bpy.ops.mesh.select_all(action="DESELECT")
+                                               for vert in dissverts2[posn]:
+                                                       vert.select = 1
+                                               for edge in dissedges2[posn]:
+                                                       edge.select = 1
+                                               bpy.ops.mesh.dissolve_limited()
+                                               mesh.calc_tessface()
+                                               negsubd[posn] = 0
+                                               possubd[posn] = 0
+                                       for vert in vertlist[posn]:
+                                               vert.select = 1
+                                       for edge in edgelist[posn]:
+                                               edge.select = 1
+                                       mesh.update()
+                       bm.free()
+                       bpy.ops.object.editmode_toggle()
+                       bmundo.free()
+                       bpy.ops.object.editmode_toggle()
+                       bpy.context.user_preferences.edit.use_global_undo = self.save_global_undo
+                       return {'FINISHED'}
+               elif event.type == "MOUSEMOVE":
+                       # do some edgecreating
+                       adapt(self, event)
+                       return {'PASS_THROUGH'}
+                       
+               return {'RUNNING_MODAL'}
+
+
+def panel_func(self, context):
+       
+       global parchange
+       
+       scn = bpy.context.scene
+       self.layout.label(text="ParEdge:")
+       self.layout.operator("mesh.paredge", text="Insert Edges")
+       if started:
+               self.layout.prop(scn, 'Distance')
+               self.layout.prop(scn, 'Both')
+               if scn.Both:
+                       self.layout.prop(scn, 'Cap')
+               parchange = 1
+               region.tag_redraw()
+
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+
+def unregister():
+       bpy.utils.unregister_class(ParEdge)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+def adapt(self, event):
+       
+       global bm, bmundo, mesh
+       global started, mbns, basex, basev, dist
+       global dist, olddist, distset, oldboth, negsubd, possubd
+       global dissverts1, dissedges1, railverts1, railedges1
+       global dissverts2, dissedges2, railverts2, railedges2
+       global caplist, oldcap, capped, capsellist
+       
+       def removecaps():
+               capped = 0
+               for posn in range(len(vertlist)):
+                       for [e1, e2, v1, v2, fj, fo1, fo2] in caplist[posn]:
+                               if e1 == None:
+                                       continue
+                               print (posn, caplist[posn])
+                               bmesh.utils.face_split(fj, v1, v2)
+                               templ = []
+                               for f in e1.link_faces:
+                                       templ.append(f)
+                               bmesh.utils.face_join(templ)
+                               templ = []
+                               for f in e2.link_faces:
+                                       templ.append(f)
+                               bmesh.utils.face_join(templ)
+               mesh.calc_tessface()
+
+
+       scn = bpy.context.scene
+       
+       if mbns == 0 and parchange == 0:
+               if scn.Cap != oldcap:
+                       if dist != 0:
+                               mbns = 2
+                       if scn.Cap == True:
+                               capped = 0
+                       else:
+                               removecaps()
+                       oldcap = scn.Cap
+               if scn.Both != oldboth:
+                       if dist != 0:
+                               # enter edge-building through the backdoor to instantaneously show both inserts 
+                               mbns = 2
+                       if scn.Both == True:
+                               # if just set
+                               for posn in range(len(vertlist)):
+                                       if negsubd[posn]:
+                                               possubd[posn] = 0
+                                       if possubd[posn]:
+                                               negsubd[posn] = 0
+                       else:
+                               if capped:
+                                       capped = 0
+                                       removecaps()
+                               # if just unset: remove one side of edges
+                               if dist < 0:
+                                       for posn in range(len(vertlist)):
+                                               bpy.ops.mesh.select_all(action="DESELECT")
+                                               for vert in dissverts2[posn]:
+                                                       vert.select = 1
+                                               for edge in dissedges2[posn]:
+                                                       edge.select = 1
+                                               bpy.ops.mesh.dissolve_limited()
+                                               mesh.calc_tessface()
+                                               for vert in dissverts1[posn]:
+                                                       vert.select = 1
+                                               for edge in dissedges1[posn]:
+                                                       edge.select = 1
+                                               possubd[posn] = 0
+                                               railedges2[posn] = []
+                                               railverts2[posn] = []
+                                               dissverts2[posn] = []
+                                               dissedges2[posn] = []
+                               if dist >= 0:
+                                       for posn in range(len(vertlist)):
+                                               if railedges1[posn] != []:
+                                                       bpy.ops.mesh.select_all(action="DESELECT")
+                                                       for vert in dissverts1[posn]:
+                                                               vert.select = 1
+                                                       for edge in dissedges1[posn]:
+                                                               edge.select = 1
+                                                       bpy.ops.mesh.dissolve_limited()
+                                                       mesh.calc_tessface()                                                                                                    
+                                                       for vert in dissverts2[posn]:
+                                                               vert.select = 1
+                                                       for edge in dissedges2[posn]:
+                                                               edge.select = 1
+                                                       negsubd[posn] = 0
+                                                       railedges1[posn] = []
+                                                       railverts1[posn] = []
+                                                       dissverts1[posn] = []
+                                                       dissedges1[posn] = []
+                               for vert in vertlist[posn]:
+                                       vert.select = 1
+                               for edge in edgelist[posn]:
+                                       edge.select = 1
+               oldboth = scn.Both
+#              if distset:
+#                      if scn.Distance != dist:
+#                              scn.Distance = dist
+#                              return {'PASS_THROUGH'}
+#                      distset = 0
+               dist = scn.Distance
+               if dist != olddist:
+                       mbns = 2
+               olddist = dist
+       else:
+               if mbns != 2:
+                       if event != None:
+                               # do mouse handling left-right
+                               mx = event.mouse_region_x
+                               mean = max(-1*meanmin, meanmax)
+                               dist = basev + ((mx - basex) / 200) * mean
+                               scn.Distance = dist
+                               distset = 1
+               else:
+                       mbns = 0
+#                      return
+               # dont do anything if zero - removing edges will be handled once exiting with ENTER
+               if scn.Distance == 0:
+                       return
+               
+               #negative side handling
+               if dist < 0 or scn.Both == True:
+                       for posn in range(len(vertlist)):
+                               if not(negsubd[posn]):
+                                       if scn.Both == False:
+                                               # if just switched sides: remove positive side
+                                               if possubd[posn] == 1:
+                                                       bpy.ops.mesh.select_all(action="DESELECT")
+                                                       for vert in dissverts2[posn]:
+                                                               vert.select = 1
+                                                       for edge in dissedges2[posn]:
+                                                               edge.select = 1
+                                                       bpy.ops.mesh.dissolve_limited()
+                                                       railedges2[posn] = []
+                                                       railverts2[posn] = []
+                                                       dissverts2[posn] = []
+                                                       dissedges2[posn] = []
+                                               possubd[posn] = 0
+                                       railedges1[posn] = []
+                                       railverts1[posn] = []
+                                       dissverts1[posn] = []
+                                       dissedges1[posn] = []
+                       
+                       for posn in range(len(vertlist)):
+                               if not(negsubd[posn]):
+                                       negsubd[posn] = 1
+                                       # if just switched sides: look for slide constellations
+                                       for vert in vertlist[posn]:
+                                               if vertlist[posn].index(vert) == len(vertlist[posn]) - 1:
+                                                       break
+                                               for loop in vert.link_loops:
+                                                       if loop.link_loop_next.vert == vertlist[posn][vertlist[posn].index(vert) + 1]:
+                                                               railverts1[posn].append(loop.link_loop_prev.vert)
+                                                               e = loop.link_loop_prev.edge
+                                                               railedges1[posn].append(e)
+                                                               if vertlist[posn].index(vert) == len(vertlist[posn]) - 2:
+                                                                       railverts1[posn].append(loop.link_loop_next.link_loop_next.vert)
+                                                                       e = loop.link_loop_next.edge        
+                                                                       railedges1[posn].append(e)                                                      
+                                       if railedges1[posn] != []:
+                                               # insert parallel edges
+                                               prev = None
+                                               popout = 0
+                                               for idx in range(len(railedges1[posn])):
+                                                       if popout:
+                                                               break
+                                                       edge = railedges1[posn][idx]
+                                                       if idx == len(railedges1[posn]) - 2 and railverts1[posn][0] == railverts1[posn][len(railverts1[posn]) - 1]:
+                                                               # this handles closed edgeloops
+                                                               vert = startvert
+                                                               railedges1[posn].pop(len(railedges1[posn]) - 1)
+                                                               railverts1[posn].pop(len(railverts1[posn]) - 1)
+                                                               popout = 1
+                                                       else:
+                                                               dummy, vert = bmesh.utils.edge_split(edge, vertlist[posn][railedges1[posn].index(edge)], 0.5)
+                                                       if idx == 0:
+                                                               startvert = vert 
+                                                       dissverts1[posn].append(vert)
+                                                       if not(prev == None):
+                                                               for f in edge.link_faces:
+                                                                       if prevedge in f.edges:
+                                                                               bmesh.utils.face_split(f, vert, prev)
+                                                                               bmesh.utils.face_split(f, prev, vert)
+                                                                               bm.faces.remove(f)
+                                                                               for e in vert.link_edges:
+                                                                                       if prev in e.verts:
+                                                                                               dissedges1[posn].append(e)
+                                                       prev = vert
+                                                       prevedge = edge
+                                               mesh.calc_tessface()
+
+                       # select inserted edges/verts
+                       for posn in range(len(vertlist)):
+                               for v in dissverts1[posn]:
+                                       v.select = 1
+                               for e in dissedges1[posn]:
+                                       e.select = 1
+
+               # do distance shifting
+               for posn in range(len(vertlist)):
+                       if railedges1[posn] != []:
+                               for v in vertlist[posn]:
+                                       pv = dissverts1[posn][vertlist[posn].index(v)]
+                                       rv = railverts1[posn][vertlist[posn].index(v)]
+                                       sv = bmundo.verts[v.index]
+                                       vec = rv.co - sv.co
+                                       vec.length = abs(dist)
+                                       pv.co = sv.co + vec
+
+
+               #positive side handling
+               if dist > 0 or scn.Both == True:
+                       for posn in range(len(vertlist)):
+                               if not(possubd[posn]):
+                                       if scn.Both == False:
+                                               # if just switched sides: remove positive side
+                                               if negsubd[posn] == 1:
+                                                       bpy.ops.mesh.select_all(action="DESELECT")
+                                                       for vert in dissverts1[posn]:
+                                                               vert.select = 1
+                                                       for edge in dissedges1[posn]:
+                                                               edge.select = 1
+                                                       bpy.ops.mesh.dissolve_limited()
+                                                       railedges1[posn] = []
+                                                       railverts1[posn] = []
+                                                       dissverts1[posn] = []
+                                                       dissedges1[posn] = []
+                                               negsubd[posn] = 0
+                                       railedges2[posn] = []
+                                       railverts2[posn] = []
+                                       dissverts2[posn] = []
+                                       dissedges2[posn] = []
+                       for posn in range(len(vertlist)):
+                               if not(possubd[posn]):
+                                       # if just switched sides: look for slide constellations
+                                       for vert in vertlist[posn]:
+                                               if vertlist[posn].index(vert) == len(vertlist[posn]) - 1:
+                                                       break
+                                               for loop in vert.link_loops:
+                                                       if loop.link_loop_prev.vert == vertlist[posn][vertlist[posn].index(vert) + 1]:
+                                                               railverts2[posn].append(loop.link_loop_next.vert)
+                                                               e = loop.edge
+                                                               railedges2[posn].append(e)
+                                                               if vertlist[posn].index(vert) == len(vertlist[posn]) - 2:
+                                                                       railverts2[posn].append(loop.link_loop_prev.link_loop_prev.vert)
+                                                                       e = loop.link_loop_prev.link_loop_prev.edge
+                                                                       railedges2[posn].append(e)
+                       for posn in range(len(vertlist)):
+                               if not(possubd[posn]):
+                                       possubd[posn] = 1
+                                       if railedges2[posn] != []:
+                                               # insert parallel edges
+                                               prev = None
+                                               popout = 0
+                                               for idx in range(len(railedges2[posn])):
+                                                       if popout:
+                                                               break
+                                                       edge = railedges2[posn][idx]
+                                                       if idx == len(railedges2[posn]) - 2 and railverts2[posn][0] == railverts2[posn][len(railverts2[posn]) - 1]:
+                                                               # this handles closed edgeloops
+                                                               vert = startvert
+                                                               railedges2[posn].pop(len(railedges2[posn]) - 1)
+                                                               railverts2[posn].pop(len(railverts2[posn]) - 1)
+                                                               popout = 1
+                                                       else:
+                                                               dummy, vert = bmesh.utils.edge_split(edge, vertlist[posn][railedges2[posn].index(edge)], 0.5)
+                                                       if idx == 0:
+                                                               startvert = vert 
+                                                       dissverts2[posn].append(vert)
+                                                       if not(prev == None):
+                                                               for f in edge.link_faces:
+                                                                       if prevedge in f.edges:
+                                                                               bmesh.utils.face_split(f, vert, prev)
+                                                                               bmesh.utils.face_split(f, prev, vert)
+                                                                               bm.faces.remove(f)
+                                                                               for e in vert.link_edges:
+                                                                                       if prev in e.verts:
+                                                                                               dissedges2[posn].append(e)
+                                                       prev = vert
+                                                       prevedge = edge
+                                               mesh.calc_tessface()
+                                       
+
+                       # select inserted edges/verts
+                       for posn in range(len(vertlist)):
+                               for v in dissverts2[posn]:
+                                       v.select = 1
+                               for e in dissedges2[posn]:
+                                       e.select = 1
+
+               # do distance shifting
+               for posn in range(len(vertlist)):
+                       if railedges2[posn] != []:
+                               for v in vertlist[posn]:
+                                       pv = dissverts2[posn][vertlist[posn].index(v)]
+                                       rv = railverts2[posn][vertlist[posn].index(v)]
+                                       sv = bmundo.verts[v.index]
+                                       vec = rv.co - sv.co
+                                       vec.length = abs(dist)
+                                       pv.co = sv.co + vec
+               
+               # create cap
+               if not(capped):
+                       capsellist = []
+                       for posn in range(len(vertlist)):
+                               if scn.Both and scn.Cap:
+                                       capped = 1
+                                       
+                                       def capendpoint(i):
+                                               capedges = []
+                                               es1 = None
+                                               es2 = None
+                                               vert = vertlist[posn][i]
+                                               for e in vert.link_edges:
+                                                       v = e.other_vert(vert)
+                                                       if not(v in vertlist[posn]) and not(v in dissverts1[posn]) and not(v in dissverts2[posn]):
+                                                               capedges.append(e)
+                                               if len(capedges) == 1:
+                                                       e = capedges[0]
+                                                       for f in e.link_faces:
+                                                               v2 = e.other_vert(vert)
+                                                               v2.select = 1
+                                                               if dissverts1[posn][i] in f.verts:
+                                                                       f1, l1 = bmesh.utils.face_split(f, v2, dissverts1[posn][i])
+                                                                       if e in f.edges:
+                                                                               fj1 = f
+                                                                               fo1 = f1
+                                                                       else:
+                                                                               fj1 = f1
+                                                                               fo1 = f
+                                                                       for es in v2.link_edges:
+                                                                               if es.other_vert(v2) == dissverts1[posn][i]:
+                                                                                       es.select = 1
+                                                                                       es1 = es
+                                                               elif dissverts2[posn][i] in f.verts:
+                                                                       f2, l1 = bmesh.utils.face_split(f, v2, dissverts2[posn][i])
+                                                                       if e in f.edges:
+                                                                               fj2 = f
+                                                                               fo2 = f2
+                                                                       else:
+                                                                               fj2 = f2
+                                                                               fo2 = f
+                                                                       for es in v2.link_edges:
+                                                                               if es.other_vert(v2) == dissverts2[posn][i]:
+                                                                                       es.select = 1
+                                                                                       es2 = es
+                                                       f3 = bmesh.utils.face_join((fj1, fj2))
+                                               if es1 == None:
+                                                       caplist[posn].append((None, None, None, None, None, None, None))
+                                               else:
+                                                       caplist[posn].append((es1, es2, vert, v2, f3, fo1, fo2))
+                                               capsellist.append(es1)
+                                               capsellist.append(es2)
+                                                       
+                                       caplist[posn] = []
+                                       capendpoint(0)
+                                       capendpoint(-1)
+                       mesh.calc_tessface()
+
+               # select original verts/edges
+               for posn in range(len(vertlist)):
+                       for edge in edgelist[posn]:
+                               edge.select = 1
+                       for vert in vertlist[posn]:
+                               vert.select = 1
+                               
+       bmesh.update_edit_mesh(mesh, destructive=True)
+       mesh.update()
+       
+
+
+
+def do_paredge(self):
+
+       global started, wrongsel, stop
+       global dist, olddist, distset, oldboth, mbns, negsubd, possubd
+       global bm, bmundo, mesh, region, scn
+       global vertlist, edgelist, facelist, sellist2
+       global meanmin, meanmax
+       global dissverts1, dissedges1, railverts1, railedges1
+       global dissverts2, dissedges2, railverts2, railedges2
+       global caplist, capped, oldcap
+
+       oldcap = 0
+       capped = 0
+       stop = 0
+       dist = 0
+       olddist = 0
+       oldboth = 0
+       wrongsel = 0
+       mbns = 0
+       negsubd = []
+       possubd = []
+       distset = 0
+       railedges1 = []
+       railedges2 = []
+       railverts1 = []
+       railverts2 = []
+       dissedges1 = []
+       dissedges2 = []
+       dissverts1 = []
+       dissverts2 = []
+       caplist = []
+       singledir = []
+       firstvert = []
+
+       if eval(str(bpy.app.build_revision)[2:7]) >= 47779:
+               bpy.ops.mesh.sort_elements(elements={"VERT"})
+       else:
+               bpy.ops.mesh.vertices_sort()
+       context = bpy.context
+       scn = context.scene
+       region = context.region  
+       area = context.area
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+       bmundo = bm.copy()
+       started = 1
+
+       sellist = []
+       sellist2 = []
+       edgelist = []
+       vertlist = []
+       for v in bm.verts:
+               if v.select:
+                       sellist.append(v)
+                       sellist2.append(v)
+       if len(sellist) <= 1:
+               wrongsel = 1
+               return
+       # find first two connected verts: v and nxv
+       # they consitute edge e
+       
+       # vertlist: make ordered list of selected vert-string
+       # edgelist: make ordered list of selected edges-string
+       p = 0
+       while len(sellist) > 0:
+               # as long as verts in selection list, keep creating new connected vert/edgelists
+               v = sellist[0]
+               railedges1.append([])
+               railedges2.append([])
+               railverts1.append([])
+               railverts2.append([])
+               dissedges1.append([])
+               dissedges2.append([])
+               dissverts1.append([])
+               dissverts2.append([])
+               caplist.append([])
+               vertlist.append([])
+               edgelist.append([])
+               possubd.append(0)
+               negsubd.append(0)
+               singledir.append(None)
+               firstvert.append(None)
+               for e in v.link_edges:
+                       if e.select:
+                               vertlist[p].append(v)
+                               edgelist[p].append(e)
+                               nxv = e.other_vert(v)
+                               vertlist[p].append(nxv)
+                               break
+               sellist.pop(sellist.index(v))
+               try:
+                       sellist.pop(sellist.index(nxv))
+               except:
+                       pass
+
+               # add in front of lists 
+               while len(sellist) > 0:
+                       facelist = []
+                       invlist = []
+                       found = 0
+                       l = len(vertlist[p])
+                       for f in vertlist[p][0].link_faces:
+                               if not(vertlist[p][1] in f.verts):
+                                       facelist.append(f)
+                               else:
+                                       invlist.append(f)
+                       # must be edgeloop(slice)
+                       if len(facelist) == 2:
+                               for fe in facelist[0].edges:
+                                       if fe in facelist[1].edges:
+                                               if fe.select:
+                                                       found = 1
+                                                       break
+                       elif len(facelist) == 1:
+                               for fe in vertlist[p][0].link_edges:
+                                       if fe in facelist[0].edges:
+                                               nt = 0
+                                               for invf in invlist:
+                                                       if fe in invf.edges:
+                                                               nt = 1
+                                               if not(nt):
+                                                       found = 1
+                                                       break
+                       if found:
+                               if fe.select:
+                                       for fv in fe.verts:
+                                               if fv != vertlist[p][0]:
+                                                       break
+                                       vertlist[p].insert(0, fv)
+                                       edgelist[p].insert(0, fe)
+                                       sellist.pop(sellist.index(fv))
+                                       continue
+                       break
+               
+               #store first vert for closedness checking
+               firstvert[p] = vertlist[p][0]
+               sellist.append(firstvert[p])
+
+               # add to end of lists
+               while len(sellist) > 0:
+                       facelist = []
+                       invlist = []
+                       found = 0
+                       l = len(vertlist[p])
+                       for f in vertlist[p][l - 1].link_faces:
+                               if not(vertlist[p][l - 2] in f.verts):
+                                       facelist.append(f)
+                               else:
+                                       invlist.append(f)
+                       # must be edgeloop(slice)
+                       if len(facelist) == 2:
+                               for fe in facelist[0].edges:
+                                       if fe in facelist[1].edges:
+                                               if fe.select:
+                                                       found = 1
+                                                       break
+                       elif len(facelist) == 1:
+                               found = 0
+                               for fe in vertlist[p][l - 1].link_edges:
+                                       if fe in facelist[0].edges:
+                                               nt = 0
+                                               for invf in invlist:
+                                                       if fe in invf.edges:
+                                                               nt = 1
+                                               if not(nt):
+                                                       found = 1
+                                                       break
+                       if found:
+                               if fe.select:
+                                       for fv in fe.verts:
+                                               if fv != vertlist[p][l - 1]:
+                                                       break
+                                       vertlist[p].append(fv)
+                                       edgelist[p].append(fe)
+                                       sellist.pop(sellist.index(fv))
+                                       continue
+                       break
+               # handle closed/open selections
+               if vertlist[p][len(vertlist[p]) - 1] == firstvert[p]:
+                       for edge in firstvert[p].link_edges:
+                               if edge.other_vert(firstvert[p]) == vertlist[p][len(vertlist[p]) - 2]:
+                                       edgelist[p].append(edge)
+                                       break
+                                       vertlist[p].append(firstvert[p])
+               else:
+                       sellist.pop(sellist.index(firstvert[p]))
+               # next selected edgeloopslice
+               p += 1
+
+
+       # orient edge and vertlists parallel - reverse if necessary
+
+       singledir[0] = edgelist[0][0].verts[0]          
+       
+       for i in range(len(edgelist) - 1):
+               bpy.ops.mesh.select_all(action="DESELECT")
+               # get first vert and edge for two adjacent slices
+               for v in edgelist[i][0].verts:
+                       if len(edgelist[i]) == 1:
+                               vt = singledir[i]       
+                               vt.select = 1
+                               bm.select_history.add(vt)
+                               v1 = vt
+                               e1 = edgelist[i][0]
+                               break
+                       elif not(v in edgelist[i][1].verts):
+                               v.select = 1
+                               bm.select_history.add(v)
+                               v1 = v
+                               e1 = edgelist[i][0]
+               for v in edgelist[i+1][0].verts:
+                       if len(edgelist[i+1]) == 1:
+                               v.select = 1
+                               bm.select_history.add(v)
+                               v2 = v
+                               e2 = edgelist[i+1][0]
+                               break
+                       elif not(v in edgelist[i+1][1].verts):
+                               v.select = 1
+                               bm.select_history.add(v)
+                               v2 = v
+                               e2 = edgelist[i+1][0]
+               singledir[i+1] = v2
+               bm.select_history.validate()
+               # get path between startverts for checking orientation
+               bpy.ops.mesh.select_vertex_path(type='TOPOLOGICAL')
+               
+               for e in bm.edges:
+                       if e.verts[0].select and e.verts[1].select:
+                               e.select = 1
+               
+               # correct selected path when not connected neatly to vert from left or right(cant know direction)
+               def correctsel(e1, v1, lst):
+                       found = 0
+                       # check situation where left/right connection is on some other slicevert than first
+                       while not(found):
+                               found = 1
+                               for edge in e1.other_vert(v1).link_edges:
+                                       if edge.select and edge != e1:
+                                               if lst.index(e1) < len(lst) - 1:
+                                                       v1.select = 0
+                                                       e1.select = 0
+                                                       v1 = e1.other_vert(v1)
+                                                       e1 = lst[lst.index(e1) + 1]
+                                               else:
+                                                       templ = list(e1.other_vert(v1).link_faces)
+                                                       for f in e1.link_faces:
+                                                               templ.pop(templ.index(f))
+                                                       if len(templ) < 2:
+                                                               v1.select = 0
+                                                               e1.select = 0
+                                                               v1 = e1.other_vert(v1)
+                                                               return e1, v1, "reverse"
+                                                       for edge in e1.other_vert(v1).link_edges:
+                                                               if edge in templ[0].edges and edge in templ[1].edges:
+                                                                       v1.select = 0
+                                                                       e1.select = 0
+                                                                       v1 = e1.other_vert(v1)
+                                                                       e1 = edge
+                                               found = 0
+                                       
+                       # check situation where left/right connection is on vert thats outside slice
+                       found = 0
+                       while not(found):
+                               templ = list(v1.link_faces)
+                               for f in e1.link_faces:
+                                       templ.pop(templ.index(f))
+                               found = 1
+                               if len(templ) < 2:
+                                       break
+                               for edge in v1.link_edges:
+                                       if edge in templ[0].edges and edge in templ[1].edges:
+                                               if edge.other_vert(v1).select:
+                                                       v1.select = 0
+                                                       edge.select = 0
+                                                       v1 = edge.other_vert(v1)
+                                                       e1 = edge
+                                                       found = 0
+                       return e1, v1, "normal"
+                                                       
+               e1, v1, state1 = correctsel(e1, v1, edgelist[i])
+               if state1 == "reverse":
+                       # special trick - mail me
+                       for j in range(i + 1):
+                               edgelist[j].reverse()
+                               vertlist[j].reverse()
+               e2, v2, state2 = correctsel(e2, v2, edgelist[i+1])                                      
+               if state2 == "reverse":
+                       # special trick - mail me
+                       edgelist[i+1].reverse()
+                       vertlist[i+1].reverse()
+
+               # do all the checking to see if the checked lists must be reversed
+               brk = 0
+               for face1 in e1.link_faces:
+                       for edge1 in face1.edges:
+                               if edge1.select:
+                                       for loop1 in face1.loops:
+                                               if loop1.vert == v1:
+                                                       if loop1.edge == e1:
+                                                               turn = loop1
+                                                       elif loop1.link_loop_next.edge == e1:
+                                                               turn = loop1.link_loop_next
+                                                       else:
+                                                               turn = loop1.link_loop_prev
+                                                       # check if turning in one direction
+                                                       if turn.link_loop_next.edge.select:
+                                                               for face2 in e2.link_faces:
+                                                                       for edge2 in face2.edges:
+                                                                               if edge2.select:
+                                                                                       for loop2 in face2.loops:
+                                                                                               if loop2.vert == v2:
+                                                                                                       if loop2.edge == e2:
+                                                                                                               turn = loop2
+                                                                                                       elif loop2.link_loop_next.edge == e2:
+                                                                                                               turn = loop2.link_loop_next
+                                                                                                       else:
+                                                                                                               turn = loop2.link_loop_prev
+                                                                                                       if turn.link_loop_next.edge.select:
+                                                                                                               singledir[i+1] = e2.other_vert(v2)
+                                                                                                               edgelist[i+1].reverse()
+                                                                                                               vertlist[i+1].reverse()
+                                                                                                       break
+                                                                                       brk = 1
+                                                                                       break
+                                                                       if brk == 1:
+                                                                               break
+                                                       # and the other
+                                                       elif loop1.link_loop_prev.edge.select:
+                                                               for face2 in e2.link_faces:
+                                                                       for edge2 in face2.edges:
+                                                                               if edge2.select:
+                                                                                       for loop2 in face2.loops:
+                                                                                               if loop2.vert == v2:
+                                                                                                       if loop2.edge == e2:
+                                                                                                               turn = loop2
+                                                                                                       elif loop2.link_loop_next.edge == e2:
+                                                                                                               turn = loop2.link_loop_next
+                                                                                                       else:
+                                                                                                               turn = loop2.link_loop_prev
+                                                                                                       if turn.link_loop_prev.edge.select:
+                                                                                                               singledir[i+1] = e2.other_vert(v2)
+                                                                                                               edgelist[i+1].reverse()
+                                                                                                               vertlist[i+1].reverse()
+                                                                                                       break
+                                                                                       brk = 1
+                                                                                       break
+                                                                       if brk == 1:
+                                                                               break
+                                                       break
+                                       break
+#              if i == 50:
+#                      stop = 1
+#                      return
+
+       bpy.ops.mesh.select_all(action="DESELECT")
+       for posn in range(len(vertlist)):
+               for v in vertlist[posn]:
+                       v.select = 1
+               for e in edgelist[posn]:
+                       e.select = 1
+
+
+
+
+
+       # try to guess min and max values for distance slider - can always use mouse to override
+       co1 = vertlist[0][0].co
+       co2 = vertlist[0][len(vertlist[0]) - 1].co                              
+       meanmin = (co1 - co2).length * -2
+       meanmax = -meanmin
+       if meanmax == 0:
+               meanmax = meanmin = 1
+
+       bpy.types.Scene.Distance = bpy.props.FloatProperty(
+                       name = "Distance", 
+                       description = "Enter distance",
+                       default = 0,
+                       min = meanmin,
+                       max = meanmax)
+       
+       
+def redraw():
+       
+       global parchange
+       
+       if not(bpy.context.mode == "EDIT_MESH"):
+               return
+       
+       # if parameter changes, reinsert/move edges
+       if parchange:
+               parchange = 0
+               adapt(scn, None)
+
diff --git a/EWOCprojects tools/mesh_quadder.py b/EWOCprojects tools/mesh_quadder.py
new file mode 100644 (file)
index 0000000..74b637b
--- /dev/null
@@ -0,0 +1,249 @@
+
+# ***** 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.
+#
+# If you have Internet access, you can find the license text at
+# http://www.gnu.org/licenses/gpl.txt,
+# if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ***** END GPL LICENCE BLOCK *****
+# --------------------------------------------------------------------------
+
+__bpydoc__ = """\
+Fills selected border verts/edges area with quads.
+Select several neighbouring verts/edges with at least one "border corner" selected.
+Invoke addon. (its on the Mesh Tools panel)
+
+If you wish to hotkey Quadder:
+In the Input section of User Preferences at the bottom of the 3D View > Mesh section click 'Add New' button.
+In the Operator Identifier box put 'mesh.quadder'.
+Assign a hotkey.
+Save as Default (Optional).
+"""
+
+bl_info = {
+       "name": "Quadder",
+       "author": "Gert De Roost",
+       "version": (0, 3, 2),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Fills selected border verts/edges area with quads",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+import bmesh
+
+
+class Quadder(bpy.types.Operator):
+       bl_idname = "mesh.quadder"
+       bl_label = "Quadder"
+       bl_description = "Fills selected border verts/edges area with quads"
+       bl_options = {"REGISTER", "UNDO"}
+       
+       @classmethod
+       def poll(cls, context):
+               obj = context.active_object
+               return (obj and obj.type == 'MESH' and context.mode == 'EDIT_MESH')
+
+       def invoke(self, context, event):
+               self.save_global_undo = bpy.context.user_preferences.edit.use_global_undo
+               bpy.context.user_preferences.edit.use_global_undo = False
+               
+               do_quadder(self)
+               
+               return {'FINISHED'}
+
+def panel_func(self, context):
+       self.layout.label(text="Quadder:")
+       self.layout.operator("mesh.quadder", text="Fill quads")
+
+def register():
+       bpy.utils.register_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.append(panel_func)
+
+def unregister():
+       bpy.utils.unregister_module(__name__)
+       bpy.types.VIEW3D_PT_tools_meshedit.remove(panel_func)
+
+
+if __name__ == "__main__":
+       register()
+
+
+
+
+def do_quadder(self):
+       
+       global bm, ecnt
+       
+       context = bpy.context
+       region = context.region  
+       selobj = bpy.context.active_object
+       mesh = selobj.data
+       bm = bmesh.from_edit_mesh(mesh)
+
+       smoothlist = []
+       for v in bm.verts:
+               if v.select:
+                       smoothlist.append(v)
+       ecnt = 0
+       for e in bm.edges:
+               if e.select:
+                       ecnt += 1
+       
+       vertlist = []
+       templist = []
+       verts = findcorner()
+       while verts:
+               if len(verts) == 5 or len(verts) == 3:
+                       off1 = verts[0].co - verts[1].co
+                       off2 = verts[2].co - verts[1].co
+                       newco = verts[1].co + off1 + off2
+                       v = bm.verts.new(newco)
+               elif len(verts) == 4:
+                       v = verts[3]
+               bm.faces.new((verts[0], verts[1], verts[2], v))
+               v.select = 1
+               templist.append(v)
+               verts[1].select = 0
+               vertlist.append(verts[1])
+               mesh.update()
+               verts = findcorner()
+               if ecnt == 2:
+                       verts = None
+               
+       for v in vertlist:
+               v.select = 1
+       for v in smoothlist:
+               v.select = 0
+       for v in bm.verts:
+               if len(v.link_faces) <= 2:
+                       v.select = 0
+       bpy.ops.mesh.vertices_smooth(repeat=4)
+       bpy.ops.mesh.select_all(action="SELECT")
+       bm.normal_update()
+       bpy.ops.mesh.normals_make_consistent()
+       for v in smoothlist:
+               v.select = 1
+       for v in templist:
+               v.select = 1
+       for v in vertlist:
+               v.select = 1
+       bpy.ops.mesh.select_all(action="DESELECT")
+               
+       bpy.ops.object.editmode_toggle()
+       bpy.ops.object.editmode_toggle()
+       bm.free()
+       
+       
+def findcorner():
+       
+       global bm
+       
+       if ecnt == 2:
+               for v in bm.verts:
+                       if v.select:
+                               vlist = []
+                               for e in v.link_edges:
+                                       if e.other_vert(v).select:
+                                               vlist.append(e.other_vert(v))
+                               if len(vlist) == 2:
+                                       return [vlist[0], v, vlist[1]]
+       for v1 in bm.verts:
+               if v1.select:
+                       if len(v1.link_edges) == 2:
+                               e1 = v1.link_edges[0]
+                               e2 = v1.link_edges[1]
+                               if len(e1.link_faces) == 0 and len(e2.link_faces) == 0:
+                                       v2 = e1.other_vert(v1)
+                                       v3 = e2.other_vert(v1)
+                                       if len(v2.link_edges) == 1 and len(v3.link_edges) == 1:
+                                               return [v2, v1, v3]
+                               continue
+                       elif len(v1.link_edges) > 2:
+                               slist = []
+                               fou = 0
+                               for e1 in v1.link_edges:
+                                       if e1.other_vert(v1).select:
+                                               if len(e1.link_faces) == 0:
+                                                       for e2 in v1.link_edges:
+                                                               if e2.other_vert(v1).select and e1 != e2:
+                                                                       if len(v1.link_edges) > 3:
+                                                                               fou = 1
+                                                                               break
+                                                       if fou:
+                                                               v2 = e1.other_vert(v1)
+                                                               v3 = e2.other_vert(v1)
+                                                               return [v2, v1, v3]
+                                       
+                       linkedges = []
+                       linkverts = []
+                       for e1 in v1.link_edges:
+                               if len(v1.link_edges) > 3:
+                                       if e1.other_vert(v1).select:
+                                               linkverts.append(e1.other_vert(v1))
+                                               linkedges.append(e1)
+                       if len(linkedges) == 2:
+                               found1 = 1
+                               if len(linkedges[0].link_faces) != 2 and len(linkedges[1].link_faces) != 2:
+                                       f1 = linkedges[0].link_faces[0]
+                                       f2 = linkedges[1].link_faces[0]
+                                       if f1 == f2:
+                                               found1 = 0
+                                       for e2 in f1.edges:
+                                               if e2 in f2.edges:
+                                                       found1 = 0
+                                                       break
+                                       if found1:
+                                               for e3 in linkverts[0].link_edges:
+                                                       if len(e3.link_faces) == 1:
+                                                               for v3 in e3.verts:
+                                                                       if v3 != linkverts[0] and v3 != v1:
+                                                                               if v3.select:
+                                                                                       found2 = 1
+                                                                                       f3 = e3.link_faces[0]
+                                                                                       f4 = linkedges[0].link_faces[0]
+                                                                                       if f3 == f4:
+                                                                                               found2 = 0
+                                                                                       for e4 in f3.edges:
+                                                                                               if e4 in f4.edges:
+                                                                                                       found2 = 0
+                                                                                                       break
+                                                                                       if found2:
+                                                                                               return [linkverts[0], v1, linkverts[1], v3]
+                                               for e3 in linkverts[1].link_edges:
+                                                       if len(e3.link_faces) == 1:
+                                                               for v3 in e3.verts:
+                                                                       if v3 != linkverts[1] and v3 != v1:
+                                                                               if v3.select:
+                                                                                       found2 = 1
+                                                                                       f3 = e3.link_faces[0]
+                                                                                       f4 = linkedges[1].link_faces[0]
+                                                                                       if f3 == f4:
+                                                                                               found2 = 0
+                                                                                       for e4 in f3.edges:
+                                                                                               if e4 in f4.edges:
+                                                                                                       found2 = 0
+                                                                                                       break
+                                                                                       if found2:
+                                                                                               return [linkverts[0], v1, linkverts[1], v3]
+                                               return [linkverts[0], v1, linkverts[1], f1, f2]
+       return False
+       
diff --git a/EWOCprojects tools/mesh_selproject.py b/EWOCprojects tools/mesh_selproject.py
new file mode 100644 (file)
index 0000000..ad3fc2e
--- /dev/null
@@ -0,0 +1,455 @@
+# ##### 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 #####
+
+__bpydoc__ = """\
+The SelProject addon enables you to "project" an object onto another object, every vertex inside the 
+projection's shape will be selected.
+
+
+Documentation
+
+First go to User Preferences->Addons and enable the SelProject addon in the Mesh category.
+It will appear in the Tools panel.  First set From and To object from the dropdown list.  From object
+is the object you project, To object the one you project on.  If switching to editmode first,
+the "Use Selection" option appears.  When choosing this you will use a copy of the selected area
+instead of a From object.
+Press Start SelProject to start the projection.  When in Use Selection mode, the object selected from
+will be temporarily hidden for the duration of the operation.  You can use manipulator and 
+G, R and S (and XYZ) hotkeys as usual to transform both objects.  Also there is the direction Empty 
+which is used in combination with the origin of the From object (which will be temporarily set to
+object geometry median) to set the projection direction.
+Press ENTER to finalize the selection projection operation.
+"""
+
+
+bl_info = {
+       "name": "SelProject",
+       "author": "Gert De Roost",
+       "version": (0, 2, 8),
+       "blender": (2, 6, 3),
+       "location": "View3D > Tools",
+       "description": "Use object projection as selection tool.",
+       "warning": "",
+       "wiki_url": "",
+       "tracker_url": "",
+       "category": "Mesh"}
+
+if "bpy" in locals():
+    import imp
+
+
+import bpy
+from bpy_extras import *
+import bmesh
+from bgl import *
+from mathutils import *
+import math
+
+
+activated = 0
+redomenus = 1
+started = 0
+cont = 0
+oldobjs = None
+selverts = []
+fromobj = None
+oldfromobj = None
+
+
+
+bpy.types.Scene.UseSel = bpy.props.BoolProperty(
+               name = "Use Selection", 
+               description = "Use selected area as From object",
+               default = False)
+
+itemlist = [("Empty", "Empty", "Empty")]
+bpy.types.Scene.FromObject = bpy.props.EnumProperty(
+     &n