Hi Im looking for a script to eliminate multiple materials, when I Append models which use identical materials I end up with lots of duplicates, like glass, glass.001 glass.002, glass.003. … Then I have to “Databrose” which dosnt have the nice new material previews.
I really dont want to write my own as Im lazy and busy although I will probably end up doing so.
Im pretty sure there isnt any way to “use existing” or “replace” materials when importing but please let me know if there is as this would help also.
You could import my script, build a list of materials with “auto names” and then call that function to automate it more… but the trick is when you get close to the 21 character limit and thenames have been truncated…
How many materials have you got that are 21 characters long? I guess it could be an option to delete any of this length, 21 char (abcdefghijklmnopqrst) This is an extreme conditional but I cant really think of any other way of doing it…
I’ve done some video game work where the naming conventions imposed by the client meant that 21 characters for a material name was woefully inadequate… I ended up having to use all sorts of hacks and workarounds in blender and maya to get stuff named right once transferred to Maya…
Which is why the “wizard” approach works for me… it only takes a few minutes for even very complex scenes… but truncated names aside:
a “slightly” dangerous way to do it (could potentially damage any material name with a “.” if what precedes the dot is the same name as another material in the scene.
importing my script and then doing something like the following should do what you want:
import bpy
import substitutemat
from substitutemat import*
mats = bpy.data.materials
for m in mats:
#find the name without any auto numbered stuff:
nm = m.name.split('.')[0]
#check to see if the portion before the "." matches an existing material
if nm in mats:
mw_replaceMat(m.name, nm)
any material names that got truncated and didn’t match would have to be cleaned by just running the first script wizard I posted… which is safer I guess, and only necesary with long material names anyway!
Oops, of course I’m checking a list of material objects against a string! that’s never match…
import bpy
import substitutemat
from substitutemat import*
mats = bpy.data.materials
#build a list of material names in the scene:
matnames = []
for m in mats:
matnames.append(m.name)
for m in mats:
#find the name without any auto numbered stuff:
nm = m.name.split('.')[0]
#check to see if the portion before the "." matches an existing material
if nm in matnames:
mw_replaceMat(m.name, nm)
I asked Letterip ages ago… he said he’d pass it on…
this stuff, whilst probably easy for someone to do, really takes someone to “need” it themselves to do the code… I’d patch it myself if I could code!!!
here’s a very basic snippet that worked for me, at least for simple scenes
## 'desduplicar' materiales
import bpy
mats = bpy.data.materials
for obj in bpy.data.objects:
for slt in obj.material_slots:
part = slt.name.rpartition('.')
if part[2].isnumeric() and part[0] in mats:
slt.material = mats.get(part[0])
to deduplicate nodegroups in materials it could be something like this:
## deduplicate nodegroups in materials from name
import bpy
n_gs = bpy.data.node_groups
for mat in bpy.data.materials:
for nt in mat.node_tree.nodes:
if nt.type == 'GROUP':
part = nt.node_tree.name.rpartition('.')
if part[2].isnumeric() and part[0] in n_gs:
nt.node_tree = n_gs.get(part[0])
but you need to be careful as it will go through all materials
there’s also the new id_remap thing meant for this situations I believe
Like a charm, thank you! In addition, I used to replace upper/lowercase duplicates:
for obj in bpy.data.objects: for slt in obj.material_slots:
if slt.name != slt.name.lower() and slt.name.lower() in mats:
slt.material = mats.get(slt.name.lower())
I posted this in the released scripts and themes forum last year. It takes all of the materials with different indexes and assigns them to the material with the base name. So, objects with the materials called mat, mat.001, mat.002, mat.003, etc will all be assigned the mat material.
Edit: sorry, it’s been a while since I’ve had to use this. Actually, what you do is pick a material slot that you like. So it could be mat.002 and all materials with the prefix mat will be assigned the material mat.002.