# Modal Operator to Keep UI Active while Listening to Network Traffic and Updating Display

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
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?

• Suggest using scene = context.scene and Not sure of the need for bpy.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" – batFINGER Sep 14 '17 at 4:03
• The redraw timer updates the 3D view after the gain values of the lights have been adjusted. If I comment it out, the data is processed and applied but the user does not see the changes in real time. The code that updates the light is a single line so isn't much. Interesting idea to move the deepcopy, but unfortunately that seems to have no effect. – KentAshfield Sep 14 '17 at 18:27