0
$\begingroup$

I managed to make a script connecting the shapekeys of different objects via drivers.

But I don't know how to overwrite an already existing driver. If anybody could give me a hint?

# Add driver from 'selected' object to target 'active' object.
# Target values are shape_key values
# 
# ShapeKeys must be named after Object for the script to work:
#
#      selected Object     = Cube
#      selected Shape Keys = Cube_abcd
#
#      active Object       = Sphere
#      active Shape Keys   = Sphere_abcd
#      
# 1. Select all object candidates to receive a driver.
# 2. Select 'active' object as driver target. 
# 3. Run script. 

import bpy

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


for obj in selected_obj:
    if not obj == active_obj:
        for key in obj.data.shape_keys.key_blocks:
            if key.name.lstrip(obj.name) in shapekey_list_string:
                if not key.name == "Basis":
                    skey_driver = key.driver_add('value')
                    skey_driver.driver.type = 'AVERAGE'
                    skey_driver.driver.show_debug_info = True
                    newVar = skey_driver.driver.variables.new()
                    newVar.name = "var"
                    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["' + active_obj.name + key.name.lstrip(obj.name)+ '"].value'
$\endgroup$

3 Answers 3

1
$\begingroup$

The line skey_driver = key.driver_add('value') will create a new driver, any existing driver will be replaced by the new driver.

You can delete an existing driver before creating a new one using key.driver_remove()

Note that replacing the driver with a new one will leave the driver variables behind, you can remove driver variables with skey_driver.driver.variables.remove(var) or all of them with -

for v in skey_driver.driver.variables:
    skey_driver.driver.variables.remove(v)
$\endgroup$
2
  • $\begingroup$ wondered from q where OP had an issue finding drivers eg active_obj.data.shape_keys.animation_data.drivers a list of driver fcurves with data_path properties like 'key_blocks["Key 1"].value' for a driver on the "Key 1" shape. $\endgroup$
    – batFINGER
    Commented Jul 30, 2017 at 13:04
  • $\begingroup$ Thanks for your answer. I confused existing drivers with existing variables. $\endgroup$
    – kopei
    Commented Jul 30, 2017 at 15:49
1
$\begingroup$

I added your solution to the script. It works, thanks.

# Add driver from 'selected' object to target 'active' object.
# Target values are shape_key values
# 
# ShapeKeys must be named after Object for the script to work:
#
#      selected Object     = Cube
#      selected Shape Keys = Cube_abcd
#
#      active Object       = Sphere
#      active Shape Keys   = Sphere_abcd
#      
# 1. Select all object candidates to receive a driver.
# 2. Select 'active' object as driver target. 
# 3. Run script. 

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'
                skey_driver.driver.show_debug_info = True
                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["' + active_obj.name + key.name.lstrip(obj.name.lower())+ '"].value'
                skey_driver = key.driver_add('mute')
                skey_driver.driver.type = 'AVERAGE'
                skey_driver.driver.show_debug_info = True
                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["' + active_obj.name + key.name.lstrip(obj.name.lower())+ '"].mute'
$\endgroup$
0
$\begingroup$

For 2.8 When I was running code, console showed me some problems, so I deleted the active objects name for the path of the key ( line 36 ), because whenever you copy path manually in 2.8 from the value you will not have to include active objects name ( just copying shape key value )

import bpy

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


for obj in selected_obj:
    if not obj == active_obj:
        for key in obj.data.shape_keys.key_blocks:
            if key.name.lstrip(obj.name) in shapekey_list_string:
                if not key.name == "Basis":
                    skey_driver = key.driver_add('value')
                    skey_driver.driver.type = 'AVERAGE'
                   # skey_driver.driver.show_debug_info = True
                    newVar = skey_driver.driver.variables.new()
                    newVar.name = "var"
                    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)+ '"].value' 
                    # litlle change was made here by deleting the active object name for the path
$\endgroup$

You must log in to answer this question.

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