1
$\begingroup$

I'm trying to create a relatively simple addon for Blender to make our workflow a little easier.

I got the scripts running... kinda. I'm sure there is something about how Blender works under the hood that I just don't understand. I am also not very experienced in Python and scripting in general, so bear with me here.

All I want to do is have an extra menu in the N-Panel in Object Mode, so that I can set Vertex Colors from there instead of selecting the object, switching to Vertex Paint Mode, pressing the hotkey to paint the object, and going back.

In general, this is working fine and as expected. What doesn't work is having the Palette UI element in this custom menu actually work. It shows up, but it seemingly never "updates". If I select any color in this menu, it seemingly is updating the Palette data (even if I switch back to Vertex Paint, it looks identical there) in all menus (my custom panel, the built in tool settings, ...), but applying the color only works if I click any color in the palette while being in Vertex Paint mode.

Or in other words: choosing the color for the Vertex Paint in my custom menu works fine when I'm in Vertex Paint Mode, but it doesn't work in Object Mode.

I hope I could clearly explain my problem.

Here's the code:

import bpy

##################    
# INTERFACE CLASS
##################
class VIEW3D_PT_gp_custom_panel(bpy.types.Panel):

    bl_space_type = "VIEW_3D" # used in the 3D View
    bl_region_type = "UI" # 
    bl_category = "GP" 
    
    bl_label = "GP Tools"
    
    def draw(self, context):
        layout = self.layout
        row = self.layout.row()
        
        ts = context.tool_settings
        
        row.operator("object.gp_apply_vertex_color", text="Vertex Color to Selected")
        layout.template_ID(ts.vertex_paint, "palette", new="palette.new")
        layout.template_palette(ts.vertex_paint, "palette", color=True)


# Register and add to the "object" menu (required to also use F3 search "Simple Object Operator" for quick access).
def register():
    bpy.utils.register_class(VIEW3D_PT_gp_custom_panel) # register to n-panel


def unregister():
    bpy.utils.unregister_class(VIEW3D_PT_gp_custom_panel) # unregister from n-panel


if __name__ == "__main__":
    register()
import bpy

##############################################
# MAIN FUNCTION THAT DOES THE VERTEX COLORING
##############################################
def main(context):
    current_mode = bpy.context.object.mode
    print("Current Object Mode is:" + current_mode)
    
    # change to Vertex Paint Mode, apply Vertex Paint and return to previous mode
    bpy.ops.object.mode_set(mode='VERTEX_PAINT')
    bpy.ops.paint.vertex_color_set()
    bpy.ops.object.mode_set(mode=current_mode)

#################
# OPERATOR CLASS
#################
class ApplyVertexColor(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.gp_apply_vertex_color"
    bl_label = "GP Apply Vertex Color"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}


def menu_func(self, context):
    self.layout.operator(ApplyVertexColor.bl_idname, text=ApplyVertexColor.bl_label)


# Register and add to the "object" menu (required to also use F3 search "Simple Object Operator" for quick access).
def register():
    bpy.utils.register_class(ApplyVertexColor) # register operator
    bpy.types.VIEW3D_MT_object.append(menu_func) # register operator to object menu


def unregister():
    bpy.utils.unregister_class(ApplyVertexColor) # unregister operator
    bpy.types.VIEW3D_MT_object.remove(menu_func) # unregister operator from object menu


if __name__ == "__main__":
    register()

    # test call
    # bpy.ops.object.apply_vertex_color()

For more clarity what the problem is, here's a short video:

https://youtu.be/wxnRfbmK1Jw?si=5Ggk4O1V5PpFU-sq

$\endgroup$

1 Answer 1

1
$\begingroup$

Update the brush color when you selecting a different color on the N panel in any mode

import bpy

active_color = [0.0, 0.0, 0.0]

def draw_callback():
    try: color = list(bpy.context.tool_settings.vertex_paint.palette.colors.active.color)
    except: return

    if active_color != color:
        print("you selected different color")
        active_color[:] = color

        # Update brush color
        bpy.context.tool_settings.vertex_paint.brush.color = color

# Run this on bpy.app.handlers.version_update if you use it on addon
bpy.types.SpaceView3D.draw_handler_add(draw_callback, (), 'WINDOW', 'POST_VIEW')


class VIEW3D_PT_gp_custom_panel(bpy.types.Panel):

    bl_space_type = "VIEW_3D" # used in the 3D View
    bl_region_type = "UI" # 
    bl_category = "GP" 
    
    bl_label = "GP Tools"
    
    def draw(self, context):
        layout = self.layout
        row = self.layout.row()
        
        ts = context.tool_settings
        
        row.operator("object.gp_apply_vertex_color", text="Vertex Color to Selected")
        layout.template_ID(ts.vertex_paint, "palette", new="palette.new")
        layout.template_palette(ts.vertex_paint, "palette", color=True)

    

def main(context):
    current_mode = bpy.context.object.mode
    print("Current Object Mode is:" + current_mode)
    
    # change to Vertex Paint Mode, apply Vertex Paint and return to previous mode
    bpy.ops.object.mode_set(mode='VERTEX_PAINT')
    bpy.ops.paint.vertex_color_set()
    bpy.ops.object.mode_set(mode=current_mode)

class ApplyVertexColor(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.gp_apply_vertex_color"
    bl_label = "GP Apply Vertex Color"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}


# Register and add to the "object" menu (required to also use F3 search "Simple Object Operator" for quick access).
def register():
    bpy.utils.register_class(VIEW3D_PT_gp_custom_panel) # register to n-panel
    bpy.utils.register_class(ApplyVertexColor) # register operator
    
def unregister():
    bpy.utils.unregister_class(VIEW3D_PT_gp_custom_panel) # unregister from n-panel
    bpy.utils.unregister_class(ApplyVertexColor) # unregister operator

if __name__ == "__main__":
    register()
$\endgroup$
1
  • $\begingroup$ That did the trick, thank you very much! $\endgroup$
    – dasfrodo
    Commented Apr 9 at 11:43

You must log in to answer this question.

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