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.
const DescID trackID = ConstDescID(DescLevel(STAGEOBJECT_CLINK, DTYPE_BASELISTLINK, 0));
// 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);
}
#define MAXON_SCOPE
Definition: apibase.h:2891
@ DTYPE_BASELISTLINK
BaseLink.
Definition: lib_description.h:73
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:69
#define ConstDescID(...)
Definition: lib_description.h:592
@ STAGEOBJECT_CLINK
Definition: ostage.h:6
const void * key2
Definition: pycore_hashtable.h:79

Access

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

  • BaseList2D::GetFirstCTrack(): Returns the first CTrack stored with the object.
  • BaseList2D::FindCTrack(): Returns the track associated with the given DescID. See example above.
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();
}
PyObject * obj
Definition: complexobject.h:60
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:204

Allocation/Deallocation

A CTrack can be created with the usual tools:

  • CTrack::Alloc(): Creates a new CTrack.
  • CTrack::Free(): Deletes the given CTrack.

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

  • BaseList2D::InsertTrackSorted(): Adds the track to the object. The object takes ownership.
  • CTrack::GetObject(): Returns the object that owns the CTrack.
// 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 relPosLevel = DescLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0);
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);
}
@ VECTOR_X
Definition: dvector.h:6
@ DTYPE_VECTOR
Vector
Definition: lib_description.h:69
@ DTYPE_REAL
Float
Definition: lib_description.h:67
#define CreateDescID(...)
Definition: lib_description.h:593
@ 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->SetParameter(ConstDescID(DescLevel(CID_SOUND_NAME)), soundFile, DESCFLAGS_SET::NONE);
soundTrack->SetName("New Sound Track"_s);
obj->InsertTrackSorted(soundTrack);
NONE
Definition: asset_browser.h:1
@ CID_SOUND_NAME
Definition: ctsound.h:7
#define CTsound
Sound.
Definition: ge_prepass.h:1553
// 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
#define MSG_UPDATE
Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
Definition: c4d_baselist.h:372
#define CTpla
PLA.
Definition: ge_prepass.h:1552
maxon::Int32 Int32
Definition: ge_sys_math.h:51
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:140
const char * doc
Definition: pyerrors.h:226

Navigation

CTrack objects are stored in a list:

  • CTrack::GetNext(): Returns the previous CTrack in the list or nullptr.
  • CTrack::GetPred(): Returns the next CTrack in the list or nullptr.
// 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:

  • CTrack::GetTrackCategory(): Returns the track category.
  • CTrack::GetValue(): Returns the track value for the given time.
  • CTrack::GetUnit(): Returns the value unit and step size. These are the settings used with ::DESC_UNIT and ::DESC_STEP.

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)
if (track->GetTrackCategory() == CTRACK_CATEGORY_VALUE)
{
const BaseTime now = doc->GetTime();
const Float value = track->GetValue(doc, now);
ApplicationOutput("Value: " + String::FloatToString(value));
}
PyObject * value
Definition: abstract.h:715
#define CTRACK_CATEGORY_VALUE
Value track.
Definition: c4d_canimation.h:632
maxon::Float Float
Definition: ge_sys_math.h:57

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:
track->SetParameter(ConstDescID(DescLevel(ID_CTRACK_USE_PREF)), false, DESCFLAGS_SET::NONE);
const Vector red { 1.0, 0, 0 };
track->SetParameter(ConstDescID(DescLevel(ID_CTRACK_FCURVE_COLOR)), GeData { red }, DESCFLAGS_SET::NONE);
@ 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)
track->ChangeNBit(NBIT::TL1_SELECT, NBITCONTROL::SET);
else
track->ChangeNBit(NBIT::TL1_SELECT, NBITCONTROL::CLEAR);
}
SET
Set.
Definition: c4d_baselist.h:1
TL1_SELECT
Selection bit for Timeline 1.
Definition: ge_prepass.h:7
CLEAR
Clear bit.
Definition: ge_prepass.h:1

See also CKey Selection.

Description ID

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

  • CTrack::GetDescriptionID(): Returns the DescID of the track.
  • CTrack::SetDescriptionID(): Sets the DescID of the track.
// This example clones a track and sets the new description ID of that clone.
const DescLevel relPosLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0);
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);
@ VECTOR_Y
Definition: dvector.h:7

Loop Settings

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

  • CTrack::GetBefore(): Returns the pre-track loop type.
  • CTrack::SetBefore(): Sets the pre-track loop type.
  • CTrack::GetAfter(): Returns the post-track loop type.
  • CTrack::SetAfter(): Sets the post-track loop type.

The loop types are:

// This example defines the loop settings of the given track.
track->SetBefore(CLOOP::CONSTANT);
track->SetAfter(CLOOP::OFFSETREPEAT);
OFFSETREPEAT
Offset repeat.
Definition: ge_prepass.h:4
CONSTANT
Constant.
Definition: ge_prepass.h:1

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));
}
maxon::Float64 Float64
Definition: ge_sys_math.h:58

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.

  • CTrack::GetTimeTrack(): Returns the assigned time track.
  • CTrack::SetTimeTrack(): Sets the assigned 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();
}
#define CTtime
Time.
Definition: ge_prepass.h:1555

Timeline Height

An animation track can be displayed in a Timeline window.

  • CTrack::GetHeight(): Returns the height of the track.
  • CTrack::GetTLHeight(): Returns the height of the mini F-Curves in the Timeline.
  • CTrack::SetTLHeight(): Sets the height of the mini F-Curves in the Timeline.

Track Information

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

  • CTrack::TrackInformation(): Returns or sets the information.
// 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);
PyObject * key
Definition: abstract.h:289
_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.

  • CTrack::IsSynchronized(): Returns true if the track is synchronized.
  • CTrack::SetSynchronized(): Sets the synchronization status.

Functionality

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

  • CTrack::GuiMessage(): Sends GUI messages to the track.
  • CTrack::Draw(): Fills the given GeClipMap. See GeClipMap Manual.
// This example calls the "Draw" function of the given sound track
// and displays the result image.
AutoAlloc<GeClipMap> clipMap;
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());
OK
User has selected a font.
Definition: customgui_fontchooser.h:0
Bool ShowBitmap(const Filename &fn)

Further utility functions are:

  • CTrack::FillKey(): Fills the given key with default values.
  • CTrack::FlushData(): Flushes the track data.
  • CTrack::GetCurve(): Returns the curve stored in with the track.
// 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