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);
}

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();
}

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 = DescID(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);
}

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 DescLevel soundTrackID = 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);
// This example adds a PLA track to the polygon object.
const DescID plaID = 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);

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);
}

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 };

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
}

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 = DescID(relPosLevel, vectorXLevel);
// find track
CTrack* const track = obj->FindCTrack(ID);
if (track == nullptr)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
// get track root
GeListHead* const trackRoot = obj->GetCTrackRoot();
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 = DescID(relPosLevel, vectorYLevel);
trackRoot->InsertLast(clone);
clone->SetDescriptionID(obj, targetID);

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.

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));
}

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.
// serach for time track
CTrack* const timeTrack = obj->FindCTrack(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();
}

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);
String info;
track->TrackInformation(doc, key, &info, false);

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());

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

String::FloatToString
static String FloatToString(Float32 v, Int32 vvk=-1, Int32 nnk=-3)
Definition: c4d_string.h:529
IMAGERESULT::OK
@ OK
Image loaded/created.
NBITCONTROL::SET
@ SET
Set bit.
CTrack::Alloc
static CTrack * Alloc(BaseList2D *bl, const DescID &id)
BaseTime
Definition: c4d_basetime.h:24
GeClipMap::Init
IMAGERESULT Init(Int32 w, Int32 h, Int32 bits)
C4DAtom::GetClone
C4DAtom * GetClone(COPYFLAGS flags, AliasTrans *trn)
Definition: c4d_baselist.h:1447
DescID
Definition: lib_description.h:328
GeListNode::ChangeNBit
Bool ChangeNBit(NBIT bit, NBITCONTROL bitmode)
VECTOR_X
@ VECTOR_X
X component.
Definition: lib_description.h:268
CCurve::GetKey
const CKey * GetKey(Int32 index) const
Definition: c4d_canimation.h:377
Float
maxon::Float Float
Definition: ge_sys_math.h:66
ID_BASEOBJECT_REL_POSITION
@ ID_BASEOBJECT_REL_POSITION
Definition: obase.h:15
DTYPE_BASELISTLINK
@ DTYPE_BASELISTLINK
BaseLink.
Definition: lib_description.h:74
CTrack::SetTimeTrack
void SetTimeTrack(CTrack *track)
Definition: c4d_canimation.h:777
CTrack::SetAfter
void SetAfter(CLOOP type)
Definition: c4d_canimation.h:759
ID_CTRACK_FCURVE_COLOR
@ ID_CTRACK_FCURVE_COLOR
Definition: ctbase.h:10
CCurve
Definition: c4d_canimation.h:354
CTrack::GetDescriptionID
const DescID & GetDescriptionID() const
Definition: c4d_canimation.h:722
BaseList2D::InsertTrackSorted
void InsertTrackSorted(CTrack *track)
MAXON_SOURCE_LOCATION
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:66
CTtime
#define CTtime
Time.
Definition: ge_prepass.h:1330
BaseList2D::FindCTrack
CTrack * FindCTrack(const DescID &id)
CCurve::AddKey
CKey * AddKey(const BaseTime &time, Int32 *nidx=nullptr, Bool bUndo=false, Bool SynchronizeKeys=false)
Definition: c4d_canimation.h:412
DESCFLAGS_SET::NONE
@ NONE
None.
VECTOR_Y
@ VECTOR_Y
Y component.
Definition: lib_description.h:269
CTrack
Definition: c4d_canimation.h:659
CTrack::SetBefore
void SetBefore(CLOOP type)
Definition: c4d_canimation.h:747
CTrack::GetValue
Float GetValue(BaseDocument *doc, const BaseTime &time)
Definition: c4d_canimation.h:844
CTpla
#define CTpla
PLA.
Definition: ge_prepass.h:1327
STAGEOBJECT_CLINK
@ STAGEOBJECT_CLINK
Definition: ostage.h:6
GeClipMap::BeginDraw
void BeginDraw()
Must be called before any drawing functions.
GeClipMap::GetBitmap
BaseBitmap * GetBitmap()
MSG_UPDATE
#define MSG_UPDATE
Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
Definition: c4d_baselist.h:340
String
Definition: c4d_string.h:38
CTrack::FillKey
Bool FillKey(BaseDocument *doc, BaseList2D *bl, CKey *key)
Definition: c4d_canimation.h:810
CLOOP::OFFSETREPEAT
@ OFFSETREPEAT
Offset repeat.
C4DAtom::SetParameter
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
CTrack::GetNext
CTrack * GetNext() const
Definition: c4d_canimation.h:705
maxon::Vec3< maxon::Float64, 1 >
BaseDocument::GetTime
BaseTime GetTime(void) const
DTYPE_VECTOR
@ DTYPE_VECTOR
Vector
Definition: lib_description.h:70
DescLevel
Represents a level within a DescID.
Definition: lib_description.h:287
CKey::SetGeData
void SetGeData(CCurve *seq, const GeData &d)
Definition: c4d_canimation.h:170
CTrack::GetTrackCategory
Int32 GetTrackCategory() const
Definition: c4d_canimation.h:830
GeData::SetBaseList2D
void SetBaseList2D(BaseList2D *bl)
Definition: c4d_gedata.h:657
GeData
Definition: c4d_gedata.h:82
BaseList2D::SetName
void SetName(const maxon::String &name)
Definition: c4d_baselist.h:2354
Int32
maxon::Int32 Int32
Definition: ge_sys_math.h:60
ApplicationOutput
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:208
C4DAtom::Message
Bool Message(Int32 type, void *data=nullptr)
Definition: c4d_baselist.h:1424
CKey
Definition: c4d_canimation.h:57
ShowBitmap
Bool ShowBitmap(const Filename &fn)
CTrack::TrackInformation
Bool TrackInformation(BaseDocument *doc, CKey *key, maxon::String *str, Bool set)
Definition: c4d_canimation.h:885
GeListHead::InsertLast
void InsertLast(GeListNode *bn)
Definition: c4d_baselist.h:2095
CID_SOUND_NAME
@ CID_SOUND_NAME
Definition: ctsound.h:7
ID_CTRACK_USE_PREF
@ ID_CTRACK_USE_PREF
Definition: ctbase.h:38
Vector
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:145
CTrack::Draw
Bool Draw(GeClipMap *map, const BaseTime &clip_left, const BaseTime &clip_right) const
Definition: c4d_canimation.h:801
Random::Get01
Float Get01(void)
CTRACK_CATEGORY_VALUE
#define CTRACK_CATEGORY_VALUE
Value track.
Definition: c4d_canimation.h:622
AutoAlloc
Definition: ge_autoptr.h:36
CTrack::Remap
Bool Remap(Float64 time, Float64 *ret_time, Int32 *ret_cycle) const
Definition: c4d_canimation.h:874
NBIT::TL1_SELECT
@ TL1_SELECT
Selection bit for Timeline 1.
GeClipMap::EndDraw
void EndDraw()
Must be called after a sequence of drawing functions to free the memory allocated by BeginDraw().
Random
Definition: c4d_tools.h:811
BaseList2D::GetName
String GetName() const
Definition: c4d_baselist.h:2348
DTYPE_REAL
@ DTYPE_REAL
Float
Definition: lib_description.h:68
CTrack::GetCurve
CCurve * GetCurve(CCURVE type=CCURVE::CURVE, Bool bCreate=true)
Definition: c4d_canimation.h:824
BaseList2D::GetFirstCTrack
CTrack * GetFirstCTrack()
GeListHead
Definition: c4d_baselist.h:2010
MAXON_SCOPE
#define MAXON_SCOPE
Definition: apibase.h:2659
COPYFLAGS::NONE
@ NONE
None.
CTrack::SetDescriptionID
Bool SetDescriptionID(BaseList2D *object, const DescID &id)
Definition: c4d_canimation.h:730
CCurve::GetKeyCount
Int32 GetKeyCount(void) const
Definition: c4d_canimation.h:370
NBITCONTROL::CLEAR
@ CLEAR
Clear bit.
Float64
maxon::Float64 Float64
Definition: ge_sys_math.h:67
CTsound
#define CTsound
Sound.
Definition: ge_prepass.h:1328
CLOOP::CONSTANT
@ CONSTANT
Constant.