BaseTake Manual

About

A BaseTake object represents a take of the Take System. It stores BaseOverride objects that define how a specific entity is changed in the given take.

Access

BaseTake objects are returned from the BaseDocument via the TakeData object.

// This example accesses the main take of the
// given BaseDocument.
// get take data
TakeData* const takeData = doc->GetTakeData();
if (takeData == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// get the main take
BaseTake* const mainTake = takeData->GetMainTake();
if (mainTake == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
Definition: lib_takesystem.h:335
Definition: lib_takesystem.h:589
BaseTake * GetMainTake()
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
const char * doc
Definition: pyerrors.h:226

Allocation/Deallocation

A BaseTake is created and deleted using the TakeData object:

// This example creates a new take and makes it the first child of the main take
// get the main take
BaseTake* const mainTake = takeData->GetMainTake();
if (mainTake == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// create new take
BaseTake* const newTake = takeData->AddTake("this is a new take", nullptr, nullptr);
if (newTake == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
takeData->InsertTake(newTake, mainTake, INSERT_UNDER);
BaseTake * AddTake(const String &name, BaseTake *parent, BaseTake *cloneFrom)
void InsertTake(BaseTake *takeToMove, BaseTake *destTake, Int32 insertMode)
#define INSERT_UNDER
Insert under.
Definition: customgui_listview.h:597
Note
Always use TakeData::AddTake() to clone a take.

Navigation

Like many other entities takes are organized in a BaseList2D tree. One can use the typical functions to navigate that tree.

// This example loops through all takes that are direct child takes of the main take.
// get main take
const BaseTake* const mainTake = takeData->GetMainTake();
// get first child
const BaseTake* take = mainTake->GetDown();
// loop through
while (take != nullptr)
{
ApplicationOutput("Take Name: " + take->GetName());
// get next take in the row
take = take->GetNext();
}
String GetName() const
Definition: c4d_baselist.h:2543
BaseTake * GetNext() const
Definition: lib_takesystem.h:353
BaseTake * GetDown() const
Definition: lib_takesystem.h:371
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:204

Marked

Takes can be marked in the Take Manager. This allows to render just a subset of all takes. The API allows to manage this marked state:

// This example loops through the takes and inverts the checked state.
BaseTake* take = mainTake->GetDown();
while (take != nullptr)
{
// get checked
const Bool marked = take->IsChecked();
// set inverted
take->SetChecked(!marked);
take = take->GetNext();
}
void SetChecked(Bool status)
Bool IsChecked()
maxon::Bool Bool
Definition: ge_sys_math.h:51

Utility

Overrides

BaseOverride

A BaseOverride defines the parameter changes for a specific object in a BaseTake. BaseOverrides are managed using methods of BaseTake:

// This example searches for an existing override for the active object in the given take.
BaseObject* const object = doc->GetActiveObject();
if (object == nullptr)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
BaseOverride* const baseOverride = take->FindOverride(takeData, object);
if (baseOverride != nullptr)
{
ApplicationOutput("Found BaseOverride");
}
Definition: c4d_baseobject.h:248
Definition: lib_takesystem.h:79
BaseOverride * FindOverride(TakeData *takeData, BaseList2D *node)

Overrides can also be created automatically:

// This example creates a new take and overrides for the currently selected object.
BaseObject* const activeObject = doc->GetActiveObject();
if (activeObject == nullptr)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
BaseTake* const newTake = takeData->AddTake("this is a new take", nullptr, nullptr);
if (newTake == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
BaseOverride* const activeObjectOverride = newTake->OverrideNode(takeData, activeObject, false);
if (activeObjectOverride == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
BaseOverride * OverrideNode(TakeData *takeData, BaseList2D *node, Bool deleteAnim)

BaseTake::AutoTake() is especially useful to create the proper overrides when "Auto Take" is enabled. Just an unaltered clone of the changed object or the reference object from the undo stack is required:

// This example edits the given sphere object.
// If auto take is enabled, the current take is used.
// undo object as reference
// alternatively, on could access the undo cache with BaseDocument::GetUndoPtr() if applicable
BaseObject* undoObject = static_cast<BaseObject*>(sphereObject->GetClone(COPYFLAGS::NONE, nullptr));
if (undoObject == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// edit the object
sphereObject->SetParameter(ConstDescID(DescLevel(PRIM_SPHERE_RAD)), GeData(100.0), DESCFLAGS_SET::NONE);
// check for autotake
TakeData* const takeData = doc->GetTakeData();
// check if auto take mode is enabled
if (takeData && takeData->GetTakeMode() == TAKE_MODE::AUTO)
{
BaseTake* const currentTake = takeData->GetCurrentTake();
// check if the given take is not the main take
if (currentTake && !currentTake->IsMain())
{
currentTake->AutoTake(takeData, sphereObject, undoObject);
}
}
// free the clone
BaseObject::Free(undoObject);
static void Free(BaseObject *&bl)
Bool IsMain()
void AutoTake(TakeData *takeData, BaseList2D *node, BaseList2D *undo)
Definition: c4d_gedata.h:83
BaseTake * GetCurrentTake() const
TAKE_MODE GetTakeMode()
@ NONE
None.
@ AUTO
Auto override: the system overrides any edited parameter (similar to Auto Key).
#define ConstDescID(...)
Definition: lib_description.h:594
@ PRIM_SPHERE_RAD
Definition: osphere.h:6
Represents a level within a DescID.
Definition: lib_description.h:298

BaseOverrideGroup

Override groups act like virtual null objects. They allow to add certain tags to a selection of objects.

// This example adds a new take and creates a new override group for all selected objects.
// If a material with the name "Green" exists a texture tag referencing that material
// is added to the override group.
AutoAlloc<AtomArray> selectedObjects;
if (selectedObjects == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
doc->GetActiveObjects(selectedObjects, GETACTIVEOBJECTFLAGS::NONE);
if (selectedObjects->GetCount() == 0)
return maxon::OK;
// new take
BaseTake* const take = takeData->AddTake("Green Objects", nullptr, nullptr);
if (take == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// create override group
BaseOverrideGroup* const group = take->AddOverrideGroup();
if (group == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
group->SetName("Green Material"_s);
// if the material was found a texture tag should be added
BaseMaterial* const mat = doc->SearchMaterial("Green"_s);
if (mat != nullptr)
group->AddTag(takeData, Ttexture, mat);
// loop through all selected objects
for (Int32 i = 0; i < selectedObjects->GetCount(); ++i)
{
BaseList2D* const element = static_cast<BaseList2D*>(selectedObjects->GetIndex(i));
group->AddToGroup(takeData, element);
}
Py_ssize_t i
Definition: abstract.h:645
Definition: ge_autoptr.h:37
Definition: c4d_baselist.h:2376
void SetName(const maxon::String &name, Bool setDirty=true)
Definition: c4d_baselist.h:2549
Definition: c4d_basematerial.h:28
Definition: lib_takesystem.h:196
BaseTag * AddTag(TakeData *takeData, Int32 type, BaseMaterial *mat)
void AddToGroup(TakeData *takeData, BaseList2D *node)
BaseOverrideGroup * AddOverrideGroup()
maxon::Int32 Int32
Definition: ge_sys_math.h:56
return OK
Definition: apibase.h:2735
#define Ttexture
Texture - TextureTag.
Definition: ge_prepass.h:1411
PyObject * element
Definition: unicodeobject.h:1016

Camera

Takes also manage the camera currently in use. These functions allow to set and get the camera used for a certain take:

  • BaseTake::GetCamera(): Returns the camera used by this take which could also be the default camera or nullptr if the parent take's camera should be used.
  • BaseTake::GetEffectiveCamera(): Returns the camera that is effectively used by the given take.
  • BaseTake::SetCamera(): Sets the camera used for this take. nullptr means the parent take's settings should apply.
// This example creates a new take for each currently selected camera object.
// get the currently selected objects
AutoAlloc<AtomArray> selectedObjects;
if (selectedObjects == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
doc->GetActiveObjects(selectedObjects, GETACTIVEOBJECTFLAGS::NONE);
// loop through all selected objects
for (Int32 i = 0; i < selectedObjects->GetCount(); ++i)
{
C4DAtom* const element = selectedObjects->GetIndex(i);
if (element == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// check if the object is a camera object
if (element->GetType() == Ocamera)
{
CameraObject* const camera = static_cast<CameraObject*>(element);
// create a take for this camera object
const String takeName { "Take for camera " + camera->GetName() };
BaseTake* const cameraTake = takeData->AddTake(takeName, nullptr, nullptr);
if (cameraTake == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// set this camera object as this take's camera
cameraTake->SetCamera(takeData, camera);
}
}
void SetCamera(TakeData *takeData, BaseObject *camera)
Definition: c4d_baselist.h:1520
Definition: c4d_baseobject.h:1407
Definition: c4d_string.h:41
#define Ocamera
Camera - CameraObject.
Definition: ge_prepass.h:1046

Render Settings

Takes also manage render settings. As with the camera, it is possible to assign specific render settings to each take.

// This example gets the first RenderData and loops through all RenderData objects in that list.
// This won't loop through all RenderData elements since it ignores
// the child objects of these elements.
RenderData* renderData = doc->GetFirstRenderData();
while (renderData != nullptr)
{
// create new take
const String renderDataName = renderData->GetName();
const String takeName = "Take for RenderData " + renderDataName;
BaseTake* const renderDataTake = takeData->AddTake(takeName, nullptr, nullptr);
if (renderDataTake == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
// set this RenderData as this take's RenderData
renderDataTake->SetRenderData(takeData, renderData);
// get next element in the list
renderData = renderData->GetNext();
}
void SetRenderData(TakeData *takeData, RenderData *rData)
Definition: c4d_basedocument.h:143
RenderData * GetNext()
Definition: c4d_basedocument.h:174

Userdata

A BaseTake can host userdata that can help to identify the take along the production pipeline. This userdata is managed using the default BaseList2D methods:

// This example adds a new Boolean userdata parameter to the given BaseTake.
// accesses the userdata of the given take
if (desc == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// defines a new Boolean parameter
bc.SetString(DESC_NAME, "Enable"_s);
// creates the new userdata parameter
const DescID userData = desc->Alloc(bc);
// sets the value
const GeData data { true };
BaseContainer GetCustomDataTypeDefault(Int32 type)
Definition: c4d_basecontainer.h:48
void SetString(Int32 id, const maxon::String &s)
Definition: c4d_basecontainer.h:651
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
DynamicDescription * GetDynamicDescriptionWritable()
Definition: lib_description.h:355
Definition: lib_description.h:828
void * userData
Definition: fileobject.h:20
@ DESC_NAME
String Name for standalone use.
Definition: lib_description.h:91
@ DTYPE_BOOL
GV Bool. ID_GV_DATA_TYPE_BOOL.
Definition: lib_description.h:75
PyStructSequence_Desc * desc
Definition: structseq.h:26

See also DynamicDescription Manual.

Utility

// This example resets the current take if it is not the main take
BaseTake* const take = takeData->GetCurrentTake();
if (take == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
if (!take->IsMain())
take->Reset();
void Reset()

Further Reading