0
$\begingroup$

I have 200 material slots. I know how to iterate through them, but I cannot make them active.

for o in bpy.data.objects:
    for m in o.material_slots:
        if "screen" in m.name:
            bpy.ops.mesh.select_similar(type='MATERIAL', threshold=0.01)

But I cannot execute the last operator, as I cannot make them active material.

I have to just select similar materials by name and separate them as a new objects. Unfortunately, I cannot way of selecting textures by name, so I cannot execute select_similar and separate operators.

To be more precise, I have a .obj file. It contains 200 materials. I should separate it into 2 groups, group 1 is wall, and group 2 is furniture. I am able to iterate through material_slots and find certain materials which I need. But I cannot select them in edit mode. I have every material's name, I should select 20 or 30 of them and separate them into new objects.

$\endgroup$
6
  • 1
    $\begingroup$ Hello and welcome. your operator will throw an exception because you did not specify the context blender.stackexchange.com/questions/6101/… $\endgroup$ Dec 29, 2022 at 12:15
  • $\begingroup$ I have to just select similar materials by name and seperate them as a new object. Unfortunetly I cannot way of selecting textures by name, so I cannot execute select_similar and seperate operators. I have been stucked for a week. $\endgroup$ Dec 29, 2022 at 12:29
  • $\begingroup$ Do you need the operator or is a bpy.context.object.active_material_index = idx good enough to make the material active? It's not really clear what you are trying to achieve. Select Similar > Material has no threshold, and it looks like it only works in Edit mode. A bit more context on what your goal is would help. $\endgroup$
    – Blunder
    Dec 29, 2022 at 16:18
  • $\begingroup$ Ok, the threshold is shown in the Python console. But bpy.ops.mesh.select_similar(type='MATERIAL', threshold=0.01) selects all faces with the material that the active face in Edit mode has. So why do you need to loop through all material slots and look for a material with "screen" in the name? $\endgroup$
    – Blunder
    Dec 29, 2022 at 16:33
  • $\begingroup$ sorry, it is my very first post in forums. To be more precise, I have a .obj file. It contains 200 hundred materials. I should seperate it 2 groups, group1 is wall, group2 is furnitures. I am able to iterate through material_slots and find certain materials which I need. BUT i cannot select them in edit mode. I have every materials name, I should select 20 or 30 of them and seperate into new group. $\endgroup$ Dec 30, 2022 at 6:46

1 Answer 1

1
$\begingroup$

Here is a script that checks the material slots of all mesh objects. If there is the word screen in the material's name then it selects the vertices of this material and checks the next material. After the check, the selection is separated into a new object if there were matches.

I think what you were actually looking for are lines 31 and 32:

31:         bpy.context.object.active_material_index = idx
32:         bpy.ops.object.material_slot_select()

but you also need to select the object to have the correct context (line 21) and do a few other safety checks.

The complete script looks like this:

import bpy

# save objects because the operation 'Separate Selection' creates new objects 
objects = set(obj for obj in bpy.data.objects)

# ensure we are in object mode
if bpy.context.active_object.mode != 'OBJECT':
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

# clear object selection so the context is correct
bpy.ops.object.select_all(action='DESELECT')
    
for obj in objects:    
    if obj.type != 'MESH':
        print(f"Skipping {obj.name} of type {obj.type}")
        continue
    
    print(f"Checking materials of {obj.name} ")

    # select object, switch to edit mode & clear vertex selection
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.select_all(action='DESELECT')
    
    # check material slots
    found = 0
    for idx, slot in enumerate(obj.material_slots):
        if "screen" in slot.material.name:              #  <-- materials to look for
            print(f"Found material slot #{idx}: {slot.name}")
            # select the material slot, then select all vertices with this material
            bpy.context.object.active_material_index = idx
            bpy.ops.object.material_slot_select()
            found += 1

    # do 'Separate Selection' if we have a selection from at least one match
    if found > 0:
        bpy.ops.mesh.separate(type='SELECTED')

    # switch back to object mode 
    bpy.ops.object.editmode_toggle()

Example output for materials with "Blue" in their name:

Checking materials of Cube
Found material slot #1: Ocean Blue
Found material slot #2: Deep Blue
Found material slot #3: Blue Sky
Checking materials of Cylinder
Skipping Camera of type CAMERA
Skipping Light of type LIGHT
Checking materials of Cube default
Checking materials of Sphere
Found material slot #1: Night Blue Sphere
$\endgroup$
3
  • $\begingroup$ thank you a lot bro, that is exactly what I was searching but couldn`t find in forums and Blender API documentations. Thank you $\endgroup$ Dec 31, 2022 at 17:46
  • $\begingroup$ Hello everybody! May I ask you about the script from Blunder? I've tried this script in Blender 3.6 but it leaves me with this error: File "C:\Program Files\Blender Foundation\Blender 3.6\3.6\scripts\modules\bpy\ops.py", line 113, in call ret = _op_call(self.idname_py(), None, kw) RuntimeError: Error: Nothing selected Allthough with print statement I verified in the console, that the correct slot was found: Checking materials of Plane Found material slot #1: metal_ornaments_29_55 > Mark as Asset I am trying to to mark the active material slot as an asset! Thx! :-) $\endgroup$
    – Taffi
    Sep 14, 2023 at 19:32
  • $\begingroup$ Hi there. The "ops.py" is a Blender internal script. I guess the error is more likely in your script ;-) It looks like there is something not selected as expected. It's hard to tell what's wrong without seeing your script. Feel free to post a new question, show your script - or even better an example that causes the error, the full error message including the calls and line numbers, and link this question here so we know what you have done. $\endgroup$
    – Blunder
    Sep 16, 2023 at 13:46

You must log in to answer this question.

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