Page MenuHome

Appended menus to VIEW3D_MT_editor_menus are not displayed
Closed, ResolvedPublic

Description

Blender Version
Broken: 2.80,

Short description of error

The code bellows illustrate the issue : a new menu is added to to VIEW3D_MT_editor_menus class which inherit from bpy.types.Menu and embed others 3d view menus, but this new menu does not appears. If VIEW3D_MT_editor_menus is displaying in another panel then the new menu appears which confirms that the append is effective.
See also related BA thread.

import bpy

class VIEW3D_MT_menu(bpy.types.Menu):
    bl_label = "Test"

    def draw(self, context):
        self.layout.operator("mesh.primitive_monkey_add")

def addmenu_callback(self, context):
    self.layout.menu("VIEW3D_MT_menu")


def register():
    bpy.utils.register_class(VIEW3D_MT_menu)
    bpy.types.VIEW3D_MT_editor_menus.append(addmenu_callback)

def unregister():
    bpy.types.VIEW3D_MT_editor_menus.remove(addmenu_callback)
    bpy.utils.register_class(VIEW3D_MT_menu)


if __name__ == "__main__":
	register()

Event Timeline

Philipp Oeser (lichtwerk) triaged this task as Confirmed, Medium priority.

Seems like VIEW3D_HT_header calls
VIEW3D_MT_editor_menus.draw_collapsible(context, layout)

which in turn calls
cls.draw_menus(layout.row(align=True), context)

then
VIEW3D_MT_editor_menus.draw_menus() is pretty hardcoded (and doesnt really take into any appended menus as it seems)

Not sure exactly why it works when the VIEW3D_MT_editor_menus is placed in a panel in the Properties Editor.

Maybe @Campbell Barton (campbellbarton) knows?

This isn't exactly a bug since this method of drawing doesn't use a menu instance.

Even so, it would be nice to support.

We could workaround this but not really happy with this solution especially since it's running in the typical case when all items are displayed.

diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index c6552334dcf..5bd3a2882a6 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -920,7 +920,11 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
         # only usable within headers
         if context.area.show_menus:
             # Align menus to space them closely.
-            cls.draw_menus(layout.row(align=True), context)
+            fake_self =  type("FakeMenu", (), {
+                "layout": layout.row(align=True),
+                "draw_menus": cls.draw_menus,
+            })
+            cls.draw(fake_self, context)
         else:
             layout.menu(cls.__name__, icon='COLLAPSEMENU')

Edit, thinking about this - I think the correct solution is to add a method that draws the menu expanded (in the header or panel...). Then we get a menu instance and don't need to have a hacky workaround.