About
A custom data type or an implementation of an interface will contain some internal data. A static custom DescribeIO()
function describes how this data is written to or from a file.
- Note
- DescribeIO() does not directly access the file but instructs Cinema 4D how to handle the data.
Data Serialization
A DescribeIO()
function handles the given maxon::DataSerializeInterface argument. This object should not be handled directly; only with these macros:
- PrepareDescribe(): Starts a description. Must happen before any
Describe()
calls are made.
- Describe(): Describes a class member for I/O operations.
- DescribeOther(): Describes a class member for I/O operations. Allows to cast to a different DataType before the description is made.
- DescribeLegacy(): Describes a legacy element that is no longer needed.
Certain elements may only be handled if a certain condition is fulfilled:
This snippet shows a simple custom data type:
class SimpleTriplet
{
public:
SimpleTriplet();
};
MAXON_DATATYPE(SimpleTriplet,
"net.maxonexample.datatype.simpletriplet");
Definition: dataserialize.h:207
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:187
Result< void > DescribeIO(const T &s, const DataSerializeInterface &dsi)
Definition: datatypefunctions.h:21
#define MAXON_DATATYPE(type, id,...)
Definition: datatype.h:296
This is the straightforward implementation of DescribeIO()
.
{
}
static constexpr ValueType NONE
Default.
Definition: dataserialize.h:136
#define Describe(name, memberName, type, flags)
Definition: dataserialize.h:294
#define PrepareDescribe(streamClass, className)
Definition: dataserialize.h:268
return OK
Definition: apibase.h:2770
#define iferr_scope
Definition: resultbase.h:1376
#define iferr_return
Definition: resultbase.h:1511
DescribeIO()
is invoked when an instance of the data type is written to or read from a file:
SimpleTriplet triplet;
triplet._a = 100;
triplet._b = 200;
triplet._c = 300;
const maxon::Id fileID {
"net.maxonexample.simpletriplet" };
SimpleTriplet loadedTriplet;
DiagnosticOutput(
"Loaded Triplet: @, @, @", loadedTriplet._a, loadedTriplet._b, loadedTriplet._c);
Definition: apibaseid.h:243
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:170
std::enable_if< GetCollectionKind< T >::value==COLLECTION_KIND::ARRAY, Result< void > >::type ReadDocument(const Url &url, const Id &id, T &object, const DataDictionary &dict=DataDictionary())
Definition: io.h:40
Result< void > WriteDocument(const Url &url, OPENSTREAMFLAGS flags, const Id &id, const T &object, IOFORMAT format=IOFORMAT::DEFAULT, const DataDictionary &dict=DataDictionary())
Definition: io.h:72
The write-process will result in a file like this:
{
"identification": "net.example.simpletriplet",
"content": {
"_a": 100,
"_b": 200,
"_c": 300
}
}
Helper Classes
A helper class is used to define code that is executed when Cinema 4D handles the data. The helper class is used with these macros:
- PrepareHelper(): Declares and initializes an I/O helper class.
- DescribeHelper(): Describes a helper class member for I/O operations
- DescribeHelperIf(): Describes a helper class member for I/O operations and compares its value.
- CONSTHASH(): Expression to calculate the hash code of a member name during compile time. Such a hash value is needed in
WriteAction()
and ReadAction()
.
class TripletHelperClass
{
public:
{
{
_combined = maxon::String::IntToString(triplet._a);
_combined += "::"_s;
_combined += maxon::String::IntToString(triplet._b);
_combined += "::"_s;
_combined += maxon::String::IntToString(triplet._c);
}
}
{
{
}
}
};
{
}
MAXON_ATTRIBUTE_FORCE_INLINE Int GetCount() const
Gets the number of array elements.
Definition: basearray.h:600
Definition: string.h:1287
#define PrepareHelper(helperName, flags)
Definition: dataserialize.h:398
#define DescribeHelper(name, memberName, type, flags)
Definition: dataserialize.h:345
UInt64 UInt
unsigned 32/64 bit int, size depends on the platform
Definition: apibase.h:188
#define DebugAssert(condition,...)
Definition: debugdiagnostics.h:242
@ FINALIZE_READ
The helper's ReadAction will get a call with FINALIZEHASH after the class has been read.
@ INITIALIZE_WRITE
The helper's WriteAction will get a call with INITIALIZEHASH before the class has been written.
static const UInt INITIALIZEHASH
Definition: dataserialize.h:172
static const UInt FINALIZEHASH
Definition: dataserialize.h:173
This will result in a file like this:
{
"identification": "net.example.helpertriplet",
"content": {
"data": "100::200::300"
}
}
This more complex example uses DescribeHelperIf():
class CompactTripletHelperClass
{
public:
{
if (elementHash == _compactHash)
{
if (aEqualsB && bEqualsC)
{
_compact = true;
_compactValue = triplet._a;
}
else
{
_compact = false;
_x = triplet._a;
_y = triplet._b;
_z = triplet._c;
}
}
}
{
switch (elementHash)
{
case (_compactValueHash):
{
triplet._a = _compactValue;
triplet._b = _compactValue;
triplet._c = _compactValue;
break;
}
case (_zHash):
{
triplet._a = _x;
triplet._b = _y;
triplet._c = _z;
break;
}
default: { break; }
}
}
};
{
{
}
{
}
}
static constexpr ValueType ACTION_AFTER_READ
If set there will be a call to the helper class ReadAction member function after an element is read.
Definition: dataserialize.h:143
static constexpr ValueType ACTION_BEFORE_WRITE
If set there will be a call to the helper class WriteAction member function before an element is writ...
Definition: dataserialize.h:142
OK
User has selected a font.
Definition: customgui_fontchooser.h:0
#define DescribeHelperIf(name, memberName, type, flags, mask, value)
Definition: dataserialize.h:389
#define DescribeEndIf()
Definition: dataserialize.h:430
#define DescribeElse()
Definition: dataserialize.h:411
#define CONSTHASH(x)
Expression to calculate the hash code of a member name during compile time.
Definition: dataserialize.h:195
bool Bool
boolean type, possible values are only false/true, 8 bit
Definition: apibase.h:180
The maxon namespace contains all declarations of the Maxon API.
Definition: autoweight.h:21
A "compact" file using the same value for each channel will look like this:
{
"identification": "net.example.compacttriplet",
"content": {
"_compact": true,
"_compactValue": 100
}
}
A non-compact file will look like this:
{
"identification": "net.example.compacttriplet",
"content": {
"_compact": false,
"_x": 10,
"_y": 100,
"_z": 1000
}
}
Further Reading