Shape Key Removal

Is there an non-ops way to remove shape keys?

You can select one and click the minus button in the Shape Keys subpanel UI, if that is.what you are asking. (?)

I am writing a script and I need to delete a shape key using code. Iā€™m asking is there another way other than using bpy.ops.object.shape_key_remove().

Hi,

Getting anywhere with this?.. been wondering about this too. The console returns shapekeys as bpy.data.keys[ā€™ā€¦ā€™].key_blocks[ā€˜keynameā€™] ā€¦ yet it reports bpy.data.keys as a method.


>>> C.object.data.shape_keys.key_blocks.keys()
['Basis', 'Key 1']

>>> C.object.data.shape_keys.key_blocks['Key 1']
bpy.data.keys['Key.001'].key_blocks["Key 1"]

>>> C.object.data.shape_keys.key_blocks['Key 1'].value
0.3272727131843567

>>> bpy.data.keys(
keys()
.. method:: keys()
Returns the keys of this objects custom properties (matches pythons
dictionary function of the same name).
:return: custom property keys.
:rtype: list of strings
.. note::
   Only :class:`bpy.types.I

No I havenā€™t made any progress. Usually I donā€™t post here until Iā€™ve run out of ideas. I donā€™t like using ops stuff and this one isnā€™t working consistently.

I wrote a patch that adds this to blender but it sits on the tracker collecting dustā€¦

Maybe someone who really needs this can kick Campbell to review.

Well that sucks. :frowning: It is definitely needed, I fully expected the function to already be there and I was just missing it.

Sorry to bring up an old topic, but Iā€™ve been struggling to remove shape keys as well. Iā€™ve tried using bpy.ops.object.shape_key_remove(all=True), but I get a context error:

Traceback (most recent call last):

  File "~/.config/blender/2.78/scripts/addons/examples.py", line 250, in execute
    bpy.ops.object.shape_key_remove(all=True)

  File "~/blender-2.78c-linux-glibc219-x86_64/2.78/scripts/modules/bpy/ops.py", line 189, in __call__
    ret = op_call(self.idname_py(), None, kw)

RuntimeError: Operator bpy.ops.object.shape_key_remove.poll() failed, context is incorrect

Iā€™m not sure how to get to the right context via code.

Does anyone have any ideas?

FYI, hereā€™s the full operator code:

class TEST_OT_load_shape_key_dyn_geo(bpy.types.Operator):
    bl_idname = "test.load_skey_dyn_geo"
    bl_label = "Dynamic Geometry (Shape Keys)"
    bl_description = "Loads with shape key dynamic geometry"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):

        # Select the Cube object
        bpy.data.objects['Cube'].select = True
        context.scene.objects.active = bpy.data.objects['Cube']

        # This line causes the error
        bpy.ops.object.shape_key_remove(all=True)


        # Add two shape keys
        bpy.ops.object.shape_key_add(from_mix=False)  # Adds "Basis" Shape Key
        bpy.ops.object.shape_key_add(from_mix=False)  # Adds "Key 1" Shape Key

        # Enter Edit Mode and deselect all
        bpy.ops.object.mode_set ( mode="EDIT" )
        bpy.ops.mesh.select_all(action='TOGGLE')

        # Move the top 4 points when on Key 1
        obj = context.object
        mesh = obj.data
        bm = bmesh.from_edit_mesh(mesh)
        bm.verts.ensure_lookup_table()
        verts = bm.verts
        for v in verts:
          if v.co[2] > 0:
            print ( "Setting vertex" )
            v.co[2] = 4.0
        bmesh.update_edit_mesh(mesh)

        # Return to Object Mode
        bpy.ops.object.mode_set ( mode="OBJECT" )

        context.scene.frame_start = 0

        context.scene.frame_current = 0
        bpy.data.shape_keys['Key'].key_blocks["Key 1"].value = 0.0
        mesh.shape_keys.key_blocks['Key 1'].keyframe_insert(data_path='value')

        context.scene.frame_current = 50
        bpy.data.shape_keys['Key'].key_blocks["Key 1"].value = 1.0
        mesh.shape_keys.key_blocks['Key 1'].keyframe_insert(data_path='value')

        context.scene.frame_current = 100
        bpy.data.shape_keys['Key'].key_blocks["Key 1"].value = 0.0
        mesh.shape_keys.key_blocks['Key 1'].keyframe_insert(data_path='value')

        area = bpy.context.area
        old_type = area.type
        area.type = 'GRAPH_EDITOR'
        bpy.ops.graph.fmodifier_add(type='CYCLES')
        area.type = old_type

        return {'FINISHED'}


Youā€™ll note that I changed the area.type in order to set the type to CYCLES for the graph. I could do that when calling shape_key_remove, but I havenā€™t been able to find an area type that works.

With obj as your object:


for k in obj.data.shape_keys.key_blocks:
    obj.shape_key_remove(k)
1 Like

Thanks for the help, but it didnā€™t solve my particular problem (maybe I wasnā€™t clear enough).

When my addon runs, it adds shape keys to an existing object and sets values with this code:


# Add the shape keys
bpy.ops.object.shape_key_add(from_mix=False)  # Adds "Basis" Shape Key
bpy.ops.object.shape_key_add(from_mix=False)  # Adds "Key 1" Shape Key

# Add a keyframe and value at time 0
context.scene.frame_current = 0
bpy.data.shape_keys['Key'].key_blocks["Key 1"].value = 0.0
mesh.shape_keys.key_blocks['Key 1'].keyframe_insert(data_path='value')

# Add a keyframe and value at time 50
context.scene.frame_current = 50
bpy.data.shape_keys['Key'].key_blocks["Key 1"].value = 1.0
mesh.shape_keys.key_blocks['Key 1'].keyframe_insert(data_path='value')

The first time I run it, thereā€™s one shape key named ā€œKeyā€:

>>> bpy.data.shape_keys.keys()
['Key']

Everything runs fine. But if I run it again, I get another copy named ā€œKey.001ā€ added to the list:

>>> bpy.data.shape_keys.keys()
['Key', 'Key.001']

I would like to remove all of those shape keys at the top of my addon so that the code can create them again as ā€œKeyā€ rather than continuing to add new shape keys (ā€œKey.001ā€, ā€œKey.002ā€, ā€¦).

I havenā€™t been able to figure out how to delete the shape keys stored in bpy.data.shape_keys.

Thanks in advance for any help.

I donā€™t get a [ā€˜Keyā€™] at all. bpy.data.shape_keys.keys() always returns [] for me.