1
$\begingroup$

In Python, I need to add a driver to specified target shape key, driven by specified source shape key's value (linking the target's value to the source's.)

An example print of the information I have:

target key is: {bpy.data.shape_keys['Key.001'].key_blocks["Morph.Upperarms.Shoulder"]}
source key is: {bpy.data.shape_keys['Key'].key_blocks["Morph.Upperarms.Shoulder"]}

I have been able to add a driver to the target mesh with the following:

bpy.data.objects['Target_Mesh'].data.shape_keys.key_blocks["Morph.Upperarms.Shoulder"].driver_add("value").driver

I have been unable to figure out how to add the Source Mesh's key value as the driving value for it, however.

Sample image of the target result without Python:

Pasted Driver

$\endgroup$

1 Answer 1

1
$\begingroup$

I had to rely on an existing answer, but modify it as the formatting wasn't working for me.

import bpy

selected_obj = bpy.context.selected_objects
selected_obj.remove(bpy.context.active_object)

active_obj = bpy.context.active_object
shapekey_list_string = str(active_obj.data.shape_keys.key_blocks.keys()).lower()


for obj in selected_obj:
    for key in obj.data.shape_keys.key_blocks:
        if key.name.lower().lstrip(obj.name.lower()) in shapekey_list_string:
            if not key.name == "Basis":
                skey_driver = key.driver_add('value')
                skey_driver.driver.type = 'AVERAGE'
                if skey_driver.driver.variables:
                    for v in skey_driver.driver.variables:
                        skey_driver.driver.variables.remove(v)
                newVar = skey_driver.driver.variables.new()
                newVar.name = "value"
                newVar.type = 'SINGLE_PROP'
                newVar.targets[0].id_type = 'KEY'
                newVar.targets[0].id = active_obj.data.shape_keys
                newVar.targets[0].data_path = 'key_blocks["' + key.name.lstrip(obj.name.lower())+ '"].value'
                skey_driver.driver.type = 'AVERAGE'
                if skey_driver.driver.variables:
                    for v in skey_driver.driver.variables:
                        skey_driver.driver.variables.remove(v)
                newVar = skey_driver.driver.variables.new()
                newVar.name = "hide"
                newVar.type = 'SINGLE_PROP'
                newVar.targets[0].id_type = 'KEY'
                newVar.targets[0].id = active_obj.data.shape_keys
                newVar.targets[0].data_path = 'key_blocks["' + key.name.lstrip(obj.name.lower())+ '"].value'

The part that seems the hardest to research on API documentation alone is the argument following newVar. I'd like to contextualize that to help others not get as caught up as I had:

newVar = obj.data.shape_keys.key_blocks['Key'].driver_add.driver.variables.new()
newVar.name
newVar.type

.name and .type represent the variables of the driver being added. .type specifies either a single property (what we're using), a transform channel, rotational difference or distance.

Whereas, following that:

newVar.targets[0].id_type
newVar.targets[0].id
newVar.targets[0].data_path

These represent:

  1. 'KEY' used as input for the driver (As in "Key' or 'Key.001' in my sample question.)
  2. Source Object: bpy.data.objects['Source_Mesh'].data.shape_keys This represents the object containing the key in item 1.
  3. Data Path: This represents the exact name you would see were you to copy the shape key as driver and paste it into the "Path" field of the driver editor.

Specifically, not knowing the formatting of this argument, or understanding how the key, key's owner, and data path were separately defined, was what made this solution take hours to find, despite many similar questions being available.

original post used as basis for solution

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .