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" );
This is the straightforward implementation of DescribeIO()
.
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);
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);
}
}
{
{
}
}
};
{
}
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 ; }
}
}
};
{
{
}
{
}
}
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
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:35
Definition: dataserialize.h:205
Result< void > DescribeIO(const T &s, const DataSerializeInterface &dsi)
Definition: datatypefunctions.h:21
#define Describe(name, memberName, type, flags)
Definition: dataserialize.h:293
#define CONSTHASH(x)
Expression to calculate the hash code of a member name during compile time.
Definition: dataserialize.h:194
The maxon namespace contains all declarations of the MAXON API.
Definition: c4d_basedocument.h:15
#define DescribeHelperIf(name, memberName, type, flags, mask, value)
Definition: dataserialize.h:388
Definition: string.h:1213
return OK
Definition: apibase.h:2546
static const ValueType NONE
Default.
Definition: dataserialize.h:136
bool Bool
boolean type, possible values are only false/true, 8 bit
Definition: apibase.h:179
#define PrepareDescribe(streamClass, className)
Definition: dataserialize.h:267
Definition: apibaseid.h:250
#define iferr_return
Definition: resultbase.h:1465
static const 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
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:167
static const UInt FINALIZEHASH
Definition: dataserialize.h:172
#define DescribeHelper(name, memberName, type, flags)
Definition: dataserialize.h:344
OK
Ok.
Definition: ge_prepass.h:2
MAXON_ATTRIBUTE_FORCE_INLINE Int GetCount() const
Definition: basearray.h:527
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:186
#define iferr_scope
Definition: resultbase.h:1374
@ INITIALIZE_WRITE
The helper's WriteAction will get a call with INITIALIZEHASH before the class has been written.
#define DescribeEndIf()
Definition: dataserialize.h:429
#define DescribeElse()
Definition: dataserialize.h:410
@ FINALIZE_READ
The helper's ReadAction will get a call with FINALIZEHASH after the class has been read.
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:67
MAXON_DATATYPE(GeData, "net.maxon.data.gedata")
#define PrepareHelper(helperName, flags)
Definition: dataserialize.h:397
UInt64 UInt
unsigned 32/64 bit int, size depends on the platform
Definition: apibase.h:187
static const UInt INITIALIZEHASH
Definition: dataserialize.h:171
static const 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
#define DebugAssert(condition,...)
Definition: debugdiagnostics.h:246