Although the question is already old, can help more developers.
You can create a modal operator and check the state of the 'is_dirty' property of the image.
import bpy
class ModalTimerOperator(bpy.types.Operator):
bl_idname = "wm.modal_timer_operator"
bl_label = "Modal Timer Operator"
_timer = None
_img = None
def modal(self, context, event):
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.cancel(context)
return {'CANCELLED'}
if event.type == 'TIMER':
if self._img.is_dirty: # <--- Wait until the image is marked as dirty
self.finish(context)
return {'FINISHED'}
return {'PASS_THROUGH'}
def execute(self, context: bpy.context):
if context.scene.render.engine != 'CYCLES':
context.scene.render.engine = 'CYCLES'
if not context.active_object.select_get() or not context.active_object.type == 'MESH':
self.report({'WARNING'}, "No valid selected objects")
return {'FINISHED'}
obj = context.active_object
mats = obj.data.materials
mats_len = len(mats)
if mats_len == 0 or not mats[0]:
mat_new = bpy.data.materials.new('BakeMaterial')
if mats_len == 0:
mats.append(mat_new)
else:
mats[0] = mat_new
pass
mat = mats[0]
mat.use_nodes = True
nodes = mat.node_tree.nodes
tex_node = nodes.new('ShaderNodeTexImage')
tex_node.name = 'BakeNode'
tex_node.select = True
nodes.active = tex_node
self._img = bpy.data.images.new('BakeResult', 1024, 1024)
tex_node.image = self._img
self.report({'INFO'}, "Execute")
result = bpy.ops.object.bake('INVOKE_DEFAULT', type='DIFFUSE')
if result != {'RUNNING_MODAL'}: # <--- Important to check the result
self.report({'WARNING'}, "Failed to start baking")
return {'FINISHED'}
wm = context.window_manager
self._timer = wm.event_timer_add(0.5, window=context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def cancel(self, context):
self.report({'INFO'}, "Baking map cancelled")
def finish(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
self.report({'INFO'}, "Baking map completed")
#save_image() # <--- Call the function after baking
def register():
bpy.utils.register_class(ModalTimerOperator)
def unregister():
bpy.utils.unregister_class(ModalTimerOperator)
if __name__ == "__main__":
register()
bpy.ops.wm.modal_timer_operator()