I have come up with an easy workaround solution that will lessen your burden with two (2) easy steps using keying_sets
to do the coypingcopying of data paththe field's data_path
which will also be used to derive the name of the field using get_property_name
.
This will automatically add a driver to the property you have right clicked and is driven by the custom propertya newly created CUSTOM_PROPERTY
Custom Property with the same name. Note that the script will only run if you have done step 1. It automatically removes the keying_sets
after execution.
import bpy
import re
import random
# First right click property and select "Add to Keying Set"
ks = bpy.context.scene.keying_sets[0].paths[0]
ks_use_entire_array = ks if ks.use_entire_array else False
obj = bpy.context.object
# ========================================================================
# Function declarations
# ========================================================================
def get_property_name(data_path) -> str:
s = data_path
i = s.find('.')
data_path_1 = ""
data_path_2 = data_path
if i > 0:
ri = s.rindex('.')
data_path_1 = '.' + s[0:ri]
data_path_2 = s[ri+1:len(s)]
data = eval("bpy.context.object" + data_path_1)
return data.rna_type.properties[data_path_2].name if hasattr(data, data_path_2) else ''
def clear_drivers(obj, data_path, index):
if not obj.animation_data is None:
drivers = obj.animation_data.drivers
for d in drivers:
if d.data_path == DATA_PATH:
if index < 0:
for idx in range(-1,3):
obj.driver_remove(d.data_path, idx)
else:
obj.driver_remove(d.data_path, index)
def create_driver(fcurve, obj, custom_prop):
d = fcurve.driver
v = d.variables.new()
v.name = "myvar"
target = v.targets[0]
target.id_type = 'OBJECT'
target.id = obj
target.data_path = '["' + CUSTOM_PROPERTYcustom_prop + '"]'
d.expression = "myvar"
# ========================================================================
# Initialize important properties
# ========================================================================
DATA_PATH = ks.data_path
CUSTOM_PROPERTY = get_property_name(DATA_PATH)
INDEX = -1 if ks_use_entire_array else ks.array_index
CUSTOM_PROPERTY = get_property_name(DATA_PATH)
bpy.ops.anim.keying_set_remove()
if INDEX < 0:
for idx in range(-1,3):
custom_prop = CUSTOM_PROPERTY + ' [' + str(idx) + ']'
if custom_prop in obj:
del obj[custom_prop]
else:
CUSTOM_PROPERTY = CUSTOM_PROPERTY + ' [' + str(INDEX) + ']'
# ========================================================================
# Execute: Add property and driver
# ========================================================================
if CUSTOM_PROPERTY in obj:
print("WARNING: to prevent overwriting custom property, substituting with data_path name")
CUSTOM_PROPERTY = CUSTOM_PROPERTY + '.' + str(random.randint(10000, 99999))
obj[CUSTOM_PROPERTY] = 1.0 # you can add the custom property like this
clear_drivers(obj, DATA_PATH, INDEX)
fcurve_or_list = obj.driver_add(DATA_PATH, INDEX)
if type(fcurve_or_list) is list:
index = 0
for fcurve in fcurve_or_list:
create_driver(fcurve, obj, CUSTOM_PROPERTY)
else:
create_driver(fcurve_or_list, obj, CUSTOM_PROPERTY)
Sample output of some properties I have added driver to. You can use Add Single to Keying Set which will create a name with array Property Name [x]
as well as Add All to Keying Set. It will work with almost all fields including fields in Modifiers.