Batch Delete Vertex Groups scriptは、ウェイト割り当てのない頂点グループを削除するBlender用アドオンです。自動ウェイトでペアレントを実行する場合やウェイト転送を実行する場合に、このような空の頂点グループが大量に追加されてしまうので、便利なアドオンです。
しかし、ミラーモディファイアを使用している場合にこのアドオンを実行すると、左右対称名の頂点グループ(L/R)のミラー側まで(現状のメッシュにはウェイト割り当てがないので)削除されてしまいます。上記リンクのスレッドには、この問題を改良するコードが提示されています。ただ、その改良コードは、左右対称のパターンが「.L」形式以外である場合(「_L」形式など)には対応していません。また、ミラーモディファイアを使用していない場合でもL/Rを残そうとします。
そこで、もう少し汎用性を高めるようにコードを改良してみました。
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):
suffix_map = {".L": ".R", ".l": ".r", "_L": "_R", "_l": "_r",
"-L": "-R", "-l": "-r",
".R": ".L", ".r": ".l", "_R": "_L", "_r": "_l",
"-R": "-L", "-r": "-l"}
ob = context.object
ob.update_from_editmode()
has_mirror = len([x for x in ob.modifiers if x.type == 'MIRROR']) > 0
suffix = suffix_map.keys()
vgroups = ob.vertex_groups
vgroup_used = {i: False for i, k in enumerate(vgroups)}
for v in ob.data.vertices:
for g in v.groups:
if g.weight > 0.0:
vgroup_used[g.group] = True
if has_mirror:
name = vgroups[g.group].name
if name[-2:] in suffix:
i = vgroups.find(name[:-2] + suffix_map[name[-2:]])
vgroup_used[i] = True
for i, used in sorted(vgroup_used.items(), reverse=True):
if not used:
vgroups.remove(vgroups[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()
公式マニュアルによると、Blenderが左右対称ボーン名と認識するパターンにはサフィックスの「.L/.R」「_L/_R」「-L/-R」形式以外もありますが、上記のコードはそのような形式には対応していないので注意してください。