3
$\begingroup$

Is it possible to remap a key to call more than one operator at a time, or to execute a python script?

In my workflow I need to use two operators, one after the other:
Set the 3D cursor to selection, followed by set origin to 3D cursor.

I never use the 0 key to switch layers,so I thought it would be faster to make it "set origin to selection", but i don't know how to make it call those two in one go.
bpy.ops.view3d.snap_cursor_to_selected()
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

If this works it would save me exactly 6 key presses:
Shift+S ,4, tab to go to object mode,Shiftctrlaltc,3,tab to go back to edit mode.

Thanks for any input


Edit : This works when executed from a text editor, now i just need to figure out a way to execute it with the 0 key.

import bpy

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        context = bpy.context.copy()
        context['area'] = area
        context['region'] = area.regions[-1]
        bpy.ops.view3d.snap_cursor_to_selected(context)
        bpy.ops.object.editmode_toggle()
        bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
        bpy.ops.object.editmode_toggle()
        break
$\endgroup$

3 Answers 3

3
$\begingroup$

Here's a quick example adapted from the ObjectCursorArray tutorial in the API documentation.

You should be able to run this in the text editor, and then pressing Numpad 0 in Object view should result in the "do work here" text printing to the console window (in OSX/Linux you have to launch Blender from the terminal to see the console output).

Note: once you copy this script into blender, you may want to check that the tab structure is still correct for each line.

bl_info = {
    "name": "Work Macro",
    "category": "Object",
}

import bpy


class WorkMacro(bpy.types.Operator):
    """Work Macro"""
    bl_idname = "object.work_macro"
    bl_label = "Work Macro"
    bl_options = {'REGISTER', 'UNDO'}


    def execute(self, context):

        print("do work here")

        return {'FINISHED'}


# store keymaps here to access after registration
addon_keymaps = []


def register():
    bpy.utils.register_class(WorkMacro)

    # handle the keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
    kmi = km.keymap_items.new(WorkMacro.bl_idname, 'NUMPAD_0', 'PRESS', ctrl=False, shift=False)
    addon_keymaps.append(km)

def unregister():
    bpy.utils.unregister_class(WorkMacro)

    # handle the keymap
    wm = bpy.context.window_manager
    for km in addon_keymaps:
        wm.keyconfigs.addon.keymaps.remove(km)
    # clear the list
    del addon_keymaps[:]


if __name__ == "__main__":
    register()
$\endgroup$
0
1
$\begingroup$

Thanks to @Todd McIntosh I finally made this work.
just in case someone needs this or wants to adapt it to their own workflow

script:

bl_info = {
    "name": "Origin to Selection",
    "category": "Object",
}

import bpy


class WorkMacro(bpy.types.Operator):
    """Origin to Selection"""
    bl_idname = "object.origin_to_selection"
    bl_label = "Origin To Selection"
    bl_options = {'REGISTER', 'UNDO'}


    def execute(self, context):

        for area in bpy.context.screen.areas:
            if area.type == 'VIEW_3D':
                context = bpy.context.copy()
                context['area'] = area
                context['region'] = area.regions[-1]
                bpy.ops.view3d.snap_cursor_to_selected(context)
                # quickly switch to object mode to set the origin
                bpy.ops.object.editmode_toggle()
                bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
                # Switch back to edit mode
                bpy.ops.object.editmode_toggle()
                break

        return {'FINISHED'}


# store keymaps here to access after registration
addon_keymaps = []


def register():
    bpy.utils.register_class(WorkMacro)

    # handle the keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
    kmi = km.keymap_items.new(WorkMacro.bl_idname, 'ZERO', 'PRESS', ctrl=False, shift=False)
    addon_keymaps.append(km)

def unregister():
    bpy.utils.unregister_class(WorkMacro)

    # handle the keymap
    wm = bpy.context.window_manager
    for km in addon_keymaps:
        wm.keyconfigs.addon.keymaps.remove(km)
    # clear the list
    del addon_keymaps[:]


if __name__ == "__main__":
    register()

Since 0 was already assigned to the operator that changes layers I had to edit it to call the operator named "object.origin_to_selection" in bl_idname in the script.

enter image description here

It can also be accessed by pressing space and searching for origin to selection

$\endgroup$
1
$\begingroup$

I came looking on how to make macros for this exact reason! The add-on script above doesn't work as desired as the keyboard shortcut is mapped to "Object Mode" which is the opposite of editmode_toggle() as you want. If you correct the following line in the script it worked for me.

Change out this:

km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')

For this:

km = wm.keyconfigs.addon.keymaps.new(name='Mesh', space_type='EMPTY')

Depending on your situation you may want a different area for it works in, eg. "3D View (Global)"

$\endgroup$

You must log in to answer this question.