3
$\begingroup$

I have a Material node, it contains the default BSDF Shader whose color is fed via an Attribute Node. The Type is Object, and Attribute Node's Name is custom_color.

enter image description here

I would like to change this attribute with my Python script.

It creates a panel called Custom Panel that you can access under an object's Object Properties.

enter image description here

Changing the color via the color picker will refresh the material in the viewport correctly.

However, when I click the button "White", the color picker will change correctly to white, but the object in the viewport will not update, it is still the color it had when I selected it with the color picker.

Of course, save and load the scene and the color will be white. I must be missing some funky update or refresh the color picker does. How do I execute an update or refresh?

import bpy

# First I define a per object attribute: custom_color

bpy.types.Object.custom_color = bpy.props.FloatVectorProperty(
    name="Custom Color",
    subtype='COLOR',
    default=(1.0, 1.0, 1.0),
    min=0.0,
    max=1.0,
)

# Here I have the function for the button to press that is supposed to set the color of custom_color

class OBJECT_OT_SetCustomColor(bpy.types.Operator):
    """Sets the custom color via default color buttons"""
    bl_idname = "object.set_custom_color"
    bl_label = "Set Custom Color"

    color : bpy.props.FloatVectorProperty(
        subtype='COLOR',
    )

    def execute(self, context):
        bpy.context.object.custom_color = self.color
        return {'FINISHED'}

# Here I have the created panel, note that it has a color picker, and a button that sets the color of custom_color.
# What I want are couple color preset buttons the user can click.

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "Custom Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        obj = bpy.context.active_object

        # Color picker UI element
        layout.prop(obj, "custom_color", text="Custom Color")

        layout.operator("object.set_custom_color", text="White").color = (1, 1, 1)

def register():
    bpy.utils.register_class(OBJECT_OT_SetCustomColor)
    bpy.utils.register_class(OBJECT_PT_CustomPanel)

def unregister():
    bpy.utils.unregister_class(OBJECT_OT_SetCustomColor)
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)
    
register()
$\endgroup$

1 Answer 1

4
$\begingroup$

For some reason you need to define an update function for it to refresh or update. In this case I added an anonymous function that does nothing using lambda keyword. So I simply added 1 line to your code update=lambda self, context: None

import bpy

# First I define a per object attribute: custom_color

bpy.types.Object.custom_color = bpy.props.FloatVectorProperty(
    name="Custom Color",
    subtype='COLOR',
    default=(1.0, 1.0, 1.0),
    min=0.0,
    max=1.0,
    update=lambda self, context: None
)

# ... the rest is the same code
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .