0
$\begingroup$

I need some help with making a python script. Anybody know how to automatically duplicate any material that's linked to multiple objects so that there is one material for every object?

For example,

enter image description here

Here you see Material231 linked to two objects; Cone and Cube. I would like to develope a script which duplicates/makes a new material based on Material231 and automatically links it to other objects.

Any help is appreciated.

Thank you!

$\endgroup$
0
1
$\begingroup$

Thankfully it’s very easy. The material datatype has a method copy() which returns a new duplicate material. Something like this:

for o in bpy.context.selected_objects:
    o.data.materials[0]=o.data.materials[0].copy()

This code assumes the material is linked to the mesh data block.

$\endgroup$
1
$\begingroup$

Object linked materials.

If you wish to have one material per object, suggest using object linked materials. Have explained this somewhat in https://blender.stackexchange.com/a/185428/15543

Albeit @ZargultheWizard's simple script will work in the question example case, where there are two distinct meshes the cube and the cone, if they were not then would end up with same material on each, that being the last copy, resulting in horrible names and unused originals. To ensure each object has its own material will instead use object linked materials.

Running script below "should" result in all scene objects that have an active material, having their own object linked material named after the object.

import bpy
from collections import defaultdict

context = bpy.context
scene = context.scene

mats = defaultdict(list)

for o in scene.objects:
    if not o.active_material:
        continue
    
    mats[o.active_material].append(o)
    # change to object linked material
    o.material_slots[o.active_material_index].link = 'OBJECT'
   
for m, obs in mats.items():
    # keep and rename the first
    o = obs.pop(0)    
    m.name = o.name
    o.active_material = m
    # copy and rename the rest
    for o in obs:
        o.active_material = m.copy()        
        o.active_material.name = o.name
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.