assign a material to a new material slot


(revolt_randy) #1

Hi all,

Straight to the problem. I have a script that creates a text file containing the names of meshes and the names of their materials. Then the script removes all the materials from all the meshes. Now, after removing all the materials, I need to add the materials back to the meshes based on the names in the text file.

here’s a small bit of the code:

# get text file - 'obj-mat_list' - that contains the object's names and
# materials assigned to it
input_filename = "obj-mat_list"
input = bpy.data.texts.get(input_filename)

print("

", input)
for index in input.lines:
    
    if index.body:
        if index.body[0] != "[":
            print("
object =", index.body)
            current_obj = index.body
            bpy.context.scene.objects.active = bpy.data.objects[index.body] 
            bpy.ops.object.material_slot_add()
        else:
            print("
material =", index.body)

This code reads the text file, and if the line in the text file is the name of a mesh, it makes it the active mesh then creates a new material slot for the mesh, the next line of the text file is the name of the material to be assigned to the mesh.

The text file that my script produces looks like this:

Cube
['Blue']
Icosphere
['Green']
Sphere
['Red']

So the first bit of code goes thru the text file, gets the mesh object’s name and makes it the active object, then it adds a new material slot. Now I need to assign the material to the object’s new material slot.

For example, the first line of the text file is the name of the mesh object ‘Cube’, the second line is the name of the material (it’s a python list in case there are multiple materials) as seen in the material panel.

So how do I assign the material named ‘Blue’ to the mesh ‘Cube’ after I’ve created the material slot? I need to do the assignment in the ‘else’ statement in the first bit of code.

Thanks for any help, and if any more information needed, I can supply that.
Randy


(cmomoney) #2

#say cube is your Cube object:
cube.material_slots[0].material = bpy.data.materials['Blue'] # assigns 'Blue' material to first material slot


(batFINGER) #3

Here’s my take on it.
You can get away with just adding a material to the materials collection of the mesh, a slot is added for you.


import bpy
# get text file - 'obj-mat_list' - that contains the object's names and
# materials assigned to it
input_filename = "data"
input = bpy.data.texts.get(input_filename)

print("

", input)
for line in input.lines:
    txt = str(line.body)
    islist = txt[0] == "["
    if islist:
        if obj is None:
            continue
        matlist = eval(txt)
        for mat in matlist:
            if mat not in obj.data.materials:
                obj.data.materials.append(bpy.data.materials.get(mat))
            else:
                print("%s in %s materials" % (mat, obj.name))
    else:
        obj = bpy.data.objects.get(txt)
        if obj is None:
            print("ERROR %s is not an object" % txt)


(revolt_randy) #4

Thanks for the help cmomoney & batFINGER! but I’m still unable to get things to work as I like. To provide more details/better example, I’ve uploaded the .blend to here:
http://www.pasteall.org/blend/12283

Basically, the script generates a text file with the mesh object’s name & names of materials assigned to the mesh. I am having problems re-assigning the materials back to the objects. A few parts of the code are remarked out as not needed now. One part that is remarked out removes the materials from the objects.

I realize that removing materials from objects to only re-assign them again to the objects may seem like a silly exercise, but it’s not, it’s a work around for a bug in blender…

Thanks,
Randy


(cmomoney) #5

Try this: http://pasteall.org/blend/12291

I changed your output file just a little, but it works, even with multiple materials.


(revolt_randy) #6

Thanks cmomoney!! That works. In my attempts I kept failing on

bpy.data.materials.get()

which no matter what I used as an argument, I couldn’t get it to return a material. It got to be quite aggravating that I couldn’t get it to work. I was about to go with your first approach, just assigning a single material to the first material slot, which would work in my case (since all my meshes only have 1 material each), but it wouldn’t work where there was more than one material.

Randy


(cmomoney) #7

Glad to help. Looking at your code made what you were trying to do clearer.


(batFINGER) #8

get is the same as


if name in bpy.data.materials:
    return bpy.data.materials[name]
else:
    return None


(revolt_randy) #9

Thanks batFINGER, didn’t know I could do it that way also. I’m thankful to both cmomoney and batFINGER for helping out here.

I’ve got the script working in my test case I posted, still have a few hurdles to over come to get it to work on the real thing, which I’m sure I can overcome. Still need to add a GUI & define operators to call various parts of the basic script I posted.

I’ll post the details when I’m finished…

Randy


(wilnix) #10

Hi Randy,

Did yoy got this to work as an addon?

//Wilnix


(revolt_randy) #11

Hi wilnix,

Quite an old thread… So I looked for the file, and to my surprise, it appears to work…


I don’t know how well it works. Please read the red text in the above screenshot to understand what this script did.

Could you tell me what you are looking for? I might be able to tell if this script would help you.

Randy


(simdal) #12

Hello. Your script would solve a big problem.
I can try it?
if you can tell me where to download it?
you’ve got a great idea. compliments.
thanks, simdal


(Martin O) #13

Hi

Check out this Addon on Blendermarket - Simple Material Replacement

//M