Using copy
on both the object and the mesh brings along all data.
Alternatively, instead of copying a new mesh each time, copy the bmesh and write to a new mesh. Once again will have to deal with materials, using all faces left after delete operator, to check which materials are assigned to faces of a particular vertex group.
See Delete all materials that aren't assigned to a face?
If the material is data (mesh) linked, can append to the Mesh.materials
collection instead of using the slot operators.
import bpy
from collections import defaultdict
import bmesh
context = bpy.context
ob = context.object
me = ob.data
vgs = ob.vertex_groups[:]
col = context.collection
rg = defaultdict(set)
for v in me.vertices:
for g in v.groups:
rg[vgs[g.group]].add(v.index)
bm = bmesh.new()
all_verts = set(range(len(me.vertices)))
bm.from_mesh(me)
for vg, verts in rg.items():
if not verts:
continue # no empty vg mesh
oc = ob.copy()
oc.name = vg.name
oc.data = bpy.data.meshes.new(vg.name)
bmc = bm.copy()
bmc.verts.ensure_lookup_table()
bmesh.ops.delete(bmc,
geom=list(bmc.verts[i] for i in (all_verts - verts)),
context='VERTS',
)
bmc.to_mesh(oc.data)
bmc.free()
for g in oc.vertex_groups:
if g.name != vg.name:
oc.vertex_groups.remove(g)
col.objects.link(oc)