Created
April 14, 2022 13:29
-
-
Save Roliga/be24418d04d30c33fdfadf480f16d557 to your computer and use it in GitHub Desktop.
Blender add-on for removing empty shape keys.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just this bundled as an add-on.
To install, save this file somewehere, then in blender: Preferences -> Add-Ons -> Install... and select the file.