0
$\begingroup$

I have imported multiple mesh objects into my scene and all imported mesh objects have material names inherited from the mesh name + number prefix, rather than the texture name.

enter image description here

I have found an excellent script here that almost works to what I want. But the script works for single selected mesh only. Batch renaming materials to texture filename, not texture name

My problem is, if I use it on several objects that are using the same mapped texture, the material will be renamed to the texture name but, if this new material name already exists, Blender adds a number suffix to the same material as the previous mesh.

I guess this is because Blender handles it as a new material and it can’t have the same name unless you manually select the original material from the dropdown in Material Properties.

enter image description here

Is there a way to rename the materials for all mesh objects to the name of linked textures and, in case such material already exists, can it be reassigned instead of renamed with same name + suffix, please (without texture file type extension)?

Thank you for any help in advance. Regards, Miro

$\endgroup$
2
  • $\begingroup$ just to clarify: if you have 2 (or more) materials (e.g. "cube.6" and "sphere.4") that use the same image texture ("wood.png") then the first material ("cube.6") will be renamed to "wood", and it will be assigned to both objects (cube->wood and sphere->wood). The other material "sphere.4" will become unused and will be discarded, right? Keep in mind that the materials just share the same image texture ("wood.png") but they can have different nodes and different settings for the Principled BSDF (e.g. "cube.6" can have roughness 0.8 and "sphere.4" can have rough. 0.9 but both use "wood.png"). $\endgroup$
    – Blunder
    Commented Oct 23, 2022 at 13:23
  • $\begingroup$ Hi, that is correct. If same texture is used, same material should be used. There are no extra settings at this point. All materials have everything same. I need to rename all materials to the texture name and if the material with the same texture already exists, I need to apply/change the same material in that existing slot. $\endgroup$
    – Miro
    Commented Oct 23, 2022 at 17:44

1 Answer 1

1
$\begingroup$

The following script loops through all material slots of all mesh objects. It looks for a Image Texture node that is connected to a Principled BSDF node.
If it is found, the material will be renamed to the base name of the image file without file extension.
If another, already processed mesh object has a material with this name then that material will be assigned to current object.

import bpy
from os import path 

material_map = {}

def image_texture_name(material):
    if not material.use_nodes:
        return None
    try:
        # Get the nodes in the node tree
        nodes = material.node_tree.nodes
        # Get a principled node
        principled = next(n for n in nodes if n.type == 'BSDF_PRINCIPLED')
        # Get the slot for 'base color'
        base_color = principled.inputs['Base Color'] #Or principled.inputs[0]
        # Get the link
        link = base_color.links[0]
        link_node = link.from_node
        # new name of the material (the image file's name w/o file extension)
        return path.splitext(path.basename(link_node.image.filepath))[0]
    except BaseException as err:
        print(f'Skipping material "{material.name}", no Image Texture connected to the Principled BSDF found.')
        return None

for obj in bpy.data.objects:
    if obj.type != 'MESH':
        continue
    i = 0
    for matslot in obj.material_slots:
        new_name = image_texture_name(matslot.material)
        if new_name is None:
            continue
        recycled_mat = material_map.get(new_name)
        if recycled_mat is None:
            # rename the material
            matslot.material.name = new_name
            material_map[new_name] = matslot.material
        else:
            # use the recycled material   
            obj.material_slots[i].material = recycled_mat
        i += 1
$\endgroup$
1
  • $\begingroup$ Hi Blunder, It works perfectly!! Thank you very much! I'm so happy :) $\endgroup$
    – Miro
    Commented Oct 27, 2022 at 20:34

You must log in to answer this question.

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