1
$\begingroup$

When I import an fbx, it has image textures that should be linked from their Alpha socket to Principled BSDF's Alpha socket, but right now link goes from texture's Color to Principled's Alpha, like this:enter image description here

I tried to write\find a script that would loop through every material and do this:

  1. Find Image Texture node and get the name of a texture used, since I don't know their names
  2. Replace Color -> Alpha link with Alpha -> Alpha link

Every thread I've found about Image texture nodes creates a new node for this and then adds an image. Tried doing it like this, creates an eternal loop:

import bpy 
nodes = bpy.context.active_object.active_material.node_tree.nodes
links = bpy.context.active_object.active_material.node_tree.links
principled = nodes.get('Principled BSDF')

    for obj in bpy.context.scene.objects: 
        for s in obj.material_slots: 
         if s.material and s.material.use_nodes:
          for n in s.material.node_tree.nodes: 
           if n.type == 'TEX_IMAGE': 
                image_node = nodes.new('ShaderNodeTexImage')
                tex = bpy.data.images.get(n.image.name)
                image_node.image = tex
                links.new(image_node.outputs[1], principled.inputs[18])
| improve this question | | | | |
$\endgroup$
  • $\begingroup$ 1 character indent is a travesty :D... Same as comment here blender.stackexchange.com/questions/133779/… loop over the materials collection. 1 material could be used twice by a million scene objects . ie Need only make changes on a per material basis. $\endgroup$ – batFINGER Dec 8 '19 at 14:32
1
$\begingroup$

Loop the materials collection

enter image description here

Loop over the material collection. Need only do this once per material, rather than for each object that uses the material.

Search for links from tex node to bsdf and from color to alpha socket, if found unlink old, make a new link, and print the image name.

import bpy

for m in bpy.data.materials:
    if not m.use_nodes:
        continue
    print(material.name)
    node_tree = m.node_tree
    links = node_tree.links
    # list comprehension to find those links
    tex_ps_links = [l for l in links 
            if l.from_node.type == 'TEX_IMAGE' 
            and l.from_socket.name == "Color"
            and l.to_node.type == 'BSDF_PRINCIPLED'
            and l.to_socket.name == "Alpha"]

    for l in tex_ps_links:
        # print tex node image
        texnode = l.from_node
        if texnode.image:
            print(texnode.image.name)
        else:
            print("No Image")

        from_socket = l.from_node.outputs["Alpha"]
        to_socket = l.to_socket
        # make the new
        links.remove(l)
        links.new(from_socket, to_socket)
        # remove the old

Blender scripting connect nodes

Also note this one, where it maps socket index to name. When playing around with languages noticed the names can be in a different language, eg Color in Spanish will fail the node.outputs["Color"] name lookup.

https://blender.stackexchange.com/a/160069/15543

eg instead of name test used above, if we know a socket number eg "Sheen Tint" is 11 could look for l.to_socket == l.to_node.inputs[11] instead of l.to_socket.name == "Sheen Tint"

| improve this answer | | | | |
$\endgroup$
  • 1
    $\begingroup$ I LOVE YOU! This is exactly what I needed, thanks! $\endgroup$ – Limarest Dec 8 '19 at 15:36
  • $\begingroup$ Happy to help...nodes are IMO a little tricky to code at first. but you'll get the hang of it. Well put together question. Upvoted. $\endgroup$ – batFINGER Dec 8 '19 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.