Batch Delete Vertex Groups script

Here is a quick script I did to quickly delete a few vertex groups at once

very simple to use, just run the script.
a screen will appear listing all the vertex groups, select the ones you want to delete and press the delete button
thats it…


#!BPY
"""
Name: 'Delete Vertex Groups'
Blender: 248
Group: 'Mesh'
Tooltip: 'Batch Delete Vertex Groups'
"""

__author__ = "Brad Gonsalves AKA AVE"
__url__ = ["blenderartists.org", "www.blender.org"]
__version__ = "1.0 2009/06/09"

# -------------------------------------------------------------------------- 
# ***** BEGIN GPL LICENSE BLOCK ***** 
# 
# This program is free software; you can redistribute it and/or 
# modify it under the terms of the GNU General Public License 
# as published by the Free Software Foundation; either version 2 
# of the License, or (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with this program; if not, write to the Free Software Foundation, 
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
# 
# ***** END GPL LICENCE BLOCK ***** 
# --------------------------------------------------------------------------



import Blender
from Blender import Draw, BGL, Scene, Mesh, Window, sys, Object

import bpy




GroupList=[]
ToggleState=[]
VGListRunning=1
co=[0,0]
GEventNumBase=20
VGColumns=4
GError=False


scn = Scene.GetCurrent()
obj= scn.getActiveObject()

if obj.getType()!='Mesh':
    obj= None
    
sel= [ob for ob in Object.GetSelected() if ob.getType()=='Mesh' if ob != obj]
if not sel and not obj:
    Draw.PupMenu('Error, select a mesh as your active object')
    GError=True
else:
    me = obj.getData(mesh=1) 
    
    InEditMode = Window.EditMode()    
    
    co=Window.GetMouseCoords()

    Window.EditMode(0)
    Window.EditMode(1)


def ToggleButton(event, val):
    global ToggleState
    global VGListRunning
    Found=False
    for x in ToggleState:
        if x[0]==event:
            Found=True
            x[1]=val
    if Found==False:
        ToggleState.append([event,val])
    VGListRunning=1

def FindToggleState(event):
    Found=False
    for x in ToggleState:
        if x[0]==event:
            Found=True
            return(x[1])
    if Found==False:
        return(0)

def DeleteVGroups(event, val):
    global VGListRunning
    Window.EditMode(0)
    if event==1:
        EventNum=GEventNumBase
        for x in GroupList:
            Toggle=FindToggleState(EventNum)
            if Toggle:
                me.removeVertGroup(x)
            EventNum+=1
    VGListRunning=0

def buttons():
    global GroupList
    global co
    global VGListRunning
    global GEventNumBase
    
    ColHeight=20
    ColWidth=105
    
    GroupList=me.getVertGroupNames()
    
    EventNum=GEventNumBase
    if len(GroupList)<VGColumns:
        CenWidth=0
        CenHeight=0
    else:
        CenWidth=(VGColumns*ColWidth)/2
        CenHeight=((len(GroupList)/VGColumns)*ColHeight)/2
    
    BaseCoX=co[0]-CenWidth
    BaseCoY=co[1]+CenHeight
    coY=BaseCoY
    coX=BaseCoX
    
    
    
    for x in GroupList:
        Toggle=FindToggleState(EventNum)
        Draw.Toggle(x,EventNum,coX,coY,100,15,Toggle, "Delete: "+x,ToggleButton)
        coX+=ColWidth
        EventNum+=1
        if coX>=BaseCoX+(ColWidth*VGColumns):
            coX=BaseCoX
            coY-=ColHeight    
    if coX!=BaseCoX:        
        coY-=ColHeight
    Draw.PushButton("Delete", 1, BaseCoX, coY, 100, 15,"Delete all selected Vertex Groups", DeleteVGroups)
        
    VGListRunning=0


def main():
    
    if GError: return        
    while VGListRunning == 1:
        Draw.UIBlock(buttons, 0)
        
    Window.EditMode(1)
    Window.EditMode(0)
    
    if InEditMode:
        Window.EditMode(1)


if __name__ == '__main__':
    main()


(by the way if you want to change the number of columns that the vertex groups are displayed in, just change the item
VGColumns=4 right near the top of the script to what ever number you want)

Hey there, is it possible to port this to 2.7?
It’s a very useful script and I can’t find its counterpart for the latest versions.

EDIT: To be honest, I’m specifically looking for a script that will automatically remove all empty vertex groups from an object. Would anyone be willing to help, please?

bl_info = {
    "name": "Remove unused Vertex Groups",
    "author": "CoDEmanX",
    "version": (1, 0),
    "blender": (2, 70, 0),
    "location": "Properties Editor > Object data > Vertex Groups > Specials menu",
    "description": "Delete Vertex Groups with no assigned weight of active object",
    "warning": "",
    "wiki_url": "",
    "category": "Mesh"}


import bpy
from bpy.types import Operator


class OBJECT_OT_vertex_group_remove_unused(Operator):
    bl_idname = "object.vertex_group_remove_unused"
    bl_label = "Remove unused Vertex Groups"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        return (context.object is not None and
                context.object.type == 'MESH')

    def execute(self, context):

        ob = context.object
        ob.update_from_editmode()
        
        vgroup_used = {i: False for i, k in enumerate(ob.vertex_groups)}
        
        for v in ob.data.vertices:
            for g in v.groups:
                if g.weight > 0.0:
                    vgroup_used[g.group] = True
        
        for i, used in sorted(vgroup_used.items(), reverse=True):
            if not used:
                ob.vertex_groups.remove(ob.vertex_groups[i])
                
        return {'FINISHED'}


def draw_func(self, context):
    self.layout.operator(
        OBJECT_OT_vertex_group_remove_unused.bl_idname,
        icon='X'
    )


def register():
    bpy.utils.register_module(__name__)
    bpy.types.MESH_MT_vertex_group_specials.prepend(draw_func)


def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.MESH_MT_vertex_group_specials.remove(draw_func)

if __name__ == "__main__":
    register()


It adds an entry to the VGroup specials menu

Worked like a charm, muchas gracias.

If you want to delete all vertex groups of an object, pythonically,
for ob in bpy.data.objects[‘OBJECTNAME’].vertex_groups:
print(ob)
bpy.data.objects[‘OBJECTNAME’].vertex_groups.remove(ob)

7quads, don’t forget to indent!


for ob in bpy.data.objects['OBJECTNAME'].vertex_groups:
    print(ob)
    bpy.data.objects['OBJECTNAME'].vertex_groups.remove(ob)


for ob in bpy.data.objects['OBJECTNAME'].vertex_groups:
    
    bpy.data.objects['OBJECTNAME'].vertex_groups.remove(ob)

How would you apply this to all selected objects? I am trying to remove all vertex groups on multiple objects and I really hope I don’t have to do them one at a time.

It’s as simple as:

for ob in bpy.context.selected_editable_objects:
    for vgroup in ob.vertex_groups:
        ob.vertex_groups.remove(vgroup)
1 Like

Thank you CoDEmanX.

coDEmanX, this is awesome. Tested it in Blender 2.76 and it works like a charm. This is going to save me a LOT of tedious list scrolling.

Much luv, 3D brother.

Sorry, I’m pretty damn new here, but how do you save and run scripts on Blender? I tried copy-pasting into console, don’t think it works…

This works great in 2.77 but it also deletes empty mirror groups, like having only the L groups weighted for an armature and the R groups are just placeholders so the deformation get’s actually mirrored.
I forgot that the empty mirror groups were neccessary and was wondering why my armature went weird suddenly and tracked it down to this having removed the empty R groups.

So could a check be added along “if groupname ends in .R or .L check the opposite for used == True” ?

I’d do it myself by I don’t know (nor like) python nor blender’s api yet, so maybe someone else who does know both can figure it out faster.

Edit: ok seems like I managed to fix this myself

bl_info = {
    "name": "Remove unused Vertex Groups",
    "author": "CoDEmanX",
    "version": (1, 0),
    "blender": (2, 70, 0),
    "location": "Properties Editor > Object data > Vertex Groups > Specials menu",
    "description": "Delete Vertex Groups with no assigned weight of active object",
    "warning": "",
    "wiki_url": "",
    "category": "Mesh"
}


import bpy
from bpy.types import Operator


class OBJECT_OT_vertex_group_remove_unused(Operator):
    bl_idname = "object.vertex_group_remove_unused"
    bl_label = "Remove unused Vertex Groups"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        return (context.object is not None and
                context.object.type == 'MESH')

    def execute(self, context):

        ob = context.object
        ob.update_from_editmode()
        
        vgs = ob.vertex_groups
        vgroup_used = {i: False for i, k in enumerate(ob.vertex_groups)}
        
        for v in ob.data.vertices:
            for g in v.groups:
                if g.weight > 0.0:
                    vgroup_used[g.group] = True
                    g_name = vgs[g.group].name
                    if g_name.endswith(".L"):
                        vgroup_used[vgs.find(g_name[0:-1] + "R")] = True
                    if g_name.endswith(".R"):
                        vgroup_used[vgs.find(g_name[0:-1] + "L")] = True
        
        for i, used in sorted(vgroup_used.items(), reverse=True):
            if not used:
                ob.vertex_groups.remove(ob.vertex_groups[i])
                
        return {'FINISHED'}


def draw_func(self, context):
    self.layout.operator(
        OBJECT_OT_vertex_group_remove_unused.bl_idname,
        icon='X'
    )


def register():
    bpy.utils.register_module(__name__)
    bpy.types.MESH_MT_vertex_group_specials.prepend(draw_func)


def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.MESH_MT_vertex_group_specials.remove(draw_func)

if __name__ == "__main__":
    register()

Probably fails for groups ending with non capital L/R but meh, works for me.

Hello,

this doesn’t work for me, I get a syntax error (how can I copy script errors?).

It says “Syntax Error: Invalid Syntax” in line 38.

That would be this one:

if g.weight > 0.0:

Awesome add-on. I had been using it everyday, till Blender 2.8 came out. Can you please upgrade it for Blender 2.8.

Updated to 2.8: https://gumroad.com/l/Gxkbp