Hello, I was wondering how you are actually meant to implement the new layout.progress() reference introduced to the API in 4.0? There aren’t any examples provided, and since it is stored in UILayout it isn’t self explanatory how you would use it in an operator. I’ve attempted a few things but UILayout isn’t seemingly directly exposed to operators so I’m unsure how to interact with the function.
where factor is the amount of progress that is filled in.
Like other layout functions you can use a custom property to drive it, so you could create a FloatProperty and just pass that in directly. IE)
layout.progress(factor = context.active_object.my_progress, type = 'BAR')
then anytime your custom property was updated, the value of the progress bar would change.
I’m going to assume that this progress bar isn’t multithreaded and would be blocked by processing that is happening on the main thread, so I’m not 100% sure what the use case is for it. for example, it would make sense to have a progress bar for an exporter or importer, but given that all of that data crunching happens on the main thread I would imagine this progress bar will stall out at 0% and then magically appear at 100% when the heavy lift is finished. Hope that’s not the case, but the rest of the UI works that way so I’m not very optimistic that this is any different.
Thanks for this, I’m curious, should the draw function just be called by default? Where in the process of calling the Operator does that happen? My question makes the assumption that our hypothetical implementation is a simple long process and we want to give progression updates.
Not entirely related but if we can’t get easy multithreaded ui updates for Blender I wonder how hard it could be to implement a Qt processEvents style function that processes all of the events up to that point? It would refresh the UI and go back to a frozen state until the event ends or processEvents is once again processed. That would be obviously a slower implementation compared to something multithreaded but genuinely useful considering we have nothing else for non-baking/rendering and sometimes I/O tools. Oh well.
Yeah, that’s what my assumption was too… Thanks @testure, I appreciate the help. This loading progress thing is nice, I wish it were better supported. One step closer!
FWIW here’s a minimal working example that displays a progress bar filling in the UI. I used a modal operator and a timer but it can be driven by any property. You’ll need Version 4.0 and bpy.types.UILayout.progress. You’re kind of obligated to use a modal operator since a regular operator’s execution will block updating the UI until it finishes. Note autosave is disabled while a modal operator runs.
I’m a novice whose sole experience is in doing “conventional” add-on operators, some of which loop through myriad objects and textures that can take quite long to process. I usually report their progress through print() to the console.
What would be the simplest way to refresh such a progress bar in an UI panel? Would it require converting the operator to Modal type, or are there easier ways to induce an UI update (for example, each 5% progress increment while inside a loop?
The only known techniques as far as I know are described in this Q&A over on BSE and I used the first one in my previous post.
TLDR : use bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)
Here’s the second technique using a non-modal operator. You’ll notice your script takes significantly longer if you update the UI a lot. I suggest doing it sparsingly. Also the cursor flickers a lot, at least on windows. Credits to @Chebhou.
I see. Thank you. I’ll explore both methods, as in my use case we are talking between 1 to 30/40 minutes of progression, where fairly spaced updates would be enough.
I snagged this function and call it whenever needed
def refresh_all_areas():
for wm in bpy.data.window_managers:
for w in wm.windows:
for area in w.screen.areas:
area.tag_redraw()
That works at least at the end of the process…but not during it
Another Edit: Solution (for me)
I just used the complete modal example of that stack overflow example and it works great. Both with the operator of that example and with the New Type Progress Bar!