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.

  • TakeData::GetMainTake(): Returns the main take.
  • TakeData::GetCurrentTake(): Returns the currently selected take.
  • TakeData::SetCurrentTake(): Sets the given take as the current take.
  • TakeData::GetTakeSelection(): Gets the selection of takes.
// 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);
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:69
const char * doc
Definition: pyerrors.h:226

Allocation/Deallocation

A BaseTake is created and deleted using the TakeData object:

  • TakeData::AddTake(): Adds a new take.
  • TakeData::InsertTake(): Moves a take in the hierarchy.
  • TakeData::DeleteTake(): Deletes the given take.
// 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);
#define INSERT_UNDER
Insert under.
Definition: customgui_listview.h:596
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.

  • BaseTake::GetNext(): Returns the next take in the row.
  • BaseTake::GetPred(): Returns the previous take in the row.
  • BaseTake::GetUp(): Returns the parent take if it exists.
  • BaseTake::GetDown(): Returns the first child take if it exists.
  • BaseTake::GetDownLast(): Returns the last child take.
// 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();
}
#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:

  • BaseTake::SetChecked(): Sets the mark status.
  • BaseTake::IsChecked(): Returns the mark status.
// 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();
}
maxon::Bool Bool
Definition: ge_sys_math.h:46

Utility

  • BaseTake::IsMain(): Returns true if the take is the main take.
  • BaseTake::SearchHierarchy(): Returns true if the take is a child of the given take.

Overrides

BaseOverride

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

  • BaseTake::GetOverrides(): Returns the BaseOverrides of the take.
  • BaseTake::FindOrAddOverrideParam(): Finds and if necessary creates an override for the given object and parameter.
  • BaseTake::DeleteOverride(): Deletes a specific parameter override.
  • BaseTake::FindOverride(): Returns the override if the given node is overridden.
  • BaseTake::FindOverrideInHierarchy(): Returns the override for the given node and given parameter ID by searching the entire hierarchy.
// 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");
}

Overrides can also be created automatically:

  • BaseTake::OverrideNode(): Overrides all parameters of the passed node.
  • BaseTake::AutoTake(): Compares the two given nodes and creates needed overrides.
// 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);

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);
NONE
Definition: asset_browser.h:1
#define ConstDescID(...)
Definition: lib_description.h:592
AUTO
Definition: lib_birender.h:1
@ PRIM_SPHERE_RAD
Definition: osphere.h:6

BaseOverrideGroup

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

  • BaseTake::GetFirstOverrideGroup(): Returns the first override group of the take.
  • BaseTake::AddOverrideGroup(): Adds an override group to the take.
  • BaseTake::GetOverrideGroups(): Returns an array with all override groups of the take.
  • BaseTake::DeleteOverrideGroup(): Deletes the given override group.
// 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
return OK
Definition: apibase.h:2740
#define Ttexture
Texture - TextureTag.
Definition: ge_prepass.h:1420
maxon::Int32 Int32
Definition: ge_sys_math.h:51
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);
}
}
#define Ocamera
Camera - CameraObject.
Definition: ge_prepass.h:1045

Render Settings

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

  • BaseTake::GetRenderData(): Returns the assigned RenderData. Might be nullptr, if the parent take's render settings should be used.
  • BaseTake::GetEffectiveRenderData(): Returns the effective RenderData.
  • BaseTake::SetRenderData(): Sets the RenderData used with this Take. nullptr is used to reset.
// 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();
}

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
DynamicDescription* const desc = take->GetDynamicDescriptionWritable();
if (desc == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// defines a new Boolean parameter
BaseContainer bc = GetCustomDataTypeDefault(DTYPE_BOOL);
bc.SetString(DESC_NAME, "Enable"_s);
// creates the new userdata parameter
const DescID userData = desc->Alloc(bc);
// sets the value
const GeData data { true };
take->SetParameter(userData, data, DESCFLAGS_SET::NONE);
void * userData
Definition: fileobject.h:20
@ DESC_NAME
String Name for standalone use.
Definition: lib_description.h:90
@ DTYPE_BOOL
GV Bool. ID_GV_DATA_TYPE_BOOL.
Definition: lib_description.h:74
BaseContainer GetCustomDataTypeDefault(Int32 type)
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();

Further Reading