I setup some shader to run on top of blender viewport and connected it’s update to SpaceView3D.draw_handler_add
. The idea was that shader will only work in EDIT mode and if user exists it then it will automatically trigger some operator.
Line that freezes Blender is bm.to_mesh(context.object.data)
although it doens’t freeze right away.
What I’ve found that if I call operator that edits mesh from bmesh then it freezes Blender entirely.
Any ideas to work around that? Could that be a bug?
Currently as a workaround I plan to move operator’s code to some function and call it insteadf because bm.to_mesh(context.object.data)
doesn’t seem to freeze Blender when it’s called from handler without operator.
Blender version: 3.5
Easy way to reproduce (create default scene, make sure cube is selected, run the script):
import bpy
from bpy.types import SpaceView3D
import bmesh
class TestHandler:
installed = None
@classmethod
def install(cls, context):
handler = cls()
cls.installed = SpaceView3D.draw_handler_add(
handler, (context, ), "WINDOW", "POST_VIEW"
)
@classmethod
def uninstall(cls):
try:
SpaceView3D.draw_handler_remove(cls.installed, "WINDOW")
except ValueError:
pass
cls.installed = None
def __call__(self, context):
obj = context.object
if obj.mode != "EDIT":
TestHandler.uninstall()
bpy.ops.test.test()
print('HANDLER CALL FINISHED') # never printed
return
print('HANDLER FINISHED')
class TestOperator(bpy.types.Operator):
bl_idname = "test.test"
bl_label = "test"
def execute(self, context):
print('TEST OPERATOR CALLED')
bm = bmesh.new()
# WITHOUT THIS LINE IT DOESN'T FREEZE
bm.to_mesh(context.object.data)
# still printed
print('TEST OPERATOR FINISHED')
return {"FINISHED"}
class TestSetupOperator(bpy.types.Operator):
bl_idname = "test.test_setup"
bl_label = "test"
def execute(self, context):
print('TEST SETUP OPERATOR CALLED')
TestHandler.install(context)
return {"FINISHED"}
bpy.utils.register_class(TestOperator)
bpy.utils.register_class(TestSetupOperator)
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.test.test_setup()
# freezes on the next step
bpy.ops.object.mode_set(mode="OBJECT")