3
$\begingroup$

I have a custom panel in which I have buttons that can use modifier keys, IE Clicking, Ctrl+Clicking, Alt+Clicking etc all do slightly different things and it works as expected. I want to hotkey the UI button but dont know how to differentiate if its called via the UI (and take modifiers into account) or via a hotkey (and not take the modifiers into account).

class dummyButton(bpy.types.Operator):
bl_idname = "view3d.fd_dummybutton"
bl_label = "Dummy Button"
bl_options = {'REGISTER', 'UNDO'}

modeEnum : bpy.props.EnumProperty(
    items = {
        ("1", "Stuff", ""),
        ("2", "Other stuff", ""),
        ("3", "Even more stuff", ""),
        ("4", "Final stuff", "")
    },
    name = "Mode",
    default = "1"
)

def invoke(self, context, event):
    
    if event.ctrl:
        self.modeEnum = "2"
    elif event.shift:
        self.modeEnum = "3"
    elif event.alt:
        self.modeEnum = "4"
    
    return self.execute(context)

def execute(self, context):
    
    if self.modeEnum == "1":
        print("Do stuff")
    elif self.modeEnum == "2":
        print("Do other stuff")
    else:
        print("Stuff")

    return {'FINISHED'}

I'd prefer to use an enum since then I can choose the function in the hotkey menuEnum dropdown to pick what the hotkey does I want to be able to use Ctrl+9 as a hotkey without it forcing the modeEnum to be set to "2"

Am I going about this in the wrong way?

$\endgroup$

2 Answers 2

3
$\begingroup$

You can catch the left-click event when the button is pressed to differentiate between UI and hotkey call, using event.type == 'LEFTMOUSE': https://docs.blender.org/api/current/bpy.types.Event.html#bpy.types.Event.type

import bpy

# https://blender.stackexchange.com/a/24002/
class OBJECT_OT_CustomOp(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"
    
    def invoke(self, context, event):
        #is_property_set
        ev = []
        if event.ctrl:
            ev.append("Ctrl")
        if event.shift:
            ev.append("Shift")
        if event.type == 'LEFTMOUSE':
            ev.append("Click")
        self.report({'INFO'}, "+".join(ev))
        return {'FINISHED'}

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"   

    def draw(self, context):
        layout = self.layout
        layout.operator(OBJECT_OT_CustomOp.bl_idname)
        layout.separator()

addon_keymaps = []

def register():
    bpy.utils.register_class(OBJECT_OT_CustomOp)
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    
    # https://blender.stackexchange.com/a/196518/
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='3D View', space_type='VIEW_3D')
        kmi = km.keymap_items.new(OBJECT_OT_CustomOp.bl_idname, type='Q', value='PRESS', ctrl=True)
        addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)
    bpy.utils.unregister_class(OBJECT_OT_CustomOp)

    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.object.simple_operator()

Python: Ctrl+Click for buttons (capture invocation event)

Create keyboard shortcut for an operator using python?

$\endgroup$
1
  • 2
    $\begingroup$ This solution is both clean and simple, seems so obvious now in hindsight. Thanks for taking the time to help out! $\endgroup$
    – CybranM
    Commented Jan 12, 2022 at 16:21
2
$\begingroup$

You can also add a (hidden) property, IE Bool or Enum to the operator (as you already do) which will be set when the button is pressed. https://docs.blender.org/api/current/bpy.types.KeyMapItem.html#bpy.types.KeyMapItem.properties

import bpy

# https://blender.stackexchange.com/a/24002/
class OBJECT_OT_CustomOp(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"
    bl_options = {'REGISTER', 'UNDO'}
    
    # https://blender.stackexchange.com/a/21108/
    hotkey_call: bpy.props.BoolProperty(options={'HIDDEN', 'SKIP_SAVE'})
    
    def invoke(self, context, event):
        ev = []
        if event.ctrl:
            ev.append("Ctrl")
        if event.shift:
            ev.append("Shift")
        if self.hotkey_call:
            ev = ["Hotkey Call"]
        self.report({'INFO'}, "+".join(ev))
        return {'FINISHED'}

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"   

    def draw(self, context):
        layout = self.layout
        layout.operator(OBJECT_OT_CustomOp.bl_idname)
        layout.separator()

addon_keymaps = []

def register():
    bpy.utils.register_class(OBJECT_OT_CustomOp)
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    
    # https://blender.stackexchange.com/a/196518/
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='3D View', space_type='VIEW_3D')
        kmi = km.keymap_items.new(OBJECT_OT_CustomOp.bl_idname, type='Q', value='PRESS', ctrl=True)
        kmi.properties.hotkey_call = True
        addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)
    bpy.utils.unregister_class(OBJECT_OT_CustomOp)
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.object.simple_operator()

Option flags for custom properties (bpy.props)

$\endgroup$
4
  • $\begingroup$ Using a hidden property partly worked, its hidden from the tools popup but still shows up in the hotkey editor which is a bit annoying $\endgroup$
    – CybranM
    Commented Jan 12, 2022 at 16:20
  • 1
    $\begingroup$ Hey nice answer ! :) could you elaborate on what the property options {'HIDDEN', 'SKIP_SAVE'} do ? $\endgroup$
    – Gorgious
    Commented Jan 13, 2022 at 9:45
  • 1
    $\begingroup$ @Gorgious this answer explains it well. $\endgroup$
    – CybranM
    Commented Jan 13, 2022 at 9:48
  • $\begingroup$ @CybranM perfect, thank you. $\endgroup$
    – Gorgious
    Commented Jan 13, 2022 at 9:50

You must log in to answer this question.

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