What would be the nicest way to code(in Python) a pie menu in Blender 2.79 or 2.8, that would have another menu as an addition to the standard 8 pie menu choices?

pie menu with an additional traditional menu beneath it


After playing with it for some time I found that this kind of works:

import bpy
from bpy.types import Menu
class VIEW3D_PIE_template(Menu):
    bl_label = "Some Pie Menu"

    def draw(self, context):
        layout = self.layout
        pie = layout.menu_pie()
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.operator("mesh.primitive_cube_add")
        pie.separator()
        pie.separator()
        gap = pie.column()
        gap.separator()
        gap.separator()
        gap.separator()
        gap.separator()
        gap.separator()
        gap.separator()
        gap.separator()
        menu = gap.box()
        menu.scale_x = 2.5
        menu.operator("mesh.primitive_monkey_add")
        menu.operator("mesh.primitive_monkey_add")

def register():
    bpy.utils.register_class(VIEW3D_PIE_template)

def unregister():
    bpy.utils.unregister_class(VIEW3D_PIE_template)

if __name__ == "__main__":
    register()

    bpy.ops.wm.call_menu_pie(name="VIEW3D_PIE_template")

enter image description here

I wonder if there is a nicer way. This feels 'hacky' and it would be nice to have a menu that would have expandable sub-menus if that is possible at all. I realize that might be too much to wish for... Any advice?

  • You can just append another menu as a submenu: How to make a sub-menu with Python?, with some formatting it could look like this: pastebin.com/7d8dzpwi. You can also do fully custom stuff with bgl drawing inside modal operator, but you would have to re-implement the pie menu functionality. – Jaroslav Jerryno Novotny Nov 13 at 8:02
  • Thank you! That really helps. That's all the functionality I wanted. I am still hesitating a bit about the code now - I mean all the separators to go around the pie menu... But it works, so I really appreciate the help. – Martin Z Nov 13 at 8:25
  • You can just leave 2 separators there and scale the gap column with gap.scale_y = 5.0 to create the distance, but this could mess with spacing of anything put after the gap.box() item in the column. So multiple separators are imho the best to make the space, I would not worry about it. You can add some comments in the code to make it feel less hacky, like # spacing between pie and column menu followed by the separators. – Jaroslav Jerryno Novotny Nov 13 at 9:11
  • .... putting the separators in a for loop or a draw_gap(self, layout, count=7): method will "clean" the code up somewhat. – batFINGER Nov 13 at 9:15
  • I am just scaling a column with one separator with .scale_y now for the gap. That seems nicer. Other than that I need two separators to start drawing my additional 'menu' at the correct place of the pie menu. I think that will have to be nice enough. – Martin Z Nov 13 at 9:46
up vote 2 down vote accepted

The solution I ended up with is the same as discussed in the comments:

import bpy
from bpy.types import Menu

class Submenu(Menu):
    bl_label = 'Some Submenu'    
    def draw(self, context):
        layout = self.layout
        layout.label("Some Submenu")
        layout.separator()
        layout.operator("mesh.primitive_cube_add", text = "Some Submenu Operator", icon = "BLENDER")
        layout.operator("mesh.primitive_cube_add", text = "Some Submenu Operator", icon = "BLENDER")
        layout.operator("mesh.primitive_cube_add", text = "Some Submenu Operator", icon = "BLENDER")
        layout.operator("mesh.primitive_cube_add", text = "Some Submenu Operator", icon = "BLENDER")

class Pie_menu(Menu):
    bl_label = "Some Pie Menu"
    def draw(self, context):
        layout = self.layout
        pie = layout.menu_pie()
        pie.operator("wm.call_menu_pie", text = "Some Other Pie", icon = "RIGHTARROW_THIN").name="Pie_menu"
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.operator("mesh.primitive_cube_add", text = "Some Operator", icon = "BLENDER")
        pie.separator()
        pie.separator()
        other = pie.column()
        gap = other.column()
        gap.separator()
        gap.scale_y = 7
        other_menu = other.box().column()
        other_menu.scale_y=1.3
        other_menu.operator("mesh.primitive_cube_add", text = "Some Menu Operator",icon = "BLENDER")
        other_menu.operator("mesh.primitive_cube_add", text = "Some Menu Operator",icon = "BLENDER") 
        other_menu.menu('Submenu', icon='RIGHTARROW_THIN',  text='Some Submenu...')


def register():
    bpy.utils.register_class(Submenu)
    bpy.utils.register_class(Pie_menu)

def unregister():
    bpy.utils.unregister_class(Submenu)
    bpy.utils.unregister_class(Pie_menu)

if __name__ == "__main__":
    register()

    bpy.ops.wm.call_menu_pie(name="Pie_menu")

It works exactly as I wanted:

enter image description here

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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