Edit material properties based on material name

I want to process an asset library that contains four assets, one for each season per Blend file. I want to change the material properties for all objects in the Blend file based on the material name.

I have four objects in the scene, which have a suffix per season:

Now I want to change the material properties based on the season and the material itself, the name of which is the text after the last underscore (e.g. "trunk" or "rock").

Ideally, I want to input a list that contains the materials that should be processed, e.g. (leaf_flowers, leaf). Then, I need to change these properties in the main nodegroup:

As you can see, input 2 corresponds to the AUTUMN property, input 3 to WINTER and input [4] to SPRING.

The changes are as follows: If the asset contains "_summer", skip it. Summer assets have all 3 properties set by 0 as default. If the asset contains "_autumn" set input 2 to value 1. If the asset contains "_winter" set input 3 to value 1. If the asset contains "_spring" set input [4] to value 1.

Note that a typical material looks something like this: So it has one node group and this nodegroup is the one that should be affected.

Probably something like this will work:

import bpy
from bpy import data as D

def find_node_by_inputs(nodes, inputs):
return next(n for n in nodes if inputs.issubset({i.name for i in n.inputs}))

for mat in D.materials:
name_parts = mat.name.split('_')
if len(name_parts) != 5:
# expecting a different name
continue
season = name_parts[-2].upper()
if season == 'SUMMER':
continue
nodes = mat.node_tree.nodes
node = find_node_by_inputs(nodes, {'SPRING', 'AUTUMN'})  # assuming no other node has such two inputs
node.inputs[season].default_value = 1


v2

I didn't test this code but it probably works. It has a more aggressive heuristic, matching a material and choosing the season if the word is present in the name, regardless of the punctuation:

import bpy
from bpy import data as D

seasons = {'SPRING', 'AUTUMN', 'WINTER'}

def find_node_by_inputs(nodes, inputs):
return next((n for n in nodes if inputs.issubset({i.name for i in n.inputs})), None)

for mat in D.materials:
detected_season = None
name_upper = mat.name.upper()
for season in seasons:
if season in name_upper:
detected_season = season
break
else:
continue
nodes = mat.node_tree.nodes
node = find_node_by_inputs(nodes, seasons)
if node:
node.inputs[detected_season].default_value = 1

• Thanks! As for your assumption in the comments, there is only one node group that has multiple input nodes. It has "VEGETATION_" as name. May 31 at 9:43
• @Hologram then it seems you can replace node = find_node_by_inputs(nodes, {'SPRING', 'AUTUMN'}) with node = nodes['Group'] or node = nodes['VEGETATION_'] if I understood you correctly in regards to the name. May 31 at 10:09
• The node name depends on the material, so it's VEGETATION_[Something else], should have mentioned it's like that. I have added the image in the initial question. ;) Similar nodes also appear in other materials, but not in the same material slot so to say. May 31 at 11:23
• Unfortunately, it doesn't change the properties of the material on my end. I also think there needs to be a debugging. You've used the season as being the part of the name with index -2. There are materials with an additional part with underscore. So sometimes the season is index -3, for instance "summer_leaf_small". I think what should happen is that the underscores after summer should be a dash, so that it becomes "[asset name]_summer_leaf-small". with [asset name] = The name of the asset. May 31 at 11:37
• Thanks! This is awsome! Really cool that you can do so much with Python :) Thanks for all your help Markus! Jun 2 at 9:02