[Addon] ShapeKey Baker: Apply the current blend of shape keys (and a couple other utilities)

EDIT 2: This now an add-on, available on GitHub: https://github.com/Nanoglyph/Shapekey-Baker

Ever want to edit a mesh after you’ve made shape keys without messing the other shape keys up? Or apply your current shape key mix as your new basis while propogating that change down through all your shape keys?

Then welcome to Shape Key Baker!

(There’s also an option to alphabetize the shape keys).

------------------------------------

Here’s a handy utility to update the Basis and all shape keys so that the current mix is the new basis, and all of the shape keys are updated to be relative to that. Basically scripts the process of doing “New shape from mix” deleting the old, renaming the new over and over again.

EDIT: Bux fixes and improved error handling. There’s also an addon version now which I’ll add in my reply below. This post just has a script you can paste and run from the text editor. Now you can have the first shape key named something different than Basis. Furthermore I’ve corrected it so that old shapekeys aren’t deleted until all of the new ones are created. This fixes a bug with relative relationships that are out of order, though it is a bit slower.

Notes:

  • Preserves min/max range values for each shape key, so you don’t have to worry about that.
  • Preserves original Basis as a shape key named OriginalBasis that is relative to the new Basis. You can delete it if you want, but the code doesn’t assume.
  • Disables Subdivision modifier (if enabled for viewport) for performance, then re-enables (if it had been enabled). No idea the ramifications if you had more than one subdivision modifier.
  • Toggles edit mode because otherwise the new Basis won’t register properly and if you delete all shapekeys it’ll revert back to the original shape.
  • New keys will be in the same order as the old (aside from OriginalBasis being the second key in the list), and will have the same names.

Caveats:

  • Will not preserve vertex groups on shape keys, they will be applied as part of the new shape key instead. It will not carry over any “relative to” relationships either. This is the same behavior as “New shape from mix”
  • Still not tested on multires. Advise disabling.
  • May be slow on higher poly meshes with 100+ shapekeys. This is why I’ve set it to disable and re-enable the subdiv modifier, but that won’t help if the mesh is just naturally high poly.
import bpy

# Get selected object and shapekeys
ob = bpy.context.object
skeys = ob.data.shape_keys.key_blocks

# Utility variables
oldBasis = 'OriginalBasis' # New name for orinal Basis
subD = False
suffix = '__axpxp'
count = 0

"""PREP WORK"""
# Rename 'OriginalBasis' if it already exists
if bool(skeys.get(oldBasis)):
    skeys.get(oldBasis).name = oldBasis + '.Older'
        
# Disable subdivision for performance, if it exists
try:
    if ob.modifiers['Subdivision'].show_viewport == True:
        subD = True
        ob.modifiers['Subdivision'].show_viewport = False
except:
    print('')
    
# Rename Basis, whether it is at the top of the stack or not
ob.active_shape_key_index = 0
ob.active_shape_key.name = oldBasis
try:
    skeys.get('Basis').name = 'Basis.Older'
except:
    print('')

"""BAKE NEW BASIS FROM MIX"""
# Create new shape from mix and zero out all shape keys
ob.shape_key_add(name = str('Basis'), from_mix=True)
bpy.ops.object.shape_key_clear()

# Enable and set active shape key to index of Basis
# Then move to index 0
skeys.get('Basis').value = 1
ob.active_shape_key_index = skeys.find('Basis')
bpy.ops.object.shape_key_move(type='TOP')
bpy.ops.object.shape_key_move(type='UP')
# Zero out all shape keys
bpy.ops.object.shape_key_clear()
    
""" BAKE NEW SHAPE KEYS """
for key in skeys:
    if  key.name != 'Basis' and key.name != oldBasis:
            
        # Prevent infinite loop by screening out "__apxpx" shape keys
        if suffix not in key.name:
            count+=1
            print("Key " + str(count) + ": " + key.name)
                
            # Preserve current value max value
            # And set max to 1 to ensure new key replicates current behavior
            kmax = key.slider_max
            key.slider_max = 1
                
            # Enable shape key and create new shape key from mix
            key.value = 1
            ob.shape_key_add(name=key.name + suffix, from_mix=True)
            
            # Copy min/max rang values
            skeys.get(key.name + suffix).slider_max = kmax
            skeys.get(key.name + suffix).slider_min = key.slider_min

            # Zero out all shape keys
            bpy.ops.object.shape_key_clear()    

""" CLEAN UP """
# Delete original keys and remove temp suffix from new keys
for key in skeys:
    if  key.name != 'Basis' and key.name != oldBasis:
        if suffix not in key.name:
            ob.active_shape_key_index = skeys.find(key.name)
            bpy.ops.object.shape_key_remove()
        else:
            key.name = key.name.replace(suffix,'')

# Set Old Basis relative to new Basis
skeys.get(oldBasis).relative_key = skeys.get('Basis')
    
# This is hacky, but for some reason if we don't toggle edit mode
# the mesh reverts to the original Basis if we don't.
bpy.ops.object.editmode_toggle()
bpy.ops.object.editmode_toggle()

# Re-enable subdvivision if it had been enabled
if subD == True:
    ob.modifiers['Subdivision'].show_viewport = True
3 Likes

Now an addon! With bug fixes. And fixes for the bugs created by the bug fixes. I also added additional functionality. It was a process. You’ll find the buttons on the n-panel tool shelf under Tools.

The addon has a couple utilities:

  1. Bake All: More or less the same as the script above. Apply the current blend of shape keys to the base shape, and all shapekeys. It’ll work even if the base shape isn’t named Basis but it will rename it to Basis.
  2. Bake and delete: Applies the current shape to the mesh and deletes all shape keys. Obviously, don’t use it on a figure with shape keys for expressions or corrective shape keys.
  3. Alphabetize shape keys: Self-explanatory. Carefully programmed not to move the base shape at the top of the stack, even if it is not named Basis anymore. Not really essential for the shapekey baking stuff, but still a useful utility, so I threw it in.

shapeKeyBaker.py (9.0 KB)

3 Likes

There’s now a GitHub page: https://github.com/Nanoglyph/Shapekey-Baker . Don’t try to install from zip, it won’t work. Annoyingly the zip has subdirectory in it for the addon. However, you only need the one shapeKeyBaker.py so either unzip it and don’t worry about it, or just download the one file.

The UI now more appropriately matches Blender norms (see below), running Alphabetize will put you back on the shapekey you were originally on before you alphabetized them, and running Bake to ShapeKeys will attempt to put you back on the same shapekey.

Oh and Bake All Shapekeys has been renamed Bake to ShapeKeys. I don’t know, but I hope it’s clearer?

1 Like