I have two scripts I've been making pie menus in the last few weeks and I came across a seeming inconsistency in how blender handles classes and their labeling. I have two examples. One is the Viewport_Pie_Menu.py script by Wazou, modified for my own uses (single file); the other is a mesh multiselect script (part of a package and imported with __init__.py as a module). I've cut down the code snippets to illustrate my point.

Viewport Pies

This is the first class, the called menu that pops up when you press Shift+Space:

class PieAreaViews(Menu):
bl_label = "Pie Views"

def draw(self, context):
    layout = self.layout
    pie = layout.menu_pie()

    pie.operator("wm.call_menu_pie", text="Images", icon='IMAGE_COL').name = "PieAreaViewsImage"
    pie.operator("wm.call_menu_pie", text="Split", icon='SPLITSCREEN').name = "pie.split_viewport"

This calls a number of subpies, the first of which changes editors:

class PieAreaViewsImage(Menu):
bl_label = "Image"

def draw(self, context):
    layout = self.layout

    pie = layout.menu_pie()
    pie.operator("object.view_menu", text="Node Editor", icon='NODETREE').variable = "NODE_EDITOR"

Another is a subpie with some operators in it:

class PieSplitViewport(Menu):
bl_idname = "pie.split_viewport"
bl_label = "Split Viewport"

def draw(self, context):
    layout = self.layout
    pie = layout.menu_pie()

    pie.operator("split.vertical", text="Vertical", icon='DOWNARROW_HLT')
    pie.operator("split.horizontal", text="Horizontal", icon='RIGHTARROW')


The main pie class:

class VIEW3D_MT_Multiselect_Menu_Pie(Menu):
bl_label = "Multiselect Pie"

def draw(self, context):
    layout = self.layout
    pie = layout.menu_pie()

    pie.operator("multi.vert", text="Vertex Select", icon='VERTEXSEL')
    pie.operator("wm.call_menu_pie", text="Multiselect", icon='FACESEL').name = "MultiPie"


class MultiPie(Menu):
bl_label = "Multiselect Options"

def draw(self, context):
    layout = self.layout
    pie = layout.menu_pie()

    pie.operator("multi.vertedge", text="Vertex/Edge", icon='EDITMODE_HLT')

The final operation:

class SelModeVert(bpy.types.Operator):
bl_idname = "multi.vert"
bl_label = "Vertex Select Mode"

def execute(self, context):
    bpy.ops.wm.context_set_value(data_path="tool_settings.mesh_select_mode", value="(True, False, False)")
    return {'FINISHED'}


Some classes include bl_idname while others do not. Operators have them, but Menus do not. If the class does not have bl_idname, I can call it with the class name, but if it does have bl_idname, it can only sometimes be called with its class and sometimes by its bl_idname string. If a Menu type includes bl_idname, you can't call it with either bl_idname string or class name.

It took me a long time to figure out I couldn't spawn my subpie simply because it contained bl_idname, which I was then calling (I couldn't call it with either bl_idname or class name), nor could I assign a hotkey through init.


Why do some types need bl_idname and others do not? Wouldn't it be better to be consistent? If I understand right, bl_idname is required if you want to search from the spacebar search menu, but you can give bl_options = {'INTERNAL', ...} to disallow searching.

Is this how blender really treats these class types or am I just being inconsistent myself? Is there a better way to handle this? What are some conventions you have found?

I will follow this convention for now, but I'm not entirely familiar with how blender handles classes and context and whatnot. I would still consider myself relatively fresh with Python, especially within blender, so any help would be appreciated.


Your Answer

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

Browse other questions tagged or ask your own question.