Skip to content

Instantly share code, notes, and snippets.

@Roliga
Created April 14, 2022 17:23
Show Gist options
  • Save Roliga/44664f933a29408556add52d12d6b358 to your computer and use it in GitHub Desktop.
Save Roliga/44664f933a29408556add52d12d6b358 to your computer and use it in GitHub Desktop.
Blender add-on for loading, saving and resetting shape key values.
bl_info = {
"name": "Load Shape Key Values",
"blender": (3, 0, 0),
"category": "Object",
"location": "Object Data Properties > Shape Key Specials",
"description": "Load, save and reset shape key values",
}
import bpy, json
from bpy_extras.io_utils import ImportHelper, ExportHelper
from bpy.types import Operator
from bpy.props import StringProperty
def get_object():
assert bpy.context.mode == 'OBJECT', "Must be in object mode!"
ob = bpy.context.object
assert ob.type == 'MESH', "A mesh must be selected!"
assert ob.data.shape_keys, "Object must have shape keys!"
return ob
class LoadShapeKeyValues(Operator, ImportHelper):
"""Load shape key values from a JSON file"""
bl_idname = "object.load_shape_keys"
bl_label = "Load Shape Key Values"
bl_options = {'REGISTER', 'UNDO'}
filter_glob: StringProperty(
default='*.json',
options={'HIDDEN'}
)
def execute(self, context):
ob = get_object()
data = {}
with open(self.filepath, 'r') as f:
data = json.load(f)
kbs = ob.data.shape_keys.key_blocks
changed = 0
skipped = 0
for k in data:
if k in kbs:
if kbs[k].value != data[k]:
kbs[k].value = data[k]
changed += 1
else:
skipped += 1
self.report({'INFO'}, f"Changed {changed} shape keys, {len(data)} in file, {skipped} missing on object.")
return {'FINISHED'}
class SaveShapeKeyValues(Operator, ExportHelper):
"""Save shape key values to a JSON file"""
bl_idname = "object.save_shape_keys"
bl_label = "Save Shape Key Values"
filter_glob: StringProperty(
default='*.json',
options={'HIDDEN'}
)
filename_ext = '.json'
def execute(self, context):
ob = get_object()
data = {}
for kb in ob.data.shape_keys.key_blocks:
if kb == kb.relative_key: continue
data[kb.name] = kb.value
with open(self.filepath, 'w') as f:
json.dump(data, f, indent=4)
self.report({'INFO'}, f"Saved {len(data)} shape keys to '{self.filepath}'.")
return {'FINISHED'}
class ZeroShapeKeyValues(Operator):
"""Set all shape key values to zero"""
bl_idname = "object.zero_shape_keys"
bl_label = "Reset Shape Key Values"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
ob = get_object()
for kb in ob.data.shape_keys.key_blocks:
if kb == kb.relative_key: continue
kb.value = 0
self.report({'INFO'}, 'All shape keys were reset.')
return {'FINISHED'}
def draw(self, context):
self.layout.separator()
self.layout.operator(LoadShapeKeyValues.bl_idname)
self.layout.operator(SaveShapeKeyValues.bl_idname)
self.layout.operator(ZeroShapeKeyValues.bl_idname)
def register():
bpy.utils.register_class(LoadShapeKeyValues)
bpy.utils.register_class(SaveShapeKeyValues)
bpy.utils.register_class(ZeroShapeKeyValues)
bpy.types.MESH_MT_shape_key_context_menu.append(draw)
def unregister():
bpy.utils.unregister_class(LoadShapeKeyValues)
bpy.utils.unregister_class(SaveShapeKeyValues)
bpy.utils.unregister_class(ZeroShapeKeyValues)
bpy.types.MESH_MT_shape_key_context_menu.remove(draw)
if __name__ == "__main__":
register()
@Roliga
Copy link
Author

Roliga commented Apr 14, 2022

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