1
$\begingroup$

is it possible to assign a new Material(principled shader) to each mesh (or a selection of meshes) in my scene using python? The script should use the individual mesh name to name the material, and delete the existing material if there was a material before. How can i approach this problem?

$\endgroup$
  • $\begingroup$ I opened a new Blender session and created a new principled Material called "Material.001" then I created a new principled Material called "Material.002" the following code allowed me to set the material I wanted to the cube and should give you a jumping off point. bpy.data.objects["Cube"].material_slots[0].material = bpy.data.materials["Material.002"] $\endgroup$ – rob Sep 26 '18 at 10:23
2
$\begingroup$

Run this with your objects selected:

import bpy

# I separated the creation of nodes to a function so it's easier 
# to edit later if needed
def create_nodes(mat): 
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    for every_node in nodes: # this removes all existing nodes
        nodes.remove(every_node)

    # creating Principled node and moving it:
    node = nodes.new('ShaderNodeBsdfPrincipled')
    node.location = (-190,100)

    # creating Output node and moving it:
    output_node = nodes.new('ShaderNodeOutputMaterial')
    output_node.location = (40,100)

    # creating the link between the two nodes:
    links = mat.node_tree.links
    link = links.new(node.outputs[0], output_node.inputs[0])

# this saves the currently active object so it can be restored later
active = bpy.context.object 

# let's loop through all selected objects
for every_object in bpy.context.selected_objects: 
    # I only want to work with objects capable of having a material
    if every_object.type in {'MESH','CURVE', 'SURFACE','META', 'FONT'}: 
        if every_object.name not in bpy.data.materials:
        # if there is no material named after the object yet let's make one
            mat = bpy.data.materials.new(every_object.name)
            # and let's create the nodes for it
            create_nodes(mat)
        else:
            # if the material already exists let's just use it
            mat = bpy.data.materials.get(every_object.name)
        if len(every_object.material_slots) == 0: # if there are no material slots
            # let's make the current object active and create a material slot
            bpy.context.scene.objects.active = every_object
            bpy.ops.object.material_slot_add() 
            # let's leave the active object as it was
            bpy.context.scene.objects.active = active

        # The only thing left now is to assign the material to 
        # all material slots. We probably do not want to loose the info
        # about how the object is divided into separate materials
        for every_slot in every_object.material_slots:
            every_slot.material = mat  
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks Martin, this does exactly what i was asking for! great! $\endgroup$ – user62799 Sep 26 '18 at 13:47
  • $\begingroup$ Would you mind explaining the steps- so i can learn from it :) ? $\endgroup$ – user62799 Sep 26 '18 at 13:48
  • $\begingroup$ I tried to add comments. If you have any questions, let me know. $\endgroup$ – Martynas Žiemys Sep 26 '18 at 14:07
0
$\begingroup$

Sorry for my English, I'm Brazilian and new to blender.

I've been looking for this script (first of all thank you very much Martynas Žiemys was very utiul for me) but it was out of date, so I'm putting it here with modifications to help someone who needs it like me, but the credit is all from the friend.

again, very grateful, helped me a lot ...

import bpy


# Separei a criação de nós em uma função para facilitar 

# para editar mais tarde, se necessário
def create_nodes(mat): 
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    for every_node in nodes: # isso remove todos os nós existentes
        nodes.remove(every_node)

    # criando nó Principled e movendo-o:
    node = nodes.new('ShaderNodeBsdfPrincipled')
    node.location = (-190,100)

    # criando nó de saída e movendo-o:
    output_node = nodes.new('ShaderNodeOutputMaterial')
    output_node.location = (40,100)

    # criando o link entre os dois nós
    links = mat.node_tree.links
    link = links.new(node.outputs[0], output_node.inputs[0])

# Isso salva o objeto ativo no momento para que possa ser restaurado mais tarde
active = bpy.context.object 

# vamos percorrer todos os objetos selecionados
for every_object in bpy.context.selected_objects: 
    # Eu só quero trabalhar com objetos capazes de ter um material
    if every_object.type in {'MESH','CURVE', 'SURFACE','META', 'FONT'}: 
        if every_object.name not in bpy.data.materials:
        # se ainda não houver material com o nome do objeto, vamos fazer um 
            mat = bpy.data.materials.new(every_object.name)
            # e vamos criar os nós para ele
            create_nodes(mat)
        else:
            # se o material já existir, vamos usá-lo
            mat = bpy.data.materials.get(every_object.name)
        if len(every_object.material_slots) == 0: # se não houver slots de material
            # vamos ativar o objeto atual e criar um slot de material
            bpy.context.view_layer.objects.active = every_object
            bpy.ops.object.material_slot_add() 
            # vamos deixar o objeto ativo como estava
            bpy.context.view_layer.objects.active = active

        # A única coisa que resta agora é atribuir o material a
        # todos os slots de material. Provavelmente não queremos perder a informação
        # sobre como o objeto é dividido em materiais separados
        for every_slot in every_object.material_slots:
            every_slot.material = mat 

Note: I didn't comment on his answer because I'm new to the community and I don't have enough reputation :P

| improve this answer | |
$\endgroup$
  • $\begingroup$ Apart from language of comments, what is the difference here? Btw would remove every instance of every_ eg for slot in ob.material_slots: IMO reads a lot better since every_slot is not "every slot" it is one item. $\endgroup$ – batFINGER Apr 3 at 19:10

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.