5
$\begingroup$

I want to disable and enable menu items (layout.operator) in my custom menu, the disabled ones should be displayed greyed. I managed to disable the whole menu with layout.enabled = False, but I failed to disable a single menu item.

Something similar what I want to achieve can be seen in the "Ui Menu" Python template with the entry "Hello world!", but this is a layout.label and not a layout.operator. Before I use this approach as workaround I'd like to know if there is a more easy way to dis- or enable single menu items.

$\endgroup$
  • 5
    $\begingroup$ You can implement operator.poll for your own operators. If the operators poll method returns false the operator will automatically be disabled in the UI. $\endgroup$ – pink vertex Jan 16 '15 at 13:49
  • $\begingroup$ Thanks, works perfectly! Will you write this as an answer? $\endgroup$ – frisee Jan 16 '15 at 16:12
5
$\begingroup$

As already said by pink vertex and Jerryno, a poll() classmethod should be added to the operator you add to the custom menu. The disabling (graying out) will be managed by Blender automatically:

import bpy

class SimpleOperator(bpy.types.Operator):
    bl_label = "Simple Operator"
    bl_idname = "wm.simple_operator"

    @classmethod
    def poll(cls, context):
        return len(context.selected_objects) % 2 == 0

    def execute(self, context):
        self.report({'INFO'}, "Simple Operator executed.")
        return {'FINISHED'}

class SimpleOperator2(bpy.types.Operator):
    bl_label = "Simple Operator 2"
    bl_idname = "wm.simple_operator2"

    @classmethod
    def poll(cls, context):
        return (context.object is not None and
                context.object.type == 'CAMERA')

    def execute(self, context):
        self.report({'INFO'}, "Simple Operator 2 executed.")
        return {'FINISHED'}


class SimpleCustomMenu(bpy.types.Menu):
    bl_label = "Simple Custom Menu"
    bl_idname = "OBJECT_MT_simple_custom_menu"

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

        layout.label("Enabled, if even number of objects selected", icon='INFO')
        layout.operator("wm.simple_operator")
        layout.separator()
        layout.label("Enabled, if active object is a camera", icon='INFO')
        layout.operator("wm.simple_operator2")


def register():
    bpy.utils.register_module(__name__)


def unregister():
    bpy.utils.unregister_module(__name__)

if __name__ == "__main__":
    register()

    # The menu can also be called from scripts
    bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
$\endgroup$
3
$\begingroup$

If you want specific GUI elements to be disabled, set corresponding row.enable or column.enable to False:

row = layout.row()
row.operator("something")
# maybe more row stuff here
row.enable = False

If you want this build in into the operator itself, include the poll method. This will grey it in the UI and also be safe when the user calls the operator from search (spacebar) for example!

$\endgroup$
  • $\begingroup$ I am not sure how these row commands could be integrated into CoDEmanX's SimpleCustomMenu above or into Blender's "Ui Menu" template I am derivating from. Sounds more they could be used in panels, but I am not familar with these yet. But anyway, I am happy with my new poll() method! $\endgroup$ – frisee Jan 20 '15 at 12:51

Your Answer

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

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