0
$\begingroup$

I'm trying to learn about modal operators in blender. I'm a complete novice and I'm struggling with the idea of how to correctly map the mouse movement onto the bmesh operators.

I'm essentially trying to figure out how to create a modal operator that does the same things as the basic commands in blender such as Extrude, Grab, Rotate etc. Would anybody be able to refer me to examples of how to create a simple Modal Operator to rotate, scale or translate my selected vertices in Edit Mode?

I understand the Operator Modal template in the Blender Text Editor which uses the MOUSEMOVE event and delta to modify the object position. However I don't see how this could work with bmesh.ops.rotate, scale or translate operators for example, since this is different than continuously specifying a new position for the object, which is the example in the Template:

import bpy
from bpy.props import IntProperty, FloatProperty


class ModalOperator(bpy.types.Operator):
    """Move an object with the mouse, example"""
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    first_mouse_x: IntProperty()
    first_value: FloatProperty()

    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':
            delta = self.first_mouse_x - event.mouse_x
            context.object.location.x = self.first_value + delta * 0.01

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

        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            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

            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "No active object, could not finish")
            return {'CANCELLED'}


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


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


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.modal_operator('INVOKE_DEFAULT')
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.