nmesh deprecated.... how to bpy?

I’ve been scripting a while but am an artist with no formal training.

I’ve been struggling with the docs on bpy and mesh and so am still using nmesh…

here’s a code example that works for my needs but I’d love to know how to do it properly!

can anyone give me some pointers on how it could be done without nmesh?
I just can’t seem to understand how to do it otherwise…

(this script is to clean up un-used material indices’s…)



import bpy 
import Blender 
from Blender import * 
from bpy import*         
 
#------------------------------------------------- 
def main(): 
     
    scn = data.scenes.active 
    for ob in scn.objects.context: 
        if not ob.lib and ob.type == 'Mesh':    # object isn't from a library and is a mesh 
      
         
            #get number of materials on mesh 
             
            me = ob.getData(mesh=1)     
            nme=NMesh.GetRaw(me.name) 
            mats = nme.materials  
            matcount = len(mats) 
             
            #check the faces on the mesh to build a list of used materials 
            usedMatIndex =[]        #we'll store materials indices here 
                     
            for f in me.faces: 
                #get the material index for this face... 
                faceindex = f.mat 
                 
                #check if it's already listed or not 
                found = 0 
                for m in usedMatIndex: 
                    if m == faceindex: 
                        found = 1 
                        break 
                     
                if found == 0: 
                    #add this index to the list 
                     
                    usedMatIndex.append(faceindex) 
                 
            #find the un-used materials: highest index first! 
            index = matcount -1 
             
            unused =[] 
            while index>= 0: 
                found = 0 
                #check if index is not used 
                 
                for i in usedMatIndex: 
                    if index == i: 
                        #used 
                        found = 1 
                if found == 0: 
                    #not used 
                    unused.append(index) 
                index -= 1 
                 
         
             
                 
            print"used material index are:" 
            print usedMatIndex 
                 
            print"material index to delete are:" 
            print unused 
 
             
            #delete them! 
            for u in unused: 
                del nme.materials[u] 
                nme.update() 
 
 
    return 1 
 
done = main() 
if done == 1: 
    print "done" 
    Draw.PupMenu("Done%t|OK")  
else: 
    print "Nothing Done"

Odd, nothing seems to work to remove the materials without NMesh. There’s one way though, just re-assign the materials on the mesh and leave the unused materials out of the list:



import bpy 
from bpy import*         

#------------------------------------------------- 
def main(): 
     
    scn = data.scenes.active 
    for ob in scn.objects.context: 
        if not ob.lib and ob.type == 'Mesh':    # object isn't from a library and is a mesh

            #get number of materials on mesh 
            me = ob.getData(mesh=1)     
            mats = me.materials
            matcount = len(mats) 

            #check the faces on the mesh to build a list of used materials 
            usedMatIndex =[]        #we'll store materials indices here 

            for f in me.faces: 
                #get the material index for this face... 
                faceindex = f.mat 

                #check if it's already listed or not 
                found = 0 
                for m in usedMatIndex: 
                    if m == faceindex: 
                        found = 1 
                        break 

                if found == 0: 
                    #add this index to the list 
                    usedMatIndex.append(faceindex) 

            print"used material index are:" 
            print usedMatIndex 
                 
            #re-assign the used mats and leave out the unused
            ml = list()
            for u in usedMatIndex:
                ml.append( mats[u] )

            me.materials = ml
            me.update() 
 
    return 1 
 
done = main() 
if done == 1: 
    print "done" 
else: 
    print "Nothing Done"

I’ve also tried to make it work on Blender 2.5, but I don’t understand everything yet. Here’s my try:


import bpy 
from bpy import*         


#------------------------------------------------- 
def main(): 
     
    scn = data.scenes.get("Scene")
    for ob in scn.objects: 
        if not ob.library and ob.type == 'MESH':    # object isn't from a library and is a mesh 
      
            #get number of materials on mesh 
            me = ob.data
            mats = me.materials
            matcount = len(mats) 

            #check the faces on the mesh to build a list of used materials 
            usedMatIndex =[]        #we'll store materials indices here 

            for f in me.faces: 
                #get the material index for this face... 
                faceindex = f.material_index

                #check if it's already listed or not 
                found = 0 
                for m in usedMatIndex: 
                    if m == faceindex: 
                        found = 1 
                        break 

                if found == 0: 
                    #add this index to the list 
                    usedMatIndex.append(faceindex)


            print"used material index are:" 
            print usedMatIndex 

            #re-assign the used mats and leave out the unused
            ml = list()
            for u in usedMatIndex:
                ml.append( mats[u] )

            #can't assign because list of materials is read-only in Blender 2.5
            #me.materials = ml
            #me.update()
            print ml

    return 1 
 
done = main() 
if done == 1: 
    print "done"
else: 
    print "Nothing Done"

The script runs, but I don’t know how to remove or assign materials (or the new material slots?). There’s an operator for it (bpy.ops.object.material_slot_remove), but I don’t know how that works either. It doesn’t seem to take any arguments.

Also, there’s no “active” scene as far as I can see. I guess you’d have to retrieve that information from the context variable instead.

btw. If you’re going to look into 2.5 as well, you’re going to like this page :slight_smile:

Try:

  1. ob.materials
  2. ob.data.materials
  3. mesh= Mesh.New()
    mesh.getFromObject(ob, 0, 1)

I think it’s just not possible to set or delete items in Blender 2.5… (yet, I presume):

http://i25.tinypic.com/2j1k1tg.jpg
(and yeah, I know those methods aren’t supposed to be used)

Thanks for the pointers! makes a bit more sense!

I’m liking the look of the 2.5 api! I was a little concerned that the bpy operators didn’t seem to have the same data access as in 2.4 but from your example oogsnoepje it seems similar enough!

shame about the set and delete thing… and passing arguments!

My script messes up the face indices so I’m fixing that…

I plan to make an “assigning” script that allows direct attaching of materials to faces from a workflow POV whilst still using the existing system… with 2.5 I could call the above script when joining and/or separating objects… to keep it clean and only materials that are used by the faces stay attached to the mesh… I’ll start on 2.4x but will definately port to 2.5!

Andreymi, does that give the materials assigned to the object rather than the mesh?