Hi, I have assets with several custom node group materials assigned to them…I’d like to change a material parameter associated to all the materials (eg: Snow Amount) rather than going through every material manually…in some cases there can be 10 or more materials.
Is it possible to have a script that goes through ALL the material (node groups) of a selected object to change a particular socket input (for simplicity the top input socket “index 0” (eg: float value - from 0 to 1)) …or does each individual node group have to be selected for any changes to be made to the node group?
tha_group = bpy.data.node_groups['Nodegroup_to_change']
for m in bpy.data.materials:
if m.use_nodes:
for n in m.node_tree.nodes:
if n.type =='GROUP' and n.node_tree == tha_group:
n.inputs[0].default_value = 1.0
this will change all node_groups in all materials of the selected objects (can be more than one)…
It will only check if there’s an input named ‘Snow Amount’, and it won’t care if the input index is 0 or anything else (thought that can also be added).
#tha_group = bpy.data.node_groups['Nodegroup_to_change'] -- not used anymore
input_name = 'Snow Amount'
new_value = 1.0
for ob in bpy.context.selected_objects:
for ms in ob.material_slots:
if ms.material and ms.material.use_nodes:
for n in ms.material.node_tree.nodes:
if n.type =='GROUP' and input_name in n.inputs:
n.inputs[input_name].default_value = new_value
Hey Secrop…here’s the result of the code and a UI made with serpens. I added two other parameters , Puddles and Wet (wet is for walls).
It would be cool to have a numeric input to change the script value before executing (I wouldn’t know how to implement it in serpens anyway)…but I’m so happy with the result
There’s a way that I prefer when I need to control something in the complete scene…
Just by using Scene Custom Properties and then reference them in the materials, with the attribute node… It doens’t involve Python and it can use floats, colors, vectors, etc.
It’s very simple to implement, and you can have the Attribute node inside nodegroups without any problem:
I’ll give it a try…i’ll setup the material node groups as shown, then maybe I can link the custom properties via serpens and see what happens.
Where do the custom properties live…are they saved in the scene, or do they live within blender every time you open blender? just wondering how the custom properties can be added to an addon for others (if that makes sense)
When you defined them, the custom properties become part of the current blend file, and they are saved into that file also.
If you want them present every time you open blender, you can add them to your startup file, or you can create an addon that adds them when active (for example, Cycles does this).
I was wondering based on the code to set a node group value, is there an addition or restructure to the script to be able to reset the entire node group inputs to their default values (as set by me when building the node group)?
I was hoping to add a button to reset a “Selected Node Group” or better still a “Selected Material” Selecting a material and executing the code to reset the node group would be much better UX if it’s possible to do so.
It’s a bit more complex, because the nodetree interface allows inputs with the same name, so you need to use the input’s identifier to correctly get the input index…
# assuming n is the node in the material..
node_tree = n.node_tree
input_id = n.inputs[input_name].identifier
items_tree = node_tree.interface.items_tree
node_tree_input = [s for s in items_tree if s.identifier==input_id][0]
n.inputs[input_name].default_value = node_tree_input.default_value
Thanks Secrop…I’m not really sure how to use that script, my python knowledge is very limited (but I’m learning).
This “reset material node group” has plagued me ever since Blender 3.6 came out…my addon use to have a node reset based on the nodewrangler addon…nodewrangler was changed in 3.6 and the reset stopped working (the person who wrote the script for me, tried to fix it and gave up…and I can’t get hold of him anymore).
There is a free utility that has the reset node that I have been using but was hoping to add my own imbedded into my addon…I’ll just recommend the utility, I imagine most people have it installed anyway…It’s called “Node Group utilities” part of the Blender 4.2 extensions.
Thanks for your help I appreciate you getting back to me!
It’s supposed to work the same as the script i posted before…
input_name = 'Snow Amount'
for ob in bpy.context.selected_objects:
for ms in ob.material_slots:
if ms.material and ms.material.use_nodes:
for n in ms.material.node_tree.nodes:
if n.type =='GROUP' and input_name in n.inputs:
node_tree = n.node_tree
input_id = n.inputs[input_name].identifier
items_tree = node_tree.interface.items_tree
node_tree_input = [s for s in items_tree if s.identifier==input_id][0]
n.inputs[input_name].default_value = node_tree_input.default_value
wow you reply quick…you don’t happen to be in Australia, do you?
I was looking for a way to reset ALL the node group inputs to their defaults…It’s all good, are you a freelance developer for hire, or just a hobbyist?
I see, that script is setup to reset the Snow Amount to it’s default value. I was able to do that with the same script…all I did was used the same code and set the value to 0.0. one button to set it to 1.0 (on) and another to set it to 0.0.(off)
Here is the UI for the on off…based on your original code.
Here is a different setup, where I have a node group input that is a “Numeric Switch” that switches from 1.0 → 6.0 changing the color of the leaves…the buttons work perfect for that, and I added some saturation values as well.
I don’t know how are you planning to distiguish which node_group you want to reset, so in this script you need to supply it…
node_group = bpy.data.node_groups['your_node_group']
for ob in bpy.context.selected_objects:
for ms in ob.material_slots:
if ms.material and ms.material.use_nodes:
for n in ms.material.node_tree.nodes:
if n.type =='GROUP' and n.node_tree == node_group:
items_tree = n.node_tree.interface.items_tree
for input in items_tree:
if input.in_out=='INPUT':
n.inputs.get(input.identifier).default_value = input.default_value
Note: at this point it may be better to start splitting the code into smaller functions…
I used your code and asked ChatGPT to look for the selected materials node group and then run your script and it works!!!..select the object, then the material and run the script (I’ll make a UI in serpens)
here’s the script, not sure if it needs to be cleaned up, but it works!
import bpy
# Get the active material (the selected material)
active_material = bpy.context.object.active_material
# Ensure that the active material is valid and uses nodes
if active_material and active_material.use_nodes:
# Get the node group within the active material
node_group = None
for node in active_material.node_tree.nodes:
if node.type == 'GROUP':
node_group = node.node_tree
break
if node_group:
# Iterate over all selected objects
for ob in bpy.context.selected_objects:
# Iterate over all material slots in the object
for ms in ob.material_slots:
if ms.material and ms.material.use_nodes:
# Iterate over all nodes in the material's node tree
for n in ms.material.node_tree.nodes:
if n.type == 'GROUP' and n.node_tree == node_group:
items_tree = n.node_tree.interface.items_tree
# Iterate over all inputs in the node group's interface
for input in items_tree:
if input.in_out == 'INPUT':
# Set the input's default value
n.inputs.get(input.identifier).default_value = input.default_value
else:
print("No node group found in the active material.")
else:
print("No active material or the active material does not use nodes.")
type or paste code here
The reason I asked if you were in Australia is cos people from Europe take a while to respond based on the time difference…they’re usually sleeping during my daytime (here in Aust). it’s currently 5am, my usual bedtime.