Changing Viewport Color to Surface Color in Cycles

I’m attempting to write my first python script. I have used Blender and others’ scripts for years, but never made my own. I did Visual Basic, and that was 12 years ago in high school.

So, why I want a script: I’ve gotten tired of changing all the viewport color settings to the Surface color settings when using Cycles and decided this would be a good chance to go to town on my first script to do it automatically for all selected objects. Seemed reasonably straight forward enough.

But I’ve run into this problem: I can’t figure out how to call all the materials of my selected objects. This is what I have gotten to, I know, it’s not much yet.

import bpy
for myobjects in bpy.context.selected_objects:
    print (myobjects)
    

So far, that’s simple and it works. It lists the objects I have selected in the viewport.
Now I want to take all the materials for all the selected objects and make their viewport color equal their surface color. Well, there are properties for both of those, but I can’t figure out how to call them up.

selected_objects doesn’t have a function to call up all the materials that are associated with those models, that I can find. Can anyone give me a pointer on this?

What I’m trying to do as a work around is working either.

I tried to set up the script to run on all the materials in a scene, but I now cannot figure out how to access the color of the node diffuse shader from within python.

When I hover over the color swatch it gives me a NodeSocketRGBA.default_value property, that I cannot figure out how to reference.

Also, I would like to understand how to call up all the materials of my selected objects for future reference. Thanks for any help you can give.

-Matt

Materials of the objects are:

myobject.data.materials

So you can iterate through them

for material in myobject.data.materials:

Viewport color of the material is:

material.diffuse_color

When you want to get to the node setup of the material, you are referring to:

material.node_tree

Nodes of this node setup are:

material.node_tree.nodes

You can call them using their names or indexes.

node1 = material.node_tree.nodes[0]
node2 = material.node_tree.nodes['Diffuse BSDF.001']

Here you have to mind that every node has a unique name. If you have 2 “Diffuse BSDF” nodes, one of them will have the name: “Diffuse BSDF” and the second: “Diffuse BSDF.001”. You can of-course change the names. Names of nodes can be viewed in the properties panel of node editor.

If you want to access the color of the input socket of say Diffuse node you are referring to default value of the input.
The color input of the diffuse node has the index of 0, so it’s accessed like this:

node2.inputs[0]

The color, i.e the default value of the color socket is called:

node2.inputs[0].default_value

default_value is an array of 4 values: [0] - red, [1] - green, [2] - blue and we also have [3] which refer to alpha

If you want to set the viewport color of the material to the default value of the node1 - you have a small issue, because default_value is an array of 4 values and diffuse_color is an array of 3 values.
However there’s an easy way to overcome this (let’s assume that out material is already defined and it’s called “mat”:

node = mat.node_tree.nodes[0]  # let's assume that it's a diffuse node.
n_color = node.inputs[0].default_value
n_color_rgb = []  # create an empty list
for i in [0, 1, 2]:
    n_color_rgb.append(n_color[i])  # this will result in having "n_color_rgb" as an array of [r, g, b]

# Now let's assign this color to viewport color
mat.diffuse_color = n_color_rgb

I have shown you how to access individual data types, but now you have to figure out which diffuse node for each material to use as the source of the viewport color etc.

You can iterate through nodes to check what types they have and if the type is ‘BSDF_DIFFUSE’ - use its color input’s default value, but of course you can have more that one diffuse nodes in your material.

You can for example say:

 for node in mat.node_tree:
    if node.type == 'BSDF_DIFFUSE':
        color = node.inputs[0].default_value

So figure out the ways of choosing the node etc.