I'm writing an addon that needs to:
Do some pre-baking setup.
Bake multiple objects' lighting to the same image texture (already UV mapped to not overlap).
(Note: this step should not block the UI. I feel like this should be obvious, but freezing the UI for long bakes with no way to cancel is not acceptable UX.)
Revert/clean up the setup from step 1 only after baking is complete, because the setup is necessary for the bake results we need, but is not something the user should be left with.
Step 1 and step 2 are pretty straightforward to accomplish by just running the setup code and then calling
INVOKE_DEFAULT. But so far step 3 seems impossible, because there doesn't seem to be a way to determine when baking is finished when run in a non-blocking way.
Things I've tried
My first thought was that I could accomplish this the same way I have for rendering in the past, via the
bpy.app.handlers.render_cancel hooks as in this answer:
Unfortunately, similar hooks do not exist for baking, and the hooks for rendering do not work for baking.
The second thing I tried was to simply do the clean up immediately after starting the bake. When baking a single object this works fine, because the bake works from the state of the scene when it was called, and ignores subsequent concurrent changes.
Unfortunately, this doesn't work when baking multiple objects because the baking operator updates its version of the scene before baking each object. So the first object bakes correctly, but the rest of the objects use the version of the scene with the setup already torn down (and as mentioned earlier, the setup is necessary for the bake results we need).
The third thing I tried is from this answer: https://blender.stackexchange.com/a/253550/146003
This solution uses the dirty state of the image to which we're baking to determine when the bake has finished. Unfortunately, this solution has two problems:
- Unlike in that answer, my addon works from an already existing image. And if the image is already dirty when the bake starts (which is common), this obviously won't work.
- Even if the image starts non-dirty, we still run into a similar problem as attempt #2: after the first object finishes baking the image is immediately marked dirty and the setup is torn down, and subsequent objects will therefore bake with the setup already torn down (and again, the setup is necessary for the bake results we need).
As suggested by @XY below, I tried checking if
img.bindcode changes when baking is finished. Unfortunately, it doesn't change at all, so that won't work.
@XY also suggested checking if the actual pixel data changed (e.g.
img.pixels), but that won't work because there is no guarantee that any particular pixel--or indeed any pixel--actually changes. The user may, for example, re-bake "just to be sure", resulting in a bake with exactly the same pixels.
An ideal solution would present a general way to wait for any modal operator to finish/cancel, not just the baking operator. Because I suspect this is an issue that I (and others) will run into with other operators as well.
Short of that, a baking-operator-specific solution would work for my specific situation.