I am using the Blender Internal render engine. I have an material slot with no material assigned to it. How can I assign a material to a slot using python? This should work in edit mode as well. Basically I would like to assign materials to specific faces.

enter image description here


6 Answers 6


This code creates 10 materials and appends it to the active object (should be a mesh). The diffuse color of every material is random. The .material_index poperty is set to the new materials by index (even if the object has materials assigned before the operation).

import bpy
from random import random

ob = bpy.context.object
me = ob.data

mat_offset = len(me.materials)
mat_count = 10

mats = []
for i in range(mat_count):
    mat = bpy.data.materials.new("Mat_%i" % i)
    mat.diffuse_color = random(), random(), random()

# Can't assign materials in editmode

i = 0
for poly in me.polygons:
    if poly.select:
        poly.material_index = i % mat_count + mat_offset
        i += 1

If you want to use UV mapped textures, you'll also have to deal with me.uv_layersand me.uv_textures. It's not enough to assign materials to faces, you also need to set the texture image for every face.

  • $\begingroup$ What if I want to use the face selection from the select random tool? $\endgroup$
    – Vader
    Commented Apr 13, 2014 at 14:03
  • $\begingroup$ Updated my example to only assign new materials to selected polygons. Note that if there's no material before the operation, unselected polygons will use the first material (.material_index has a default of 0, which is automatically the first material). $\endgroup$
    – CodeManX
    Commented Apr 13, 2014 at 21:27
  • $\begingroup$ @CoDEmanX I want to go over all of my materials and select (or get indices of) faces to which that specific material has been applied to. I haven't been able to find a good solution for doing that as of now. I would appreciate if you can take a look at my question here and see if you can offer a solution? $\endgroup$
    – Amir
    Commented Mar 17, 2018 at 4:59

That would be -

import bpy

D = bpy.data

if len(D.objects['Cube'].material_slots) < 1:
    # if there is no slot then we append to create the slot and assign
    # we always want the material in slot[0]
    D.objects['Cube'].material_slots[0].material = D.materials['Material']
  • $\begingroup$ This doesn't work when I want to assign random faces a material in edit mode. $\endgroup$
    – Vader
    Commented Apr 11, 2014 at 13:02
  • $\begingroup$ @Vader Perhaps the source of this addon has some clues. $\endgroup$
    – gandalf3
    Commented Apr 12, 2014 at 21:19
  • $\begingroup$ @gandalf3 I already know how to do this on object level. I need to do it in edit mode though. This tut only does objects. $\endgroup$
    – Vader
    Commented Apr 12, 2014 at 21:26
  • $\begingroup$ @Vader Your question is assigning a material to a slot not assigning a material to faces. $\endgroup$
    – sambler
    Commented Apr 13, 2014 at 8:39
  • $\begingroup$ @sambler updated question. $\endgroup$
    – Vader
    Commented Apr 13, 2014 at 11:20

Abandon the approach of edit mode/non-edit mode and just focus on the datablock. Materials for faces are specified via material_index inside the datablock of a mesh type object.

Add a Suzanne mesh to the scene and try this code:

import bpy, random

ob = bpy.data.objects.get("Suzanne")
if ob != None:
    # Create a materials.
    mat_one = bpy.data.materials.get("mat_one")
    if mat_one == None:
        mat_one = bpy.data.materials.new("mat_one")
    mat_one.diffuse_color = (random.random(),random.random(),random.random())

    mat_two = bpy.data.materials.get("mat_two")
    if mat_two == None:
        mat_two = bpy.data.materials.new("mat_two")
    mat_two.diffuse_color = (random.random(),random.random(),random.random())

     # Add materials to slots.       

    # Determine random count and poly count.  
    rnd_face_count = 12
    l = len(ob.data.polygons)

    # Note: By default all faces have a material index of 0.
    for i in range(rnd_face_count):
        # Generate a random face index.
        rnd_face_index = random.randint(0,(l-1))
        ob.data.polygons[rnd_face_index].material_index = 1

This is not the cleanest code but it shows one way to accomplish the task mentioned. If you run this code twice, however, you will discover that you are building up a list of new materials on the Suzanne object.


This sequence would assign the currently selected material to the first slot:

bpy.context.object.active_material_index = 0

The material-utils addon makes heavy use of the API methods for materials, there you should find further details. SVN space_view3d_materials_utils.py

  • $\begingroup$ I need to specify the material that is assigned though $\endgroup$
    – Vader
    Commented Apr 10, 2014 at 21:29

I used sambler's answer for the .append() idea,
but I referenced context, instead of name:
(R, G, B are standard 0-255 values)

obj = bpy.context.object
colorstring  = 'r' + str(R) + ' g' + str(G) + ' b' + str(B)

if colorstring in bpy.data.materials.keys():

  material  = bpy.data.materials.new(colorstring)
  material.diffuse_color  = (R / 255, G / 255, B / 255)

Just to put in my two cents:

I have created my object, and I have a list that contains the index to what material slot each face should be assigned to. Running this code:

 i = 0
    for poly in bpy.context.object.data.polygons:
        poly.material_index = MyTextures[i]
        i += 1

did the trick for what I needed it to do.

Now if I can only find the simple solution for assigning the UV's I will be almost done with my project.


You must log in to answer this question.

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