Help with modal operator.


(Way2Close) #1

Hey guys I made an addon that is a modal operator, all it does is add a solidify modifier and then alters the
thickness when shift is held down and the mouse is moved.
I have worked on it for 2 days and admit defeat, I don’t know how to make it remember what the thickness is at
if shift is not pressed.
To clarify I want to add thickness when shift is held, and continue to add thickness when shift is held again.
at the moment it is resetting each time i release and press shift.
Please help :slight_smile:


bl_info = {
    "name": "test",
    "author": "",
    "version": (1, 0),
    "blender": (2, 78, 0),
    "description": "Test",
    "category": "3D View"}
    
import bpy


class ModalOperator(bpy.types.Operator):


    bl_idname = "test.test"
    bl_label = "Simple Modal Operator"
    
    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':


            if event.shift:
                delta = self.first_mouse_x - event.mouse_x
                
                for mod in bpy.context.scene.objects.active.modifiers:
                    if mod.type == "SOLIDIFY":                
                        bpy.context.object.modifiers[mod.name].thickness = self.first_value + delta * 0.01 


        elif event.type == 'LEFTMOUSE':
            return {'FINISHED'}


        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            bpy.ops.object.modifier_remove(modifier="Solidify")
            context.object.location.x = self.first_value
            return {'CANCELLED'}


        return {'RUNNING_MODAL'}


    def invoke(self, context, event):
        if context.object:
            self.first_mouse_x = event.mouse_x
            self.first_value = context.object.location.x
            bpy.ops.object.modifier_add(type='SOLIDIFY')
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            pass
            return {'CANCELLED'}


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


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


(Martynas Žiemys) #2

So, OK, if I understand you correctly you want to be able to release shift so that if you press it again you carry on from where you released it. You need to store the initial values before shift is pressed then but after the modal operator started.


bl_info = {
    "name": "test",
    "author": "",
    "version": (1, 0),
    "blender": (2, 78, 0),
    "description": "Test",
    "category": "3D View"}
    
import bpy

class ModalOperator(bpy.types.Operator):

    bl_idname = "test.test"
    bl_label = "aaaa"  
    def modal(self, context, event):
        if event.type == 'MOUSEMOVE' and not event.shift: # Store initial mouse and thickness before shift is pressed
            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':
            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.scene.objects.active.modifiers: # only run loop once instead of repeating it when mouse is moved
                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 # in case shift is pressed imediatly
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            pass
            return {'CANCELLED'}

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

def unregister():
    bpy.utils.unregister_class(ModalOperator)
    
if __name__ == "__main__":
    register()

That should be what you described you were after, but then that’s a bit weird kind of functionality because you cannot do much while shift is released. What are you trying to do here?


(Way2Close) #3

I cut this code down massively just so it wouldnt be confusing on the forum. But when shift isnt held down the camera controls are PASS_THROUGH so i can move the camera and then hold shift to add thickness, But thank you so much for helping I will see if this works :D:D

[Edit] Thank you so much works amazingly