I'm trying to 'INVOKE_DEFAULT'
using thread in the following code:
import bpy
import gpu,threading
def draw(self, context):
if self.modal_redraw == True:
self.framebuffer = gpu.state.active_framebuffer_get()
self.viewport_info = gpu.state.viewport_get()
self.width = self.viewport_info[2]
self.height = self.viewport_info[3]
self.framebuffer_image.scale(self.width, self.height)
self.pixelBuffer = self.framebuffer.read_color(0, 0, self.width, self.height, 4, 0, 'FLOAT')
self.pixelBuffer.dimensions = self.width * self.height * 4
self.framebuffer_image.pixels.foreach_set(self.pixelBuffer)
self.modal_redraw = False
class ModalFramebufferCopy(bpy.types.Operator):
bl_idname = "view3d.modal_framebuffer_copy"
bl_label = "Draw 3D View Framebuffer"
def __init__(self):
print("Start example code")
# init variables
self.width = 32
self.height = 32
self.modal_redraw = False
self.image_name = "color_buffer_copy"
self.framebuffer = None
self.viewport_info = None
self.pixelBuffer = None
if not self.image_name in bpy.data.images:
self.framebuffer_image = bpy.data.images.new(self.image_name , 32, 32, float_buffer=True)
else:
self.framebuffer_image = bpy.data.images[self.image_name ]
#
def __del__(self):
print("End example code")
# modal operator for controlled redraw of the image
def modal(self, context, event):
# stop the execution of this example code if 'ESC' is pressed
if event.type in {'ESC'}:
bpy.types.SpaceView3D.draw_handler_remove(self._handle_3d, 'WINDOW')
print("Removing draw handler")
return {'CANCELLED'}
else:
self.modal_redraw = True
return {'PASS_THROUGH'}
def invoke(self, context, event):
print("Invoking modal operator")
self._handle_3d = bpy.types.SpaceView3D.draw_handler_add(draw, (self, context), 'WINDOW', 'PRE_VIEW')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def register():
bpy.utils.register_class(ModalFramebufferCopy)
def unregister():
bpy.utils.unregister_class(ModalFramebufferCopy)
def invoke_draw():
bpy.ops.view3d.modal_framebuffer_copy('INVOKE_DEFAULT')
if __name__ == "__main__":
register()
server_thread=threading.Thread(target=invoke_draw)
server_thread.start()
but at the following line
bpy.ops.view3d.modal_framebuffer_copy('INVOKE_DEFAULT')
it gives the following error
RuntimeError: Operator bpy.ops.view3d.modal_framebuffer_copy.poll() Missing 'window' in context
I've desperately tried everything but I'm out of ideas, how do I fix this?
Edit
Let me state what I'm trying to achieve.
I have another application which needs the images, so it sends blender a signal to generate the image via servers, which is why I'm using threading in the first place so that listening for signals
i.e. to listen for incoming messages-> move the 3D figure -> generate image
here's the entire code if you'd like to dive deeper
Edit 2
I changed my approach, you can follow it here
def invoke_draw(self, context):
$\endgroup$def invoke_draw(self, context)
toclass ModalFramebufferCopy
? if so how do I run it through a thread? $\endgroup$def
at the bottom of your script, change todef invoke_draw(self, context)
But this is just a guess :) I don't know about multi-threading and I could not find any documentation onbpy.ops.view3d.modal_framebuffer_copy
$\endgroup$def invoke_draw(self, context)
would help exactly? it's not a part of theModalFramebufferCopy
class so what would I pass as arguments inthreading.Thread(target=invoke_draw)
? also itmodal_framebuffer_copy
isn't inbuilt, I got it from this answer $\endgroup$invoke_draw()
blender.stackexchange.com/questions/6101/… $\endgroup$