List of material users

Hi,

I know there is a “method” (or is it a method ???) in the material module of the API to get the number of users of a material datablock.

But is there a simple way to get a list of these users ?

Or do I have to do it the reversed way and iterate over all the objects/meshes/surfaces/metaballs etc and add them to a list if they are linked to the material i am interested in ?

You choose which strategy you’re to implement… Just start it… Otherwise you’ll hardly have the issue solved! :slight_smile:

I’d be glad to see your solution :wink:

Regards,

You may want to examine the LuxBlend exporter script, I think it populates a drop down box with materials in the scene.

No use re-inventing the wheel.

Well I can easily create a list of all the material used in the scene, that is dead easy.
What is more tricky (or it seems so…) is to get the list of objects or meshes linked to a particular material.

It seems I have to test all objects of the scene.

But i think I had to do that in the past: i may find the solution in one of my own script :wink:

i wrote a script that will “select by material”… in object mode it’ll select all the objecxts that use the material you choose, in edit mode it’ll select all the faces that use the material in the active object…

and yes, you do have to iterate through all objects in the scene…


#!BPY
"""
Name: 'Find Items with Material'
Blender: 234
Group: 'Object'
Tooltip: 'In object mode: selects all objects with the chosen material/n in edit mode selects faces.'
""" 
import bpy
from Blender import *
from Blender import Scene, Mesh, Window, sys
import BPyMessages
#late version!

def getAllMaterials(is_editmode):
    matlist =[]
    
    
    if is_editmode:
        scn = bpy.data.scenes.active
        ob_act = scn.objects.active
        me = ob_act.getData(mesh=1) 
        mats= me.materials
        for m in mats:
            matlist.append(m.name)
                                            
        return matlist
        
    else:
        for mat in bpy.data.materials:  
            matlist.append(mat.name)
        return matlist



def ui(is_editmode):
    #create a menu for the user to pick materials from
    
    #get the existing materials
    
    matlist = getAllMaterials(is_editmode)
    pupmessage = "Select Objects With Material:%t"
    if is_editmode:
        pupmessage = "Select Faces With Material:%t"
    
    Puplist = pupmessage
    for mat in matlist:
        Puplist+= "|"+ mat
    
    #Ok, make the menu
    chan = Draw.PupMenu(Puplist,30)

    
    if chan != -1:            #something was chosen process it
        try:
            material = matlist[chan-1]        
            print"chosen Material  is", material

            return material
        except:
            return none

    
def findMaterial(matToFind):
    is_editmode = Window.EditMode()
    scn = bpy.data.scenes.active
    if is_editmode: 
        Window.EditMode(0)
        #only current object
        ob_act = scn.objects.active
        me = ob_act.getData(mesh=1) 
        mats = me.materials     
        if mats:
            
            i=0
            matindex = 0
            for m in mats:
                if m.name == matToFind:
                    matindex = i
                    break
                i += 1

            for f in me.faces: 
                f.sel = False
                if f.mat == matindex:
                    f.sel = True

                else:
                    f.sel = False
        else:
            print "no mats on mesh"
                
        me.update()
        Window.EditMode(is_editmode)
        
    else:
        

        #check each scene starting with current:
        scn = bpy.data.scenes.active
        print "----------------"
        for ob in scn.objects:
            ob.sel = False    
            try:
                if not ob.lib and ob.type == 'Mesh':    # object isn't from a library and is a mes
                    me = ob.getData(mesh=1) 
                    mats = me.materials 
                    if len(mats) >= 1:
                    
                        for m in mats:
                            if m.name == matToFind:
                                ob.sel = True
                                print("found %s in object " %matToFind, ob.name)
                                break
                            else:
                                 ob.sel = False
            except:
                print "error with" ,ob.name
                continue
    
    
        Window.WaitCursor(0)
        #Draw.PupMenu('Material "%s" Not found.' % matToFind)


def main():
        
    is_editmode = Window.EditMode()
    matToFind = ui(is_editmode)
    if matToFind == None:
        return
    findMaterial(matToFind)


if __name__ == '__main__':
    main()

Correct me if I’m wrong, but doesn’t that do the same thing as the ‘Select’ button under the material indices on an object?

yes and no…
in object mode it selects the objects that use that material. you can;t do that in the standard GUI…

in edit mode you’re right that it does the same thing, but it offers you a list of the materials on the current object rather than having to fiddle with the “indeces” which is a particulartly nasty GUI in my opinion…(gladly addressed in 2.5!)

I have my own GUI that calls a bunch of my scripts (this is one of them) that gives me everything I need to use often in one compact panel…and as 2.49 dosen’t have “operators” I’ve had to duplicate some built in functionality to do that…

I thought as much. :slight_smile: