0
$\begingroup$

I got this error once yesterday but not since I finalized the function. Now I'm making more of the same buttons for similar but different functions, and now the first one is throwing this:

experiment.blend/bake_script", line 71, in execute
IndexError: tuple index out of range

There isn't any tuple in this code, as far as I can tell.

for mat in obj.data.materials:

                mat.use_nodes = True #Here it is assumed that the materials have been created with nodes, otherwise it would not be possible to assign a node for the Bake, so this step is a bit useless
                bake_one.is_active_output = True
                mat.node_tree.links.new(skin_comp.outputs[0], bake_one.inputs[0])
                linkToDelete = baked_BSDF.inputs[0].links[0]
                mat.node_tree.links.remove(linkToDelete)
                bump_main.mute = True
                texture_node = diffuse
                texture_node.select = True
                nodes.active = texture_node
                texture_node.image = imgbake #Assign the image to the node

The line that's throwing the error is linkToDelete = baked_BSDF.inputs[0].links[0]

There are two mysteries here:

1: Why is it throwing this error today, when it wasn't yesterday?

2: Why does it think it's getting a tuple in this?

Edit: enter image description here It's this connection in particular, but I'm having the same issue with the new button I'm making too.

It occurred to me that maybe the nodes are listing connections as tuples, but then 0,0 should be within that list...

$\endgroup$
6
  • $\begingroup$ I think both questions are legitimate but neither will help you solve your problem :) Without having access to the file or showing a screenshot of the node editor, it's only a wild guess, but at first glance I'd say either your baked_BSDF doesn't have any input which seems unlikely, or its first input isn't linked to any other node, which is possible. Are you sure you're in a scenario where this node has a link to another node ? $\endgroup$
    – Gorgious
    Commented Oct 26, 2022 at 19:19
  • $\begingroup$ I've added a screenshot, and some further musings. $\endgroup$ Commented Oct 26, 2022 at 19:27
  • $\begingroup$ I just tried something that worked, but I don't know why it worked. I switched from using my defs, to calling the node directly, and it worked. Then I switched back to using the defs, and now it works... Maybe I should call it in the in-module defs instead of in the main script defs? $\endgroup$ Commented Oct 26, 2022 at 19:36
  • $\begingroup$ It depends on what you mean by "defs" :) but yeah it's better not to rely too much on variables that are way outside the scope of your functions. Nodes are easily fetched from the node tree by name if need be. $\endgroup$
    – Gorgious
    Commented Oct 26, 2022 at 19:59
  • 1
    $\begingroup$ you can test if a socket is linked to at least one other socket with if node.inputs[0].links: for example. It will evaluate to False if links is empty (ie length 0, no link) $\endgroup$
    – Gorgious
    Commented Oct 26, 2022 at 20:12

1 Answer 1

1
$\begingroup$

Many thanks to Gorgious for helping me formulate an elegant solution to this problem.

I'm still not entirely sure why the node connections are listed in a way that requires this, but the solution turns out to be fairly simple. Rather than trying to define all possible connections in a block for the entire script to use, you define them ad-hoc for each function.

Also, to avoid the problem of the script failing if the connection happens to not exist, you can use an if statement to either confirm or skip the step.

Here's the full code of one module:

class WM_OT_Bake_Diffuse(Operator):
    bl_label = "Bake Diffuse"
    bl_idname = "wm.bake_diffuse"
    bl_options = {'REGISTER', 'INTERNAL'}
    
    
    @classmethod
    def poll(cls, context):
        return True
    
    def execute(self, context):
            size = bpy.data.scenes["Scene"].bake_tool.bake_int, bpy.data.scenes["Scene"].bake_tool.bake_int
            obj = bpy.context.active_object
            diffuse = bpy.data.materials["Skin"].node_tree.nodes["DiffuseBake"]
            imgbake = bpy.data.images.new("DiffuseBake", width=size[0], height=size[1])
            BSDF = bpy.data.materials["Skin"].node_tree.nodes["Baked_BSDF"]
                    
                        
        # set bake type and parameters
            for mat in obj.data.materials:

                mat.use_nodes = True #Here it is assumed that the materials have been created with nodes, otherwise it would not be possible to assign a node for the Bake, so this step is a bit useless
                bake_one.is_active_output = True
                mat.node_tree.links.new(skin_comp.outputs[0], bake_one.inputs[0])
                if BSDF.inputs[0].links: # Checks if the connection in question exists, skips the step if it doesn't.
                    linkToDelete = BSDF.inputs[0].links[0]
                    mat.node_tree.links.remove(linkToDelete)
# the rest of this script sets up the bake, bakes the appropriate image, then reconnects everything.
                bump_main.mute = True
                texture_node = diffuse
                texture_node.select = True
                nodes.active = texture_node
                texture_node.image = imgbake #Assign the image to the node
                
            bpy.context.view_layer.objects.active = obj
            bpy.ops.object.bake(type='DIFFUSE', save_mode='EXTERNAL')
            imgbake.filepath_raw = "//bakes/DiffuseBake.png"
            imgbake.file_format = 'PNG'
            imgbake.save()

        # find node and assign the texture to it
            img = bpy.data.images.load("//bakes/DiffuseBake.png", check_existing=True)
            bpy.data.materials["Skin"].node_tree.nodes["DiffuseBake"].image = img
            bpy.data.images["DiffuseBake"].colorspace_settings.name = 'sRGB'
            mat.node_tree.links.new(diffuse.outputs[0], baked_BSDF.inputs[0])
            bump_main.mute = False
            return {'FINISHED'}
$\endgroup$
2
  • $\begingroup$ Also note AFAIK since pretty much all sockets of shader nodes only accept 1 link, linking a socket to another socket will automatically unlink its previous link if it had any. So those 3 lines with the if might be overkill anyways $\endgroup$
    – Gorgious
    Commented Oct 27, 2022 at 6:00
  • $\begingroup$ Actually I need the output socket of the image node empty for this to work. $\endgroup$ Commented Oct 27, 2022 at 14:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .