How to get random color variation on a single mesh? I am trying to get color variation and to bake it in a single mesh but the Object Info Random only works if i separate the meshes. Is there an alternative way to get the same result with the meshes combined, they aren't attached between them.
Following the several comments, I've thought an addon can be useful to do that and may have a general interest.



What does it do:


Identify loose parts of the object (or all selected objects)
Generate a random color for each loose part
Follow the mesh loops to assign the vertex colors


(can be installed as an addon)

The code is commented below (please comment if needed):

bl_info = {
    "name": "Assign random vertex color to each loose part of a mesh",
    "author": "lemon",
    "version": (1, 0),
    "blender": (2, 78, 0),
    "location": "Properties Editor &gt; Object data",
    "description": "",
    "warning": "",
    "wiki_url": "",
    "category": "Mesh"}

import bpy
import time
import random
from mathutils import Color

def LoosePartsMakeVertPaths( verts, edges ):
    #Initialize the path with all vertices indexes
    result = {v.index: set() for v in verts}
    #Add the possible paths via edges
    for e in edges:
        result[e.vertices[0]].add(e.vertices[1])
        result[e.vertices[1]].add(e.vertices[0])
    return result

def LoosePartsFollowEdges( startingIndex, paths ):
    current = [startingIndex]
    result = set( current )

    follow = True
    while follow:
        #Get indexes that are still in the paths
        eligible = set( [ind for ind in current if ind in paths] )
        if len( eligible ) == 0:
            follow = False #Stops is no more
        else:
            #Get the corresponding links
            next = [paths.pop( i ) for i in eligible]
            #Get the new links as new inputs
            current = set( [ind for sub in next for ind in sub] )
            result = result.union( current )

    return result

def LoosePartsCountIslands( obj ):
    #Prepare the paths/links from each vertex to others
    paths = LoosePartsMakeVertPaths( obj.data.vertices, obj.data.edges )
    found = True
    n = 0
    while found:
        try:
            #Get one input as long there is one
            startingIndex = next( iter( paths.keys() ) )
            n = n + 1
            #Deplete the paths dictionary following this starting index
            LoosePartsFollowEdges( startingIndex, paths )               
        except:
            found = False
    return n

def LoosePartGetIslands( obj ):
    paths = LoosePartsMakeVertPaths( obj.data.vertices, obj.data.edges )

    result = []

    found = True
    while found:
        try:
            #Get one input as long there is one
            startingIndex = next( iter( paths.keys() ) )
            #Deplete the paths dictionary following this starting index and append the result
            result.append( LoosePartsFollowEdges( startingIndex, paths ) )
        except:
            found = False

    return result

def RandomColor( rnd ):
    return Color( (rnd.random(), rnd.random(), rnd.random()) )

def RandomColors( rnd, count ):
    return [RandomColor( rnd ) for i in range( count )]

def ColorFromVertexIndex( vertexIndex, looseParts, colors ):
    for c, lp in zip( colors, looseParts ):
        if vertexIndex in lp:
            return c
    return Color()

def RandomVertexColorsByLooseParts( obj, vcolName, useSeed, seed ):

    rnd = random.Random()
    if useSeed:
        rnd.seed( seed )

    mesh = obj.data

    #Create vertex colors if it does not already exist    
    if vcolName not in mesh.vertex_colors:
        mesh.vertex_colors.new( vcolName )
    #Update it so that it is available below
    mesh.vertex_colors.update()
    #Get the vertex colors
    vertexColors = mesh.vertex_colors[vcolName]

    #Get loose parts
    looseParts = LoosePartGetIslands( obj )
    #Generate random colors
    colors = RandomColors( rnd, len(looseParts) )

    mesh.loops.update()

    #Follow the loops    
    for i, vertexIndex in enumerate( [loop.vertex_index for loop in mesh.loops] ):
        #Assign vertex colors from loop index and vertex index
        vertexColors.data[i].color = ColorFromVertexIndex( vertexIndex, looseParts, colors )

def InitProperties():
    bpy.types.Scene.VertexColorsName = bpy.props.StringProperty( name = "Vertex colors", description = "Vertex colors to use or create", default = "Col" )
    bpy.types.Scene.VertexColorsUseSeed = bpy.props.BoolProperty( name = "Use seed", description = "Use fixed seed to generate random values" ) 
    bpy.types.Scene.VertexColorsSeed = bpy.props.IntProperty( name = "Seed", description = "Seed for random values" ) 
    bpy.types.Scene.VertexColorsAllSelected = bpy.props.BoolProperty( name = "All selected objects", description = "Apply to all selected object or only active one" ) 

class RndVColToLoosePartsPanel(bpy.types.Panel):
    bl_label = "Random vcol to loose parts"
    bl_space_type = "PROPERTIES";
    bl_region_type = "WINDOW";
    bl_context = ""

    @classmethod
    def poll(self, context):
        return context.object and context.scene

    def draw(self,context):
        layout = self.layout
        scn = context.scene

        layout.prop( scn, 'VertexColorsName', icon='GROUP_VCOL' )
        layout.prop( scn, 'VertexColorsUseSeed' )
        layout.prop( scn, 'VertexColorsSeed' )
        layout.operator( "rndvcoltolooseparts.ope")
        layout.prop( scn, 'VertexColorsAllSelected' )

class RndVColToLooseParts(bpy.types.Operator):
    bl_idname="rndvcoltolooseparts.ope"
    bl_label="Generate random vcol to each loose parts"

    def execute(self, context):

        scene = context.scene
        obj = context.object

        if scene and obj and obj.type == 'MESH':

            prevMode = obj.mode
            bpy.ops.object.mode_set( mode='OBJECT', toggle=False )

            if scene.VertexColorsAllSelected:
                for obj in [obj for obj in context.selected_objects if obj.type == 'MESH']:
                    RandomVertexColorsByLooseParts( obj, scene.VertexColorsName, scene.VertexColorsUseSeed, scene.VertexColorsSeed )
            else:
                RandomVertexColorsByLooseParts( obj, scene.VertexColorsName, scene.VertexColorsUseSeed, scene.VertexColorsSeed )

            bpy.ops.object.mode_set( mode=prevMode, toggle=False )

        return {'FINISHED'}     


def register():
    InitProperties()
    bpy.utils.register_class(RndVColToLooseParts)
    bpy.utils.register_class(RndVColToLoosePartsPanel)


def unregister():
    bpy.utils.unregister_class(RndVColToLooseParts)
    bpy.utils.unregister_class(RndVColToLoosePartsPanel)


if __name__ == "__main__":
    register()