# Baking a series of textures with INVOKE_DEFAULT

I'm trying to build a simple bake tool that will allow me to bake a set of objects. Everything works if I EXEC_DEFAULT the bake operator, but this doesn't give me a progress bar and completely freezes the UI.

Switching to INVOKE_DEFAULT causes a problem with async- the loop executes but only the first bake operation is performed.

The relevant code is here:

class BakeryOperation(bpy.types.Operator):
bl_idname = "bakery.bake"
bl_label = "Bake textures"

def invoke(self, context, event):
scn = context.scene
materials = set()
for o in scn.bake_objects:
materials = materials.union(set(map(lambda x: (o.name, x.name), bpy.data.objects[o.name].data.materials)))

for (name, material) in materials:
bpy.data.materials[material].use_nodes = True
node_tree = bpy.data.materials[material].node_tree
found = False

img_name = name+"_bake"
for n in [n for n in node_tree.nodes if n.type == 'TEX_IMAGE']:
found = False

if n.image != None and n.image.name == img_name:
n.select = True
node_tree.nodes.active = n
found = True
break
if not found:
node = node_tree.nodes.new("ShaderNodeTexImage")
node.select = True
node_tree.nodes.active = node
if img_name in bpy.data.images:
node.image = bpy.data.images[img_name]
else:
node.image = bpy.data.images.new(name + "_bake", 512, 512)

img = bpy.data.images[img_name]

bpy.ops.object.select_all("EXEC_DEFAULT", action="DESELECT")
bpy.ops.object.select_pattern(pattern = name)
bpy.context.scene.objects.active = bpy.data.objects[name]
bpy.ops.uv.lightmap_pack("EXEC_SCREEN")
print("Baking " + name)
bpy.ops.object.bake("INVOKE_DEFAULT") # or EXEC_DEFAULT
return {'FINISHED'}


I've seen posts about using macros to order sequences of operators, but it doesn't seem possible to configure specific settings (in this case, which object to bake). This is my first foray into Blender scripting, so I'm surely missing something.

How would I achieve this, and are there any best practices I should be be aware of?

UPDATE

After a bit of playing around, I've solved this particular case. The solution is as follows:

class BakeryOperation(bpy.types.Operator):
bl_idname = "bakery.bake"
bl_label = "Bake Textures"

def invoke(self, context, event):
scn = context.scene
materials = set()
bake_pass = scn.bake_passes[scn.bake_passes_index]
scn.cycles.samples = bake_pass.samples
for o in scn.bake_objects:
materials = materials.union(set(map(lambda x: (o.name, x.name), bpy.data.objects[o.name].data.materials)))

bpy.ops.object.select_all("EXEC_SCREEN", action="DESELECT")
for (name, material) in materials:
bpy.data.materials[material].use_nodes = True
node_tree = bpy.data.materials[material].node_tree
found = False

img_name = name+"_bake"
for n in [n for n in node_tree.nodes if n.type == 'TEX_IMAGE']:
found = False

if n.image != None and n.image.name == img_name:
n.select = True
node_tree.nodes.active = n
found = True
break
if not found:
node = node_tree.nodes.new("ShaderNodeTexImage")
node.select = True
node_tree.nodes.active = node
if img_name in bpy.data.images:
node.image = bpy.data.images[img_name]
else:
node.image = bpy.data.images.new(name + "_bake", 512, 512)

img = bpy.data.images[img_name]

bpy.ops.uv.lightmap_pack("EXEC_SCREEN", PREF_CONTEXT="ALL_FACES")
bpy.ops.object.select_pattern("EXEC_SCREEN", pattern = name)
bpy.ops.object.bake("INVOKE_SCREEN")
return {'FINISHED'}


Simply selecting all objects and then invoking the bake operation fixes the problem.

• Hey, can you take a look at this – Sum-Al Jul 18 '16 at 10:24
• Well this means you can't use the same material in multiple objects you are baking and thus you can't even bake multiple instances of the same object, correct? Each material has its img node set to that of the last object that uses it. Baaaaaaad. bake() should give a handle that we could use to progress with baking scripts but I've been unable to find any documentation or experimenting with this. Ideally Blender could sort their baking stuff out (assigning images to objects) so everybody and their cousins wouldn't have to make baking scripts in the first place. – kheetor Oct 10 '16 at 19:40
• Yep. you are absolutely correct. When cycles baking was added to Blender, they improved the quality no end. Unfortunately the user interface (for artists and programmers) to both systems leaves a lot to be desired. You can work around these problems by creating proxy materials for each clone and swap them back at the end, but it's a complete pain. – mseddon Oct 11 '16 at 10:02

## 1 Answer

In this case, (doh), simply selecting the objects during the loop and then invoking the bake operation does what I need.