5

I have 3 vertexgroups VG1 VG2 VG3 and 3 materials with exactly the same name VG1 VG2 VG2 as the vertexgroups, how I can assign each material to the corresponding vertexgroup in python? Also how I can get a list of faces in a vertexgroup?

Tak
  • 6,293
  • 7
  • 43
  • 85

2 Answers2

5

enter image description here

EDITED:

A slightly more sophisticated version of the previous script, that now finds all the vertex groups of all the vertices of each polygon, isolates the most frequent vertex group and uses it to choose the correct material from the list. Also uses the method to find the material name that matches the vertex group name, as suggested by @batFINGER.

Try this (with the selected object):

import bpy

o = bpy.context.object

for p in o.data.polygons:
    # Get all the vertex groups of all the vertices of this polygon
    verts_vertexGroups = [ g.group for v in p.vertices for g in o.data.vertices[ v ].groups ]

    # Find the most frequent (mode) of all vertex groups
    counts    = [ verts_vertexGroups.count( idx ) for idx in verts_vertexGroups ]
    modeIndex = counts.index( max( counts ) )
    mode      = verts_vertexGroups[ modeIndex ]

    groupName = o.vertex_groups[ mode ].name

    # Now find the material slot with the same VG's name
    ms_index = o.material_slots.find( groupName )

    # Set material to polygon
    if ms_index != -1: # material found
        p.material_index = ms_index
JakeD
  • 8,467
  • 2
  • 30
  • 73
TLousky
  • 16,043
  • 1
  • 40
  • 72
  • 2
    A couple of things, firstly surely only the faces with vertices all in a group would satisfy setting the material_index... and material_index = o.material_slots.find(groupName) – batFINGER Dec 05 '16 at 12:07
  • Good points @batFINGER. Will edit later when I have access to a computer. – TLousky Dec 05 '16 at 12:45
1

A more operator-centric approach

import bpy

context = bpy.context
obj = context.object
bpy.ops.object.mode_set(mode='EDIT')
for vg in obj.vertex_groups:    
    bpy.ops.mesh.select_all(action='DESELECT')
    #obj.vertex_groups.active = vg # don't work
    obj.vertex_groups.active_index = vg.index
    bpy.ops.object.vertex_group_select()
    i = obj.material_slots.find(vg.name)
    if i >= 0:
        obj.active_material_index = i
        bpy.ops.object.material_slot_assign()

bpy.ops.object.mode_set(mode='OBJECT')
  • can ofcourse have multiple vert groups per vertex, above code will set material to last vg in list with all verts in face in group. I suppose that's why vg's and materials aren't often linked together, as a face can be in multiple vg's and have only one material.

It's also easy to select the faces from the material with

bpy.ops.object.material_slot_select() 

As for faces in a vertex group, run the bpy.ops.object.vertex_group_select() operator after selecting active vertex group, (and clearing selection) then all selected faces will be in that group.

batFINGER
  • 84,216
  • 10
  • 108
  • 233