Solved Creating Keyframes with AutoKey

Hello,
I'd like to set keyframes for the changed attributes of an object using scripting.

How should I go about doing this?

Here are the two approaches I've tried:

Autokey Method

  • Just going for the position, I tried turning on Autokeying and then using SetMl() with the Matrix but it did not create a keyframe (even with animation track with keyframes).
  • I then tried using the BaseDocument.AutoKey method, but could not understand how it works.
obj = doc.GetActiveObject()
doc.AddUndo(c4d.UNDOTYPE_CHANGE,obj)
obj.SetMl(myMatrix)
# Should this be turning Autokeying on for this object? Am I using undo correctly with this?
# There are no examples I could find on this forum, in the documentation, or online.
doc.AutoKey(obj, obj, recursive=True, pos=True, scale=True, rot=True, param=True, pla=False)

c4d.EventAdd() 
  • Can I access/change the Document's Autokeying settings with code? (e.g. turning on/off Position for recording)

Setting Attributes One-by-One
If Autokeying isn't an option, I could get all of the Desc IDs for the attributes and set keys manually, which is probably what will need to happen, but I didn't know if there was a faster, more flexible way.

Thank you!

Hi @blastframe

Find an example of AutoKey bellow.

Note that the AutoKey command needs to be enabled to make it works.
Instead of GetUndoPtr, you could try op.GetClone, but its mail fail if you need to AutoKey Parameter/Pla so it's preferred to use it as I demonstrate it in the code example.

import c4d

def main():
    ID_AUTOKEYING_COMMAND = 12425

    # If autokey is not enable, enables it
    previousAutokeyEnableState = c4d.IsCommandChecked(ID_AUTOKEYING_COMMAND)
    if not previousAutokeyEnableState:
        c4d.CallCommand(ID_AUTOKEYING_COMMAND)

    # Starts the undo process
    doc.StartUndo()

    # Defines that we will change the current object
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)

    # Retrieves the object we put in the undo stack with AddUndo
    undoObj = doc.GetUndoPtr()

    # Modifies the X position of the object, here do any modification
    op[c4d.PRIM_CUBE_SUBX] = 10
    op[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = 100

    # Adds a keyframe by comparing the stored obj in the undo and
    # the obj with the position modified in the scene
    doc.AutoKey(op, undoObj, False, True, True, True, True, True)

    # Finalizes the undo process
    doc.EndUndo()

    # If the command was disabled, re CallCommand to disable it
    if not previousAutokeyEnableState:
        c4d.CallCommand(ID_AUTOKEYING_COMMAND)

    # Pushes an update event to Cinema 4D
    c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()

Cheers,
Maxime.

Hi @blastframe

Find an example of AutoKey bellow.

Note that the AutoKey command needs to be enabled to make it works.
Instead of GetUndoPtr, you could try op.GetClone, but its mail fail if you need to AutoKey Parameter/Pla so it's preferred to use it as I demonstrate it in the code example.

import c4d

def main():
    ID_AUTOKEYING_COMMAND = 12425

    # If autokey is not enable, enables it
    previousAutokeyEnableState = c4d.IsCommandChecked(ID_AUTOKEYING_COMMAND)
    if not previousAutokeyEnableState:
        c4d.CallCommand(ID_AUTOKEYING_COMMAND)

    # Starts the undo process
    doc.StartUndo()

    # Defines that we will change the current object
    doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)

    # Retrieves the object we put in the undo stack with AddUndo
    undoObj = doc.GetUndoPtr()

    # Modifies the X position of the object, here do any modification
    op[c4d.PRIM_CUBE_SUBX] = 10
    op[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X] = 100

    # Adds a keyframe by comparing the stored obj in the undo and
    # the obj with the position modified in the scene
    doc.AutoKey(op, undoObj, False, True, True, True, True, True)

    # Finalizes the undo process
    doc.EndUndo()

    # If the command was disabled, re CallCommand to disable it
    if not previousAutokeyEnableState:
        c4d.CallCommand(ID_AUTOKEYING_COMMAND)

    # Pushes an update event to Cinema 4D
    c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()

Cheers,
Maxime.

@m_adam Thank you for this quick response! It works.

Note: I'm not sure if this is just for me, but the script does not work on Frame 0 with AutoKey on unless there are existing Animation Tracks for the attributes (in this case op[c4d.PRIM_CUBE_SUBX] and op[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_X]).

It does work for me if the frame is higher than 0 and there are no existing Animation Tracks.

Thanks again!

Hi @blastframe this is also the behavior of AutoKey in the Editor, so I would say is not an API issue.

But you can use BaseDocument.Record to simulate the click of AddKeyFrame (but of course correct parameter have to be checked).

Cheers,
Maxime.