Newer
Older
for x in range(iterate):
bpy.ops.object.modifier_add(type='SHRINKWRAP')
mod_id = (len(bpy.context.object.modifiers)-1)
shrink_name = bpy.context.object.modifiers[mod_id].name
bpy.context.object.modifiers[shrink_name].target = bpy.data.objects[shrink_ob]
bpy.context.object.modifiers[shrink_name].vertex_group = sel
bpy.context.object.modifiers[shrink_name].wrap_method = 'PROJECT'
bpy.context.object.modifiers[shrink_name].use_negative_direction = True
bpy.context.object.modifiers[shrink_name].subsurf_levels = self.subsurf
bpy.ops.mesh.vertices_smooth(factor=1, repeat=1)
bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
bpy.ops.object.convert(target='MESH')
bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
bpy.ops.object.vertex_group_remove(all = False)
bpy.ops.object.modifier_remove(modifier=shrink_name)
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_pattern(pattern=shrink_ob)
bpy.context.view_layer.objects.active = bpy.data.objects[shrink_ob]
#Delete all geo inside Shrink_Object
bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
bpy.ops.object.delete(use_global=True)
bpy.ops.object.select_pattern(pattern=tmp_ob)
bpy.context.view_layer.objects.active = bpy.data.objects[tmp_ob]
bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
if pin == True:
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.vertex_group_select(org_id)
bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
bpy.ops.object.delete(use_global=False)
bpy.ops.object.select_pattern(pattern=org_ob)
bpy.context.view_layer.objects.active = bpy.data.objects[org_ob]
bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
# Fix for Blender remembering the previous selection
bpy.ops.object.vertex_group_assign_new()
bpy.ops.object.vertex_group_remove(all = False)
class buildCorner(bpy.types.Operator):
"""Builds corner topology. Good for converting ngons"""
bl_idname = "mesh.build_corner"
bl_label = "Build Corner"
def modal(self, context, event):
delta = self.offset - event.mouse_x
if delta >= 0:
offset = 1
else:
offset = 0
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
bpy.ops.mesh.poke()
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
bpy.ops.object.vertex_group_assign_new()
sel_id = bpy.context.object.vertex_groups.active_index
bpy.ops.mesh.region_to_loop()
bpy.ops.object.vertex_group_remove_from()
bpy.ops.mesh.select_nth(nth=2, skip=1, offset=offset)
bpy.ops.object.vertex_group_select(sel_id)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
bpy.ops.mesh.dissolve_mode(use_verts=False)
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
bpy.ops.object.vertex_group_select()
bpy.ops.mesh.select_more()
bpy.ops.object.vertex_group_remove(all = False)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
elif event.type == 'LEFTMOUSE':
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
bpy.ops.ed.undo()
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.object:
bpy.ops.mesh.edge_face_add()
bpy.ops.mesh.region_to_loop()
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
me = bpy.context.object.data
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
face_sel = []
edge_sel = []
for v in bm.faces:
if v.select:
face_sel.append(v.index)
for v in bm.edges:
if v.select:
edge_sel.append(v.index)
bm.to_mesh(me)
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.loop_to_region()
###################################
if edge_sel == 4:
return {'FINISHED'}
elif edge_sel%2 == 0:
self.offset = event.mouse_x
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
#elif edge_sel == 5:
# bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')
# bpy.ops.mesh.tris_convert_to_quads(face_threshold=3.14159, shape_threshold=3.14159)
# return {'FINISHED'}
else:
bpy.ops.mesh.poke()
bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')
bpy.ops.mesh.tris_convert_to_quads(face_threshold=3.14159, shape_threshold=3.14159)
return {'FINISHED'}
else:
self.report({'WARNING'}, "No active object, could not finish")
return {'CANCELLED'}
class drawPoly(bpy.types.Operator):
"""Draw a polygon"""
bl_idname = "mesh.draw_poly"
bl_label = "Draw Poly"
cursor_co: FloatVectorProperty()
manip: BoolProperty()
vgrp: IntProperty()
sel_mode = BoolVectorProperty()
cursor_depth: BoolProperty()
snap: BoolProperty()
def modal(self, context, event):
# set header gui
context.area.tag_redraw()
context.area.header_text_set("LMB = Create New Point, SHIFT = Flip Normals, RMB / ENTER = Accept NGon, MMB = Accept QuadFill")
mesh = bpy.context.active_object.data
if event.type == 'LEFTMOUSE':
if event.value == 'PRESS':
bpy.ops.view3d.cursor3d('INVOKE_DEFAULT')
obj = bpy.context.active_object
vert_co = bpy.context.scene.cursor_location
world = obj.matrix_world.inverted_safe()
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
me = bpy.context.object.data
bm = bmesh.new()
bm.from_mesh(me)
# Add new vert
new_vert = bm.verts.new(vert_co)
new_vert.co = world*new_vert.co
new_vert_id = new_vert.index
self.vert_count += 1
if self.vert_count >= 2:
bm.verts.ensure_lookup_table()
set_of_verts = set(bm.verts[i] for i in range(-2,0))
bm.edges.new(set_of_verts)
# Get index of first and last vertex
first_index = len(bm.verts)-self.vert_count
second_index = first_index+1
third_index = first_index+2
second_to_last_index = len(bm.verts)-2
mesh.vertices[new_vert_id].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.context.scene.cursor_location = self.cursor_co
if self.vert_count >= 4:
bpy.ops.object.vertex_group_assign()
if self.vert_count == 3:
# remove second vertex from group
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.vertices[first_index].select = True
mesh.vertices[third_index].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.object.vertex_group_assign()
bpy.ops.mesh.select_more()
if self.vert_count == 2:
bpy.ops.mesh.select_more()
if self.vert_count >= 4:
# make core poly
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.vertices[first_index].select = True
mesh.vertices[second_index].select = True
mesh.vertices[third_index].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.edge_face_add()
if self.vert_count == 4:
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.vertex_group_select(self.vgrp)
bpy.ops.mesh.edge_face_add()
# Remove remaining core edge
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.vertices[second_index].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.edge_face_add()
if self.vert_count >= 5:
#bpy.ops.object.vertex_group_assign()
bpy.ops.mesh.select_all(action='DESELECT')
# Remove Last Edge
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.vertices[first_index].select = True
mesh.vertices[second_to_last_index].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.delete(type='EDGE')
# Fill in rest of face
bpy.ops.object.vertex_group_select(self.vgrp)
bpy.ops.mesh.edge_face_add()
# Remove remaining core edge
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.vertices[second_index].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.edge_face_add()
bpy.ops.mesh.flip_normals()
#return {'FINISHED'}
elif event.type == 'MIDDLEMOUSE':
# reset header gui
context.area.tag_redraw()
context.area.header_text_set(None)
# Convert to Quads
bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')
bpy.ops.mesh.tris_convert_to_quads()
bpy.ops.mesh.tris_convert_to_quads(face_threshold=3.14159, shape_threshold=3.14159)
# restore selection mode and manipulator
bpy.context.tool_settings.mesh_select_mode = self.sel_mode
bpy.context.space_data.show_manipulator = self.manip
bpy.context.preferences.input.use_mouse_depth_cursor = self.cursor_depth
bpy.context.scene.tool_settings.use_snap = self.snap
# Remove and make sure vertex group data is gone
bpy.ops.object.vertex_group_remove_from(use_all_verts=True)
bpy.ops.object.vertex_group_remove()
bpy.ops.object.vertex_group_assign_new()
bpy.context.object.vertex_groups.active.name = "drawPoly_temp"
bpy.ops.object.vertex_group_remove()
elif event.type in {'RIGHTMOUSE', 'ESC', 'SPACE'}:
# reset header gui
context.area.tag_redraw()
context.area.header_text_set(None)
# restore selection mode and manipulator
bpy.context.tool_settings.mesh_select_mode = self.sel_mode
bpy.context.space_data.show_manipulator = self.manip
bpy.context.preferences.input.use_mouse_depth_cursor = self.cursor_depth
bpy.context.scene.tool_settings.use_snap = self.snap
# Remove and make sure vertex group data is gone
bpy.ops.object.vertex_group_remove_from(use_all_verts=True)
bpy.ops.object.vertex_group_remove()
bpy.ops.object.vertex_group_assign_new()
bpy.context.object.vertex_groups.active.name = "drawPoly_temp"
bpy.ops.object.vertex_group_remove()
elif event.type == 'LEFT_SHIFT' or event.type == 'RIGHT_SHIFT':
bpy.ops.mesh.flip_normals()
elif event.type == 'LEFT_CTRL' or event.type == 'RIGHT_CTRL' :
if bpy.context.preferences.input.use_mouse_depth_cursor == True:
bpy.context.preferences.input.use_mouse_depth_cursor = False
bpy.context.scene.tool_settings.use_snap = False
else:
bpy.context.preferences.input.use_mouse_depth_cursor = True
bpy.context.scene.tool_settings.use_snap = True
return {'PASS_THROUGH'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
sel_ob = len(bpy.context.selected_objects)
if sel_ob >= 1:
sel_type = bpy.context.object.type
if sel_type == 'MESH':
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
else:
self.report({'WARNING'}, "Active object is not a mesh.")
return {'CANCELLED'}
elif sel_ob == 0:
bpy.ops.mesh.primitive_plane_add()
bpy.context.selected_objects[0].name = "polyDraw"
bpy.context.selected_objects[0].data.name = "polyDraw"
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.delete(type='VERT')
# Store selection mode, snap and manipulator settings
self.sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
bpy.context.tool_settings.mesh_select_mode = True, False, False
self.manip = bpy.context.space_data.show_manipulator
bpy.context.space_data.show_manipulator = False
self.cursor_depth = bpy.context.preferences.input.use_mouse_depth_cursor
bpy.context.preferences.input.use_mouse_depth_cursor = False
self.snap = bpy.context.scene.tool_settings.use_snap
bpy.context.scene.tool_settings.use_snap = False
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.vertex_group_assign_new()
self.vgrp = bpy.context.object.vertex_groups.active_index
bpy.context.object.vertex_groups.active.name = "drawPoly_temp"
self.cursor_co = bpy.context.scene.cursor_location
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
class toggleSilhouette(bpy.types.Operator):
"""Turns everything black so that you can evaluate the overall shape. Useful when designing"""
bl_idname = "object.toggle_silhouette"
bl_label = "Toggle Silhouette"
diff_col: FloatVectorProperty(default = (0.226, 0.179, 0.141))
disp_mode: StringProperty(default = 'SOLID')
matcap: BoolProperty(default = False)
only_render: BoolProperty(default = False)
light_check = bpy.context.preferences.system.solid_lights[0].use
if light_check == True:
# Set Lights to Off
bpy.context.preferences.system.solid_lights[0].use = False
bpy.context.preferences.system.solid_lights[1].use = False
self.diff_col = bpy.context.preferences.system.solid_lights[2].diffuse_color
self.disp_mode = bpy.context.space_data.viewport_shade
self.matcap = bpy.context.space_data.use_matcap
self.only_render = bpy.context.space_data.show_only_render
bpy.context.preferences.system.solid_lights[2].diffuse_color = 0,0,0
bpy.context.space_data.viewport_shade = 'SOLID'
bpy.context.space_data.use_matcap = False
bpy.context.space_data.show_only_render = True
bpy.context.preferences.system.solid_lights[0].use = True
bpy.context.preferences.system.solid_lights[1].use = True
bpy.context.preferences.system.solid_lights[2].diffuse_color = self.diff_col
bpy.context.space_data.viewport_shade = self.disp_mode
bpy.context.space_data.use_matcap = self.matcap
bpy.context.space_data.show_only_render = self.only_render
class growLoop(bpy.types.Operator):
"""Grows the selected edges in both directions """
bl_idname = "mesh.grow_loop"
bl_label = "Grow Loop"
bl_options = {'REGISTER', 'UNDO'}
grow: IntProperty(name="Grow Selection", description="How much to grow selection", default= 1, min=1, soft_max=10)
grow = self.grow
sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
for x in range(grow):
if sel_mode[2] == True:
edge_sel = []
border = []
interior = []
face_org = []
face_loop = []
face_grow = []
face_sel = []
mesh_edges = bpy.context.active_object.data.edges
mesh_faces = bpy.context.active_object.data.polygons
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for e in bm.edges:
if e.select:
edge_sel.append(e.index)
for f in bm.faces:
if f.select:
face_org.append(f.index)
bpy.ops.mesh.region_to_loop()
for e in bm.edges:
if e.select:
border.append(e.index)
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
for e in edge_sel:
if e not in border:
interior.append(e)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
#Select the interior edges
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for e in interior:
mesh_edges[e].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.loop_multi_select(ring=True)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=True, type='FACE')
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for f in bm.faces:
if f.select:
face_loop.append(f.index)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
# Select original faces
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for x in face_org:
mesh_faces[x].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_more(use_face_step=False)
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for f in bm.faces:
if f.select:
face_grow.append(f.index)
for f in face_grow:
if f in face_loop:
face_sel.append(f)
for f in face_org:
face_sel.append(f)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for f in face_sel:
mesh_faces[f].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
else:
mesh = bpy.context.active_object.data.edges
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
org_sel = []
grow_sel = []
loop_sel = []
sel = []
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
for e in bm.edges:
if e.select:
org_sel.append(e.index)
bpy.ops.mesh.select_more(use_face_step=False)
for e in bm.edges:
if e.select:
grow_sel.append(e.index)
bpy.ops.mesh.select_all(action='DESELECT')
bmesh.update_edit_mesh(me, True, False)
# Select the original edges
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for e in org_sel:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
bpy.ops.mesh.loop_multi_select(ring=False)
for e in bm.edges:
if e.select:
loop_sel.append(e.index)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
for x in loop_sel:
if x in grow_sel:
sel.append(x)
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for e in sel:
mesh[e].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.context.tool_settings.mesh_select_mode = sel_mode
class extendLoop(bpy.types.Operator):
"""Uses the active face or edge to extends the selection in one direction"""
bl_idname = "mesh.extend_loop"
bl_label = "Extend Loop"
bl_options = {'REGISTER', 'UNDO'}
extend: IntProperty(name="Extend Selection", description="How much to extend selection", default= 1, min=1, soft_max=10)
sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
extend = self.extend
for x in range(extend):
if sel_mode[2] == True:
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
active_face = bpy.context.object.data.polygons.active # find active face
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
edge_sel = []
interior = []
face_org = []
face_loop = []
face_grow = []
face_sel = []
active_edges = []
# Get face selection
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for f in bm.faces:
if f.select:
face_org.append(f.index)
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
face_org.remove(active_face)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
mesh = bpy.context.active_object.data.polygons
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for x in face_org:
mesh[x].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Get edge selection
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for e in bm.edges:
if e.select:
edge_sel.append(e.index)
bmesh.update_edit_mesh(me, True, False)
# Select Active Face
bpy.ops.mesh.select_all(action='DESELECT')
mesh = bpy.context.active_object.data.polygons
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh[active_face].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
# Store the interior edge
for e in bm.edges:
if e.select:
active_edges.append(e.index)
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
for e in active_edges:
if e in edge_sel:
interior.append(e)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
#Select the interior edges
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh = bpy.context.active_object.data.edges
for e in interior:
mesh[e].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.loop_multi_select(ring=True)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=True, type='FACE')
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for f in bm.faces:
if f.select:
face_loop.append(f.index)
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
# Select active face
mesh = bpy.context.active_object.data.polygons
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh[active_face].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.select_more(use_face_step=False)
face_org.append(active_face)
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for f in bm.faces:
if f.select:
face_grow.append(f.index)
for f in face_grow:
if f in face_loop:
face_sel.append(f)
for f in face_sel:
if f not in face_org:
active_face = f
for f in face_org:
face_sel.append(f)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for f in face_sel:
mesh[f].select = True
bpy.context.object.data.polygons.active = active_face
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
elif sel_mode[1] == True:
mesh = bpy.context.active_object.data
org_sel = []
grow_sel = []
loop_sel = []
sel = []
org_verts = []
active_verts = []
# Get active edge
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for x in reversed(bm.select_history):
if isinstance(x, bmesh.types.BMEdge):
active_edge = x.index
break
# Store the originally selected edges
for e in bm.edges:
if e.select:
org_sel.append(e.index)
bmesh.update_edit_mesh(me, True, False)
# Select active edge
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.edges[active_edge].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Get verts of active edge
bm = bmesh.from_edit_mesh(me)
for v in bm.verts:
if v.select:
active_verts.append(v.index)
bmesh.update_edit_mesh(me, True, False)
# Select original selection minus active edge
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for x in org_sel:
mesh.edges[x].select = True
mesh.edges[active_edge].select = False
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Store the original vertices minus active edge
for v in bm.verts:
if v.select:
org_verts.append(v.index)
# Compare verts
for x in active_verts:
if x in org_verts:
active_verts.remove(x)
bmesh.update_edit_mesh(me, True, False)
# Select end vertex
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
mesh.vertices[active_verts[0]].select = True
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Grow the end vertex and store the edges
bpy.ops.mesh.select_more(use_face_step=False)
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
bm = bmesh.from_edit_mesh(me)
for e in bm.edges:
if e.select:
grow_sel.append(e.index)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
# Run loop of the active edges and store it
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
bpy.ops.mesh.loop_multi_select(ring=False)
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
for e in bm.edges:
if e.select:
loop_sel.append(e.index)
bmesh.update_edit_mesh(me, True, False)
bpy.ops.mesh.select_all(action='DESELECT')
# Compare loop_sel vs grow_sel
for x in loop_sel:
if x in grow_sel:
sel.append(x)
# Add original selection to new selection
for x in org_sel:
if x not in sel:
sel.append(x)
# Compare org_sel with sel to get the active edge
for x in sel:
if x not in org_sel:
active_edge = x
# Select the resulting edges
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
for e in sel:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
# Set the new active edge
bm = bmesh.from_edit_mesh(me)
bm.edges.ensure_lookup_table()
bm.select_history.add(bm.edges[active_edge])
bmesh.update_edit_mesh(me, True, False)
class shrinkLoop(bpy.types.Operator):
"""Shrink the selected loop"""
bl_idname = "mesh.shrink_loop"
bl_label = "Shrink Loop"
bl_options = {'REGISTER', 'UNDO'}
shrink: IntProperty(name="Shrink Selection", description="How much to shrink selection", default= 1, min=1, soft_max=15)
sel_mode = bpy.context.tool_settings.mesh_select_mode[:]
shrink = self.shrink
for x in range(shrink):
if sel_mode[2] == True:
me = bpy.context.object.data
bm = bmesh.from_edit_mesh(me)
mesh = bpy.context.active_object.data
sel = []
edge_dic = {}
vert_list = []
end_verts = []
org_faces = []
cur_faces = []
new_faces = []
# Store edges and verts
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 original faces
for f in bm.faces:
if f.select:
org_faces.append(f.index)
# Store end verts
for v in vert_list:
if vert_list.count(v) == 2:
end_verts.append(v)