Newer
Older
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
for key, value in edge_dic.items():
if value[0] in end_verts:
sel.remove(key)
continue
if value[1] in end_verts:
sel.remove(key)
bmesh.update_edit_mesh(me, True, False)
# Select the resulting edges
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for e in sel:
mesh.edges[e].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
bm = bmesh.from_edit_mesh(me)
# Store current faces
for f in bm.faces:
if f.select:
cur_faces.append(f.index)
# Compare current and original faces
for x in org_faces:
if x in cur_faces:
new_faces.append(x)
bmesh.update_edit_mesh(me, True, False)
# Select the resulting faces
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for e in new_faces:
mesh.polygons[e].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
else:
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
sel = []
edge_dic = {}
vert_list = []
end_verts = []
# Store edges and verts in dictionary
for e in bm.edges:
if e.select:
sel.append(e.index)
# Populate vert_list
vert_list.append(e.verts[0].index)
vert_list.append(e.verts[1].index)
# Store dictionary
edge_dic[e.index] = [e.verts[0].index, e.verts[1].index]
# Store end verts
for v in vert_list:
if vert_list.count(v) == 1:
end_verts.append(v)
# Check verts in dictionary
for key, value in edge_dic.items():
if value[0] in end_verts:
sel.remove(key)
continue
if value[1] in end_verts:
sel.remove(key)
bmesh.update_edit_mesh(me, True, False)
# Select the resulting edges
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh = bpy.context.active_object.data.edges
for e in sel:
mesh[e].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
return {'FINISHED'}
class paintSelect(bpy.types.Operator):
"""Click and drag to select"""
bl_idname = "view3d.select_paint"
bl_label = "Paint Select"
deselect: BoolProperty(default = False, description = 'Deselect objects, polys, edges or verts')
toggle: BoolProperty(default = False, description = 'Toggles the selection. NOTE: this option can be slow on heavy meshes')
sel_before: IntProperty(description = 'Do Not Touch', options = {'HIDDEN'})
sel_after: IntProperty(description = 'Do Not Touch', options = {'HIDDEN'})
def modal(self, context, event):
#if event.type == 'MOUSEMOVE':
refresh = event.mouse_x
if self.deselect == False:
bpy.ops.view3d.select('INVOKE_DEFAULT', extend = True, deselect = False)
else:
bpy.ops.view3d.select('INVOKE_DEFAULT', extend = False, deselect = True, toggle = True)
return {'FINISHED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if self.toggle:
sel_ob = len(bpy.context.selected_objects)
if sel_ob >= 1:
mode = bpy.context.object.mode
if mode == 'EDIT':
sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
# Get Selection before
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
ob = bpy.context.object.data
# check verts
if sel_mode[0]:
for v in ob.vertices:
if v.select:
self.sel_before += 1
# check edges
elif sel_mode[1]:
for e in ob.edges:
if e.select:
self.sel_before += 1
# check polys
else:
for p in ob.polygons:
if p.select:
self.sel_before += 1
# Toggle Selection
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.view3d.select('INVOKE_DEFAULT', extend = False, toggle = True)
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
ob = bpy.context.object.data
# check verts after
if sel_mode[0]:
for v in ob.vertices:
if v.select:
self.sel_after += 1
# check edges after
elif sel_mode[1]:
for e in ob.edges:
if e.select:
self.sel_after += 1
# check polys after
else:
for p in ob.polygons:
if p.select:
self.sel_after += 1
if self.sel_after > self.sel_before:
self.deselect = False
elif self.sel_after == self.sel_before:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_all(action='DESELECT')
return {'FINISHED'}
else:
self.deselect = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
elif mode == 'OBJECT':
bpy.ops.view3d.select('INVOKE_DEFAULT', extend = False, toggle = True)
sel_ob_after = len(bpy.context.selected_objects)
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
class pathSelectRing(bpy.types.Operator):
"""Selects the shortest edge ring path"""
bl_idname = "mesh.path_select_ring"
bl_label = "Path Select Ring"
pick: BoolProperty(name = "Pick Mode", description = "Pick Mode", default = False)
collapse: BoolProperty(name = "Collapse", description = "Collapses everything between your two selected edges", default = False)
def draw(self, context):
layout = self.layout
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
mesh = bpy.context.active_object.data
sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
org_sel = []
start_end = []
active_edge = []
border_sel = []
vert_sel = []
face_sel = []
bpy.context.tool_settings.mesh_select_mode = [False, True, False]
if self.pick:
bpy.ops.view3d.select('INVOKE_DEFAULT', extend=True, deselect=False, toggle=False)
iterate = 0
for e in reversed(bm.select_history):
if isinstance(e, bmesh.types.BMEdge):
iterate += 1
start_end.append(e)
if iterate >= 2:
if len(start_end) <= 1:
if self.collapse:
bpy.ops.mesh.merge(type='COLLAPSE', uvs=True)
return{'FINISHED'}
return{'CANCELLED'}
# Store active edge
for e in reversed(bm.select_history):
if isinstance(e, bmesh.types.BMEdge):
active_edge = e.index
# Store original edges
for e in bm.edges:
if e.select:
org_sel.append(e)
# Store visible faces
bpy.ops.mesh.select_all(action='SELECT')
for f in bm.faces:
if f.select:
face_sel.append(f)
# Store boundry edges
bpy.ops.mesh.region_to_loop()
for e in bm.edges:
if e.select:
border_sel.append(e)
bpy.ops.mesh.select_all(action='DESELECT')
# Select Start and End edges
for e in start_end:
e.select = True
# Hide trick
bpy.ops.mesh.loop_multi_select(ring=True)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=True, type='FACE')
bpy.ops.mesh.hide(unselected=True)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
bpy.ops.mesh.select_all(action='DESELECT')
for e in start_end:
e.select = True
bpy.ops.mesh.shortest_path_select()
bpy.ops.mesh.select_more()
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=True, type='EDGE')
# Deselect border edges
for e in border_sel:
e.select = False
# Add to original selection
for e in bm.edges:
if e.select:
org_sel.append(e)
# Restore hidden polygons
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
for f in face_sel:
f.select = True
bpy.ops.mesh.hide(unselected=True)
# Reselect original selection
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
bpy.ops.mesh.select_all(action='DESELECT')
for e in org_sel:
e.select = True
# Set active edge
bm.select_history.add(bm.edges[active_edge])
if self.collapse:
bpy.ops.mesh.merge(type='COLLAPSE', uvs=True)
bmesh.update_edit_mesh(me, True, False)
else:
self.report({'WARNING'}, "This tool only workins in edge mode.")
return {'CANCELLED'}
#Draws the Custom Menu in Object Mode
class ktools_menu(bpy.types.Menu):
bl_label = "KTools - Object Mode"
bl_idname = "OBJECT_MT_ktools_menu"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("mesh.draw_poly")
layout.operator("mesh.quickbool")
layout.operator("mesh.calc_normals")
layout.operator("object.custom_autosmooth")
layout.operator("object.basic_rename")
layout.operator("object.lattice_to_selection")
#Draws the Custom Menu in Edit Mode
class VIEW3D_MT_edit_mesh_ktools_menuEdit(bpy.types.Menu):
bl_label = "KTools - Edit Mode"
bl_idname = "VIEW3D_MT_edit_mesh_ktools_menuEdit"
def draw(self, context):
layout = self.layout
layout.operator("mesh.cut_tool")
layout.operator("mesh.snaptoaxis")
layout.operator("mesh.autotubes")
layout.operator("mesh.shrinkwrap_smooth")
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("mesh.build_corner")
layout.operator("object.lattice_to_selection")
layout.operator("mesh.path_select_ring")
layout.operator("mesh.grow_loop")
layout.operator("mesh.shrink_loop")
layout.operator("mesh.extend_loop")
layout.operator("mesh.draw_poly")
layout.operator("object.toggle_silhouette")
layout.operator("mesh.quickbool")
layout.operator("object.custom_autosmooth")
layout.operator("mesh.calc_normals")
layout.operator("object.basic_rename")
#Calls the KTools Object Menu
class ktools(bpy.types.Operator): #Namesuggestion: K-Tools or K-Mac
"""Calls the KTools Menu"""
bl_idname = "object.ktools"
bl_label = "KTools Object Menu"
#bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
bpy.ops.wm.call_menu(name=ktools_menu.bl_idname)
return {'FINISHED'}
"""
sel_ob = bpy.context.object
mode = bpy.context.active_object.mode
if mode == 'EDIT':
bpy.ops.wm.call_menu(name=VIEW3D_MT_edit_mesh_ktools_menuEdit.bl_idname)
else:
bpy.ops.wm.call_menu(name=ktools_menu.bl_idname)
else:
bpy.ops.wm.call_menu(name=ktools_menu.bl_idname)
return {'FINISHED'}
#self.report({'WARNING'}, "Active object is not a mesh.")
#return {'CANCELLED'}
"""
#Calls the KTools Edit Menu
class ktools_mesh(bpy.types.Operator): #Namesuggestion: K-Tools or K-Mac
"""Calls the KTools Edit Menu"""
bl_idname = "mesh.ktools_mesh"
bl_label = "KTools Mesh Menu"
#bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
bpy.ops.wm.call_menu(name=VIEW3D_MT_edit_mesh_ktools_menuEdit.bl_idname)
# draw function for integration in menus
def menu_func(self, context):
self.layout.separator()
self.layout.menu("VIEW3D_MT_edit_mesh_ktools_menuEdit", text = "KTools")
meta-androcto
committed
def menu_func_ob(self, context):
self.layout.separator()
self.layout.menu("OBJECT_MT_ktools_menu", text = "KTools")
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
#Register and Unregister all the operators
def register():
bpy.utils.register_class(lattice_to_selection)
bpy.utils.register_class(calc_normals)
bpy.utils.register_class(snaptoaxis)
bpy.utils.register_class(quickbool)
bpy.utils.register_class(autotubes)
bpy.utils.register_class(basicRename)
bpy.utils.register_class(cut_tool)
bpy.utils.register_class(customAutoSmooth)
bpy.utils.register_class(shrinkwrapSmooth)
bpy.utils.register_class(buildCorner)
bpy.utils.register_class(drawPoly)
bpy.utils.register_class(toggleSilhouette)
bpy.utils.register_class(growLoop)
bpy.utils.register_class(extendLoop)
bpy.utils.register_class(shrinkLoop)
bpy.utils.register_class(paintSelect)
bpy.utils.register_class(pathSelectRing)
bpy.utils.register_class(ktools_menu)
bpy.utils.register_class(VIEW3D_MT_edit_mesh_ktools_menuEdit)
bpy.utils.register_class(ktools)
bpy.utils.register_class(ktools_mesh)
meta-androcto
committed
bpy.types.VIEW3D_MT_edit_mesh_specials.prepend(menu_func)
bpy.types.VIEW3D_MT_object_specials.prepend(menu_func_ob)
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
# Add paint select to CTRL+SHIFT+ALT+LeftMouse
km = kc.keymaps.new(name="3D View", space_type="VIEW_3D")
kmi = km.keymap_items.new('view3d.select_paint', 'LEFTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
def unregister():
bpy.utils.unregister_class(lattice_to_selection)
bpy.utils.unregister_class(calc_normals)
bpy.utils.unregister_class(snaptoaxis)
bpy.utils.unregister_class(quickbool)
bpy.utils.unregister_class(autotubes)
bpy.utils.unregister_class(basicRename)
bpy.utils.unregister_class(cut_tool)
bpy.utils.unregister_class(customAutoSmooth)
bpy.utils.unregister_class(shrinkwrapSmooth)
bpy.utils.unregister_class(buildCorner)
bpy.utils.unregister_class(drawPoly)
bpy.utils.unregister_class(toggleSilhouette)
bpy.utils.unregister_class(growLoop)
bpy.utils.unregister_class(extendLoop)
bpy.utils.unregister_class(shrinkLoop)
bpy.utils.unregister_class(paintSelect)
bpy.utils.unregister_class(pathSelectRing)
bpy.utils.unregister_class(ktools_menu)
bpy.utils.unregister_class(VIEW3D_MT_edit_mesh_ktools_menuEdit)
bpy.utils.unregister_class(ktools)
bpy.utils.unregister_class(ktools_mesh)
meta-androcto
committed
bpy.types.VIEW3D_MT_edit_mesh_specials.remove(menu_func)
meta-androcto
committed
bpy.types.VIEW3D_MT_object_specials.remove(menu_func_ob)
kc = bpy.context.window_manager.keyconfigs.addon
if kc:
km = kc.keymaps["3D View"]
for kmi in km.keymap_items:
if kmi.idname == 'view3d.select_paint':
km.keymap_items.remove(kmi)
break
# This allows you to run the script directly from blenders text editor
# to test the addon without having to install it.
if __name__ == "__main__":
register()