When creating a new Cycles material by clicking the New button in the Materials panel, there is a disconnect between the two colour wells that are created, one for the Diffuse shader, the other for Viewport colour. As you adjust the Diffuse colour, the change doesn't transfer over to Viewport. If you want them to match, you have to manually copy the colour.
I decided to finally solve the issue with some Python code. I couldn't find a callback function to fully automate the copying, so I created a button. Because dark objects are difficult to work with in the Viewport, I added a lightness offset (Value in HSV colour space). Very dark colours from the shader are copied a little lighter to the Viewport.
Further to what I posted on BlenderArtists, I improved the script by dispensing with a new panel for the button, appending it to the Settings panel instead. The button will only appear if Cycles is the active render engine.
You can test the script by running it from the Text window in Blender. You can also download it as a full add-on (with tab indentation) from Google Drive: CyclesColorToViewport.py
import bpy import mathutils class CopyCyclesColorToViewport(bpy.types.Operator): '''Copies Color of first Cycles node with Color input to Viewport Color of the material''' bl_idname = "object.copy_cycles_color_to_viewport" bl_label = "Copy Cycles Color to Viewport" bl_options = {"REGISTER", "UNDO", "INTERNAL"} @classmethod def poll(cls, context): return context.active_object is not None def execute(self, context): if context.active_object.active_material != None: obMat = context.active_object.active_material if obMat.cycles.id_data.node_tree != None: for node in obMat.cycles.id_data.node_tree.nodes: for nodeInput in node.inputs: if nodeInput.type == 'RGBA': cyColor = mathutils.Color((nodeInput.default_value[0], nodeInput.default_value[1], nodeInput.default_value[2])) # prevent the color from being too dark for viewport # by using a minimum HSV Value of 0.1 cyColor.v = max(0.1,cyColor.v) obMat.diffuse_color = cyColor break return {'FINISHED'} def btn_draw(self, context): if context.scene.render.engine == "CYCLES": layout = self.layout row = layout.row() row.operator("object.copy_cycles_color_to_viewport") def register(): bpy.utils.register_module(__name__) bpy.types.CyclesMaterial_PT_settings.append(btn_draw) def unregister(): bpy.types.CyclesMaterial_PT_settings.remove(btn_draw) bpy.utils.unregister_module(__name__) if __name__ == '__main__': register()
Thanks a lot! This has been a growing thorn in my side, recently. Works like a charm.
ReplyDeleteGreat! Thanks you very much
ReplyDeleteMuito bom, me ajudou bastante.
ReplyDeleteObrigado!