Skip to main content
deleted 6 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
import bpy

# 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:
        return
    drivers = obj.animation_data.drivers

        for d in drivers:
            if d.data_path ==!= DATA_PATH:
            continue
        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_prop + '"]'
    d.expression = "myvar"

# ========================================================================
# Initialize important properties
# ========================================================================

DATA_PATH = ks.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")

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:
    for fcurve in fcurve_or_list:
        create_driver(fcurve, obj, CUSTOM_PROPERTY)
else:
    create_driver(fcurve_or_list, obj, CUSTOM_PROPERTY)
import bpy

# 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_prop + '"]'
    d.expression = "myvar"

# ========================================================================
# Initialize important properties
# ========================================================================

DATA_PATH = ks.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")

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:
    for fcurve in fcurve_or_list:
        create_driver(fcurve, obj, CUSTOM_PROPERTY)
else:
    create_driver(fcurve_or_list, obj, CUSTOM_PROPERTY)
import bpy

# 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 obj.animation_data is None:
        return
    drivers = obj.animation_data.drivers

    for d in drivers:
        if d.data_path != DATA_PATH:
            continue
        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_prop + '"]'
    d.expression = "myvar"

# ========================================================================
# Initialize important properties
# ========================================================================

DATA_PATH = ks.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")

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:
    for fcurve in fcurve_or_list:
        create_driver(fcurve, obj, CUSTOM_PROPERTY)
else:
    create_driver(fcurve_or_list, obj, CUSTOM_PROPERTY)
fix bugs i script
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74

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_PROPERTYCustom 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.

enter image description here

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 coyping of data path.

This will automatically add a driver to the property you have right clicked and is driven by the custom property CUSTOM_PROPERTY. 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:
                obj.driver_remove(d.data_path, index)

def create_driver(fcurve, obj):
    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_PROPERTY + '"]'
    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

bpy.ops.anim.keying_set_remove()

# ========================================================================
# 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 # 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)
else:
    create_driver(fcurve_or_list, obj)

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 copying of the 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 a newly created 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

# 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_prop + '"]'
    d.expression = "myvar"

# ========================================================================
# Initialize important properties
# ========================================================================

DATA_PATH = ks.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")

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:
    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.

enter image description here

deleted 2 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74

I have come up with an easy workaround solution that will lessen your burden with threetwo (2) easy steps using keying_sets to do the coyping of data path.

I have come up with an easy workaround solution that will lessen your burden with three (2) easy steps using keying_sets to do the coyping of data path.

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 coyping of data path.

added 721 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
deleted 400 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
added 161 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
handle modifiers as well in script
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
added 1006 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
added 48 characters in body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
edited body
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading
Source Link
Harry McKenzie
  • 14.5k
  • 11
  • 34
  • 74
Loading