Hi All,
New-ish blender artist here - great program. I am looking to fix some material problems in my scene. I have 150+ materials so far to look through, so looking to automate this edit.
I dabbled in python to try to make this work, but not really sure what to do - new to python as well.
The script i tried did not work, and i would rather not spend 2 weeks trying to figure it out.
I would ask if a python expert could tell be what this code should be.
The basic idea:
scan through all the materials
do not delete or rename anything
if the material has any image node, reset the material node to just Principled BDSF >> Material Output nodes connected to each other (i will redo the image files later with Node Wrangler).
leave other materials with no image nodes unchanged
# --------------------------------------------------------------------------------
# Finds materials with image textures, deletes all the nodes,
# and resets to BDSF to Material Output node
# --------------------------------------------------------------------------------
# loop thru all materials and see ...
# if there are **any** image nodes, then ...
# 1. delete all nodes
# 2. add BDSF and connected output node only
# 3. do not delete or rename anything
# repeat ...
# I made this to clean all images from the file, and redo those
# with better versions using Node Wranger - wanted to automate
# since i have 150+ materials
import bpy
for mat in bpy.data.materials:
doit = 0
nodes = mat.node_tree.nodes
for node in nodes:
if node.type == 'Image Texture':
doit = -1
if doit==-1:
for node in nodes:
nodes.remove(node)
principled = mat.node_tree.nodes.new('Principled BDSF')
principled.location = (0,0) # x,y
matlout = mat.node_tree.nodes.new('Material Output')
matlout.location = (50,0) # x,y
matlout.inputs[0] = principled.outputs[0]
matlout.inputs[0] = principled.outputs[0]
# end script
You can paste code using the MarkDown ``` before and after your code.
here’s some code that you can use (not including any replacement function, as it depends from what you really want to do; for now it will just print the material name in the console):
import bpy
def doSomethingWithMaterial(mat):
print(mat.name)
def loopOver():
for m in bpy.data.materials:
if m.use_nodes:
imageNodes = [node for node in m.node_tree.nodes
if node.type == 'TEX_IMAGE']
if len(imageNodes)>0:
doSomethingWithMaterial(m)
loopOver()
Copied and saved your py file.
Ran it, got this error:
Python: Traceback (most recent call last):
File “C:\lightwave\BLENDER\lakehouse\blend\lakehouse_copy.blend\resetmatl.py”, line 35, in
File “C:\lightwave\BLENDER\lakehouse\blend\lakehouse_copy.blend\resetmatl.py”, line 33, in loopOver
File “C:\lightwave\BLENDER\lakehouse\blend\lakehouse_copy.blend\resetmatl.py”, line 24, in doSomethingWithMaterial
NameError: name ‘false’ is not defined. Did you mean: ‘False’?
Changed two lines to “False”, with a capitol “F”.
mo.select = False
prc.select = False
Worked great - ran it, purged the images and saved the file, reloaded, then started working on better texturing.
Thank you so much !! And i learned a bit from your example (like split into defined sub routines).
One question, how did you know what to use for #node names# in the nt.nodes.new(‘#node names#’) calls? List somewhere??
To complement @nezumi.blend’s answer, you can allways poke a node’s rna_type in the Python_Console and get its identifier (this is common when you’re using blender collections in python):