I've asked a very similar question yesterday, but I have a more concrete example here. I'm using the template "Operator Modal View3d Raycast" with some modifications:

class ViewOperatorRayCast(bpy.types.Operator):

    bl_idname = "view3d.modal_operator_raycast"
    bl_label = "RayCast View Operator"

    def modal(self, context, event):
        if context.space_data.type != 'VIEW_3D': # This doesn't work           
            return {'PASS_THROUGH'} # This doesn't work
        if event.type == 'RIGHTMOUSE' and event.value == 'PRESS': # The operator only does any thing for RMB
            main(context, event) # This is where the raycasting goes on. See the template                           
            return {'RUNNING_MODAL'}
        elif event.type in {'ESC'}:
            return {'CANCELLED'}

        return {'PASS_THROUGH'} # I want the operator to keep going

    def invoke(self, context, event):
        if context.space_data.type == 'VIEW_3D':
            return {'RUNNING_MODAL'}
            self.report({'WARNING'}, "Active space must be a View3d")            
            return {'CANCELLED'}

    def Execute(self, context)
        return {'RUNNING_MODAL'}

I can start the operator fine by pressing F3:

Invoking the modal operator

But I would like to start the operator from python. I have tried by adding the execute method, but this doesn't work since the context is either the text editor or console (not the view3d). I got the idea of using execute here (top link), but he just mentions the problem with context and not the resolution - if any:

https://www.youtube.com/watch?v=A8S-s7tuTdY (about 15:30) Constantly running modal operator (also have some of what I seek)

Is it possible to trick Blender to think that I called the operator from view3d or something like that?

  • $\begingroup$ You can right-click the yt video and select "Copy video URL at current time": youtu.be/A8S-s7tuTdY?t=904 $\endgroup$
    – brockmann
    Commented Dec 16, 2020 at 8:48
  • $\begingroup$ docs.blender.org/api/current/… -> TLDR; By default the execute method will be called, see blender.stackexchange.com/a/73548/31447 (helped me a lot a few years ago). To answer your question you should add how do you want to call it... "I want to call it with python" not pretty useful TBH. $\endgroup$
    – brockmann
    Commented Dec 16, 2020 at 8:54
  • $\begingroup$ Take out the conditional? See "overriding context" $\endgroup$
    – batFINGER
    Commented Dec 16, 2020 at 9:47
  • $\begingroup$ @ brockmann. I missed the documentation you linked. Looks like what I need. Thanks. I want to call the operator from a script like this: bpy.ops.view3d.modal_operator_raycast() which calles the execute method, but from a wrong context (the text editor). $\endgroup$
    – DrDress
    Commented Dec 16, 2020 at 10:40
  • $\begingroup$ See the second code snippet in the docs. Also I'd recommend add any relevant information to your q since others may not read the comments. $\endgroup$
    – brockmann
    Commented Dec 16, 2020 at 10:45


Browse other questions tagged .