# alternatives for operator's report() function?

it seems that the report() function of Operator type lets all other routines finish before it actually reports. this makes it useless in many instances: for example, when reporting progress on baking (I have abandoned the idea of a progress bar and merely want to show a message: 'baking ith map out of n maps'). However, this message would always come at the end. Are there ways to supress this behavior and output a message instantaneously? In Excel VBA, there's DoEvents() built-in function. It lets all processes freeze until the ongoing processes finish

• – batFINGER Mar 23 '19 at 4:40
• @batFINGER thanks looks useful. I'll check it out and update – SerhiiPoklonskyi Mar 23 '19 at 16:34

probably, such thing as reporting to user interface must be the easiest thing to do in any API but... this is life. anyways, here's what I have found for myself.

Idea in short: so, when blender script runs, Blender does not redraw screen any longer. So I start drawing text into a particular window with blf. Because Blender is not redrawn while the script runs, you actually don't see it. So I force redrawing. And then you can see the text. Don't know how robust that solution is but anyways.

This is the function which starts drawing:

def UI_report_start(message, space_type):

"""
draws specified message, in the specified space_type. space_type is a value in:

['Image Editor',
'Node Editor',
'UV Editor',
'3D View']

returns the draw handler and the space type
for later deletion
"""

# the drawer function
try:
blf
except:
import blf

def draw_message(self, context):
blf.position(0, 15, 30, 0)
blf.size(0, 20, 72)
blf.draw(0, message)

if space_type == 'Image Editor':
handler = bpy.types.SpaceImageEditor.draw_handler_add(draw_message, (None, None), 'WINDOW', 'POST_PIXEL')
return handler, space_type
elif space_type == 'Node Editor':
handler = bpy.types.SpaceNodeEditor.draw_handler_add(draw_message, (None, None), 'WINDOW', 'POST_PIXEL')
return handler, space_type
elif space_type == '3D View':
handler = bpy.types.SpaceView3D.draw_handler_add(draw_message, (None, None), 'WINDOW', 'POST_PIXEL')
return handler, space_type
elif space_type == 'UV Editor':
handler = bpy.types.SpaceUVEditor.draw_handler_add(draw_message, (None, None), 'WINDOW', 'POST_PIXEL')
return handler, space_type
else:
raise Exception('UI_report_start', 'Incorrect Window type specified')


this is the function that stops drawing:

def UI_report_stop(reporter, space_type):
"""
stops drawing the report
the drawing handler and the space type must be input
"""

if space_type == 'Image Editor':
bpy.types.SpaceImageEditor.draw_handler_remove(reporter, 'WINDOW')
elif space_type == 'Node Editor':
bpy.types.SpaceNodeEditor.draw_handler_remove(reporter, 'WINDOW')
elif space_type == '3D View':
bpy.types.SpaceView3D.draw_handler_remove(reporter, 'WINDOW')
elif space_type == 'UV Editor':
bpy.types.SpaceUVEditor.draw_handler_remove(reporter, 'WINDOW')
else:
raise Exception('UI_report_stop', 'Incorrect Window type specified')


this is a hypothetical function taking much time to complete and reporting is embedded into it:

def execute(self, context):
handler, space = UI_report_start("does it have to be THAT difficult?!?!#\$", '3D View') # <--- this starts drawing blf but you don't see it yet!
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) # <--- this is redrawing the screen and you see the message!
# from now on redrawing stops but the message is still 'frozen' in place and you can see it!
for i in range(0, len(bpy.data.images['heavy'].pixels)):
bpy.data.images['heavy'].pixels[i] = random()
UI_report_stop(handler, space) # <-- this removes the message!
return {'FINISHED'}


as you can see, it does not draw the progress bar, only a message but I can live with it.

You can also update the screen more frequently but redrawing and drawing blf takes resources, so do it only once in a while