1
$\begingroup$

There are two items that are not in the UI, but just available by a hotkey. Dupli Extrude and Dupli Extrude Rotate.

I want them to be visually available in the Extrude dropdown box in the tool shelf in the Tools panel. So I added them to the submenu for it, which is in the space_view3d-py file, the class VIEW3D_MT_edit_mesh_extrude. And there I am stuck.

The operator is mesh.dupli_extrude_cursor. With a flag to tell if the target object rotates randomly or not. And this flag is the trouble maker here. I can add a normal button that way:

        col.operator("mesh.dupli_extrude_cursor" , icon='DUPLI_EXTRUDE',  text = " DupliExtrude    ").rotate_source = False
        col.operator("mesh.dupli_extrude_cursor", icon='DUPLI_EXTRUDE_ROTATE', text = " DupliExRotate  ").rotate_source = True

But when I do the same in the dropdown box menu then the whole Blender menu vanishes. VS marks me the whole code red then. I also tried to include the flag with the operator. But then Blender doesn't find it and gives a missing srna error in the console. I cannot leave the flag away, that's what separates the tools. And also curious, the dropdown box entry does not show the hotkey for it.

What's the right way to put those two items into the dropdown box?

class VIEW3D_MT_edit_mesh_extrude(Menu):
    bl_label = "Extrude"

    _extrude_funcs = {
        'VERT': lambda layout:
            layout.operator("mesh.extrude_vertices_move", text="Vertices Only"),
        'EDGE': lambda layout:
            layout.operator("mesh.extrude_edges_move", text="Edges Only"),
        'FACE': lambda layout:
            layout.operator("mesh.extrude_faces_move", text="Individual Faces"),
        'REGION': lambda layout:
            layout.operator("view3d.edit_mesh_extrude_move_normal", text="Region"),
        'REGION_VERT_NORMAL': lambda layout:
            layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Region (Vertex Normals)"),
        'DUPLI_EXTRUDE': lambda layout:
            layout.operator("mesh.dupli_extrude_cursor(rotate_source = False)", text = "DupliExtrude"), # does not work, Blender does not find the operator
        'DUPLI_EX_ROTATE': lambda layout:
            layout.operator("mesh.dupli_extrude_cursor", text="Dupli Extrude Rotate").rotate_source = True,  # does not work, Blender Menu vanishes

    }

EDIT: I could of course add two helper classes. It works. See this example. But i am not a happy bunny with this solution. I want to add the operators in the way the other operators in this dropdown box are added too. There should be a solution.

class VIEW3D_MT_edit_mesh_extrude_dupli(bpy.types.Operator):
    """Duplicate or Extrude to Cursor"""      # blender will use this as a tooltip for menu items and buttons.
    bl_idname = "mesh.dupli_extrude_cursor_norotate"        # unique identifier for buttons and menu items to reference.
    bl_label = "Duplicate or Extrude to Cursor"         # display name in the interface.
    bl_options = {'REGISTER', 'UNDO'}  # enable undo for the operator.

    def execute(self, context):        # execute() is called by blender when running the operator.
        bpy.ops.mesh.dupli_extrude_cursor('INVOKE_DEFAULT', rotate_source = False)
        return {'FINISHED'}

class VIEW3D_MT_edit_mesh_extrude_dupli_rotate(bpy.types.Operator):
    """Duplicate or Extrude to Cursor Rotated"""      # blender will use this as a tooltip for menu items and buttons.
    bl_idname = "mesh.dupli_extrude_cursor_rotate"        # unique identifier for buttons and menu items to reference.
    bl_label = "Duplicate or Extrude to Cursor Rotated"         # display name in the interface.
    bl_options = {'REGISTER', 'UNDO'}  # enable undo for the operator.

    def execute(self, context):        # execute() is called by blender when running the operator.
        bpy.ops.mesh.dupli_extrude_cursor('INVOKE_DEFAULT', rotate_source = True)
        return {'FINISHED'}


class VIEW3D_MT_edit_mesh_extrude(Menu):
    bl_label = "Extrude"

    _extrude_funcs = {
        'VERT': lambda layout:
            layout.operator("mesh.extrude_vertices_move", text="Vertices Only"),
        'EDGE': lambda layout:
            layout.operator("mesh.extrude_edges_move", text="Edges Only"),
        'FACE': lambda layout:
            layout.operator("mesh.extrude_faces_move", text="Individual Faces"),
        'INDIVIDUAL': lambda layout:
            layout.operator("view3d.edit_mesh_extrude_individual_move", text="Individual"),
        'REGION_VERT_NORMAL': lambda layout:
            layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Region (Vertex Normals)"),
        'DUPLI_EXTRUDE': lambda layout:
            layout.operator("mesh.dupli_extrude_cursor_norotate", text="Dupli Extrude"),
        'DUPLI_EX_ROTATE': lambda layout:
            layout.operator("mesh.dupli_extrude_cursor_rotate", text="Dupli Extrude Rotate")
    }

    @staticmethod
    def extrude_options(context):
        mesh = context.object.data
        select_mode = context.tool_settings.mesh_select_mode

        menu = []
        if mesh.total_face_sel:
            menu += ['INDIVIDUAL', 'REGION_VERT_NORMAL', 'FACE']
        if mesh.total_edge_sel and (select_mode[0] or select_mode[1]):
            menu += ['EDGE']
        if mesh.total_vert_sel and select_mode[0]:
            menu += ['VERT', 'DUPLI_EXTRUDE', 'DUPLI_EX_ROTATE']

        # should never get here
        return menu

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_REGION_WIN'

        for menu_id in self.extrude_options(context):
            self._extrude_funcs[menu_id](layout)

enter image description here

$\endgroup$
0
$\begingroup$

Can quite simply ap(pre)pend those operators to the menu

import bpy
def draw_dupli_extrude(self, context):
    col = self.layout
    col.operator_context = 'INVOKE_REGION_WIN'
    col.operator("mesh.dupli_extrude_cursor" ,  text="DupliExtrude").rotate_source = False
    col.operator("mesh.dupli_extrude_cursor", text="DupliExRotate").rotate_source = True
# prepend to menu
bpy.types.VIEW3D_MT_edit_mesh_extrude.prepend(draw_dupli_extrude)

enter image description here

NOTE: The operators are kind of useless in the menu as that's where the mouse is to invoke... which could be why they are not there in the first place.

Always look at system console for errors, as in your sample code there are no icons for

icon='DUPLI_EXTRUDE'
icon='DUPLI_EXTRUDE_ROTATE'

which will lead to a TypeError.

$\endgroup$
  • $\begingroup$ Thanks batFINGER for this working solution. I would still be happy though to have a direct way to put the dupli_extrude_cursor into the menu, already with the flag. But i guess there is really no way. - The point to have them visually available is to know that the tool exists, to show the hotkey, and to give a way to modify the hotkey. Border select for example is also a menu item ... - And sorry for the icon code. I've added those icons in my custom build here. There those icons really exists. Currently those two items are buttons. I will remove the icon code from the initial posting. $\endgroup$ – Tiles Sep 15 '16 at 6:40
  • $\begingroup$ Hm. Still in trouble. The menu items does not show up that way. Most probably because of the extrude_options. $\endgroup$ – Tiles Sep 15 '16 at 6:57
  • $\begingroup$ Added an image as "proof". AFAIK ap(pre)pended draw methods wont be affected by the code in the original draw method. $\endgroup$ – batFINGER Sep 15 '16 at 7:09
  • $\begingroup$ Interesting. I wonder what i do wrong here :( $\endgroup$ – Tiles Sep 15 '16 at 7:19
  • $\begingroup$ Okay, works in native Blender 2.77. The error must be in my custom build. I will find out where. Thanks :) $\endgroup$ – Tiles Sep 15 '16 at 7:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.