I'm new to using Python in Blender and I would really appreciate some help with understanding Modal operators. I copied some code from the Blender documentation and tried changing some of it to do what I need. The original code moved an object using the MOUSEMOVE event and then placed it when you left clicked.

I'm trying to make a program that lets you build the shape of a house or building out of planes, and then eventually, replace them with assets I've sculpted (different types of walls, windows, etc.). I'm not quite at that point yet. The gray plane is supposed to be one of the placeholder walls. The green plane is meant to be clicked on to create another gray plane, and then move to the left of the new gray plane. (Eventually I'll have green planes all around the original gray plane so you can build out walls in whichever direction you like.

Maybe there's a better way to do this, but the best option I can see so far is using a modal operator. I'd like to create a new gray plane when I click on the green plane.

I changed some of the code that I copied from the documentation. The part I'm interested in is the LEFTMOUSE event. I didn't delete all of the old code, because I wanted to change as little as possible, in order to not mess everything up. So the green plane moves when I run the script. But nothing happens when I click. Part of the problem is, I don't have much experience with modal operators. I've watched several tutorials and read the documentation, but I'm still confused.

If someone could explain how this code works, and the difference between the execute, modal and invoke functions, I would really appreciate it. And, if you could help me figure out how to create a new plane when I click on the green plane, that would be really awesome!

[![enter image description here][1]][1]

import bpy

class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    def __init__(self):

    def __del__(self):

    def execute(self, context):
        context.object.location.x = self.value / 50.0
        return {'FINISHED'}

    def modal(self, context, event):

        if event.type == 'LEFTMOUSE':  # Confirm
            if bpy.context.view_layer.objects.active == 'greenplane':
                bpy.ops.mesh.primitive_plane_add(size=2, enter_editmode=False, location=(0, 0, 0))
                print("not working")

        elif event.type in {'RIGHTMOUSE', 'ESC'}:  # Cancel
            context.object.location.x = self.init_loc_x
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.init_loc_x = context.object.location.x
        self.value = event.mouse_x

        return {'RUNNING_MODAL'}

  • 1
    $\begingroup$ Related blender.stackexchange.com/questions/80565/… $\endgroup$
    – batFINGER
    Mar 12, 2021 at 5:31
  • 1
    $\begingroup$ Strongly recommend going to the python console and get some basics down, to test code first. Contend that context.view_layer.objects.active == 'greenplane' will never be true. $\endgroup$
    – batFINGER
    Mar 12, 2021 at 5:52
  • $\begingroup$ Ahh, that looks very helpful. I will look through that code. And I think you're right. It looks like what I actually needed was bpy.data.objects["creator"].select_get == True. Thanks! $\endgroup$ Mar 12, 2021 at 6:11
  • $\begingroup$ lol, bpy.data.objects["creator"].select_get == True will never be true either. Go to blender's python console type in bpy.data.objects["creator"].select_get then press TAB. $\endgroup$
    – batFINGER
    Mar 12, 2021 at 6:15
  • $\begingroup$ My bad, I meant bpy.data.objects["greenplane"].select_get() == True, haha it's getting a little late here :) $\endgroup$ Mar 12, 2021 at 6:19


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.