-
首页
-
C4D R23.110 C++ SDK
BaseDocument
Manual
内容表
关于
A
BaseDocument
represents a
Cinema 4D
scene with all its content.
Cinema 4D
can manage multiple open scenes simultaneously in a document list. It is possible to load, create, edit, render and save scenes in the background. A document contains:
-
Objects, materials and tags
-
Render settings
-
Document settings
-
层
-
Takes
-
Scene hooks
-
Undo actions
-
警告
-
The active
BaseDocument
is the scene currently displayed in the editor. This active
BaseDocument
must not be edited from another thread than the main thread. Watch out for functions marked as "called in a thread context". If one needs to change the document from an asynchronous dialog,
StopAllThreads()
must be called before.
BaseDocument
objects are an instance of
Tbasedocument
.
// This example shows how to create a virtual document, add a cube and render the document.
// create document
AutoAlloc<BaseDocument>
virtualDoc;
if
(virtualDoc ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// create and add a new cube
BaseObject
*
const
cube =
BaseObject::Alloc
(
Ocube
);
if
(cube ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
virtualDoc->
InsertObject
(cube,
nullptr
,
nullptr
);
// prepare bitmap
AutoAlloc<BaseBitmap>
bitmap;
if
(bitmap ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
const
Int32
width = 1280;
const
Int32
height = 720;
const
IMAGERESULT
imageRes = bitmap->
Init
(width, height);
if
(imageRes !=
IMAGERESULT::OK
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// define render settings
RenderData
*
const
rdata = virtualDoc->
GetActiveRenderData
();
if
(rdata ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
BaseContainer
renderSettings = rdata->
GetData
();
renderSettings.
SetFloat
(
RDATA_XRES
, width);
renderSettings.
SetFloat
(
RDATA_YRES
, height);
// render the document
const
RENDERFLAGS
flags =
RENDERFLAGS::NODOCUMENTCLONE
;
const
RENDERRESULT
res =
RenderDocument
(virtualDoc, renderSettings,
nullptr
,
nullptr
, bitmap, flags,
nullptr
);
if
(res !=
RENDERRESULT::OK
)
return
maxon::UnknownError(
MAXON_SOURCE_LOCATION
);
// show result
ShowBitmap
(bitmap);
Access
Cinema 4D
can handle multiple open scenes in a document list:
To navigate the document list GetNext() and GetPred() can be used:
// This example iterates through all BaseDocuments in the document list.
// The active BaseDocument is marked with a star.
const
BaseDocument
*
const
activeDocument =
GetActiveDocument
();
if
(activeDocument ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
BaseDocument
* document =
GetFirstDocument
();
while
(document !=
nullptr
)
{
const
GeMarker
& docMarker = document->
GetMarker
();
const
GeMarker
& activeDocMarker = activeDocument->
GetMarker
();
// use GeMarker to compare identity of the BaseDocuments
if
(docMarker.
IsEqual
(activeDocMarker))
{
ApplicationOutput
(
"Document: "
+ document->
GetDocumentName
().
GetString
() +
" *"
);
}
else
{
ApplicationOutput
(
"Document: "
+ document->
GetDocumentName
().
GetString
());
}
document = document->
GetNext
();
}
-
注意
-
GetActiveDocument()
and
GetFirstDocument()
only work in
Cinema 4D
versions that have an active document (not in Team Render Client, Command Line etc.). Use
GetActiveDocument()
only in combination with dialogs etc. but NEVER in
NodeData
based plugins or expressions.
-
GeListNode::GetDocument()
returns the
BaseDocument
that hosts a given entity. Use this method to access the document in a
NodeData
based plugin and all functions that are part of the execution or drawing pipeline. But never forget to check for
nullptr
, as there are situations where elements are not part of any document at all.
Allocation/Deallocation
A
BaseDocument
can be created with the usual tools:
AutoAlloc
can be used to handle a temporary document. A new document can be added to the document list:
// This example creates a new BaseDocument and inserts it
// into the list of documents.
// create new document
BaseDocument
*
const
newDocument =
BaseDocument::Alloc
();
if
(newDocument ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// insert document as the active document.
InsertBaseDocument
(newDocument);
SetActiveDocument
(newDocument);
// set document file name
newDocument->
SetDocumentName
(
"new_document.c4d"
);
// update Cinema
EventAdd
();
-
注意
-
BaseDocuments can also be created by loading
Cinema 4D
files. See
Disc I/O
below.
Destroy
A dynamically created
BaseDocument
should be destroyed with
BaseDocument::Free()
. To remove a
BaseDocument
from the document list use
KillDocument()
.
拷贝
BaseDocument
is based on
C4DAtom
and can be cloned using
C4DAtom::GetClone()
:
// This example clones the given document add adds it to the document list.
C4DAtom
*
const
cloneAtom = doc->
GetClone
(
COPYFLAGS::NONE
,
nullptr
);
BaseDocument
*
const
cloneDocument =
static_cast<
BaseDocument
*
>
(cloneAtom);
if
(cloneDocument ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
InsertBaseDocument
(cloneDocument);
SetActiveDocument
(cloneDocument);
cloneDocument->
SetDocumentName
(
"clone.c4d"
);
EventAdd
();
预览图像
When a scene is saved the current editor image is saved with the
BaseDocument
to create a thumbnail preview image.
// This example shows the preview bitmap in the Picture Viewer.
BaseBitmap
*
const
bitmap = doc->
GetDocPreviewBitmap
();
if
(bitmap !=
nullptr
)
{
ShowBitmap
(bitmap);
}
特性
数据
Multiple settings are stored inside the
BaseDocument
. The different types of settings are defined in
DOCUMENTSETTINGS
, the parameter IDs in
ddoc.h
.
// This example switches the statue of the "Use Generators" setting.
const
BaseContainer
data = doc->
GetData
(
DOCUMENTSETTINGS::GENERAL
);
const
Bool
useGenerators = data.
GetBool
(
DOCUMENT_USEGENERATORS
);
// set new settings
BaseContainer
settings;
设置。
SetBool
(
DOCUMENT_USEGENERATORS
, !useGenerators);
doc->
SetData
(
DOCUMENTSETTINGS::GENERAL
, settings);
and
// This example accesses the document settings to set the "Author" setting.
BaseContainer
*
const
settings = doc->
GetSettingsInstance
((
Int32
)
DOCUMENTSETTINGS::DOCUMENT
);
if
(settings ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
settings->
SetString
(
DOCUMENT_INFO_AUTHOR
,
"User"
_s);
-
注意
-
BaseDocument::GetSettingsInstance()
won't work with
DOCUMENTSETTINGS::GENERAL
.
对象
A
BaseDocument
hosts multiple
BaseObject
based scene objects. These objects are organized in an object tree.
-
注意
-
使用
BaseDocument::InsertObject()
will trigger the message
MSG_DOCUMENTINFO_TYPE_OBJECT_INSERT
.
另请参阅
BaseObject Manual
.
// This example searches for an object named "Cube".
// If it cannot be found a new cube with that name will be created.
BaseObject
*
const
object
= doc->
SearchObject
(
"Cube"
_s);
if
(
object
!=
nullptr
)
{
ApplicationOutput
(
"found \"Cube\""
_s);
return
maxon::OK
;
}
BaseObject
*
const
cubeObject =
BaseObject::Alloc
(
Ocube
);
if
(cubeObject ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
cubeObject->
SetName
(
"Cube"
_s);
doc->
InsertObject
(cubeObject,
nullptr
,
nullptr
);
In some cases multiple instances of a certain object class can be inserted into the scene but only one instance will be used (e.g. the Sky object). This is typically the "highest" instance.
// This example searches for the highest (and thus used) stage object
BaseObject
*
const
stageObject = doc->
GetHighest
(
Ostage
,
false
);
if
(stageObject ==
nullptr
)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
ApplicationOutput
(
"Found stage object \""
+ stageObject->
GetName
() +
"\""
);
材质
A
BaseDocument
hosts multiple
BaseMaterial
based materials. These materials are stored in a list and can be applied to objects in the scene.
另请参阅
BaseMaterial Manual
// This example searches for a material with the given name.
// If the material cannot be found, a new material with that
// name will be created and inserted into the document.
// search material
BaseMaterial
*
const
material = doc->
SearchMaterial
(
"Green"
_s);
if
(material)
{
ApplicationOutput
(
"Found \"Green\""
_s);
return
maxon::OK
;
}
// create material
BaseMaterial
*
const
greenMaterial =
BaseMaterial::Alloc
(
Mmaterial
);
if
(greenMaterial ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
greenMaterial->
SetName
(
"Green"
_s);
// insert material into the document
doc->
InsertMaterial
(greenMaterial);
选择
Inside a scene multiple objects, materials or tags can be selected.
// This example prints the name and type of all selected scene elements.
AutoAlloc<AtomArray>
selection;
if
(selection ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
doc->
GetSelection
(selection);
const
Int32
cnt = selection->
GetCount
();
if
(cnt == 0)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
for
(
Int32
i = 0; i < cnt; ++i)
{
C4DAtom
*
const
element = selection->
GetIndex
(i);
// check if the given C4DAtom is a BaseList2D element
const
Bool
validElement = element !=
nullptr
;
if
(validElement && element->
IsInstanceOf
(
Tbaselist2d
))
{
BaseList2D
* baseList2D =
static_cast<
BaseList2D
*
>
(element);
ApplicationOutput
(baseList2D->
GetName
() +
" ("
+ baseList2D->
GetTypeName
() +
")"
);
}
else
{
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
}
}
Object selections can be managed separately:
-
注意
-
To get the position of the anchor of an object multi-selection one can use
BaseDocument::GetHelperAxis()
.
-
To correctly add objects to the selection of active objects with
BaseDocument::SetActiveObject()
one must update internal caches by calling
BaseDocument::GetActiveObject()
after an object was added to the selection.
// This example gets all selected null objects.
// For each null object a cube is created at its position.
// The new cubes will be selected instead of the original nulls.
// get all selected null objects
AutoAlloc<AtomArray>
selection;
if
(selection ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
doc->
GetActiveObjectsFilter
(selection,
true
,
Onull
,
NOTOK
);
const
Int32
cnt = selection->
GetCount
();
if
(cnt == 0)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
// clear object selection
doc->
SetActiveObject
(
nullptr
);
for
(
Int32
i = 0; i < cnt; ++i)
{
C4DAtom
* element = selection->
GetIndex
(i);
const
BaseObject
*
const
nullobject =
static_cast<
BaseObject
*
>
(element);
if
(nullobject ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// create a cube
BaseObject
*
const
cube =
BaseObject::Alloc
(
Ocube
);
if
(cube ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
const
矩阵
nullMg = nullobject->
GetMg
();
cube->
SetMg
(nullMg);
doc->
InsertObject
(cube,
nullptr
,
nullptr
);
doc->
SetActiveObject
(cube,
SELECTION_ADD
);
}
材质
selections can be managed separately, too:
// This example gets the material that is assigned to the given object.
// If a material is found, it will be selected.
// get texture tag
BaseTag
*
const
tag =
object
->GetTag(
Ttexture
);
if
(tag ==
nullptr
)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
// get material
TextureTag
*
const
ttag =
static_cast<
TextureTag
*
>
(tag);
BaseMaterial
*
const
material = ttag->
GetMaterial
();
// set active material
if
(material !=
nullptr
)
doc->
SetActiveMaterial
(material,
SELECTION_NEW
);
Finally tag selections can be managed:
// This example loops through all selected tags.
// If a tag is a Texture Tag, the given material is applied.
// get all selected tags
AutoAlloc<AtomArray>
tags;
if
(tags ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
doc->
GetActiveTags
(tags);
const
Int32
cnt = tags->
GetCount
();
if
(cnt == 0)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
for
(
Int32
i = 0; i < cnt; i++)
{
C4DAtom
*
const
tag = tags->
GetIndex
(i);
if
(tag ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// check if texture tag
if
(tag->
GetType
() ==
Ttexture
)
{
// set material
TextureTag
* ttag =
static_cast<
TextureTag
*
>
(tag);
ttag->
SetMaterial
(material);
}
}
RenderData
RenderData
objects represent the render settings stored in a document. They allow access to the actual settings, multipass objects and post effects.
另请参阅
RenderData Manual
.
// This example adds a new RenderData to the document and set this RenderData as the active one.
RenderData
*
const
renderData =
RenderData::Alloc
();
if
(renderData ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
renderData->
SetName
(
"Preview Render Settings"
_s);
doc->
InsertRenderDataLast
(renderData);
doc->
SetActiveRenderData
(renderData);
Scene Hooks
Scene hooks are used to add additional data to the document or to influence the execution pipeline. These scene hooks are stored in the document:
// This example accesses the Dynamics scene hook to disable Dynamics globally.
// gets the dynamics scene hook
BaseSceneHook
*
const
dynamicsHook = doc->
FindSceneHook
(180000100);
if
(dynamicsHook ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
BaseContainer
& bc = dynamicsHook->
GetDataInstanceRef
();
bc.
SetBool
(
WORLD_ENABLED
,
false
);
层
Layers are used to organize a document. A layer is represented by a
LayerObject
and these
LayerObject
objects are organized in a tree:
另请参阅
Layer Manual
.
// This example gets the layer root object to access the first layer.
GeListHead
*
const
layers = doc->
GetLayerObjectRoot
();
if
(layers ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
LayerObject
*
const
layer =
static_cast<
LayerObject
*
>
(layers->
GetFirst
());
if
(layer !=
nullptr
)
ApplicationOutput
(
"First Layer: "
+ layer->
GetName
());
Takes
Takes allow to handle multiple versions of a scene within the same document. The takes of a document are stored in a
TakeData
object:
// This example simply creates a new take and makes it the current one.
TakeData
*
const
takeData = doc->
GetTakeData
();
if
(takeData ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
BaseTake
*
const
newTake = takeData->
AddTake
(
"This is a new take"
,
nullptr
,
nullptr
);
if
(newTake ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
takeData->
SetCurrentTake
(newTake);
见
Take System Overview
Changed Mode
The change status of a document indicates that the scene was changed after the last time it was saved. The status is displayed with a little star (*) in the application title bar.
// This example closes and frees the currently active document only if it is not "dirty".
BaseDocument
* activeDoc =
GetActiveDocument
();
if
(activeDoc ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// check dirty state of the document
if
(activeDoc->
GetChanged
() ==
false
)
KillDocument
(activeDoc);
Document Name and Path
A document is presented in the application using its filename. Because of this the name of the document cannot be obtained with
BaseList2D::GetName()
that returns a
String
and not a
Filename
.
// This example checks the suffix of the current document name.
const
Filename
docName = doc->
GetDocumentName
();
const
String
suffix = docName.
GetSuffix
();
// check if the suffix is defined
if
(suffix.
IsPopulated
())
{
if
(suffix ==
"c4d"
)
ApplicationOutput
(
"Cinema 4D File"
_s);
else
ApplicationOutput
(
"Filetype: "
+ suffix);
}
else
{
ApplicationOutput
(
"unsaved document"
_s);
}
Level of Detail
The level of detail defines how detailed certain objects are displayed in the editor. This is typically used in custom
ObjectData
based generators.
// This example sets the LOD to the level set in the current render settings.
// check if the document uses render LOD in the editor
if
(doc->
GetRenderLod
() ==
false
)
{
RenderData
*
const
renderData = doc->
GetActiveRenderData
();
if
(renderData ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
const
BaseContainer
bc = renderData->
GetDataInstanceRef
();
const
Float
lod = bc.
GetFloat
(
RDATA_LOD
);
// set new LOD
doc->
SetLOD
(lod);
}
-
注意
-
The LOD buttons in the editor represent the values 25%, 50% and 100%.
时间
The current timeline position of a document and the timeline size is defined using
BaseTime
对象。
-
注意
-
Setting the current time will not animate the document. See paragraph
动画
below.
Current time:
// This example jumps one second ahead and updates the document.
const
BaseTime
now = doc->
GetTime
();
const
BaseTime
target = now +
BaseTime
(1.0);
doc->
SetTime
(target);
// animate document
doc->
ExecutePasses
(
nullptr
,
true
,
true
,
true
,
BUILDFLAGS::NONE
);
Framerate:
-
注意
-
The framerate defined in the render settings is independent from the document framerate.
In the viewport, and for a render in the viewport, it will return the project's setting FrameRate.
Rendering elsewhere, it will return the
RenderData
FrameRate setting.
// This example synchronizes the document framerate with the render framerate.
RenderData
*
const
renderData = doc->
GetActiveRenderData
();
if
(renderData ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
const
BaseContainer
bc = renderData->
GetDataInstanceRef
();
const
Int32
fps = bc.
GetInt32
(
RDATA_FRAMERATE
);
doc->
SetFps
(fps);
Timeline dimensions:
Used Time:
Loop Preview:
// This example moves the timeline loop to the start of the timeline.
const
BaseTime
minTime = doc->
GetMinTime
();
// current loop duration
const
BaseTime
loopDuration = doc->
GetLoopMaxTime
() - doc->
GetLoopMinTime
();
// move loop to the start
doc->
SetLoopMinTime
(minTime);
doc->
SetLoopMaxTime
(minTime + loopDuration);
模式
A document can be in different modes defining which elements should be edited (objects, points, edges, etc.).
// This example sets the document mode based on the currently active selection tag.
BaseTag
*
const
tag = doc->
GetActiveTag
();
if
(tag ==
nullptr
)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
// check tag type
switch
(tag->
GetType
())
{
case
Tpointselection
: doc->
SetMode
(
Mpoints
);
break
;
case
Tpolygonselection
: doc->
SetMode
(
Mpolygons
);
break
;
case
Tedgeselection
: doc->
SetMode
(
Medges
);
break
;
}
Active Tool
The currently active tool is stored in the document.
// This example switches the mode and enables and configures the "Knife" tool.
BaseContainer
*
const
tool =
GetToolData
(doc,
ID_MODELING_KNIFE_LINE
);
if
(tool ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
tool->
SetBool
(
MDATA_KNIFELINE_ANGLE_CONSTRAINT
,
true
);
doc->
SetMode
(
Mpoints
);
doc->
SetAction
(
ID_MODELING_KNIFE_LINE
);
-
注意
-
To edit the settings of the Move/Scale/Rotate tools the actual plugin instance has to be accessed with
FindPlugin()
.
Axis and Plane
The helper axis represents the position of the handles used to move a multi-selection.
// This example creates a null object at the position of the helper axis.
// The currently selected objects (stored in "selection") are placed under that null object.
// check if model mode
if
(doc->
GetMode
() !=
Mmodel
)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
// get helper object and matrix
const
BaseObject
*
const
helperAxis = doc->
GetHelperAxis
();
if
(helperAxis ==
nullptr
)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
const
矩阵
matrix = helperAxis->
GetMg
();
// create null object
BaseObject
*
const
nullObject =
BaseObject::Alloc
(
Onull
);
if
(nullObject ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
doc->
InsertObject
(nullObject,
nullptr
,
nullptr
);
nullObject->
SetMg
(matrix);
// make selected object child of the new null
for
(
Int32
i = 0; i < objectCnt; ++i)
{
C4DAtom
* element = selection->
GetIndex
(i);
BaseObject
*
const
baseObject =
static_cast<
BaseObject
*
>
(element);
if
(baseObject ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
const
矩阵
position = baseObject->
GetMg
();
baseObject->
移除
();
doc->
InsertObject
(baseObject, nullObject,
nullptr
);
baseObject->
SetMg
(position);
}
Editor Windows
An editor window is represented by a
BaseDraw
object. Such a
BaseDraw
object allows access to the currently used camera. The render view is the editor window used to define the camera that will be used while rendering the final image.
另请参阅
BaseView / BaseDraw Manual
.
// This example accesses the active BaseDraw to get its camera.
// Then it moves the active object into the view of that camera.
BaseDraw
*
const
baseDraw = doc->
GetActiveBaseDraw
();
if
(baseDraw ==
nullptr
)
return
maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION
);
BaseObject
*
const
cameraObject = baseDraw->
GetEditorCamera
();
// move active object into the camera view
const
矩阵
cameraMatrix = cameraObject->
GetMg
();
矩阵
targetPosition = activeObject->
GetMg
();
targetPosition.
off
= cameraMatrix.
off
+ (900.0 * cameraMatrix.
sqmat
.
v3
);
activeObject->
SetMg
(targetPosition);
Net Context
If the document is currently handled inside a Team Render context can be checked using the net render context:
// This example checks if the current context is a Team Render context.
// If so, the error message will be printed just to the console, not displayed as a message box.
const
BaseDocument
*
const
doc = op->
GetDocument
();
NetRenderDocumentContext
*
const
context = doc->
GetNetRenderDocumentContext
();
if
(context)
ApplicationOutput
(
"Some Error occured!"
_s);
else
MessageDialog
(
"Some Error occured!"
_s);
Functionality
动画
Scene elements can be animated by setting keyframes with specific values at a specific time. The
BaseDocument
class offers functions to create such keyframes:
// This example creates automatically keys for the given object if "Auto Key" is enabled.
BaseObject
* undoObject =
static_cast<
BaseObject
*
>
(cubeObject->
GetClone
(
COPYFLAGS::NONE
,
nullptr
));
if
(undoObject ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// edit the object
cubeObject->
SetParameter
(
DescID
(
PRIM_CUBE_SUBX
), 10,
DESCFLAGS_SET::NONE
);
cubeObject->
SetParameter
(
DescID
(
PRIM_CUBE_SUBY
), 10,
DESCFLAGS_SET::NONE
);
cubeObject->
SetParameter
(
DescID
(
PRIM_CUBE_SUBZ
), 10,
DESCFLAGS_SET::NONE
);
// create auto keys if "Auto Key" is enabled.
doc->
AutoKey
(undoObject, cubeObject,
true
,
true
,
true
,
true
,
true
,
true
);
BaseObject::Free
(undoObject);
另请参阅
Animation Tracks
.
To apply keyframe animation, expressions, generators and deformers the document has to be animated.
// This example executes the document at different frames
// and prints the position of the "Cube" object.
// save current frame
const
BaseTime
originalTime = doc->
GetTime
();
for
(
Int32
i = 0; i < 30; ++i)
{
BaseTime
time(i, doc->
GetFps
());
doc->
SetTime
(time);
doc->
ExecutePasses
(
nullptr
,
true
,
true
,
true
,
BUILDFLAGS::INTERNALRENDERER
);
BaseObject
*
const
cube = doc->
SearchObject
(
"Cube"
_s);
if
(cube)
{
const
向量
position = cube->
GetMg
().
off
;
ApplicationOutput
(
"Cube Position: "
+
String::VectorToString
(position));
}
}
// reset frame
doc->
SetTime
(originalTime);
When a new keyframe is created a default template is used. This template can be edited:
// This example changes the default key of the document.
AutoAlloc<CKey>
key;
if
(key ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
Bool
overdub;
doc->
GetDefaultKey
(key, overdub);
// new keys should use linear interpolation
key->
SetInterpolation
(
nullptr
,
CINTERPOLATION::LINEAR
);
doc->
SetDefaultKey
(key, overdub);
The result of simulations is often iterative: The current frame depends on the results of previous calculations. To calculate the state of a particle simulation at a certain frame all frames before that have to be calculated:
// This example reads the emitter end time from the given particle object.
// The document time is set to this frame and SetRewind() is called to animate
// all frame before that frame.
GeData
data;
// access PARTICLEOBJECT_STOP parameter
DescID
particleStopID(
PARTICLEOBJECT_STOP
);
if
(particleEmitter->GetParameter(particleStopID, data,
DESCFLAGS_GET::NONE
) ==
false
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
const
BaseTime
endTime = data.
GetTime
();
doc->
SetTime
(endTime);
doc->
SetRewind
();
Undo
The undo system of
Cinema 4D
allows to store operations in undo actions that can be executed to undo and redo user interaction.
另请参阅
Undo System Manual
.
// This example creates a cube object and adds it to the document with an undo step.
BaseObject
*
const
cube =
BaseObject::Alloc
(
Ocube
);
if
(cube ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
doc->
StartUndo
();
doc->
InsertObject
(cube,
nullptr
,
nullptr
);
doc->
AddUndo
(
UNDOTYPE::NEWOBJ
, cube);
doc->
EndUndo
();
Undo actions can be executed:
Pick Session
A pick session can be used to select multiple objects.
见
PickSessionDataStruct
.
Send Messages
Convert and Export
The objects of a
BaseDocument
can be converted to polygon objects and associated sounds and textures can be collected:
// This example prints the file paths of all textures of the given material selection.
const
BaseContainer
textures = doc->
GetAllTextures
(materials);
BrowseContainer
browse(&textures);
Int32
id;
GeData
* data;
// loop through elements of the BaseContainer
while
(browse.GetNext(&
id
, &data))
{
// check if the found element is a Filename
if
(data !=
nullptr
)
{
if
(data->
GetType
() ==
DA_FILENAME
)
ApplicationOutput
(
"Texture: "
+ data->
GetFilename
().
GetString
());
}
}
-
IsolateObjects()
: Creates a new document that contains only copies of the given objects and their materials.
// This example creates a new BaseDocument containing the objects from the given selection.
// The new document is added to the document list and set as the active document.
BaseDocument
*
const
newDoc =
IsolateObjects
(doc, selection);
if
(newDoc ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
newDoc->
SetDocumentName
(
"isolated_objects.c4d"
);
InsertBaseDocument
(newDoc);
SetActiveDocument
(newDoc);
Disc I/O
A
BaseDocument
can be created by reading if from a file on disc. It is possible to load *.c4d files and supported import file formats.
The list of recently opened scene files is accessed with:
// This example loads the given c4d file and prints its min. and max. frame to the console.
// check if the Filename references a "c4d" file
if
(filename.CheckSuffix(
"c4d"
_s))
{
BaseDocument
* loadedDoc =
LoadDocument
(filename,
SCENEFILTER::NONE
,
nullptr
);
if
(loadedDoc ==
nullptr
)
return
maxon::IoError(
MAXON_SOURCE_LOCATION
,
MaxonConvert
(filename,
MAXONCONVERTMODE::NONE
),
"Could not load document."
_s);
const
Int32
fps = loadedDoc->
GetFps
();
const
Int32
startFrame = loadedDoc->
GetMinTime
().
GetFrame
(fps);
const
Int32
endFrame = loadedDoc->
GetMaxTime
().
GetFrame
(fps);
BaseDocument::Free
(loadedDoc);
// convert to String to print the data to the console
const
String
fileStr = filename.GetString();
const
String
startFrameStr =
String::IntToString
(startFrame);
const
String
endFrameStr =
String::IntToString
(endFrame);
// print to console
ApplicationOutput
(
"Document "
+ fileStr +
": "
+ startFrameStr +
" - "
+ endFrameStr);
}
-
SaveDocument()
: Saves the document to a
Cinema 4D
file or to a supported export file format.
-
SaveProject()
: Saves the document like the "Save Project with Assets" command.
// This example creates a new BaseDocument, adds an cube to it to save it to file.
AutoAlloc<BaseDocument>
tempDoc;
if
(tempDoc ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
BaseObject
*
const
cube =
BaseObject::Alloc
(
Ocube
);
if
(cube ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
tempDoc->
InsertObject
(cube,
nullptr
,
nullptr
);
if
(!
SaveDocument
(tempDoc, savepath,
SAVEDOCUMENTFLAGS::DONTADDTORECENTLIST
,
FORMAT_C4DEXPORT
))
return
maxon::IoError(
MAXON_SOURCE_LOCATION
,
MaxonConvert
(savepath,
MAXONCONVERTMODE::NONE
),
"Could not save document."
_s);
渲染
A
BaseDocument
can be rendered independently from the GUI and the Picture Viewer into a
BaseBitmap
(见
BaseBitmap Manual
).
// This example loads the given c4d file.
// One frame of the loaded document is rendered and displayed in the Picture Viewer.
const
SCENEFILTER
flags =
SCENEFILTER::OBJECTS
|
SCENEFILTER::MATERIALS
;
BaseDocument
*
const
loadedDoc =
LoadDocument
(filename, flags,
nullptr
);
if
(loadedDoc ==
nullptr
)
return
maxon::IoError(
MAXON_SOURCE_LOCATION
,
MaxonConvert
(filename,
MAXONCONVERTMODE::NONE
),
"Could not load document."
_s);
// auto free the loaded document
AutoFree<BaseDocument>
docFree;
docFree.
赋值
(loadedDoc);
RenderData
*
const
rdata = loadedDoc->
GetActiveRenderData
();
if
(rdata ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
BaseContainer
renderSettings = rdata->
GetData
();
// just render one frame
const
BaseTime
startFrame = renderSettings.
GetTime
(
RDATA_FRAMEFROM
,
BaseTime
());
renderSettings.
SetTime
(
RDATA_FRAMETO
, startFrame);
// prepare target bitmap
AutoAlloc<BaseBitmap>
bitmap;
if
(bitmap ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
const
Int32
width = renderSettings.
GetInt32
(
RDATA_XRES
);
const
Int32
height = renderSettings.
GetInt32
(
RDATA_YRES
);
const
IMAGERESULT
imageRes = bitmap->
Init
(width, height);
if
(imageRes !=
IMAGERESULT::OK
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// render the image
const
RENDERFLAGS
renderFlags =
RENDERFLAGS::NODOCUMENTCLONE
;
const
RENDERRESULT
res =
RenderDocument
(loadedDoc, renderSettings,
nullptr
,
nullptr
, bitmap, renderFlags,
nullptr
);
if
(res !=
RENDERRESULT::OK
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// show result
ShowBitmap
(bitmap);
Messages
On certain events (load, save, render,...) a
MSG_DOCUMENTINFO
message is sent to elements contained in a document.
// This example catches MSG_DOCUMENTINFO in a ObjectData::Message() function.
// When the document is loaded the value of a old (legacy) parameter is copied
// into a new parameter.
case
MSG_DOCUMENTINFO
:
{
DocumentInfoData
*
const
msg =
static_cast<
DocumentInfoData
*
>
(data);
if
(msg ==
nullptr
)
return
false
;
// switch message sub-type
switch
(msg->
type
)
{
case
MSG_DOCUMENTINFO_TYPE_LOAD
:
{
BaseObject
*
const
op =
static_cast<
BaseObject
*
>
(node);
if
(!op)
return
false
;
BaseContainer
& bc = op->
GetDataInstanceRef
();
bc.
SetInt32
(NEW_PARAMETER, bc.
GetInt32
(OLD_PARAMETER));
ApplicationOutput
(
"document is loaded"
_s);
break
;
}
}
break
;
}
Futher document related messages:
延伸阅读
#define Ostage
Stage.
定义:
ge_prepass.h:1007
@ Medges
Edge edit mode.
定义:
c4d_basedocument.h:1703
Message struct for the MSG_DOCUMENTINFO message.
定义:
c4d_baselist.h:986
BaseContainer GetData()
定义:
c4d_baselist.h:2266
@ PRIM_CUBE_SUBY
定义:
ocube.h:9
@ OK
Image loaded/created.
void GetActiveObjectsFilter(AtomArray &selection, Bool children, Int32 type, Int32 instanceof) const
#define Tpointselection
Point selection - SelectionTag.
定义:
ge_prepass.h:1248
void SetData(DOCUMENTSETTINGS type, const BaseContainer &bc)
void MessageDialog(const maxon::String &str)
BaseDocument * GetActiveDocument(void)
@ PARTICLEOBJECT_STOP
定义:
oparticle.h:29
void SetTime(Int32 id, const BaseTime &b)
定义:
c4d_basecontainer.h:590
void InsertObject(BaseObject *op, BaseObject *parent, BaseObject *pred, Bool checknames=false)
@ DOCUMENT
Document settings.
BaseObject * SearchObject(const maxon::String &str)
@ RDATA_YRES
定义:
drendersettings.h:153
定义:
c4d_basedocument.h:245
RENDERRESULT
定义:
ge_prepass.h:409
V v3
The Z axis.
定义:
matrix.h:31
void Assign(TYPE *p)
定义:
ge_autoptr.h:225
SCENEFILTER
定义:
ge_prepass.h:287
@ PRIM_CUBE_SUBX
定义:
ocube.h:8
C4DAtom * GetClone(COPYFLAGS flags, AliasTrans *trn)
定义:
c4d_baselist.h:1417
定义:
lib_description.h:327
String GetSuffix(void) const
Int32 GetType(void) const
定义:
c4d_gedata.h:407
void SetInt32(Int32 id, Int32 l)
定义:
c4d_basecontainer.h:505
BaseMaterial * SearchMaterial(const maxon::String &str)
void SetString(Int32 id, const maxon::String &s)
定义:
c4d_basecontainer.h:569
void SetActiveDocument(BaseDocument *doc)
@ RDATA_FRAMETO
定义:
drendersettings.h:165
maxon::Float Float
定义:
ge_sys_math.h:64
@ RDATA_FRAMERATE
定义:
drendersettings.h:171
void SetRewind(Int32 flags=0)
GeListNode * GetFirst()
定义:
c4d_baselist.h:2037
Bool AddUndo(UNDOTYPE type, void *data, Bool allowFromThread=false)
#define Onull
Null.
定义:
ge_prepass.h:1009
void SetActiveMaterial(BaseMaterial *mat, Int32 mode=0)
@ Mpolygons
Polygon edit mode.
定义:
c4d_basedocument.h:1704
void SetMg(const Matrix &m)
定义:
c4d_baseobject.h:488
void SetDefaultKey(CKey *pKey, Bool bOverdub)
RENDERRESULT RenderDocument(BaseDocument *doc, const BaseContainer &rdata, ProgressHook *prog, void *private_data, BaseBitmap *bmp, RENDERFLAGS renderflags, BaseThread *th, WriteProgressHook *wprog=nullptr, void *data=nullptr)
static BaseDocument * Alloc(void)
void SetTime(const BaseTime &t)
Bool SaveDocument(BaseDocument *doc, const Filename &name, SAVEDOCUMENTFLAGS saveflags, Int32 format)
RENDERFLAGS
定义:
ge_prepass.h:4423
Matrix GetMg() const
定义:
c4d_baseobject.h:482
Manages file and path names.
定义:
c4d_file.h:93
#define MSG_DOCUMENTINFO
Sent as broadcast message by the document when it is loaded, saved , merged etc. The corresponding da...
定义:
c4d_baselist.h:445
return OK
定义:
apibase.h:2532
const GeMarker & GetMarker() const
定义:
c4d_baselist.h:2365
BaseTake * AddTake(const String &name, BaseTake *parent, BaseTake *cloneFrom)
void GetSelection(AtomArray &selection) const
BaseDocument * LoadDocument(const Filename &name, SCENEFILTER loadflags, BaseThread *thread, maxon::String *errorString=nullptr)
@ Mpoints
Point edit mode.
定义:
c4d_basedocument.h:1702
Int32 GetFrame(Float fps) const
定义:
c4d_basetime.h:107
Int32 GetCount() const
定义:
c4d_baselist.h:1619
Bool IsPopulated() const
定义:
string.h:1396
@ NONE
No check if file exists under case-sensitive drives.
#define Ocube
Cube.
定义:
ge_prepass.h:1040
#define MAXON_SOURCE_LOCATION
定义:
memoryallocationbase.h:66
Float GetFloat(Int32 id, Float preset=0.0) const
定义:
c4d_basecontainer.h:335
Bool ExecutePasses(BaseThread *bt, Bool animation, Bool expressions, Bool caches, BUILDFLAGS flags)
void SetActiveRenderData(RenderData *rd)
BaseTag * GetActiveTag(void)
void SetBool(Int32 id, Bool b)
定义:
c4d_basecontainer.h:498
void SetInterpolation(CCurve *seq, CINTERPOLATION inter)
定义:
c4d_canimation.h:214
static IMAGERESULT Init(BaseBitmap *&res, const Filename &name, Int32 frame=-1, Bool *ismovie=nullptr, BitmapLoaderPlugin **loaderplugin=nullptr, const maxon::Delegate< void(Float progress)> &progressCallback=nullptr)
void KillDocument(BaseDocument *&doc)
GeListHead * GetLayerObjectRoot(void)
BaseDraw * GetActiveBaseDraw(void)
const BaseTime & GetTime(void) const
定义:
c4d_gedata.h:481
BaseObject * GetHighest(Int32 type, Bool editor)
void SetActiveObject(BaseObject *op, Int32 mode=0)
maxon::Url MaxonConvert(const Filename &fn, MAXONCONVERTMODE convertMode)
BaseDocument * GetFirstDocument(void)
String GetString(void) const
static RenderData * Alloc(void)
BaseObject * GetHelperAxis(void)
BaseTime GetTime(Int32 id, const BaseTime &preset=BaseTime()) const
定义:
c4d_basecontainer.h:411
Bool IsEqual(const GeMarker &m) const
定义:
c4d_baselist.h:1287
void SetLoopMaxTime(const BaseTime &t)
void InsertMaterial(BaseMaterial *mat, BaseMaterial *pred=nullptr, Bool checknames=false)
A unique marker that identifies an object.
定义:
c4d_baselist.h:1256
static String IntToString(Int32 v)
定义:
c4d_string.h:495
@ OK
Function was successful.
@ OBJECTS
Load/save objects.
void SetMaterial(BaseMaterial *mat)
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
void GetActiveTags(AtomArray &selection) const
BaseTime GetTime(void) const
const BaseContainer & GetDataInstanceRef() const
定义:
c4d_baselist.h:2299
BaseBitmap * GetDocPreviewBitmap()
SqrMat3< V > sqmat
The 3×3 matrix for rotation, scale and shear.
定义:
matrix.h:282
Bool SetCurrentTake(BaseTake *take)
#define FORMAT_C4DEXPORT
Cinema 4D export.
定义:
ge_prepass.h:3280
void InsertBaseDocument(BaseDocument *doc)
BaseMaterial * GetMaterial(Bool ignoredoc=false)
BaseTime GetMinTime(void)
BaseTime GetLoopMinTime(void)
@ RDATA_XRES
定义:
drendersettings.h:152
定义:
c4d_basedocument.h:43
#define NOTOK
定义:
ge_sys_math.h:265
#define Tbaselist2d
2D list.
定义:
ge_prepass.h:938
BaseObject * GetEditorCamera(void)
定义:
c4d_basedraw.h:868
void SetLoopMinTime(const BaseTime &t)
@ DOCUMENT_INFO_AUTHOR
定义:
ddoc.h:46
const Filename & GetFilename(void) const
定义:
c4d_gedata.h:475
void SetName(const maxon::String &name)
定义:
c4d_baselist.h:2324
maxon::Int32 Int32
定义:
ge_sys_math.h:58
@ RDATA_LOD
定义:
drendersettings.h:63
BaseDocument * GetDocument()
定义:
c4d_baselist.h:1915
#define ApplicationOutput(formatString,...)
定义:
debugdiagnostics.h:207
void Remove()
定义:
c4d_baselist.h:1854
Bool GetDefaultKey(CKey *pKey, Bool &bOverdub) const
Bool ShowBitmap(const Filename &fn)
@ WORLD_ENABLED
定义:
dynworldobject.h:6
static void Free(BaseDocument *&bl)
Bool GetBool(Int32 id, Bool preset=false) const
定义:
c4d_basecontainer.h:295
void SetFloat(Int32 id, Float r)
定义:
c4d_basecontainer.h:533
BaseSceneHook * FindSceneHook(Int32 id) const
定义:
c4d_basedocument.h:1234
@ Mmodel
Model mode.
定义:
c4d_basedocument.h:1707
#define Ttexture
Texture - TextureTag.
定义:
ge_prepass.h:1236
#define SELECTION_ADD
Adds to the current selection.
定义:
c4d_basedocument.h:383
NetRenderDocumentContext * GetNetRenderDocumentContext() const
@ DA_FILENAME
Filename.
定义:
c4d_gedata.h:48
void SetDocumentName(const Filename &fn)
void InsertRenderDataLast(RenderData *rd)
@ DONTADDTORECENTLIST
Do not add the saved document to the recent file list.
#define Mmaterial
Standard material.
定义:
ge_prepass.h:950
RenderData * GetActiveRenderData(void)
static BaseMaterial * Alloc(Int32 type)
static BaseObject * Alloc(Int32 type)
BaseTime GetLoopMaxTime(void)
void EventAdd(EVENT eventflag=EVENT::NONE)
@ INTERNALRENDERER
Rendering in the editor.
V off
The translation vector.
定义:
matrix.h:279
#define Tedgeselection
Edge selection - SelectionTag. The edges are encodes like this: (4*poly)+edge, where edge goes from 0...
定义:
ge_prepass.h:1265
static void Free(BaseObject *&bl)
BaseDocument * IsolateObjects(BaseDocument *doc, const AtomArray &t_objects)
@ NEWOBJ
New object/material/tag etc. was created. (Needs to be called after action.)
定义:
c4d_basedocument.h:136
#define Tpolygonselection
Polygon selection - SelectionTag.
定义:
ge_prepass.h:1247
maxon::Bool Bool
定义:
ge_sys_math.h:53
#define MSG_DOCUMENTINFO_TYPE_LOAD
Document was loaded.
定义:
c4d_baselist.h:457
Bool IsInstanceOf(Int32 id) const
定义:
c4d_baselist.h:1373
String GetName() const
定义:
c4d_baselist.h:2318
IMAGERESULT
定义:
ge_prepass.h:3659
BaseContainer GetData(DOCUMENTSETTINGS type)
static String VectorToString(const Vector32 &v, Int32 nnk=-1)
定义:
c4d_string.h:571
void AutoKey(BaseList2D *undo, BaseList2D *op, Bool recursive, Bool pos, Bool scale, Bool rot, Bool param, Bool pla)
定义:
c4d_basedocument.h:1093
@ DOCUMENT_USEGENERATORS
定义:
ddoc.h:24
Int32 GetType() const
定义:
c4d_baselist.h:1348
定义:
c4d_basematerial.h:27
Int32 GetInt32(Int32 id, Int32 preset=0) const
定义:
c4d_basecontainer.h:303
BaseContainer * GetSettingsInstance(Int32 type)
Filename GetDocumentName(void)
Int32 GetMode(void) const
@ PRIM_CUBE_SUBZ
定义:
ocube.h:10
@ RDATA_FRAMEFROM
定义:
drendersettings.h:164
BaseDocument * GetNext(void)
定义:
c4d_basedocument.h:527
@ GENERAL
General settings.
定义:
c4d_basedocument.h:490
Int32 type
The message type: MSG_DOCUMENTINFO_TYPE.
定义:
c4d_baselist.h:993
BaseContainer GetAllTextures(const AtomArray *ar)
BaseTime GetMaxTime(void)
定义:
c4d_basecontainer.h:46
#define SELECTION_NEW
Starts a new selection.
定义:
c4d_basedocument.h:382
@ MATERIALS
Load/save materials.
C4DAtom * GetIndex(Int32 idx) const
定义:
c4d_baselist.h:1634
@ NODOCUMENTCLONE
Set to avoid an automatic clone of the scene sent to RenderDocument().