UNSOLVED Python script to keyframe visibility of object

Hello,

I'm pretty new to C4D and I am tasked with creating a script.
What I want to achieve is pretty basic, in theory, but I have been struggling so I hope you'll be able to provide me with a solution.

I want to toggle the visibility of an object and keyframe that parameter.
Here's what I've tried so far:

import c4d
from c4d import gui


def main():
    # c4d.CallCommand(12410)
    curTime = doc.GetTime()
    fps = doc[c4d.DOCUMENT_FPS]
    obj = doc.SearchObject('Tshirt_white')

    print(obj)
    print(curTime.GetFrame(fps))

    # setting visibility ON
    obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 0

    # getting the animation track for the object's visibility'
    visTrack = c4d.CTrack(obj, c4d.ID_BASEOBJECT_VISIBILITY_EDITOR)

    # getting the curve? of the track
    curve = visTrack.GetCurve()

    # adding a keyframe to the curve of the track
    keyDict = curve.AddKey (curTime)

    # no idea what's going on here
    visTrack.FillKey (doc, obj, keyDict["key"])
    obj.InsertTrackSorted(visTrack)

Some of these comments might be wrong as I'm not entirely sure what I'm doing and the documentation is not a lot of help.

This does change the value of the editor visibility and toggles the keyFrame indicator orange. Orange is not really the color I want though as it doesn't save the value if I move up one frame and come back.

Any suggestions would be appreciated.

Well I found the solution.

I was creating a new CTrack instead of getting the one already attached to the object. That lead to a conflict, I imagine. Anyway it's working now.

Hello @augustin,

thank you for reaching out to us. It is great that you found a solution, but since you did not post your solution and your previous code also contained some problems, I have provided a small code example at the end of the posting. Helpful for this and future animation endeavors with the Python API might also be our animation examples section on GitHub.

Cheers,
Ferdinand

The result:
723ed914-03ad-44cc-bcd2-4ceb53358dc5-image.png
The code:

"""Example for creating tracks and keys in an object and setting the values
of keys.

To be run as a script manger script.
"""

import c4d


def main():
    """Crates a short visibility animation in the selected object.
    """
    # op is a predefined attribute pointing to the selected object in script
    # manger script. When op is None, then there is no selection.
    if op is None:
        raise RuntimeError("Please select an object.")

    # Attempt to get an existing animation track for the visibility of op or
    # create a new one when there is no existing track.
    visibiltyTrack = op.FindCTrack(c4d.ID_BASEOBJECT_VISIBILITY_EDITOR)
    if visibiltyTrack is None:
        visibiltyTrack = c4d.CTrack(op, c4d.ID_BASEOBJECT_VISIBILITY_EDITOR)
        if visibiltyTrack is None:
            raise MemoryError("Could not allocate track.")
        op.InsertTrackSorted(visibiltyTrack)

    # Print out the category type of the track which is important for
    # handling key values.
    print (f"{visibiltyTrack.GetTrackCategory()=}")
    # Get the standard curve of the track, containing all its keys.
    curve = visibiltyTrack.GetCurve()

    # Modify the keys at second 0 and 1 in the curve.
    for t, value in [(0., c4d.OBJECT_OFF), (1., c4d.OBJECT_ON)]:
        # Attempt to get an existing key at the given time.
        result = curve.FindKey(c4d.BaseTime(t))
        # Or create a new one when no key can be found.
        if result is None:
            result = curve.AddKey(c4d.BaseTime(t))
            if result is None:
                raise MemoryError("Could not allocate key.")

        # Set the value of the key, OBJECT_OFF for t=0 and OBJECT_ON for t=1.
        # This must be done with SetGeData() and not with SetValue() since
        # visibility track is of category type data.
        result["key"].SetGeData(curve, value)
        # Set the interpolation of the key.
        result["key"].SetInterpolation(curve, c4d.CINTERPOLATION_STEP)

    # Push an update event to Cinema 4D, so that the changes we made are
    # being reflected in the GUI.
    c4d.EventAdd()

if __name__ == '__main__':
    main()