-
首页
-
C4D R23.110 C++ SDK
BaseContainer
Manual
内容表
关于
A
BaseContainer
is a collection of individual values. Each value has its own ID and type. A
BaseContainer
can also carry any number of child containers. 90% of
Cinema 4D
's internal values are stored in containers and all messages are working with containers, so this class is an essential part of the SDK. Containers can store any
GeData
type, including custom data types. It is recommended to use the available containers to store values in custom
NodeData
based plugins.
-
警告
-
Keep in mind that there is no guarantee for a value to be in the container. Use default values whenever possible when accessing container's ID data.
-
Use the typed access methods (for example
BaseContainer::GetBool()
) whenever possible, instead of the low-level
BaseContainer::GetData()
。见
Access
.
-
Once a container value has been set using one type one must neither try to access it using another type, nor overwrite it with a value of another type. Using the wrong access will not crash, but it is illegal.
-
注意
-
To browse through all elements of a
BaseContainer
use the class
BrowseContainer
.
Access
Every
BaseList2D
based object of the
Cinema 4D
API has a
BaseContainer
that stores its data. This
BaseContainer
can be accessed with:
见
BaseList2D Manual
.
-
注意
-
Object parameters should be edited with
C4DAtom::GetParameter()
/
C4DAtom::SetParameter()
. Not all parameters of an object may be stored in the
BaseContainer
.
// This example accesses the BaseContainer storing the render settings.
// The BaseContainer is needed as an argument of RenderDocument().
RenderData
*
const
rdata = doc->
GetActiveRenderData
();
if
(rdata ==
nullptr
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
const
BaseContainer
renderSettings = rdata->
GetData
();
AutoAlloc<BaseBitmap>
bitmap;
if
(bitmap ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// prepare target bitmap
const
Int32
width = renderSettings.
GetInt32
(
RDATA_XRES
, 1280);
const
Int32
height = renderSettings.
GetInt32
(
RDATA_YRES
, 720);
const
IMAGERESULT
imageRes = bitmap->
Init
(width, height);
if
(imageRes !=
IMAGERESULT::OK
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// render the image
const
RENDERFLAGS
flags =
RENDERFLAGS::NODOCUMENTCLONE
;
const
RENDERRESULT
res =
RenderDocument
(doc, renderSettings,
nullptr
,
nullptr
, bitmap, flags,
nullptr
);
if
(res !=
RENDERRESULT::OK
)
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
// show the result in the Picture Viewer
ShowBitmap
(bitmap);
BaseContainer
elements are also often used as an argument in a function call.
拷贝
The complete content of a
BaseContainer
object can be copied to another object:
It is also possible to copy a
BaseContainer
using the copy constructor.
// This example creates a BaseContainer copies in different ways:
BaseContainer
original;
original.
SetString
(100,
"foo"
_s);
original.
SetString
(200,
"bar"
_s);
// CopyTo()
BaseContainer
target;
target.
SetString
(300,
"foobar"
_s);
if
(!original.
CopyTo
(&target,
COPYFLAGS::NONE
,
nullptr
))
return
maxon::UnexpectedError(
MAXON_SOURCE_LOCATION
);
ApplicationOutput
(target.
GetString
(100));
ApplicationOutput
(target.
GetString
(200));
ApplicationOutput
(target.
GetString
(300));
// This value is now deleted.
// GetClone()
BaseContainer
* clone = original.
GetClone
(
COPYFLAGS::NONE
,
nullptr
);
if
(clone ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
ApplicationOutput
(clone->
GetString
(100));
ApplicationOutput
(clone->
GetString
(200));
DeleteObj
(clone);
// Copy Constructor
BaseContainer
copy(original);
ApplicationOutput
(copy.GetString(100));
ApplicationOutput
(copy.GetString(200));
// Assignment
BaseContainer
assignment = original;
ApplicationOutput
(assignment.
GetString
(100));
ApplicationOutput
(assignment.
GetString
(200));
-
注意
-
To merge containers see
BaseContainer::MergeContainer()
in chapter
Functionality
.
数据
ID
A
BaseContainer
can have an ID. This ID can be used to identify the container.
// This example shows how GetId() is used to identify the message sent to GeDialog::Message().
Int32
Message(
const
BaseContainer
& msg,
BaseContainer
& result)
{
switch
(msg.
GetId
())
{
case
BFM_INTERACTSTART
:
{
// interaction start; if the value is changed create an undo
_interactStart =
true
;
break
;
}
case
BFM_INTERACTEND
:
{
// interaction end, if an undo was created, end it
if
(_undoStarted)
{
BaseDocument
*
const
doc =
GetActiveDocument
();
doc->
EndUndo
();
_undoStarted =
false
;
}
_interactStart =
false
;
break
;
}
}
return
SUPER::Message(msg, result);
}
Access
A
BaseContainer
stores its data using
GeData
objects. It is possible to access these
GeData
objects or the stored values directly using typed access functions. It is recommended to prefer the typed access functions.
A copy of a
GeData
element can be obtained with:
-
注意
-
The
DescLevel::id
property is used as the actual ID.
// This example stores some data in
// the BaseContainer using SetParameter().
BaseContainer
bc;
bc.
SetParameter
(
DescID
{ 100 },
GeData
{
"foobar"
});
GeData
data;
bc.
GetParameter
(
DescID
{ 100 }, data);
ApplicationOutput
(data.
GetString
());
The
GeData
elements are also accessible via:
// This example stores some data in the
// BaseContainer using a GeData object.
BaseContainer
bc;
bc.
SetData
(100,
GeData
{
"foobar"
});
GeData
data = bc.
GetData
(100);
ApplicationOutput
(data.
GetString
());
For fast access read-only pointers to the
GeData
elements are accessible:
// This example accesses the data stored
// in the BaseContainer using data pointers.
BaseContainer
bc;
bc.
SetData
(100,
GeData
{
"foo"
});
bc.
SetData
(200,
GeData
{
"bar"
});
const
Int
count = 2;
const
GeData
* data[count];
Int32
ids[] = { 100, 200 };
bc.
GetDataPointers
(ids, count, data);
if
(data[0])
ApplicationOutput
(data[0]->GetString());
if
(data[1])
ApplicationOutput
(data[1]->GetString());
A
GeData
element is also accessible via its index in the
BaseContainer
:
// This example accesses the data stored in the
// BaseContainer using the element index.
BaseContainer
bc;
bc.
SetData
(100,
GeData
{
"foo"
});
bc.
SetData
(200,
GeData
{
"bar"
});
GeData
*
const
first = bc.
GetIndexData
(0);
if
(first !=
nullptr
)
ApplicationOutput
(first->
GetString
());
GeData
*
const
second = bc.
GetIndexData
(1);
if
(second !=
nullptr
)
ApplicationOutput
(second->
GetString
());
New
GeData
elements can be added to the
BaseContainer
:
// This example inserts some data into the
// BaseContainer after the first element.
BaseContainer
bc;
bc.
SetData
(100,
"foo"
);
bc.
SetData
(200,
"foobar"
);
GeData
*
const
data = bc.
GetIndexData
(0);
bc.
InsDataAfter
(150,
String
(
"bar"
), data);
To access the values of primitive data types, these access functions are available:
另请参阅
Primitive Data Types Manual (Classic)
.
A
BaseContainer
can store a void pointer.
-
注意
-
This should not be used to store a reference to a
C4DAtom
based element; instead a
BaseLink
should be used.
// This example stores a void pointer
// in the BaseContainer object.
BaseContainer
bc;
bc.
SetVoid
(100, &
object
);
// ...
SomeObject*
const
obj =
static_cast<
SomeObject*
>
(bc.
GetVoid
(100));
A
BaseContainer
can store raw memory:
// This example stores a BaseArray as raw memory. (in that case an array of Vectors)
// Calculates the size of the memory
maxon::Int
size = myArray.GetCount() *
SIZEOF
(
maxon::Vector
);
if
(size == 0)
{
bc.
SetMemory
(uniqueID,
nullptr
, 0);
}
else
{
// Retrieves the memory pointer using Disconnect. (so the memory will not be freed twice)
void
* pArray = myArray.Disconnect().Begin().GetPtr();
if
(pArray ==
nullptr
)
return
maxon::UnknownError(
MAXON_SOURCE_LOCATION
);
// Sets the memory in the BaseContainer
bc.
SetMemory
(uniqueID, pArray, size);
}
// This Example reads a BaseArray stored as raw memory.
// Creates an array
maxon::BaseArray<maxon::Vector>
myOtherArray;
// Creates a block to retrieves the memory from the block.
maxon::Block<maxon::Vector>
myblock;
// Retrieves the memory, use GetMemoryAndRelease to release the pointer or the memory will be freed twice)
void
* memFromContainer = bc.
GetMemoryAndRelease
((
Int32
)uniqueID, size);
if
(memFromContainer !=
nullptr
&& size > 0)
{
// Calculates the number of elements for vectors
size = size /
SIZEOF
(
maxon::Vector
);
maxon::Vector
* myMem =
static_cast<
maxon::Vector
*
>
(memFromContainer);
if
(myMem ==
nullptr
)
return
maxon::NullptrError(
MAXON_SOURCE_LOCATION
);
// Fills the block with the memory.
myblock.
Set
(myMem, size);
// Connects the array with the block.
myOtherArray.
连接
(myblock, size);
}
// Prints the value of the array.
for
(
auto
& value : myOtherArray)
ApplicationOutput
(
"Value is @"
, value);
A
BaseContainer
offers also access functions for mathematical data types:
另请参阅
Vector Manual (Classic)
and
Matrix Manual (Classic)
.
A
BaseContainer
offers further access functions for typical
Cinema 4D
data types:
另请参阅
String Manual (Classic)
and
Filename Manual
.
另请参阅
BaseTime 手册
.
A
BaseContainer
also offers special functions to store and handle
BaseLink
objects:
另请参阅
BaseLink Manual
.
// store the current selection in the BaseContainer
BaseContainer
bc;
bc.
SetLink
(100, doc->
GetActiveMaterial
());
bc.
SetLink
(200, doc->
GetActiveObject
());
bc.
SetLink
(300, doc->
GetActiveTag
());
// ...
// get the material
BaseMaterial
*
const
mat = bc.
GetMaterialLink
(100, doc);
if
(mat)
ApplicationOutput
(mat->
GetName
());
// get the object
BaseObject
*
const
obj = bc.
GetObjectLink
(200, doc);
if
(obj)
ApplicationOutput
(obj->
GetName
());
// get tag
BaseList2D
*
const
link = bc.
GetLink
(300, doc);
if
(link)
ApplicationOutput
(link->
GetName
());
A
BaseContainer
object can also store further sub-containers:
// This example stores a sub-container
// in the BaseContainer object.
BaseContainer
subcontainer;
subcontainer.
SetString
(100,
"foobar"
_s);
BaseContainer
bc;
bc.
SetContainer
(100, subcontainer);
// ...
BaseContainer
sub = bc.
GetContainer
(100);
ApplicationOutput
(sub.
GetString
(100));
A
BaseContainer
can also store custom data types. To set the value of the custom data type a
GeData
object is needed.
// This example gets the current time and saves is as DateTimeData in the BaseContainer.
// Then the DateTimeData is received from that BaseContainer.
DateTime
time;
GetDateTimeNow
(time);
AutoAlloc<DateTimeData>
date;
if
(date ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
date->
SetDateTime
(time);
GeData
data;
data.
SetCustomDataType
(
DATETIME_DATA
, *date);
BaseContainer
bc;
bc.
SetData
(100, data);
// ...
const
CustomDataType
*
const
customData = bc.
GetCustomDataType
(100,
DATETIME_DATA
);
const
DateTimeData
*
const
dateTimeData =
static_cast<
const
DateTimeData
*
>
(customData);
if
(dateTimeData)
{
const
DateTime
dt = dateTimeData->
GetDateTime
();
String
result;
result +=
String::IntToString
(dt.
year
) +
":"
;
result +=
String::IntToString
(dt.
month
) +
":"
;
result +=
String::IntToString
(dt.
day
) +
" - "
;
result +=
String::IntToString
(dt.
hour
) +
":"
;
result +=
String::IntToString
(dt.
minute
) +
":"
;
result +=
String::IntToString
(dt.
second
);
// print output
ApplicationOutput
(result);
}
These functions can be used to limit the values of a
向量
or
Float
value inside a BaseContaier:
-
注意
-
These functions simply apply
ClampValue()
, see also
Mathematical Functions Manual (Classic)
.
索引
The elements stored within a
BaseContainer
are accessible through their index and their ID:
另请参阅
BaseContainer::GetIndexData()
above. To loop through values see also
BrowseContainer
.
// This example loops through the values of the BaseContainer.
Int32
i = 0;
while
(
true
)
{
const
Int32
id
= bc.
GetIndexId
(i++);
if
(
id
==
NOTOK
)
break
;
else
ApplicationOutput
(bc.
GetData
(
id
).
GetString
());
}
移除
Elements can be removed from a
BaseContainer
:
// This example removes some element from
// the BaseContainer object.
BaseContainer
bc;
bc.
SetData
(100,
"foo"
);
bc.
SetData
(200,
"bar"
);
// remove data entry 100
if
(bc.
RemoveData
(100))
{
GeData
data = bc.
GetData
(100);
// check if data has no type (data is not set)
if
(data.
GetType
() ==
DA_NIL
)
ApplicationOutput
(
"Data removed"
_s);
}
Functionality
Several operations can be performed on a
BaseContainer
对象。
// This example merges the content of two
// BaseContainer objects.
BaseContainer
bc;
bc.
SetData
(100,
"foo"
);
bc.
SetData
(200,
"bar"
);
BaseContainer
bc2;
bc2.
SetData
(100,
"100"
);
bc2.
SetData
(300,
"300"
);
bc.
MergeContainer
(bc2);
// this will result in the values
// 100: "100"
// 200: "bar"
// 300: "300"
比较
Two
BaseContainer
are identical if they have the same ID, the same number of entries and if the entries are also identical and in the same order.
Detect Changes
The dirty state of a
BaseContainer
changes incrementally when a value stored in the
BaseContainer
is changed.
// This example checks the dirty state after a value was added and changed.
BaseContainer
bc;
bc.
SetData
(100,
"foo"
);
UInt32
dirty = bc.
GetDirty
();
ApplicationOutput
(
"Dirty State: "
+
String::UIntToString
(dirty));
bc.
SetData
(100,
"bar"
);
dirty = bc.
GetDirty
();
ApplicationOutput
(
"Dirty State: "
+
String::UIntToString
(dirty));
BrowseContainer
The
BrowseContainer
class can be used to browse through the values stored in a
BaseContainer
. See also
索引
.
// This example loops through all values of the given BaseContainer.
Int32
id;
GeData
* dat =
nullptr
;
// init BrowseContainer
BrowseContainer
browse(&bc);
// loop through the values
while
(browse.GetNext(&
id
, &dat))
{
ApplicationOutput
(
"id: "
+
String::IntToString
(
id
));
// check if the current data stores a String
if
(dat !=
nullptr
)
{
if
(dat->
GetType
() ==
DA_STRING
)
ApplicationOutput
(
"value: "
+ dat->
GetString
());
}
}
Disc I/O
A
BaseContainer
can be stored in a
HyperFile
.
// This example stores a BaseContainer in a HyperFile on disc.
AutoAlloc<HyperFile>
hf;
if
(hf ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// open HyperFile to write
if
(hf->
Open
(123, filename,
FILEOPEN::WRITE
,
FILEDIALOG::ANY
))
{
hf->
WriteContainer
(bc);
hf->
关闭
();
}
else
{
return
maxon::IoError(
MAXON_SOURCE_LOCATION
,
MaxonConvert
(filename,
MAXONCONVERTMODE::NONE
),
"Could not open file."
_s);
}
// This example reads a BaseContainer from a HyperFile on disc.
AutoAlloc<HyperFile>
hf;
if
(hf ==
nullptr
)
return
maxon::OutOfMemoryError(
MAXON_SOURCE_LOCATION
);
// open HyperFile to read
if
(hf->
Open
(123, filename,
FILEOPEN::READ
,
FILEDIALOG::ANY
))
{
BaseContainer
bc;
hf->
ReadContainer
(&bc,
true
);
另请参阅
HyperFile Manual
on
BaseContainer
.
延伸阅读
const GeData & GetData(Int32 id) const
定义:
c4d_basecontainer.h:262
BaseContainer GetData()
定义:
c4d_baselist.h:2266
void SetDateTime(const DateTime &d, Bool bSetDate=true, Bool bSetTime=true)
@ OK
Image loaded/created.
Bool CopyTo(BaseContainer *dst, COPYFLAGS flags, AliasTrans *trans) const
定义:
c4d_basecontainer.h:110
BaseObject * GetObjectLink(Int32 id, const BaseDocument *doc) const
void SetMemory(Int32 id, void *mem, Int count)
定义:
c4d_basecontainer.h:548
BaseDocument * GetActiveDocument(void)
MAXON_ATTRIBUTE_FORCE_INLINE void Connect(const Block< T > &block, Int capacity=0)
定义:
basearray.h:1417
GeData * SetData(Int32 id, const GeData &n)
定义:
c4d_basecontainer.h:255
@ RDATA_YRES
定义:
drendersettings.h:153
#define DeleteObj(obj)
定义:
newobj.h:159
maxon::Int Int
定义:
ge_sys_math.h:62
void SetCustomDataType(Int32 datatype, const CustomDataType &v)
定义:
c4d_gedata.h:664
BaseMaterial * GetMaterialLink(Int32 id, const BaseDocument *doc) const
RENDERRESULT
定义:
ge_prepass.h:409
static String UIntToString(UInt32 v)
定义:
c4d_string.h:511
GeData * InsDataAfter(Int32 id, const GeData &n, GeData *last)
定义:
c4d_basecontainer.h:247
void SetVoid(Int32 id, void *v)
定义:
c4d_basecontainer.h:540
GeData * GetIndexData(Int32 index) const
定义:
c4d_basecontainer.h:229
定义:
lib_description.h:327
Int32 GetType(void) const
定义:
c4d_gedata.h:407
@ BFM_INTERACTEND
Sent when user interaction ends.
定义:
gui.h:917
@ ANY
Show an error dialog for any error.
void SetString(Int32 id, const maxon::String &s)
定义:
c4d_basecontainer.h:569
Int32 minute
Minute.
定义:
customgui_datetime.h:67
maxon::UInt32 UInt32
定义:
ge_sys_math.h:59
RENDERRESULT RenderDocument(BaseDocument *doc, const BaseContainer &rdata, ProgressHook *prog, void *private_data, BaseBitmap *bmp, RENDERFLAGS renderflags, BaseThread *th, WriteProgressHook *wprog=nullptr, void *data=nullptr)
BaseMaterial * GetActiveMaterial(void)
RENDERFLAGS
定义:
ge_prepass.h:4423
void GetDateTimeNow(DateTime &t)
BaseList2D * GetLink(Int32 id, const BaseDocument *doc, Int32 instanceof=0) const
定义:
c4d_basecontainer.h:443
@ DA_NIL
No value.
定义:
c4d_gedata.h:38
@ NONE
No check if file exists under case-sensitive drives.
#define MAXON_SOURCE_LOCATION
定义:
memoryallocationbase.h:66
BaseTag * GetActiveTag(void)
定义:
customgui_datetime.h:156
void Set(T *ptr, Int size, Int stride=(STRIDED &&GENERIC) ? -1 :SIZEOF(StrideType))
定义:
block.h:528
Bool RemoveData(Int32 id)
定义:
c4d_basecontainer.h:160
void * GetMemoryAndRelease(Int32 id, Int &count, void *preset=nullptr)
定义:
c4d_basecontainer.h:354
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)
@ DA_STRING
String.
定义:
c4d_gedata.h:47
Int32 GetId() const
定义:
c4d_basecontainer.h:131
Bool Open(Int32 ident, const Filename &filename, FILEOPEN mode, FILEDIALOG error_dialog)
maxon::Url MaxonConvert(const Filename &fn, MAXONCONVERTMODE convertMode)
const CustomDataType * GetCustomDataType(Int32 id, Int32 datatype) const
static String IntToString(Int32 v)
定义:
c4d_string.h:495
@ OK
Function was successful.
Bool GetParameter(const DescID &id, GeData &t_data) const
定义:
c4d_basecontainer.h:628
Represents a date and time.
定义:
customgui_datetime.h:38
BaseContainer GetContainer(Int32 id) const
定义:
c4d_basecontainer.h:418
#define SIZEOF(x)
Calculates the size of a datatype or element.
定义:
apibasemath.h:205
Int64 Int
signed 32/64 bit int, size depends on the platform
定义:
apibase.h:184
@ RDATA_XRES
定义:
drendersettings.h:152
Bool ReadContainer(BaseContainer *v, Bool flush)
#define NOTOK
定义:
ge_sys_math.h:265
BaseContainer * GetClone(COPYFLAGS flags, AliasTrans *trans) const
定义:
c4d_basecontainer.h:101
maxon::Int32 Int32
定义:
ge_sys_math.h:58
#define ApplicationOutput(formatString,...)
定义:
debugdiagnostics.h:207
Int32 day
Day in month.
定义:
customgui_datetime.h:64
Bool ShowBitmap(const Filename &fn)
void GetDataPointers(const Int32 *ids, Int32 cnt, const GeData **data) const
定义:
c4d_basecontainer.h:217
void * GetVoid(Int32 id, void *preset=nullptr) const
定义:
c4d_basecontainer.h:343
Bool SetParameter(const DescID &id, const GeData &t_data)
定义:
c4d_basecontainer.h:635
void MergeContainer(const BaseContainer &src)
void SetLink(Int32 id, C4DAtomGoal *link)
定义:
c4d_basecontainer.h:604
Base class for custom data types.
定义:
c4d_customdatatype.h:50
const String & GetString(void) const
定义:
c4d_gedata.h:463
Bool WriteContainer(const BaseContainer &v)
DateTime GetDateTime() const
@ READ
Open the file for reading.
RenderData * GetActiveRenderData(void)
String GetString(Int32 id, const maxon::String &preset=maxon::String()) const
定义:
c4d_basecontainer.h:387
#define DATETIME_DATA
DateTime custom data ID.
定义:
customgui_datetime.h:23
void SetContainer(Int32 id, const BaseContainer &s)
定义:
c4d_basecontainer.h:597
Int32 year
Year.
定义:
customgui_datetime.h:62
定义:
c4d_basedocument.h:136
@ BFM_INTERACTSTART
定义:
gui.h:898
BaseObject * GetActiveObject(void)
String GetName() const
定义:
c4d_baselist.h:2318
IMAGERESULT
定义:
ge_prepass.h:3659
Int32 hour
Hour.
定义:
customgui_datetime.h:66
Int32 month
Month.
定义:
customgui_datetime.h:63
定义:
c4d_basematerial.h:27
Int32 GetIndexId(Int32 index) const
定义:
c4d_basecontainer.h:197
Int32 GetInt32(Int32 id, Int32 preset=0) const
定义:
c4d_basecontainer.h:303
Int32 second
Second.
定义:
customgui_datetime.h:68
UInt32 GetDirty() const
定义:
c4d_basecontainer.h:148
定义:
c4d_basedocument.h:490
定义:
c4d_basecontainer.h:46
@ NODOCUMENTCLONE
Set to avoid an automatic clone of the scene sent to RenderDocument().