How can I call and edit animation keys from the Dope Sheet in Python? I have an animation in which a forcefield blows a bunch of chunks apart using the standard physics engine. This animation was then cached for each object, and from within the dope I selected all of them and scaled by &quot;-1&quot;, invertng them and reversing the animation. I then manually re-alligned them to 0, and I had a perfect animation of all the pieces coming together.
I am now trying to create an addon that can do this automatically (not new to Python but new to doing it in Blender) and so I want to know what it is I have to call, a property of the object I assume, to get the keyframes in the dope sheet, so I can then scale them by -1.
Step 1: An object with two keyframes 100 frames apart

Step 2: Using &quot;Bake Action&quot;, all the key frames from the first to the last are baked.

Step 3: As you can see, all keyframes are now in the Dope Sheet

Step 4: These are then scaled by -1

Step 5: Finally, they are then moved (&quot;g&quot;) the total number of frames, in this case 100, in order to realign them.

This is an overview just for useful insights, but the core part I want to know is what I have to call to access the keyframes FROM the Dope Sheet, since IIRC the scaling doesn't work anywhere else.
This is just a basic mockup from what I understand the barebones to be (I found the context.object.animation_data.action line online and am just using it as a sub-in for what I am looking for:
import bpy

class ReverseAnimationOperator(bpy.types.Operator):
    &quot;&quot;&quot;Reverse Animation Operator&quot;&quot;&quot;
    bl_idname = &quot;object.animationReverse_operator&quot;
    bl_label = &quot;Reverse Animation&quot;

    def execute(self, context):
        context.object.animation_data.action = context.object.animation_data.action * -1
        return {'FINISHED'}

def add_object_button(self, context):
    self.layout.operator(
        ReverseAnimationOperator.bl_idname,
        text=ReverseAnimationOperator.__doc__,
        icon='PLUGIN')

def register():
    bpy.utils.register_class(ReverseAnimationOperator)
    bpy.types.VIEW3D_MT_object.append(add_object_button)

if __name__ == &quot;__main__&quot;:
    register()

Blender throws up the error of &quot;-1&quot; being an invalid location.
Thank you in advance!
Action is a read-only object that contains a lot more than just location attributes that can be modified by arithmetic.

The first tool you should know about (if you don't already) is dir(). Print the result of dir(an object) (ex: print(dir(context.object.animation_data.action))) to get a list of related members and methods. This isn't a list of everything you can do with an object but just its members. There's also help(a method) which will print some text that may or may not be helpful in describing the usage of a method.

This information might be useful, if only barely: https://docs.blender.org/manual/en/dev/animation/actions.html


As you can see, the relationships are a bit more complex. You MIGHT be able to get to "XLocation" and "YLocation" and modify them directly, but I'd be surprised if that's the intended approach.

This documentation might also help you explore the relationships between these various objects (note that animation_data contains an action object in that list, which you can drill into, to see its members):
https://docs.blender.org/api/blender_python_api_2_77_release/bpy.types.Object.html?highlight=animation_data#bpy.types.Object.animation_data

I suspect that you'll have more success transforming the fcurve object belonging to that action: https://docs.blender.org/api/blender_python_api_2_77_release/bpy.types.FCurve.html?highlight=fcurve

I'm not finding any clear clues, but it's likely that your process will look like the following:
 - for a given Object -> animation_data -> action -> ActionFCurves
 - select the keyframes in the fcurve that you care about (all of them)
 - perform some kind of transformation on them

I hope that helps!

EDIT: Unfortunately, it looks like ActionFCurves is also read-only, meaning that Blender likely intends for you to transform the keyframes belonging to it, using a different approach.

I'm not sure what that approach might be, at this point, but I hope that at least gets you closer.