When I invoke my modal operator from my other operator (invoked from a panel button) and the modal operator finishes, Blender's UI is blocked until the mouse moves (i.e. click on the same button has no effect unless the mouse is moved or clicked first).
Also, if the modal operator is invoked from a property update function then the UI is blocked until LMB click (moving or clicking other buttons has no effect).
However, occasionally blocking does not happen.
When looking at events in modal()
, event.type
/event.value
for the first two events are:
- UI blocked -
MOUSMOVE
/RELEASE
,MOUSMOVE
/RELEASE
- UI not blocked -
MOUSMOVE
/RELEASE
,NONE
/NOTHING
An obvious question is why are there two MOUSMOVE
/RELEASE
events anyway ...
I am wondering why is this happening and even more is there a way to avoid this UI blocking?
(The reason I'm doing all this is in my other question.)
Example code:
import bpy
from bpy.types import Operator
class TheModalOperator(Operator):
bl_idname = "my.themodaloperator"
bl_label = "TheModalOperator Operator"
# counter of calls to modal()
countmodal = 0
def __del__(self):
print("TheModalOperator End")
def invoke(self, context, event):
print("TheModalOperator invoke")
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def modal(self, context, event):
self.countmodal += 1
print("TheModalOperator modal", self.countmodal, event.type, event.value)
if self.countmodal >= 2:
print("---TheModalOperator modal finished")
return {'FINISHED'}
else:
print("---TheModalOperator modal running")
return {'RUNNING_MODAL'}
class MyOperator(Operator):
"""This is my operator"""
bl_idname = "my.operator"
bl_label = "My Operator"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
print("MyOperator execute")
self.report({'INFO'}, "MyOperator executed")
bpy.ops.my.themodaloperator('INVOKE_DEFAULT')
return {'FINISHED'}
# button on the toolshelf
class MyTestPanel(bpy.types.Panel):
bl_idname = "mytestpanel"
bl_category = "My Stuff"
bl_label = "My Test Panel"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_context = "objectmode"
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.label(text="This blocks UI until a mouse event:")
col.operator("my.operator", text="Run my operator")
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()
modal
should returnPASS_THROUGH
(solves invoking from a property update function) and a timer (solves invoking from another operator). Will post this as an answer tomorrow. $\endgroup$