0

Did you know, you can assign different materials (eg:colors) to different faces in a polygon?

Before Blender 2.8 you could get a list of the materials used for each Face with:

for aFace in anObject.data.polygons : print ("material: ", face.material_index)

However, in Blender 2.8, I guess 'material_index' is no longer a property of polygons. I'll show you:

>>> anObject.data.polygons.material_index
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
AttributeError: 'bpy_prop_collection' object has no attribute 'material_index'

How can I walk through polygons or faces and get the material_index for each?

Trying to write a file exporter for faces and their colors.

Ray Mairlot
  • 29,192
  • 11
  • 103
  • 125
Quinn Carver
  • 103
  • 4
  • It hasn't changed, use anObject.data.polygons[index].material_index where index is the face index. It is a property of a polygon, not of the polygons collection. – batFINGER Jun 20 '20 at 14:35
  • Respectfully, IT HAS CHANGED. The example above does work before 2.8, it DOES NOT work now. Hence, there has been a change. Thank you for your feedback, I see that given your example above to affect the same result I would enter: for aPolygon in anObject.data.polygons : print ("material: ", aPolygon.material_index). So polygons instead of face. Furthermore you have marked my question as a duplicate. Also false, the reference is to a question asked 2 years ago - PRE BLENDER 2.8. Therefore it cannot be a duplicate. Please be more careful. Thank you. – Quinn Carver Jun 23 '20 at 01:47
  • Please review your question carefully. This is wrong "Did you know, you can assign different materials (eg:colors) to different faces in a polygon?" a polygon is aka face. Circa 2.6x the Mesh.faces collection was renamed to Mesh.polygons with the introduction of ngon faces (over 4 verts). The first piece of code uses aFace as iter variable, instead you are trying to print one named face. The second is as pointed out in first comment. material_index has never been a property of the polygons collection. There is no need for a new 2.8 answer if there is no change. – batFINGER Jun 23 '20 at 04:19

1 Answers1

2

I used faces, I'm pretty sure that's what you were going after . It requires you are in edit mode to work and a mesh is currently selected.

import bpy
import bmesh

ob = bpy.context.object assert ob is not None and ob.type == 'MESH', "active object invalid, select a mesh" materials = ob.data.materials.items() mesh = bmesh.from_edit_mesh(ob.data) indexes = [[face.index, face.material_index] for face in mesh.faces] material_indexes = [] for index in indexes: tuple = (index[0], materials[index[1]]) print(tuple) material_indexes.append(tuple)

Result:

(0, ('mat2', bpy.data.materials['mat2']))
(1, ('Material', bpy.data.materials['Material']))
(2, ('Material', bpy.data.materials['Material']))
(3, ('Material', bpy.data.materials['Material']))
(4, ('Material', bpy.data.materials['Material']))
(5, ('Material', bpy.data.materials['Material']))

if you need just the material_index, you can take it back a step: print(indexes)

4nof
  • 490
  • 3
  • 8
  • Yes, exactly thanks. So, does that mean that in 2.8 "face" is synonymous with "polygon"? – Quinn Carver Jun 23 '20 at 01:50
  • 2
    mesh.faces, yes , but also your original call can be done with: for index in range(0, len(bpy.context.object.data.polygons.items())): bpy.context.object.data.polygons.items()[index][1].material_index = 2 , I just found the bmesh way , this polygon way may be simpler – 4nof Jun 23 '20 at 02:01
  • As clearly demonstrated in answer to question marked as duplicate. Can also create a bmesh in object mode. To clarify edit mode is not necessary to get the face data. it is used here re the choice of an edit mode bmesh.. As demonstrated in dupe answer use the Object.material_slots to index the objects materials. Using Mesh.materials will only work for mesh linked materials. – batFINGER Jun 23 '20 at 06:15