Open Search
    CTrack Manual

    About

    A CTrack represents an animation track of a parameter of an object in Cinema 4D. The tracks are stored with the animated object and contain curves and keys.

    CTrack objects are an instance of CTbase.

    // This example creates a track for the "Camera" parameter of the given Stage object.
    // Two keyframes for the given two camera objects are created.
    // search for the track and create a new one if needed
    CTrack* track = stage->FindCTrack(trackID);
    if (track == nullptr)
    {
    track = CTrack::Alloc(stage, trackID);
    if (track == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // add track to stage object
    stage->InsertTrackSorted(track);
    }
    CCurve* const curve = track->GetCurve();
    if (curve == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // Create first key
    CKey* const key1 = curve->AddKey(BaseTime(0.0));
    if (key1 == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    {
    GeData data;
    data.SetBaseList2D(camera1);
    key1->SetGeData(curve, data);
    }
    // Create second key
    CKey* const key2 = curve->AddKey(BaseTime(1.0));
    if (key2 == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    {
    GeData data;
    data.SetBaseList2D(camera2);
    key2->SetGeData(curve, data);
    }
    CTrack * FindCTrack(const DescID &id)
    Definition: c4d_baselist.h:2753
    Definition: c4d_basetime.h:25
    Definition: c4d_canimation.h:366
    CKey * AddKey(const BaseTime &time, Int32 *nidx=nullptr, Bool bUndo=false, Bool SynchronizeKeys=false)
    Definition: c4d_canimation.h:423
    Represents a key in the CCurve of a track which represent the animation of a parameter.
    Definition: c4d_canimation.h:58
    void SetGeData(CCurve *seq, const GeData &d)
    Sets the data of the key.
    Definition: c4d_canimation.h:177
    Definition: c4d_canimation.h:671
    static CTrack * Alloc(BaseList2D *bl, const DescID &id)
    CCurve * GetCurve(CCURVE type=CCURVE::CURVE, Bool bCreate=true)
    Definition: c4d_canimation.h:835
    Definition: lib_description.h:355
    Definition: c4d_gedata.h:83
    void SetBaseList2D(BaseList2D *bl)
    Definition: c4d_gedata.h:730
    #define MAXON_SCOPE
    Definition: apibase.h:2898
    @ DTYPE_BASELISTLINK
    BaseLink.
    Definition: lib_description.h:74
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:67
    #define ConstDescID(...)
    Definition: lib_description.h:594
    @ STAGEOBJECT_CLINK
    Definition: ostage.h:6
    const void * key2
    Definition: pycore_hashtable.h:79
    Represents a level within a DescID.
    Definition: lib_description.h:298

    Access

    The animation tracks of an object's parameters are stored with the object itself:

    Note
    The keyframe selection is defined with the BaseList2D class, see BaseList2D Manual.
    // This snippet loops through all animation tracks of the given object.
    const CTrack* track = obj->GetFirstCTrack();
    while (track != nullptr)
    {
    ApplicationOutput("Track: " + track->GetName());
    track = track->GetNext();
    }
    String GetName() const
    Definition: c4d_baselist.h:2412
    CTrack * GetNext() const
    Definition: c4d_canimation.h:716
    PyObject * obj
    Definition: complexobject.h:60
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:210

    Allocation/Deallocation

    A CTrack can be created with the usual tools:

    A newly created CTrack must be added to a host object:

    // This example checks if an animation track for the position X parameter
    // exists in the given object. If not, the track will be created.
    const DescLevel vectorXLevel = DescLevel(VECTOR_X, DTYPE_REAL, 0);
    const DescID id = CreateDescID(relPosLevel, vectorXLevel);
    CTrack* track = obj->FindCTrack(id);
    if (track == nullptr)
    {
    track = CTrack::Alloc(obj, id);
    if (track == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    track->SetName("My New Animation Track"_s);
    obj->InsertTrackSorted(track);
    }
    void SetName(const maxon::String &name, Bool setDirty=true)
    Definition: c4d_baselist.h:2419
    @ DTYPE_VECTOR
    Vector
    Definition: lib_description.h:70
    @ DTYPE_REAL
    Float
    Definition: lib_description.h:68
    @ VECTOR_X
    X component.
    Definition: lib_description.h:279
    #define CreateDescID(...)
    Definition: lib_description.h:595
    @ ID_BASEOBJECT_REL_POSITION
    Definition: obase.h:15

    To create special tracks the ID of that special track must be used. The special tracks are:

    // This example adds a sound track to the given object
    // and sets the referenced sound file.
    const DescID soundTrackID = ConstDescID(DescLevel(CTsound, CTsound, 0));
    CTrack* const soundTrack = CTrack::Alloc(obj, soundTrackID);
    if (soundTrack == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    soundTrack->SetName("New Sound Track"_s);
    obj->InsertTrackSorted(soundTrack);
    Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
    @ CID_SOUND_NAME
    Definition: ctsound.h:7
    #define CTsound
    Sound.
    Definition: ge_prepass.h:1531
    // This example adds a PLA track to the polygon object.
    const DescID plaID = ConstDescID(DescLevel(CTpla, CTpla, 0));
    CTrack* const plaTrack = CTrack::Alloc(polyObject, plaID);
    if (plaTrack == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    polyObject->InsertTrackSorted(plaTrack);
    CCurve* curve = plaTrack->GetCurve();
    if (curve == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // set first key
    CKey* const key1 = curve->AddKey(BaseTime(0.0));
    if (key1 == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    plaTrack->FillKey(doc, polyObject, key1);
    // change polygon object randomly
    Random random;
    for (Int32 i = 0; i < count; ++i)
    points[i] = points[i] + Vector(0, 100.0 * random.Get01(), 0.0);
    polyObject->Message(MSG_UPDATE);
    // set second key
    CKey* const key2 = curve->AddKey(BaseTime(1.0));
    if (key2 == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    plaTrack->FillKey(doc, polyObject, key2);
    Py_ssize_t i
    Definition: abstract.h:645
    Py_ssize_t count
    Definition: abstract.h:640
    Bool FillKey(BaseDocument *doc, BaseList2D *bl, CKey *key)
    Definition: c4d_canimation.h:821
    Definition: c4d_tools.h:835
    MAXON_ATTRIBUTE_FORCE_INLINE Float Get01()
    Definition: c4d_tools.h:865
    maxon::Vec3< maxon::Float64, 1 > Vector
    Definition: ge_math.h:145
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    #define MSG_UPDATE
    Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
    Definition: c4d_baselist.h:359
    #define CTpla
    PLA.
    Definition: ge_prepass.h:1530
    const char * doc
    Definition: pyerrors.h:226

    Navigation

    CTrack objects are stored in a list:

    // This snippet loops through all animation tracks of the given object.
    const CTrack* track = obj->GetFirstCTrack();
    while (track != nullptr)
    {
    ApplicationOutput("Track: " + track->GetName());
    track = track->GetNext();
    }
    Note
    The GeListHead object that is the parent of the tracks can be obtained with BaseList2D::GetCTrackRoot().

    Read-Only Properties

    Several values can be read from a CTrack:

    The track categories are:

    // This example checks if the given track is a "value" track.
    // If so, the current value is printed to the console.
    // check if the track is "value" track (float)
    {
    const BaseTime now = doc->GetTime();
    const Float value = track->GetValue(doc, now);
    }
    PyObject * value
    Definition: abstract.h:715
    Int32 GetTrackCategory() const
    Definition: c4d_canimation.h:851
    Float GetValue(const BaseDocument *doc, const BaseTime &time) const
    Definition: c4d_canimation.h:865
    static String FloatToString(Float32 v, Int32 vvk=-1, Int32 nnk=-3)
    Definition: c4d_string.h:529
    maxon::Float Float
    Definition: ge_sys_math.h:66
    #define CTRACK_CATEGORY_VALUE
    Value track.
    Definition: c4d_canimation.h:633

    See also CKey Value.

    Properties

    Parameters

    The parameters of a track can be edited as usual with C4DAtom::SetParameter() and C4DAtom::GetParameter(). The parameter IDs are defined in ctbase.h.

    // This example sets the color to display the track's f-curve:
    const Vector red { 1.0, 0, 0 };
    @ ID_CTRACK_USE_PREF
    Definition: ctbase.h:38
    @ ID_CTRACK_FCURVE_COLOR
    Definition: ctbase.h:10

    Selection

    In Cinema 4D there can be up to four timeline windows. An animation track can be selected in one or multiple of these windows. The selection state is stored as a bit:

    // This example selects the given track if it does not contain any keys.
    const CCurve* const curve = track->GetCurve();
    if (curve)
    {
    const Int32 keyCount = curve->GetKeyCount();
    if (keyCount == 0)
    else
    }
    Int32 GetKeyCount() const
    Definition: c4d_canimation.h:381
    Bool ChangeNBit(NBIT bit, NBITCONTROL bitmode)
    @ CLEAR
    Clear bit.
    @ SET
    Set bit.
    @ TL1_SELECT
    Selection bit for Timeline 1.

    See also CKey Selection.

    Description ID

    The parameter animated using a certain track is defined with its DescID. This DescID can be accessed:

    // This example clones a track and sets the new description ID of that clone.
    const DescLevel vectorXLevel(VECTOR_X, DTYPE_REAL, 0);
    const DescID ID = CreateDescID(relPosLevel, vectorXLevel);
    // find track
    CTrack* const track = obj->FindCTrack(ID);
    if (track == nullptr)
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    // get track root and create it if it does not already exists
    GeListHead* trackRoot = obj->GetCTrackRoot(true);
    if (trackRoot == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // clone track
    CTrack* const clone = static_cast<CTrack*>(track->GetClone(COPYFLAGS::NONE, nullptr));
    if (clone == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // insert and set new ID
    const DescLevel vectorYLevel(VECTOR_Y, DTYPE_REAL, 0);
    const DescID targetID = CreateDescID(relPosLevel, vectorYLevel);
    trackRoot->InsertLast(clone);
    clone->SetDescriptionID(obj, targetID);
    C4DAtom * GetClone(COPYFLAGS flags, AliasTrans *trn) const
    Definition: c4d_baselist.h:1481
    Bool SetDescriptionID(BaseList2D *object, const DescID &id)
    Definition: c4d_canimation.h:741
    Definition: c4d_baselist.h:2077
    void InsertLast(GeListNode *bn)
    Definition: c4d_baselist.h:2164
    @ NONE
    None.
    @ VECTOR_Y
    Y component.
    Definition: lib_description.h:280

    Loop Settings

    The loop settings define how an animation track should behave before the first key and after the last key.

    The loop types are:

    // This example defines the loop settings of the given track.
    void SetBefore(CLOOP type)
    Definition: c4d_canimation.h:758
    void SetAfter(CLOOP type)
    Definition: c4d_canimation.h:770
    @ OFFSETREPEAT
    Offset repeat.
    @ CONSTANT
    Constant.

    Points in time beyond the defined animation track can be mapped into time inside the track.

    • CTrack::Remap(): Remaps the given time into a position inside the animation track.
    // This example calculates the remapped time for each given time in seconds.
    // loop from 0.0 to 1.0
    for (Float64 t = 0.0; t < 10.0; t = t + 0.1)
    {
    Float64 remapTime;
    Int32 cycle;
    track->Remap(t, &remapTime, &cycle);
    ApplicationOutput("Remap Time: " + String::FloatToString(remapTime));
    }
    Bool Remap(Float64 time, Float64 *ret_time, Int32 *ret_cycle) const
    Definition: c4d_canimation.h:895
    maxon::Float64 Float64
    Definition: ge_sys_math.h:67

    Time Track

    The behavior of an animation track depends on the current time which is typically the current time of the BaseDocument. But the time that controls a track can be also defined with a time track.

    // This example applies the found time track to all other tracks.
    // search for time track
    CTrack* const timeTrack = obj->FindCTrack(ConstDescID(DescLevel(CTtime)));
    if (timeTrack == nullptr)
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    // apply time track to other tracks
    CTrack* track = obj->GetFirstCTrack();
    while (track != nullptr)
    {
    const DescID id = track->GetDescriptionID();
    // check if the track is not a "Time" track
    if (id[0].id != CTtime)
    track->SetTimeTrack(timeTrack);
    track = track->GetNext();
    }
    void SetTimeTrack(CTrack *track)
    Definition: c4d_canimation.h:788
    const DescID & GetDescriptionID() const
    Definition: c4d_canimation.h:733
    #define CTtime
    Time.
    Definition: ge_prepass.h:1533

    Timeline Height

    An animation track can be displayed in a Timeline window.

    Track Information

    An animation track can provide additional information for each key or the current time in form of a String.

    // This example prints the information for each key of the track.
    CKey* const key = curve->GetKey(i);
    if (key == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    track->TrackInformation(doc, key, &info, false);
    PyObject * key
    Definition: abstract.h:289
    const CKey * GetKey(Int32 index) const
    Definition: c4d_canimation.h:388
    Bool TrackInformation(BaseDocument *doc, CKey *key, maxon::String *str, Bool set)
    Definition: c4d_canimation.h:906
    Definition: c4d_string.h:39
    _Py_clock_info_t * info
    Definition: pytime.h:197

    Synchronisation

    Multiple tracks can be synchronized. Typically this applies to tracks of the components of a Vector parameter.

    Functionality

    Since a track might be displayed in the GUI (Timeline window) it can draw an image:

    // This example calls the "Draw" function of the given sound track
    // and displays the result image.
    if (clipMap == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    if (clipMap->Init(400, 100, 32) != IMAGERESULT::OK)
    return maxon::UnknownError(MAXON_SOURCE_LOCATION);
    clipMap->BeginDraw();
    soundTrack->Draw(clipMap, BaseTime(0), BaseTime(1.0));
    clipMap->EndDraw();
    ShowBitmap(clipMap->GetBitmap());
    Bool ShowBitmap(const Filename &fn)
    Definition: ge_autoptr.h:37
    Bool Draw(GeClipMap *map, const BaseTime &clip_left, const BaseTime &clip_right) const
    Definition: c4d_canimation.h:812
    @ OK
    Image loaded/created.

    Further utility functions are:

    // This eample accesses the CCurve from the given animation track.
    CCurve* const curve = track->GetCurve();
    if (curve)
    {
    // do something with the curve
    }

    See also CCurve Manual.

    Further Reading