Callback/Hook Possible on Vertex Paint?

Hi!

I’m using vertex colors to control texture splatting on a mesh. To speed up my shader, I simply scale the different splat textures by the colors channels, thus, vertex colors need to be normalized (for any vertex color, r + g + b == 1.0).

I posted about this on Blender Stack Exchange (Can Vertex Paint Normalize Color Channels?) and I managed to put together a small Add-On that adds a vertex color normalization option to meshes:


import bpy
import random
import math
from mathutils import Color, Vector
bl_info = {
  "name": "Vertex Color Normalizer",
  "description": "Allows the vertex colors of a mesh to be normalized (useful if colors control texture splatting).",
  "author": "Markus Ewald",
  "version": (1, 0),
  "blender": (2, 65, 0),
  "location": "View3D > Add > Mesh",
  "warning": "", # used for warning icon and text in addons panel
  "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
              "Scripts/VertexColorNormalizer",
  "category": "Paint"
}
class VertexColorNormalizer(bpy.types.Operator):
    bl_idname = "object.normalize_vertex_colors"
    bl_label = "Normalize Vertex Colors"
    bl_description = "Normalize vertex colors to enable additive texture splatting"
    
    def execute(self, context):
        
        # What I want to do:
        # - Iterate over the colors of all the vertices in active mesh
        # - Normalize each color (divide by sqrt(r *r + g * g + b * b))
        # - Assign it back to the vertex
      
        for i in context.active_object.data.vertex_colors[0].data:   
            r = i.color[0]
            g = i.color[1]
            b = i.color[2]
            
            magnitude = math.sqrt(r * r + g * g + b * b)
            if magnitude > 1:
                normalized_color = (r / magnitude, g / magnitude, c / magnitude)
                i.color = Color((normalized_color))
        return {'FINISHED'}

def register():
    bpy.utils.register_class(VertexColorNormalizer)

if __name__ == "__main__":
    register()

Is it possible to automatically do this as any vertices are modified by Blender (basically some kind of callback or hook function that I can toggle on and off for Blender’s vertex color paint mode)?

Just noticed that my script has some problems, too.

It works from when I open a model in Blender until the moment I use vertex painting. Then it silently fails (does nothing) until I save and reopen the model again :frowning: