Skip to content

Instantly share code, notes, and snippets.

@Roliga
Created April 14, 2022 13:29
Show Gist options
  • Save Roliga/be24418d04d30c33fdfadf480f16d557 to your computer and use it in GitHub Desktop.
Save Roliga/be24418d04d30c33fdfadf480f16d557 to your computer and use it in GitHub Desktop.
Blender add-on for removing empty shape keys.
bl_info = {
"name": "Remove Unused Shape Keys",
"blender": (2, 80, 0),
"category": "Object",
}
import bpy
import numpy as np
class RemoveShapeKeys(bpy.types.Operator):
"""Removes unused shape keys on all selected objects owo""" # Use this as a tooltip for menu items and buttons.
bl_idname = "object.rm_shapekeys" # Unique identifier for buttons and menu items to reference.
bl_label = "Remove Unused Shape Keys" # Display name in the interface.
bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
def execute(self, context): # execute() is called when running the operator.
# Tolerance to small differences, change it if you want
tolerance = 0.001
assert bpy.context.mode == 'OBJECT', "Must be in object mode!"
for ob in bpy.context.selected_objects:
if ob.type != 'MESH': continue
if not ob.data.shape_keys: continue
if not ob.data.shape_keys.use_relative: continue
kbs = ob.data.shape_keys.key_blocks
nverts = len(ob.data.vertices)
to_delete = []
# Cache locs for rel keys since many keys have the same rel key
cache = {}
locs = np.empty(3*nverts, dtype=np.float32)
for kb in kbs:
if kb == kb.relative_key: continue
kb.data.foreach_get("co", locs)
if kb.relative_key.name not in cache:
rel_locs = np.empty(3*nverts, dtype=np.float32)
kb.relative_key.data.foreach_get("co", rel_locs)
cache[kb.relative_key.name] = rel_locs
rel_locs = cache[kb.relative_key.name]
locs -= rel_locs
if (np.abs(locs) < tolerance).all():
to_delete.append(kb.name)
for kb_name in to_delete:
ob.shape_key_remove(ob.data.shape_keys.key_blocks[kb_name])
return {'FINISHED'} # Lets Blender know the operator finished successfully.
def menu_func(self, context):
self.layout.operator(RemoveShapeKeys.bl_idname)
def register():
bpy.utils.register_class(RemoveShapeKeys)
bpy.types.VIEW3D_MT_object.append(menu_func) # Adds the new operator to an existing menu.
def unregister():
bpy.utils.unregister_class(RemoveShapeKeys)
# This allows you to run the script directly from Blender's Text editor
# to test the add-on without having to install it.
if __name__ == "__main__":
register()
@Roliga
Copy link
Author

Roliga commented Apr 14, 2022

Just this bundled as an add-on.

To install, save this file somewehere, then in blender: Preferences -> Add-Ons -> Install... and select the file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment