2

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

Serhii
  • 293
  • 2
  • 13
  • 1
    Related https://blender.stackexchange.com/questions/45731/how-to-run-an-external-command-showing-its-progress-without-locking-blender-e https://blender.stackexchange.com/questions/3219/how-to-show-to-the-user-a-progression-in-a-script https://blender.stackexchange.com/questions/47138/how-to-run-a-python-script-without-locking-blender – batFINGER Mar 23 '19 at 04:40
  • @batFINGER thanks looks useful. I'll check it out and update – Serhii Mar 23 '19 at 16:34

1 Answers1

0

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

Serhii
  • 293
  • 2
  • 13