Addon - Scroll Select. Use the scroll wheel to change mesh select mode

This is the first version of my addon. It uses shift + scroll wheel to change the selection mode in edit mode. There is a slight bug, where on initial activation, it skips edge select if you are either in vert or face mode. Not sure how to fix that. So to use it, simply hold shift and scroll up or down to change modes. This is my first released addon, what do you think? Also, it would be great if anyone can tell me why it it skipping initially.

bl_info = {"name": "Scroll Select",
"author": "Lee Hesketh",
"version": (1, 0),
"blender": (2, 79, 0),
"location": "",
"description": "Change mesh selection mode with the scroll wheel",
"warning": "",
"wiki_url": "",
"category": "Mesh",
}

import bpy

class scrollSelect(bpy.types.Operator):
"""Change Selection mode with scroll wheel"""bl_idname = "mesh.scroll_select"
bl_label = "Scroll Select"
bl_options = { 'REGISTER', 'UNDO' }


@classmethod
def poll(cls, context):
[INDENT=2]return (context.active_object is not None)[/INDENT]
mode = 1
mode_type = [(True, False, False), (False, True, False), (False, False, True)]
def modal(self, context, event):
[INDENT=2]if event.type == 'WHEELUPMOUSE' and self.mode < 2:[/INDENT]
[INDENT=3]self.mode +=1[/INDENT]
[INDENT=2]elif event.type == 'WHEELDOWNMOUSE' and self.mode > 0:[/INDENT]
[INDENT=3]self.mode -=1[/INDENT]
[INDENT=2]context.tool_settings.mesh_select_mode = self.mode_type[self.mode][/INDENT]
[INDENT=2]if not event.shift:[/INDENT]
[INDENT=3]return {'FINISHED'}[/INDENT]
[INDENT=2]return {'RUNNING_MODAL'}

[/INDENT]
def invoke(self, context, event):
[INDENT=2]context.window_manager.modal_handler_add(self)[/INDENT]
[INDENT=2]return {'RUNNING_MODAL'}[/INDENT]


addon_keymaps = [] 
def register():wm = bpy.context.window_managerkm = wm.keyconfigs.default.keymaps['Mesh']
kmi = km.keymap_items.new(scrollSelect.bl_idname, 'WHEELDOWNMOUSE', 'PRESS', shift=True)
kmj = km.keymap_items.new(scrollSelect.bl_idname, 'WHEELUPMOUSE', 'PRESS', shift=True)
addon_keymaps.append((km, kmi))
addon_keymaps.append((km, kmj))
bpy.utils.register_module(__name__)


def unregister():for km, kmi in addon_keymaps:km.keymap_items.remove(kmi)
addon_keymaps.clear()
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":register()

Interesting idea!

The skipping sounds like an initialization issue. Moving the “mode” and “mode_type” initialization down to the “invoke” function and checking for the “mode_type” when the add-on is run might fix it. Something like this:


    def invoke(self, context, event):
        self.mode_type = (True, False, False), (False, True, False), (False, False, True)
        start_mode = context.tool_settings.mesh_select_mode
        if start_mode in self.mode_type:
            self.mode = self.mode_type.index(start_mode)
        else:
            self.mode = 1

You can also simplify the mode change using the modulo operator (%):


        if event.type == 'WHEELUPMOUSE':
            self.mode = (self.mode + 1) % 3
        elif event.type == 'WHEELDOWNMOUSE':
            self.mode = (self.mode - 1) % 3

It looks like Blender Artist mangled your code a bit, so I’ve reposted it below with my changes:


bl_info = {
    "name": "Scroll Select",
    "author": "Lee Hesketh",
    "version": (1, 0),
    "blender": (2, 79, 0),
    "location": "",
    "description": "Change mesh selection mode with the scroll wheel",
    "warning": "",
    "wiki_url": "",
    "category": "Mesh",
}


import bpy


class scrollSelect(bpy.types.Operator):
    """Change Selection mode with scroll wheel"""
    bl_idname = "mesh.scroll_select"
    bl_label = "Scroll Select"
    bl_options = { 'REGISTER', 'UNDO' }


    @classmethod
    def poll(cls, context):
        return (context.active_object is not None)


    def modal(self, context, event):
        if event.type == 'WHEELUPMOUSE':
            self.mode = (self.mode + 1) % 3
        elif event.type == 'WHEELDOWNMOUSE':
            self.mode = (self.mode - 1) % 3
        context.tool_settings.mesh_select_mode = self.mode_type[self.mode]
        if not event.shift:
            return {'FINISHED'}
        return {'RUNNING_MODAL'}


    def invoke(self, context, event):
        self.mode_type = (True, False, False), (False, True, False), (False, False, True)
        start_mode = context.tool_settings.mesh_select_mode
        if start_mode in self.mode_type:
            self.mode = self.mode_type.index(start_mode)
        else:
            self.mode = 1
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


addon_keymaps = [] 
def register():
    wm = bpy.context.window_manager
    km = wm.keyconfigs.default.keymaps['Mesh']
    kmi = km.keymap_items.new(scrollSelect.bl_idname, 'WHEELDOWNMOUSE', 'PRESS', shift=True)
    kmj = km.keymap_items.new(scrollSelect.bl_idname, 'WHEELUPMOUSE', 'PRESS', shift=True)
    addon_keymaps.append((km, kmi))
    addon_keymaps.append((km, kmj))
    bpy.utils.register_module(__name__)


def unregister():
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()
    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()

Setting self.mode_type here doesn’t really do anything.

start_mode = context.tool_settings.mesh_select_mode
if start_mode in self.mode_type:
    self.mode = self.mode_type.index(start_mode)
else:
    self.mode = 1

This won’t actually work because context.tool_settings.mesh_select_mode is really a bpy_boolean[3] and not a tuple so you will always do self.mode = 1 instead. You can fix it with start_mode = tuple(context.tool_settings.mesh_select_mode)

You can also simplify the mode change using the modulo operator (%):

    if event.type == 'WHEELUPMOUSE':
        self.mode = (self.mode + 1) % 3
    elif event.type == 'WHEELDOWNMOUSE':
        self.mode = (self.mode - 1) % 3

This changes the behavior from having vertex select at the bottom scroll (held) and face select at the top scroll (held) to having a looping selection which is not great because you now need to be careful with how much you scroll. I think the op behavior is better.

Also to the op I recommend posting your code on github or somewhere online, that way it’s easier for people to download your addon.

I’ve fixed the issue. I simply added made the selection mode to edge select in the inkoke function

Here’s a link to the file