Here is an example of a simple menu. Menus differ from panels in that they must
reference from a header, panel or another menu.

Notice the ‘CATEGORY_MT_name’ in Menu.bl_idname, this is a naming
convention for menus.

Note

Menu subclasses must be registered before referencing them from blender.

Note

Menus have their Layout.operator_context initialized as
‘EXEC_REGION_WIN’ rather than ‘INVOKE_DEFAULT’ (see Execution Context).
If the operator context needs to initialize inputs from the
Operator.invoke function, then this needs to be explicitly set.

importbpyclassSubMenu(bpy.types.Menu):bl_idname="OBJECT_MT_select_submenu"bl_label="Select"defdraw(self,context):layout=self.layoutlayout.operator("object.select_all",text="Select/Deselect All").action='TOGGLE'layout.operator("object.select_all",text="Inverse").action='INVERT'layout.operator("object.select_random",text="Random")# access this operator as a submenulayout.operator_menu_enum("object.select_by_type","type",text="Select All by Type...")layout.separator()# expand each operator option into this menulayout.operator_enum("object.lamp_add","type")layout.separator()# use existing memulayout.menu("VIEW3D_MT_transform")bpy.utils.register_class(SubMenu)# test call to display immediately.bpy.ops.wm.call_menu(name="OBJECT_MT_select_submenu")

Preset menus are simply a convention that uses a menu sub-class
to perform the common task of managing presets.

This example shows how you can add a preset menu.

This example uses the object display options,
however you can use properties defined by your own scripts too.

importbpyfrombpy.typesimportOperator,Menufrombl_operators.presetsimportAddPresetBaseclassOBJECT_MT_display_presets(Menu):bl_label="Object Display Presets"preset_subdir="object/display"preset_operator="script.execute_preset"display=Menu.display_presetclassAddPresetObjectDisplay(AddPresetBase,Operator):'''Add a Object Display Preset'''bl_idname="camera.object_display_preset_add"bl_label="Add Object Display Preset"preset_menu="OBJECT_MT_display_presets"# variable used for all preset valuespreset_defines=["obj = bpy.context.object"]# properties to store in the presetpreset_values=["obj.display_type","obj.show_bounds","obj.display_bounds_type","obj.show_name","obj.show_axis","obj.show_wire",]# where to store the presetpreset_subdir="object/display"# Display into an existing paneldefpanel_func(self,context):layout=self.layoutrow=layout.row(align=True)row.menu(OBJECT_MT_display_presets.__name__,text=OBJECT_MT_display_presets.bl_label)row.operator(AddPresetObjectDisplay.bl_idname,text="",icon='ZOOMIN')row.operator(AddPresetObjectDisplay.bl_idname,text="",icon='ZOOMOUT').remove_active=Trueclasses=(OBJECT_MT_display_presets,AddPresetObjectDisplay,)defregister():forclsinclasses:bpy.utils.register_class(cls)bpy.types.OBJECT_PT_display.prepend(panel_func)defunregister():forclsinclasses:bpy.utils.unregister_class(cls)bpy.types.OBJECT_PT_display.remove(panel_func)if__name__=="__main__":register()

This example enables you to insert your own menu entry into the common
right click menu that you get while hovering over a value field,
color, string, etc.

To make the example work, you have to first select an object
then right click on an user interface element (maybe a color in the
material properties) and choose Execute Custom Action.

Executing the operator will then print all values.

importbpyfrombpy.typesimportMenudefdump(obj,text):forattrindir(obj):print("%r.%s = %s"%(obj,attr,getattr(obj,attr)))classWM_OT_button_context_test(bpy.types.Operator):"""Right click entry test"""bl_idname="wm.button_context_test"bl_label="Run Context Test"@classmethoddefpoll(cls,context):returncontext.active_objectisnotNonedefexecute(self,context):value=getattr(context,"button_pointer",None)ifvalueisnotNone:dump(value,"button_pointer")value=getattr(context,"button_prop",None)ifvalueisnotNone:dump(value,"button_prop")value=getattr(context,"button_operator",None)ifvalueisnotNone:dump(value,"button_operator")return{'FINISHED'}# This class has to be exactly named like that to insert an entry in the right click menuclassWM_MT_button_context(Menu):bl_label="Unused"defdraw(self,context):passdefmenu_func(self,context):layout=self.layoutlayout.separator()layout.operator(WM_OT_button_context_test.bl_idname)classes=(WM_OT_button_context_test,WM_MT_button_context,)defregister():forclsinclasses:bpy.utils.register_class(cls)bpy.types.WM_MT_button_context.append(menu_func)defunregister():forclsinclasses:bpy.utils.unregister_class(cls)bpy.types.WM_MT_button_context.remove(menu_func)if__name__=="__main__":register()

If this is set, the menu gets a custom ID, otherwise it takes the name of the class used to define the menu (for example, if the class name is “OBJECT_MT_hello”, and bl_idname is not set by the script, then bl_idname = “OBJECT_MT_hello”)