# assigning a new material for each Mesh using python

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?

• 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"] – rob Sep 26 '18 at 10:23

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.location = (-190,100)

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

# creating the link between the two nodes:

# 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
# 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

• Thanks Martin, this does exactly what i was asking for! great! – user62799 Sep 26 '18 at 13:47
• Would you mind explaining the steps- so i can learn from it :) ? – user62799 Sep 26 '18 at 13:48

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.location = (-190,100)

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

# criando o link entre os dois nós

# 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

• 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. – batFINGER Apr 3 at 19:10