5

I try to remove all the faces of different objects that have a certain material assigned to its face. But I can't get the select part to work.

import bpy
import bmesh

scene = bpy.context.scene

mat1 = bpy.data.materials['c1'] #This is the material name that I want

for ob in scene.objects: #For all objects
    if ob.type == 'MESH':
        for mat in ob.material_slots:
            if mat.material == mat1:
             bpy.ops.object.editmode_toggle() 

             mat.material.material_slot_select() # This doesnt work and i dont know if the later code work aswell
             me = ob.data


             bm = bmesh.from_edit_mesh(me)
             faces_select = [f for f in bm.faces if f.select] 

             bmesh.ops.delete(bm, geom=faces_select, context=5)  

             bmesh.update_edit_mesh(me, True)
else: 
    ob.select = False

What is wrong, what shall I write?

Br

Jaroslav Jerryno Novotny
  • 51,077
  • 7
  • 129
  • 218

2 Answers2

6
import bpy
import bmesh

mat_c1 = bpy.data.materials['c1']

for ob in bpy.context.scene.objects:
    if ob.type == 'MESH':
        # get all the slot indexes to which mat_c1 is assigned
        c1_slots = [id for id, mat in enumerate(ob.data.materials) if mat == mat_c1]

        # you can also change active_material with
        # ob.active_material_index = some_number
        # and then run operators to deselect all faces and select material with
        # bpy.ops.material_slot_select()
        # but operators are bad so we will do it differently

        faces_mat_c1 = []
        bm = bmesh.new()
        bm.from_mesh(ob.data)
        # no need to swith into edit mode

        for face in bm.faces:
            if face.material_index in c1_slots:
                # face has mat_c1 assigned
                faces_mat_c1.append(face)

        # delete faces with mat_c1
        bmesh.ops.delete(bm, geom=faces_mat_c1, context=5)
        bm.to_mesh(ob.data)
        bm.free()
    else: 
        ob.select = False
Jaroslav Jerryno Novotny
  • 51,077
  • 7
  • 129
  • 218
  • thank you for a really helpful answer! It worked perfectly! – Marcus Pousette Jan 28 '15 at 10:22
  • Glad it helped, you can mark it as correct for others to know, thx.) – Jaroslav Jerryno Novotny Jan 28 '15 at 10:38
  • @JaroslavJerrynoNovotny I want to go over all materials and select (or get indices of) faces to which that specific material has been applied to, without using bmesh (if possible). 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? – Amir Mar 17 '18 at 04:54
0

Excellent question and answer. If you are changing a single object, this code should help.

This code is a script that changes the size of the UV layer of the selected active material's UV.

For Blender 3.2

import bpy
import bmesh

factor = 1.01

Get the active material for the object

obj = bpy.context.active_object mat = obj.active_material

savemode = str(bpy.context.mode) if savemode == "EDIT_MESH": savemode = "EDIT"

bpy.ops.object.mode_set(mode='EDIT')

obj = bpy.context.active_object mat_c1 = mat c1_slots = [id for id, mat in enumerate(obj.data.materials) if mat == mat_c1]

me = obj.data bm = bmesh.new() bm = bmesh.from_edit_mesh(me) uv_layer = bm.loops.layers.uv.verify()

currently blender needs both layers.

bm.faces.layers.face_map.verify()

scale UVs xfactor

for f in bm.faces: if f.material_index in c1_slots: for l in f.loops: l[uv_layer].uv *= factor

bmesh.update_edit_mesh(me) bpy.ops.object.mode_set(mode=savemode)

mml
  • 443
  • 2
  • 9