A vertex group, as the name says, is a group of vertices. A material is assigned to a face, not to a group. So how do you translate between the two? This will cause issues in a moment.
How to count the number of faces of each vertex group?
I think the most reasonable approach is the "select a face if all its vertices are selected" - it's also intuitive because that's how selection in Blender works. So I'm using the Bmesh - All Corners solution. First let's prepare Suzanne for make-up:
Whoops! You can't select lips without selecting the mouth as well. Again, this will cause a problem in a moment. Also, notice how the vertex groups and the material slots appear in the same order - this is needed, because the script will operate on indices rather than names - bmesh doesn't even store the names (neither does a mesh, only an object stores this information, to my knowledge).
import bpy, bmesh
from bpy import context as C, data as D
from collections import Counter
me = C.object.data
bm = bmesh.from_edit_mesh(me)
layer = bm.verts.layers.deform.active
for f in bm.faces:
groups = (v[layer].keys() for v in f.verts)
groups_set = set(next(groups))
for g in groups:
groups_set.intersection_update(g)
if groups_set:
f.material_index = groups_set.pop() + 1
else:
f.material_index = 0
Whoops! The entire mouth (the inside) has the lip color. Or at least for me this is the case, since I'm just popping from a set, I'm getting the first vertex group found for a given face - Lips
is indexed before Mouth
so it was found first, and is popped first. However, fixing this by swapping both vertex groups would be a mistake - while current CPython implementation is deterministic in this regard, there's no formal guarantee that this will always be so:
A set is an unordered collection
source
Instead, just explicitly prioritize the index of the Mouth
vertex group:
import bpy, bmesh
from bpy import context as C, data as D
from collections import Counter
me = C.object.data
bm = bmesh.from_edit_mesh(me)
layer = bm.verts.layers.deform.active
for f in bm.faces:
groups = (v[layer].keys() for v in f.verts)
groups_set = set(next(groups))
for g in groups:
groups_set.intersection_update(g)
if 3 in groups_set: # prioritize Mouth
f.material_index = 4
elif groups_set:
f.material_index = groups_set.pop() + 1
else:
f.material_index = 0