2
$\begingroup$

Still getting to grips with writing add-ons. Can I add a custom menu for my own add-ons that are available on specific modes (say Modeling, UV editing and Rendering) that appear in a separate menu (say "myAddons") instead of relying on the Object menu alone?

Hello World Add on on Object menu

Does that make sense?

$\endgroup$
2
  • 1
    $\begingroup$ Hello. I renamed your question so hopefully it is a bit more accurate to what you're actually asking. Feel free to revert if you don't like it $\endgroup$
    – Gorgious
    Commented May 12, 2023 at 13:14
  • $\begingroup$ @Gorgious, that's absolutely fine. I didn't want to dig myself a hole and call something by the wrong name. $\endgroup$
    – Ghoul Fool
    Commented May 12, 2023 at 14:31

1 Answer 1

7
$\begingroup$

Sure. One of the great things about Blender is that it's open source and its UI is written in Python. So you can just right-click on any of the Topbar menus and choose Edit Source to see how it's coded. To have this functionality you first need to enable Developer extras in the Preferences(F4->P):

enter image description here

Then you you get this option when you right-click stuff on the UI:

enter image description here

It opens a new text data block that you can find in the Text Editor.

In this case the most interesting part is how the the place in the Topbar where you want to add your menu is called, and that seems to be in the beginning of the file:

enter image description here

So now we can modify the "UI Menu" example from the Text Editor's Templates menu to see if it works:

import bpy


class CustomMenu(bpy.types.Menu):
    bl_label = "Custom Menu"
    bl_idname = "OBJECT_MT_custom_menu"

    def draw(self, context):
        layout = self.layout
        layout.operator("wm.open_mainfile")
        layout.operator("wm.save_as_mainfile").copy = True


def draw_item(self, context):
    layout = self.layout
    layout.menu(CustomMenu.bl_idname)

def register():
    bpy.utils.register_class(CustomMenu)
    bpy.types.TOPBAR_HT_upper_bar.append(draw_item)


def unregister():
    bpy.utils.unregister_class(CustomMenu)
    bpy.types.TOPBAR_HT_upper_bar.remove(draw_item)

if __name__ == "__main__":
    register()

Unfortunately it adds the menu after all the Workspace tabs:

enter image description here

That's not fun at all, so we need to read more of the Topbar code, and here it is:

enter image description here

Apparently all the menus are in a single menu - makes sense, because you can chose not to show the menus and they are then collapsed into a single 'burger' menu. So this must be the menu. That makes things easy again as we can just add our menu to that TOPBAR_MT_editor_menus menu.

So I change this bit:

enter image description here

And it works:

enter image description here

If you want something like a menu or an operator to be available just in some context you can use poll() classmethod:

@classmethod
def poll(cls, context):
    return context.active_object is not None

You can see how it's used in the Text Editor's Templates menu examples like "Operator Simple". It works exactly the same way with menus as with operators.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .