I am working on a Blender plugin that updates light fixtures in response to network data. I have the main aspect of the program completed (parsing the network packages into instructions for how exactly a certain light should be changed), and now I am trying to address lingering issues, the most critical of which is the UI locking up while the program runs. My understanding is that a modal operator would allow my program to essentially run in the background, which would let packages be processed and lights be updated without restricting the user's ability to interact with the 3D view (for example, lights could be pulsing while the user rotates their view).
Current State: Right now, I have a version of my code that is essentially spliced into the Blender template modal operator (timer version). Here is an outline of what I have:
/* import statements and initial setup here */
class ModalTimerOperator(bpy.types.Operator):
"""Operator which runs its self from a timer"""
bl_idname = "wm.modal_timer_operator"
bl_label = "Modal Timer Operator"
_timer = None
def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.cancel(context)
return {'CANCELLED'}
if event.type == 'TIMER':
/*code that process a network packet into an array called dmx here*/
#now change the lights based on the dmx data
objects = bpy.data.scenes
scene = objects[0]
#if this packet is different than the last one we applied
if(dmxOLD != dmx):
for light in scene.objects:
if "prop" in light:
chan = math.floor(light["prop"]+17)
/*code that updates the light here*/
#now update the display
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
dmxOLD = copy.deepcopy(dmx)
#END CONTROL OF LIGHTS
return {'PASS_THROUGH'}
def execute(self, context):
wm = context.window_manager
self._timer = wm.event_timer_add(0.1, context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
def register():
bpy.utils.register_class(ModalTimerOperator)
def unregister():
bpy.utils.unregister_class(ModalTimerOperator)
if __name__ == "__main__":
register()
# test call
bpy.ops.wm.modal_timer_operator()
So when I run the full version of this, it basically runs as though the code was inside of an infinite loop and not in a modal operator. In other words, the packets are processed and the display is updated but the user is locked out.
Am I using a modal operator incorrectly? Is this the wrong template to be using?
scene = context.scene
and Not sure of the need forbpy.ops.wm.redraw_timer
The timer ticks every 0.1 seconds, How heavy is "code that updates the light". ..Whats the timing on deepcopy and array comparison, vs doing so in "code that process a network packet into an array called dmx here" $\endgroup$