0
$\begingroup$

Let's say I have this code for adding the Solidify mod to the object by ctrl+W. By holding Shift I can control the Thickness parameter. How can I switch to the Offset parameter and still be able to control it by Mouse move event (switching by pressing the O key for example)? And by T key switch back to Thickness.

PS Could be without Shift, just start control with the same keys.

import bpy
import math
import numpy as np
class ModalOperator(bpy.types.Operator):
    bl_idname = "modal.test"
    bl_label = "modalctrl"  
    @classmethod
    def poll(cls, context):    
        return context.object is not None
    def modal(self, context, event):

        if event.type == 'MOUSEMOVE' and not event.shift: 
            self.first_mouse_x = event.mouse_x 
            self.first_thickness = bpy.context.object.modifiers[self.mod].thickness  
           
        if event.type == 'MOUSEMOVE' and event.shift: 
            delta = self.first_mouse_x - event.mouse_x                
            bpy.context.object.modifiers[self.mod].thickness = self.first_thickness + delta * 0.01 
        
        elif event.type == 'LEFTMOUSE':
            #bpy.ops.object.modifier_apply(modifier=self.mod)
            return {'FINISHED'}
        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.ops.object.modifier_remove(modifier=self.mod)
            return {'CANCELLED'}
        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        if context.object:
            self.mod = bpy.ops.object.modifier_add(type='SOLIDIFY')
            for mod in bpy.context.view_layer.objects.active.modifiers: 
                if mod.type == "SOLIDIFY": 
                    self.mod = mod.name
            self.first_mouse_x = event.mouse_x
            self.first_thickness = bpy.context.object.modifiers[self.mod].thickness 
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            pass
            return {'CANCELLED'}

Here is the keymaps part:

addon_keymaps = []

def register():
    bpy.utils.register_class(ModalOperator)
    # Add the hotkey
    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(ModalOperator.bl_idname, type='W', value='PRESS', ctrl=True)
        addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_class(OBJECT_OT_CustomOp)
    
    # Remove the hotkey
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()


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

1 Answer 1

0
$\begingroup$

Default in thinkness mode

'O' switch to offset mode

'T' switch to thinkness mode

hold shift to do thinkess

import bpy
import math
import numpy as np
class ModalOperator(bpy.types.Operator):
    bl_idname = "modal.test"
    bl_label = "modalctrl"  
    @classmethod
    def poll(cls, context):    
        return context.object is not None
    def modal(self, context, event):
        self.dx = event.mouse_x - self.event_x
        self.dy = event.mouse_y - self.event_y

        if event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.ops.object.modifier_remove(modifier=self.mod.name)
            return {'CANCELLED'}
        if event.type == 'LEFTMOUSE':   return {'FINISHED'}
        if event.shift:
            self.modal_thinkness()
            self.event_x, self.event_y = event.mouse_x, event.mouse_y
            return {'RUNNING_MODAL'}

        if event.type == 'O':       self.sub_modal = self.modal_offset
        elif event.type == 'T':     self.sub_modal = self.modal_thinkness

        self.sub_modal()

        self.event_x, self.event_y = event.mouse_x, event.mouse_y
        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        if context.object:
            bpy.ops.object.modifier_add(type='SOLIDIFY')
            self.mod = bpy.context.object.modifiers[-1]
            self.event_x, self.event_y = event.mouse_x, event.mouse_y
            self.sub_modal = self.modal_thinkness
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}

        return {'CANCELLED'}

    def modal_thinkness(self):
        self.mod.thickness += self.dx * 0.01
    def modal_offset(self):
        self.mod.offset += self.dx * 0.01

addon_keymaps = []

def register():
    bpy.utils.register_class(ModalOperator)
    # Add the hotkey
    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(ModalOperator.bl_idname, type='W', value='PRESS', ctrl=True)
        addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_class(OBJECT_OT_CustomOp)
    
    # Remove the hotkey
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()


if __name__ == "__main__":
    register()

Here is the warp cursor verson

cursor will jump to other side if in limit position

import bpy
import math
import numpy as np
class ModalOperator(bpy.types.Operator):
    bl_idname = "modal.test"
    bl_label = "modalctrl"  
    @classmethod
    def poll(cls, context):    
        return context.object is not None
    def modal(self, context, event):
        self.dx = event.mouse_x - self.event_x

        if event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.ops.object.modifier_remove(modifier=self.mod.name)
            return {'CANCELLED'}
        if event.type == 'LEFTMOUSE':   return {'FINISHED'}
        if event.shift:
            self.modal_thinkness()
            self.wrap_cursor(event)
            return {'RUNNING_MODAL'}

        if event.type == 'O':       self.sub_modal = self.modal_offset
        elif event.type == 'T':     self.sub_modal = self.modal_thinkness

        self.sub_modal()

        self.wrap_cursor(event)
        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        if context.object:
            bpy.ops.object.modifier_add(type='SOLIDIFY')
            self.mod        = bpy.context.object.modifiers[-1]
            self.event_x    = event.mouse_x
            self.sub_modal  = self.modal_thinkness

            # use for wrap cursor
            region          = bpy.context.window
            self.L          = 20
            self.R          = region.width - 20

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}

        return {'CANCELLED'}

    def modal_thinkness(self):
        self.mod.thickness += self.dx * 0.01
    def modal_offset(self):
        self.mod.offset += self.dx * 0.01

    def wrap_cursor(self, event):
        x       = event.mouse_x
        new_pos = x

        if x < self.L:
            new_pos = self.R - 20
            bpy.context.window.cursor_warp(new_pos, event.mouse_y)
        elif x > self.R:
            new_pos = self.L + 20
            bpy.context.window.cursor_warp(new_pos, event.mouse_y)

        self.event_x = new_pos

addon_keymaps = []

def register():
    bpy.utils.register_class(ModalOperator)
    # Add the hotkey
    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(ModalOperator.bl_idname, type='W', value='PRESS', ctrl=True)
        addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_class(OBJECT_OT_CustomOp)
    
    # Remove the hotkey
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()


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

You must log in to answer this question.

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