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$
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$
  • $\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 Jul 30 '17 at 13:04
  • $\begingroup$ Thanks for your answer. I confused existing drivers with existing variables. $\endgroup$ – kopei Jul 30 '17 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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.