8
$\begingroup$

Using python, how can I check to see if some property (like context.object.location) has any keyframes, or has a driver attached?

$\endgroup$
1

2 Answers 2

5
$\begingroup$

A keyframe check could be done like this:

import bpy

def has_keyframe(ob, attr):
    anim = ob.animation_data
    if anim is not None and anim.action is not None:
        for fcu in anim.action.fcurves:
            if fcu.data_path == attr:
                return len(fcu.keyframe_points) > 0
    return False

print(has_keyframe(bpy.context.object, "location"))

But don't think there is an easy way to test for drivers.

$\endgroup$
2
  • $\begingroup$ drivers can be done similarly with ob.animation_data.drivers - thanks :) $\endgroup$
    – Greg Zaal
    Nov 20, 2013 at 7:48
  • $\begingroup$ Nice, I didn't know you could access drivers that easily. You could extend my has_keyframe() function so it handles single properties as well (e.g. location.x), but it should work for array properties already. $\endgroup$
    – CodeManX
    Nov 20, 2013 at 11:16
2
$\begingroup$

What we call "drivers" are technically "driven f-curves" attached through a Python object's animation_data attribute, just like action data. In an object, those attributes are present in the object itself, its data (whatever type it is), shape keys, particle settings, materials and textures. So we need to check those places to know if there's any driver.

The following sample code is adapted from my driver-copying operator, it merely prints the data paths of available animation and driver f-curves:

import bpy

def main():
    obj = bpy.context.active_object

    # Collect places where animation/driver data possibly present.
    keyable_list = [getattr(obj.data, 'shape_keys', None)]
    for ms in obj.material_slots:
        if not ms:
            continue
        keyable_list.append(ms.material)
        for ts in ms.material.texture_slots:
            if not ts:
                continue
            keyable_list.append(ts.texture)
    for ps in obj.particle_systems:
        keyable_list.append(ps.settings)
    keyable_list.append(obj)
    keyable_list.append(obj.data)

    # Print data paths of available animation/driver f-curves.
    for keyable in keyable_list:
        if not keyable or not keyable.animation_data:
            continue
        action = keyable.animation_data.action
        for fc in keyable.animation_data.drivers:
            print(fc.data_path)
        if action:
            for fc in action.fcurves:
                print(fc.data_path)

main()

I'm keeping it simple, but it's possible to extract only the name of the attribute using e.g. regular expression, if one needs to.

$\endgroup$
2
  • $\begingroup$ Good answer - but a bit over complicated for my needs - thanks anyway :) $\endgroup$
    – Greg Zaal
    Nov 20, 2013 at 7:49
  • $\begingroup$ @GregZaal: Great if you've found a solution. If a code doesn't capture all drivers in an object, just note that there are several places in the object that contains animation_data. $\endgroup$
    – Adhi
    Nov 20, 2013 at 8:44

You must log in to answer this question.

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