Get image filepath and variables from a shader node

Hi!

I am looking for a method to read various variables from a shader node from within my python script.

In order to get for instance a texture map filepath from the BSDF I use something like:

                if (Material):
                    bsdf_node = Material.node_tree.nodes.get('Principled BSDF')
                    if (bsdf_node):
                        try:
                            link = node.links[0]
                            link_node = link.from_node
                            texture = link_node.image.name
                        except:
                            print("[%s] no diffuse texture set."%(Material.name),True,False)

This works fine, and I extended the program for various other inputs of the BSDF shader. My problem is that I try to extract the same information from a connected normal map. In other words I would like to:

  1. find the connected ‘Normal Map’ node
  2. save the normal map strength to a variable
  3. find the connected ‘Image’ node, which will hold the normal map
  4. Extract the filename from the image node.

Of course, I could use Material.node_tree.nodes.get(‘Normal Map’), however I would like to make sure that I am dealing with a node that is connected to my Principled BSDF node.

I can’t really figure out how to navigate from node to node and hope you could give me pointers.

Cheers,
Vitus

Access the link through the node’s sockets.
ie

node_tree.nodes['Principled BSDF'].inputs['Normal'].links

Thanks for the reply!
I think I begin to understand the correlations. I got this now:

# 1. this gets me the normal input of the BSDF node:
n_normal = bsdf_node.inputs.get('Normal')
# 2. this gets me the color input of the Normal Map node:
n_normal_map = n_normal.links[0].from_node.inputs.get('Color')
# 3. this is the link between the input node of the normal map and the image texture node:
link = n_normal_map.links[0]
# 4. this gets me the filename of the texture node:
texture = link.from_node.image.name

Additionally, in my addon, I wrap every crucial part into try-except blocks, to catch missing nodes - similar to my first example above.
Is this good practice, or am I missing something?

And then there’s part 2: how do I get the “strength” float value from the normal map?

# 4. this gets me the filename of the texture node:
texture = link.from_node.image.name

No, that’s getting you the name of the image datablock being referenced by the image node. You shouldn’t assume it’ll always match the filename.

You can easily check the attributes of a particular node by:

  • Hovering over the relevant UI element with python tooltips enabled
  • Using autocomplete in the python terminal
  • Using dir on the datablock

Whaaaaaaaaaaaaaaaaat? That is amazing! I had no idea this was a thing!. Thank you!

OK, I’ll keep that in mind.