Assign face material in loop


I have a small script I’ve written. It creates a grid of faces, all part of a single object. What I want to do is assign a material to certain faces. I’m more interested in the viewport color, and I don’t care if it’s cycles or BI. Basically where I print the color, I need some code that looks somthing like: face.assignmat(’#ff0000’)


import bpy

def deleteOldObject():
    scene = bpy.context.scene
    for ob in scene.objects:
        if ob.type == 'MESH' and (ob.name.startswith("Cube") or ob.name.startswith("Plane")):
            ob.select = True
        else: 
            ob.select = False

    bpy.ops.object.delete()    


deleteOldObject()

xmax = 3
ymax = 7
cubescale = .2
scale = .2

verts=[]
faces=[]
facecount = 0
facecolor =[]
for x in range(0,xmax):
    for y in range(0,ymax):
        verts.append((scale + x , scale+y, 0))  
        verts.append((scale+x, -scale+y, 0))  
        verts.append((-scale+x, -scale+y, 0))  
        verts.append((-scale+x, scale+y, 0)) 
        facecount = facecount + 1
        if (x==2 and y==3):
            facecolor.append('red')
        else:
            facecolor.append('blue') 
            
for findex in range(0,facecount):
    f = ( ((findex*4)) , ((findex*4)+1) , ((findex*4)+2) , ((findex*4)+3)  )
    print(facecolor[findex])  #I WANT TO ACTUALLY CHANGE THE FACE COLOR/MATERIAL
    faces.append(f)
        
  
mesh_data = bpy.data.meshes.new("cube_mesh_data")  
mesh_data.from_pydata(verts, [], faces)  
mesh_data.update() # (calc_edges=True) not needed here  
  
cube_object = bpy.data.objects.new("Cube_Object", mesh_data)  
  
scene = bpy.context.scene    
scene.objects.link(cube_object)    
cube_object.select = True    


If you already have the materials in the objects material slots, all you have to do is assign the faces material_index to the material you want.


obj.data.polygons[0].material_index = 2 #with obj as your object, change face[0] material to third material in object.

Ok, thank you. But the problem is the object is created each time the script the script runs. It has no materials.

Where will you have the materials then, sitting in memory?

I want to either create the material on the fly and then assign them to the newly created faces, or possibly borrow them from a separate object which I can keep in the scene created manually. Are you saying you can’t create material slots programmatically?

Yes, you can. That’s why I was asking. So which one do you want to do?

It doesn’t really matter. I guess I’d like to know how to create it completely with code, so something like
mat = bpy.foo.bar.mat("#ff00000,“myredmat”,"")
f.assignmat(mat)
faces.append(f)

As I mentioned before, I am much more interested in changing the viewport color.


redMat = bpy.data.materials.new('redMat') #creates new material
redmat.diffuse_color = 255,0,0 changes color to red
obj.data.materials.append(redMat) # adds material to object

Ok, thank you very much @cmomoney. It works now. It looks a little ugly, because at the time the vertices and faces are being defined, there exists no object, so I had to create the object, add the materials, and then loop through the faces again and assign them. I appreciate your help. Here is the working code.


import bpy

def deleteOldObject():
    scene = bpy.context.scene
    for ob in scene.objects:
        if ob.type == 'MESH' and (ob.name.startswith("Cube") or ob.name.startswith("Plane")):
            ob.select = True
        else: 
            ob.select = False

    bpy.ops.object.delete()    


deleteOldObject()

xmax = 3
ymax = 7
scale = .2

verts=[]
faces=[]
facecount = 0
facecolor =[]
for x in range(0,xmax):
    for y in range(0,ymax):
        verts.append((scale + x , scale+y, 0))  
        verts.append((scale+x, -scale+y, 0))  
        verts.append((-scale+x, -scale+y, 0))  
        verts.append((-scale+x, scale+y, 0)) 
        if (x==2 and y==3):
            facecolor.append(1)  #0 IS THE INDEX OF RED
        else:
            facecolor.append(0)  #1 IS THE INDEX OF BLUE
        facecount = facecount + 1
            
for findex in range(0,facecount):
    f = ( ((findex*4)) , ((findex*4)+1) , ((findex*4)+2) , ((findex*4)+3)  )
    print(facecolor[findex])  #I WANT TO ACTUALLY CHANGE THE FACE COLOR/MATERIAL
    faces.append(f)
         
mesh_data = bpy.data.meshes.new("cube_mesh_data")  
mesh_data.from_pydata(verts, [], faces)  
mesh_data.update() # (calc_edges=True) not needed here  
  
cube_object = bpy.data.objects.new("Cube_Object", mesh_data)  
  
scene = bpy.context.scene    
scene.objects.link(cube_object)    
cube_object.select = True   

redMat = bpy.data.materials.new('redMat') #creates new material
redMat.diffuse_color = (255,0,0) #changes color to red
blueMat = bpy.data.materials.new('blueMat') #creates new material
blueMat.diffuse_color = (0,0,255) 
cube_object.data.materials.append(blueMat) 
cube_object.data.materials.append(redMat) 

for f in cube_object.data.polygons:
    f.material_index = facecolor[f.index]