Home Technical Talk

Pedro's Super Smart Create for Blender

interpolator
Offline / Send Message
maxivz interpolator
Hey Guys, I have been playing around with blender and some scripting lately. I decided to port Pedro's excellent  super smart create script
I am really new to Blender and my python coding skills are not the finest, so please if you find any better way to do stuff or if i'm making any stupid shit just let me know.
Anyways, here's the tool (the descriptions are taken from Pedro's thread, so you can compare the functionality).

Connects verts that belong to the same face 



If you select one vert or two verts that share the same edge and are on a border it will invoke f2(make sure you have f2 enabled):


Divides the selected edge in 2, putting a vert in the middle of the edge




Connects the selected edges if there is faces in between the edges


Caps selected borders

Bridges selected edges if possible

When you select 2 adjacent edges it creates a face


Bridges selected polys


Heres an extra one, tries to make quads from a selected face.



This last feature  works pretty good if you cap a border and then run the script again to make quads out of it:


Installation:
Pretty much the standard blender plugin installation. Load it up from the install from file option in user Preferences and make sure you enable it.
You can either run it from the mesh-> Super Smart Create menu or assign a hotkey to it. Id recommend you to assign a hotkey to it, to make it even easier to use. To assign a hotkey you can find it in Input ->  3D View- > Mesh -> Super Smart Create
I have developed it in Blender 2.78c, so no idea if it works with older versions or not

Download(save this as a .py file):
  1. bl_info = {
  2. "name": "Super Smart Create",
  3. "author": "Maximiliano Vazquez, Original idea: Pedro Amorim",
  4. "version": (1, 0),
  5. "blender": (2, 65, 0),
  6. "location": "Mesh > Super Smart Create",
  7. "description": "Context Sensitive mesh modification",
  8. "warning": "",
  9. "wiki_url": "",
  10. "tracker_url": "",
  11. "category": "Mesh"}
  12. import bpy
  13. import bmesh
  14. from bpy.types import Operator, AddonPreferences
  15. from bpy.props import StringProperty
  16. import mesh_f2
  17.  
  18. #Global Variables
  19. ITERATION_LIMIT = 200
  20.  
  21. #Functions
  22.  
  23. def list_intersection(a, b):
  24. return list(set(a) & set(b))
  25.  
  26. def list_difference(a,b):
  27. return list(set(a)- set(b))
  28.  
  29. def get_bmesh():
  30. return bmesh.from_edit_mesh(bpy.context.edit_object.data)
  31.  
  32. def update_indexes(bm ,verts=False, edges=False, faces=False):
  33. if verts:
  34. bm.verts.index_update()
  35. if edges:
  36. bm.edges.index_update()
  37. if faces:
  38. bm.faces.index_update()
  39. bm.verts.ensure_lookup_table()
  40. bm.edges.ensure_lookup_table()
  41. bm.faces.ensure_lookup_table()
  42. bmesh.update_edit_mesh(bpy.context.edit_object.data)
  43. return bm
  44.  
  45. def get_selected(bm,verts=False, edges = False, faces = False, get_item = False):
  46. if verts:
  47. bm = update_indexes(bm, verts=True)
  48. selected_verts = []
  49. for vert in bm.verts:
  50. if vert.select :
  51. if get_item:
  52. selected_verts.append(vert)
  53. else:
  54. selected_verts.append(vert.index)
  55. return selected_verts
  56. if edges:
  57. bm = update_indexes(bm,edges=True)
  58. selected_edges = []
  59. for edge in bm.edges:
  60. if edge.select:
  61. if get_item:
  62. selected_edges.append(edge)
  63. else:
  64. selected_edges.append(edge.index)
  65. return selected_edges
  66. if faces:
  67. bm = update_indexes(bm,faces=True)
  68. selected_faces = []
  69. for face in bm.faces:
  70. if face.select:
  71. if get_item:
  72. selected_faces.append(face)
  73. else:
  74. selected_faces.append(face.index)
  75. return selected_faces
  76.  
  77. def select_from_index(bm,indexes, verts = False,edges = False, faces = False, replace = False, add_to_history = False):
  78. if replace:
  79. bpy.ops.mesh.select_all(action='DESELECT')
  80. if verts:
  81. for index in indexes:
  82. bm.verts[index].select = True
  83. if add_to_history:
  84. bm.select_history.add(bm.verts[index])
  85. if edges:
  86. for index in indexes:
  87. bm.edges[index].select = True
  88. if add_to_history:
  89. bm.select_history.add(bm.edges[index])
  90. if faces:
  91. for index in indexes:
  92. bm.faces[index].select = True
  93. if add_to_history:
  94. bm.select_history.add(bm.faces[index])
  95. def select_from_item(bm,items, verts = False,edges = False, faces = False, replace = False, add_to_history = False):
  96. if replace:
  97. bpy.ops.mesh.select_all(action='DESELECT')
  98. if verts:
  99. for item in items:
  100. bm.verts[item.index].select = True
  101. if add_to_history:
  102. bm.select_history.add(bm.verts[item.index])
  103. if edges:
  104. for item in items:
  105. bm.edges[item.index].select = True
  106. if add_to_history:
  107. bm.select_history.add(bm.edges[item.index])
  108. if faces:
  109. for item in items:
  110. bm.faces[item.index].select = True
  111. if add_to_history:
  112. bm.select_history.add(bm.faces[item.index])
  113.  
  114. def verts_share_edge(bm):
  115. other_verts = []
  116. verts = get_selected(bm,verts = True, get_item = True)
  117. for vert in verts:
  118. for edge in vert.link_edges:
  119. other_vert = edge.other_vert(vert)
  120. other_verts.append(other_vert)
  121. return vert in other_verts
  122. def is_border(bm):
  123. edge_list = get_selected(bm,edges = True, get_item = True)
  124. select_from_index(bm,[edge_list[0].index],edges = True, replace = True)
  125. bpy.ops.mesh.loop_multi_select(ring=False)
  126. border_selection = get_selected(bm, edges = True, get_item = True)
  127. border_edges = all(len((edge.link_faces)) is 1 for edge in edge_list)
  128. is_complete_border = all(edge in edge_list for edge in border_selection)
  129. select_from_item(bm,edge_list,edges = True, replace = True)
  130. return border_edges and is_complete_border
  131.  
  132. def is_adjacent(bm):
  133. edge_list = get_selected(bm,edges = True)
  134. select_from_index(bm,[edge_list[0]],edges = True, replace = True)
  135. bpy.ops.mesh.select_more()
  136. new_selection = get_selected(bm, edges = True)
  137. select_from_index(bm,edge_list,edges = True, replace = True)
  138. return all(edge in new_selection for edge in edge_list)
  139.  
  140. def is_ring(bm):
  141. selection = get_selected(bm,edges = True, get_item = True)
  142. result = all(len((edge.link_faces)) is 2 for edge in selection)
  143. return result
  144.  
  145. def split_edge_select_vert(bm, change_selection = False):
  146. selection = get_selected(bm,verts = True)
  147. bpy.ops.mesh.subdivide()
  148. new_selection = get_selected(bm,verts = True)
  149. new_selection = list_difference(new_selection, selection)
  150. if change_selection:
  151. select_from_index(bm,new_selection, verts = True,replace = True)
  152. bpy.context.scene.tool_settings.mesh_select_mode = [True,False,False]
  153. return new_selection
  154.  
  155. def are_border_verts(bm, selection):
  156. selection = get_selected(bm,verts = True)
  157. return all(len(bm.verts[vert].link_faces) <= 3 for vert in selection)
  158.  
  159.  
  160. def quad_fill(bm):
  161. selection = get_selected(bm,edges = True)
  162. bpy.ops.mesh.delete(type='FACE')
  163. select_from_index(bm,selection, edges = True,replace = True)
  164. bpy.ops.mesh.fill_grid()
  165.  
  166. def super_smart_create():
  167. bm = get_bmesh()
  168. selectionMode = (tuple(bpy.context.scene.tool_settings.mesh_select_mode))
  169. #if Vertex is selected
  170. if selectionMode[0]:
  171. selection = get_selected(bm,verts = True)
  172. if len(selection) == 1 or (verts_share_edge(bm) and are_border_verts(bm,selection)):
  173. print(are_border_verts(bm,selection))
  174. mesh_f2.bpy.ops.mesh.f2('INVOKE_DEFAULT')
  175. else:
  176. bpy.ops.mesh.vert_connect()
  177. #if Edge is selected
  178. elif selectionMode[1]:
  179. selection = get_selected(bm,edges = True)
  180. if len(selection) == 1:
  181. split_edge_select_vert(bm,change_selection = True)
  182. elif is_border(bm):
  183. bpy.ops.mesh.edge_face_add()
  184. bpy.context.scene.tool_settings.mesh_select_mode = [False,False,True]
  185. elif is_ring(bm):
  186. bpy.ops.mesh.subdivide(number_cuts = 1, quadcorner = 'INNERVERT')
  187. bpy.ops.mesh.select_less()
  188. elif is_adjacent(bm):
  189. bpy.ops.mesh.edge_face_add()
  190. bpy.context.scene.tool_settings.mesh_select_mode = [False,True,False]
  191. else:
  192. bpy.ops.mesh.bridge_edge_loops()
  193. bpy.context.scene.tool_settings.mesh_select_mode = [False,True, False]
  194. #if Face is selected
  195. elif selectionMode[2]:
  196. selection = get_selected(bm,faces = True)
  197. if len(selection) == 1:
  198. quad_fill(bm)
  199. if len(selection) > 1:
  200. bpy.ops.mesh.bridge_edge_loops()
  201. #bm.free()
  202. class SuperSmartCreate(bpy.types.Operator):
  203. """ Super Smart Create"""
  204. bl_idname = "mesh.super_smart_create"
  205. bl_label = "Super Smart Create"
  206. bl_options = {'REGISTER', 'UNDO'}
  207. def execute(self,context):
  208. super_smart_create()
  209. return {'FINISHED'}
  210.  
  211. class SuperSmartCreatePreferences(bpy.types.AddonPreferences):
  212. bl_idname = __name__
  213. assigned_hotkey = StringProperty(
  214. name="Assigned Hotkey",
  215. default = 'NONE',
  216. )
  217. def draw(self, context):
  218. layout = self.layout
  219. layout.prop(self,assigned_hotkey)
  220. def SuperSmartCreatePrefs_Menu(self, context):
  221. self.layout.operator(SuperSmartCreate.bl_idname)
  222.  
  223. # store keymaps here to access after registration
  224. addon_keymaps = []
  225. def register():
  226. bpy.utils.register_class(SuperSmartCreate)
  227. #Make menu
  228. bpy.types.VIEW3D_MT_edit_mesh.append(SuperSmartCreatePrefs_Menu)
  229. ##Handle Keymap
  230. wm = bpy.context.window_manager
  231. km = wm.keyconfigs.addon.keymaps.new(name='Mesh', space_type='EMPTY')
  232. kmi = km.keymap_items.new(SuperSmartCreate.bl_idname, 'W', 'PRESS', alt = True)
  233. addon_keymaps.append((km, kmi))
  234.  
  235. def unregister():
  236. bpy.utils.unregister_class(SuperSmartCreate)
  237. #bpy.utils.unregister_class(SuperSmartCreatePreferences)
  238. #Remove Menu
  239. bpy.types.VIEW3D_MT_edit_mesh.remove(SuperSmartCreatePrefs_Menu)
  240. #Remove Keymaps
  241. for km, kmi in addon_keymaps:
  242. km.keymap_items.remove(kmi)
  243. addon_keymaps.clear()
  244. if __name__ == "__main__":
  245. register()

Please report any problems, suggestions, so I can *hopefully* improve it . Hope you guys find it useful.

Replies

Sign In or Register to comment.