From 33b1cbf06d2c822c68676390b1775eb5d78de6e6 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Fri, 12 Feb 2010 22:13:47 +0000 Subject: [PATCH] Smart Extrude (hotkeys are tentative) Ekey: Extrude Region Based on selection totals: Extrude region along normal if at least one face selected Extrude vertex along normal if only one vertex selected (experimental) Extrude edge on its plane if only one edge selected (experimental) Extrude with no constraint axis otherwise Shift-Ekey: Extrude Individual Based on selection modes and selection totals Individual Faces if face select and some faces are selected Individual Edges if edge select and some edges are selected Individual Vertice otherwise Alt-Ekey: Extrude Menu (only shows valid options for selection mode and selection totals) --- release/scripts/ui/space_view3d.py | 109 +++++++++++++++++++++++-- source/blender/editors/mesh/mesh_ops.c | 7 +- 2 files changed, 106 insertions(+), 10 deletions(-) diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/ui/space_view3d.py index f294c2a5b8d..160ee5ddea9 100644 --- a/release/scripts/ui/space_view3d.py +++ b/release/scripts/ui/space_view3d.py @@ -1203,19 +1203,113 @@ class VIEW3D_MT_edit_mesh_selection_mode(bpy.types.Menu): prop.value = "(False, False, True)" prop.path = "tool_settings.mesh_selection_mode" + class VIEW3D_MT_edit_mesh_extrude(bpy.types.Menu): bl_label = "Extrude" + @staticmethod + def extrude_options(context): + mesh = context.object.data + selection_mode = context.tool_settings.mesh_selection_mode + + totface = mesh.total_face_sel + totedge = mesh.total_edge_sel + totvert = mesh.total_vert_sel + + if selection_mode[0]: # vert + if totvert == 0: + return () + elif totvert == 1: + return (3,) + elif totedge == 0: + return (3,) + elif totface == 0: + return (2, 3) + elif totface == 1: + return (0, 2, 3) + else: + return (0, 1, 2, 3) + elif selection_mode[1]: # edge + if totedge == 0: + return () + elif totedge == 1: + return (2,) + elif totface == 0: + return (2,) + elif totface == 1: + return (0, 2) + else: + return (0, 1, 2) + elif selection_mode[2]: # face + if totface == 0: + return () + elif totface == 1: + return (0,) + else: + return (0, 1) + + # should never get here + return () + def draw(self, context): layout = self.layout - layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("mesh.extrude_region_move", text="Region") - layout.operator("mesh.extrude_faces_move", text="Individual Faces") - layout.operator("mesh.extrude_edges_move", text="Edges Only") - layout.operator("mesh.extrude_vertices_move", text="Vertices Only") + region_menu = lambda: layout.operator("mesh.extrude_region_move", text="Region") + face_menu = lambda: layout.operator("mesh.extrude_faces_move", text="Individual Faces") + edge_menu = lambda: layout.operator("mesh.extrude_edges_move", text="Edges Only") + vert_menu = lambda: layout.operator("mesh.extrude_vertices_move", text="Vertices Only") + + menu_funcs = region_menu, face_menu, edge_menu, vert_menu + + for i in self.extrude_options(context): + func = menu_funcs[i] + func() +class VIEW3D_OT_edit_mesh_extrude_individual_move(bpy.types.Operator): + bl_label = "Extrude Individual and Move" + bl_idname = "view3d.edit_mesh_extrude_individual_move" + + def execute(self, context): + mesh = context.object.data + selection_mode = context.tool_settings.mesh_selection_mode + + totface = mesh.total_face_sel + totedge = mesh.total_edge_sel + totvert = mesh.total_vert_sel + + if selection_mode[2] and totface == 1: + return bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate = {"constraint_orientation":"NORMAL", "constraint_axis":[False, False, True]}) + elif selection_mode[2] and totface > 1: + return bpy.ops.mesh.extrude_faces_move('INVOKE_REGION_WIN') + elif selection_mode[1] and totedge >= 1: + return bpy.ops.mesh.extrude_edges_move('INVOKE_REGION_WIN') + else: + return bpy.ops.mesh.extrude_vertices_move('INVOKE_REGION_WIN') + + def invoke(self, context, event): + return self.execute(context) + +class VIEW3D_OT_edit_mesh_extrude_move(bpy.types.Operator): + bl_label = "Extrude and Move" + bl_idname = "view3d.edit_mesh_extrude_move" + + def execute(self, context): + mesh = context.object.data + + totface = mesh.total_face_sel + totedge = mesh.total_edge_sel + totvert = mesh.total_vert_sel + + if totface >= 1 or totvert == 1: + return bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate = {"constraint_orientation":"NORMAL", "constraint_axis":[False, False, True]}) + elif totedge == 1: + return bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate = {"constraint_orientation":"NORMAL", "constraint_axis":[True, True, False]}) + else: + return bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN') + + def invoke(self, context, event): + return self.execute(context) class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu): bl_label = "Vertices" @@ -1987,6 +2081,9 @@ class VIEW3D_PT_context_properties(bpy.types.Panel): rna_prop_ui.draw(self.layout, context, member, False) +bpy.types.register(VIEW3D_OT_edit_mesh_extrude_move) # detects constraints setup and extrude region +bpy.types.register(VIEW3D_OT_edit_mesh_extrude_individual_move) + bpy.types.register(VIEW3D_HT_header) # Header bpy.types.register(VIEW3D_MT_view) #View Menus @@ -2050,7 +2147,7 @@ bpy.types.register(VIEW3D_MT_edit_mesh_edges) bpy.types.register(VIEW3D_MT_edit_mesh_faces) bpy.types.register(VIEW3D_MT_edit_mesh_normals) bpy.types.register(VIEW3D_MT_edit_mesh_showhide) -bpy.types.register(VIEW3D_MT_edit_mesh_extrude) +bpy.types.register(VIEW3D_MT_edit_mesh_extrude) # use with VIEW3D_OT_edit_mesh_extrude_menu bpy.types.register(VIEW3D_MT_edit_curve) bpy.types.register(VIEW3D_MT_edit_curve_ctrlpoints) diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 2788469a23e..87fe9948a37 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -172,7 +172,6 @@ void ED_operatormacros_mesh(void) { wmOperatorType *ot; wmOperatorTypeMacro *otmacro; - int constraint_axis[3] = {0, 0, 1}; ot= WM_operatortype_append_macro("MESH_OT_loopcut_slide", "Loop Cut and Slide", OPTYPE_UNDO|OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "MESH_OT_loopcut"); @@ -193,8 +192,6 @@ void ED_operatormacros_mesh(void) RNA_enum_set(otmacro->ptr, "type", 1); otmacro= WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); - RNA_enum_set(otmacro->ptr, "constraint_orientation", V3D_MANIP_NORMAL); - RNA_boolean_set_array(otmacro->ptr, "constraint_axis", constraint_axis); ot= WM_operatortype_append_macro("MESH_OT_extrude_faces_move", "Extrude Individual Faces and Move", OPTYPE_UNDO|OPTYPE_REGISTER); otmacro= WM_operatortype_macro_define(ot, "MESH_OT_extrude"); @@ -264,7 +261,9 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0); RNA_boolean_set(WM_keymap_add_item(keymap, "MESH_OT_normals_make_consistent", NKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0)->ptr, "inside", 1); - WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_extrude", EKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_edit_mesh_extrude_move", EKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_edit_mesh_extrude_individual_move", EKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_extrude", EKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_spin", RKEY, KM_PRESS, KM_ALT, 0);