1
$\begingroup$

The original working code is here. Works fine by clicking a button (btn), it copies the color from the displacement to the viewport.

http://blendervisionpro.blogspot.be/2014/12/copy-cycles-color-to-viewport.html

I would like to do it automatically without having to click the button (btn).

So I tried to do an "update" but doesn't work. (onChange).

My level of python is nul. But I can see it detects the shader color: variable cyColor and assigns it to the viewport: obMat.diffuse_color = cyColor

At the bottom of this post,

https://stackoverflow.com/questions/41021920/blender-python-onchange-event

I see @sambler edited a function called onChange of Map type:

but I don't know how to make it work onChange of Displacement (Shader) color.

I don't even know if the function I created "def update_viewport_color" ( exact copy of the execute function ) is even correct.

        bl_info = {  
 "name": "Copy Cycles ViewPort Color from Shader Automatically SBB",  
 "author": "BVP source blenderartists.org/forum/archive/index.php/t-357610.html",  
 "version": (1, 0),  
 "blender": (2, 6, 4),  
 "location": "Material > Settings > Copy Cycles Color to Viewport",  
 "description": "Copy Cycles ViewPort Color from Shader Automatically SBB",  
 "warning": "",  
 "wiki_url": "",  
 "tracker_url": "",  
 "category": "Material"
 }  

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 ViewPort Color from Shader"
  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
              # update=update_viewport_color
              break
    return {'FINISHED'}


def update_viewport_color(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'}

# HOW TO CALL THE FUNCTION ABOVE ???
# ONCHANGE OF COLOR DISPLACEMENT (SHADER).
# update=update_viewport_color


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.CYCLES_MATERIAL_PT_settings.append(btn_draw)

def unregister():
  bpy.types.CYCLES_MATERIAL_PT_settings.append(btn_draw)
  bpy.utils.unregister_module(__name__)

if __name__ == '__main__':
  register()
$\endgroup$
3
  • $\begingroup$ For more recent versions of blender may need to use bpy.types.CYCLES_MATERIAL_PT_settings rather than bpy.types.CyclesMaterial_PT_settings $\endgroup$
    – batFINGER
    Commented Oct 2, 2017 at 23:12
  • $\begingroup$ Could use method used in answer here and run it as a modal operator, instead of a button you have a boolean switch that runs it (sets every timer tick.. if necsessary) or switches auto off. $\endgroup$
    – batFINGER
    Commented Oct 3, 2017 at 9:21
  • $\begingroup$ @batFINGER isn't it possible to run it with the onChange example I provide? => onChange trigger function "def update_viewport_color ". So, there are no buttons to click? with the modal I'll have to click a button on the modal window, correct? My biggest problem is that my level of python is so low (nul) that I don't understand everything that happens, nor I know how and where to call the onChange event. $\endgroup$
    – sebseb
    Commented Oct 3, 2017 at 14:09

0

You must log in to answer this question.

Browse other questions tagged .