Well, rather than a roasting, I’m actually asking for peer review
I’ve made some additions to my add-on, but I wonder if I’m going about it the long way. I’m posting here to see if anyone has any suggestions for improving or simplifying it.
The goal is to let users select one, several, or all nodes in a material, and change the Base Color of all selected nodes that have a Base Color input.
Currently, I give each type of shader node that has a Base Color input its own if statement.
To test if I should display an error message, I have a counter that ticks up for each node changed.
Here’s the relevant chunk:
# COLOR SWITCHER
def set_base_color(hex):
material = bpy.context.object.active_material
if material:
AN = material.node_tree.nodes
g = 0
for n in AN:
if n.select:
if n and n.bl_idname == "ShaderNodeBsdfAnisotropic":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfDiffuse":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeEmission":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfGlass":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfGlossy":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfHair":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfPrincipled":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfHairPrincipled":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeVolumePrincipled":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfRefraction":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeSubsurfaceScattering":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfToon":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfTranslucent":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfTransparent":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBsdfVelvet":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeBackground":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeVolumeAbsorption":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
elif n and n.bl_idname == "ShaderNodeVolumeScatter":
n.inputs[0].default_value = hex_to_rgb(hex)
material.diffuse_color = hex_to_rgb(hex)
g += 1
if g == 0:
ShowMessageBox(no_active, "Unable To Comply")
return {'FINISHED'}
else:
ShowMessageBox(no_material, "Unable To Comply")
return {'FINISHED'}
First off…
It’s obvious I should take the repeating code and make it a separate class like so:
def apply_color(na,ma,ga)
na.inputs[0].default_value = hex_to_rgb(hex)
ma.diffuse_color = hex_to_rgb(hex)
ga += 1
and then apply it to each case:
if n and n.bl_idname == "ShaderNodeBsdfAnisotropic":
apply_color(n,material,g)
But beyond that…
Four questions occur to me:
-
Do I actually need to include
bpyinmaterial = bpy.context.object.active_material? -
Am I using
return {'FINISHED'}too many times? -
Is there a better way of testing for
no nodes changedthan the counter? -
And most importantly, is there a more efficient way of looping through the node types than by using multiple
ifstatements? Maybe an array?