4
$\begingroup$

how can I modify properties, for example adding variables, changing their type and targets in a driver on an object all via python, so that I can loop that on multiple objects?

$\endgroup$
6
$\begingroup$

It's best if you create the driver itself in Python using the driver_add() methods, as they return the driver object back to you. This way it's convenient to access and modify them. Below is a short documented example which should get you started. I'm creating two drivers, one for the location and one single channel one for the rotation, just to show the syntax difference. In the example, I then only setup a variable for the location one, so the rotation one has no function.

in the second part, I iterate over all created Driver FCurves and then create a variable for each of them. Setting the variable name is optional, I only did it for demonstration. Further down in the code I access it by calling the name property of the variable object, which is much more robust in terms of programming. There is quite a few options to set up, too many to document them all here in this example. However, the dir() function of Python can help you out, as well as Blenders ToolTips and the console of course. A list of all drivers in the active object can by the way be retrieved using bpy.context.object.animation_data.drivers.

For the code here to run, you need to have an object called 'Sphere' in the scene, as well as another one which is the active object and will receive the driver. So now, here's the eample:

import bpy

# work on the active object
ao = bpy.context.active_object

# create a driver for all three transform channels
# the return value is a list of FCurves, each one containing a driver
drvList = ao.driver_add('location')

# if you want to create a driver for only one channel, you need to
# pass on the index of the channel, starting with 0.
# So: rotate.x = 0, rotate.y = 1, rotate.z = 2
# note that for rotations, there is Euler and Quarternions!
drvList2 = ao.driver_add('rotation_euler', 1)


# create and manipulate variables
for drv in drvList:

    # create a variable
    var = drv.driver.variables.new()

    var.name = 'HelloVar'

    # set the type first (default is 'SINGLE_PROP')
    var.type = 'TRANSFORMS' # you can use 'SINGLE_PROP', 'LOC_DIFF' or 'ROTATION_DIFF'

    # the targets are the fields which you can fill in in Blender Driver UI
    # in essence, you set the Object here from which the variable receives its values
    # sometimes there are more than one target fields (like in case of LOC_DIFF
    # that's why the targets object is a list
    target = var.targets[0]

    # the id property takes an Object for TRANSFORMS drivers
    target.id = bpy.data.objects.get('Sphere') # assuming you have an object named 'Sphere' in your File

    # take the X location of the Sphere as the driving channel
    target.transform_type = 'LOC_X' # others are ROT_X, SCALE_X

    # use local space transforms for this example
    target.transform_space = 'LOCAL_SPACE' # others are TRANSFORM_SPACE and WORLD_SPACE

    # now set the expression on the driver
    # as an example, set it to 2 * var
    drv.driver.expression = '2 * %s' % var.name
$\endgroup$
1
  • $\begingroup$ nice tip. as i stated above, i made a few assumptions on the scene, but calling the object this way is nicer. about the two targets i had made a note in the code comments already. $\endgroup$
    – aliasguru
    Jul 30 '16 at 9:39
4
$\begingroup$

There is an example of constructing a driver that uses the max of two variables at http://web.purplefrog.com/~thoth/blender/python-cookbook/driver-multi-chain.html

Here is a code excerpt that specifically deals with drivers:

def addDrivers(obj, oa, zArray5):

    mesh = obj.data

    z0,z1,z2,z3,z4 = zArray5

    za = z1 + z3-z2
    zb = z3
    zc = z4

    data_path = "key_blocks[\"Key1\"].value"
    dr = mesh.shape_keys.driver_add(data_path)
    dr.driver.type='MAX'

    var = dr.driver.variables.new()
    var.type = 'TRANSFORMS'
    var.targets[0].id = oa
    var.targets[0].bone_target = "bone.L"
    var.targets[0].transform_type = 'LOC_Z'
    dr.modifiers[0].coefficients = ABFor(za, zb)


    var = dr.driver.variables.new()
    var.type = 'TRANSFORMS'
    var.targets[0].id = oa
    var.targets[0].bone_target = "bone.R"
    var.targets[0].transform_type = 'LOC_Z'
    dr.modifiers[0].coefficients = ABFor(za, zb)

    #

    data_path = "key_blocks[\"Key2A\"].value"
    dr = mesh.shape_keys.driver_add(data_path)
    dr.driver.type='MAX'

    var = dr.driver.variables.new()
    var.type = 'TRANSFORMS'
    var.targets[0].id = oa
    var.targets[0].bone_target = "bone.L"
    var.targets[0].transform_type = 'LOC_Z'
    dr.modifiers[0].coefficients = ABFor(zb, zc)

    #

    data_path = "key_blocks[\"Key2B\"].value"
    dr = mesh.shape_keys.driver_add(data_path)
    dr.driver.type='MAX'

    var = dr.driver.variables.new()
    var.type = 'TRANSFORMS'
    var.targets[0].id = oa
    var.targets[0].bone_target = "bone.R"
    var.targets[0].transform_type = 'LOC_Z'
    dr.modifiers[0].coefficients = ABFor(zb, zc)
$\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.