Assign same material to all objects of the same diffuse color

(gull1ver) #1

Complete scripting newbie here.
The thread title says it all. I have a bunch of objects in a scene of which none are using the same material, but some materials share the same diffuse color. There are three different colors in total.
Now I want to reduce all of the materials used by the scene objects to one per color, so that in the end no more than three materials are in use.

If any of you decide to help me with this, could you maybe also explain how you go about solving a problem like this? Is it just general coding experience? I don’t want to have to bother you people with questions like this too often.

(<== Lost? Click Me) #2

Pen, paper, math, pseudocode, playing Frankenstein mostly (sometimes literally). In this case you’ll need:

  1. a loop to iterate through your objects
  2. to bin them by their material diffuse color
  3. to assign an appropriate new mat according to the binning

This is from a python noob btw.
Try out the Scripting Layout, it helps pick up some things.

Should help some starting out. https://www.youtube.com/watch?v=hfYgCwC_4iE

What are your color values btw? RGB 0-1 or 0-255 will do.

(gull1ver) #3

What does that mean exactly? I learnd about “sets” today. Sounds similar.

The meshes I’m working with are converted from imported .svg vector files. The diffuse colors of their materials are not something I can control. They could be virtually anything, all that is certain is that there will always be three unique colors in the scene in total.

(<== Lost? Click Me) #4

Try this.

'''
By LoboTommy
Circa Blender 2.79

Go to object mode.
Select an object preferably of an unpicked diffuse material color.
Run the script (Hover over Text window and hit Alt P).
All materials of matching diffuse color are replaced by that of the selected object.

Fails on objects without materials if selected.
'''

import bpy

selMat = bpy.context.object.active_material
selCol = selMat.diffuse_color[:]

for obj in bpy.data.objects:
    if (obj.type == 'MESH' or obj.type == 'CURVE') and selCol == obj.data.materials[0].diffuse_color[:]:
        obj.data.materials[0] = selMat

By binning I meant to define ranges within the color gamut. Separate items according to some distinguishing criteria in other words. With the further info I ended up using an equality check rather than that approach.

Remove duplicate mat with same name and diff index
(cmomoney) #5

Which render engine, Blender Internal?

(<== Lost? Click Me) #6

If asking about the script, it works in BI and Cycles, maybe BGE too.

(cmomoney) #7

Nah, I was asking about the OP’s question.

(gull1ver) #8

@LoboTommy
Hey, that’s a great start. Thanks. Your script works.
I guess now I just have to make it so the script gets all the colors in the scene, groups all objects by color, and then runs this material replacer script for each of the groups.
I should maybe just look up some general python coding tutorials.

@cmomoney
It’s just BI.

(<== Lost? Click Me) #9

No problem. There are also some verified fail conditions currently to do with no material objects. Possibly others to be found too, should you wish to account for these situations via code.