Changes in R23

Changes in R23.008

Development Environment

Cinema 4D R23 is supported on Windows 10 and on macOS 10.15 (recommended) and macOS 10.14. Developing Cinema 4D R23 requires Visual Studio 2019 and Xcode 11 on the respective operating systems.

R23 Compatibility with previous versions

Plugins built against previous versions are not compatible with Cinema 4D R23 and require a rebuild against the R23 API.
Minor code adoption could also be required to build against R23.

In R23 the source processor could generate more files and it's recommended to include them at the end of the corresponding header file as shown below.

#include "headerFileName1.hxx"
#include "headerFileName2.hxx"

Classic API Resources Documentation

R23 API documentation includes a section concerning to the Classic API resources resulting by parsing the files located in {C4D Install Folder}/resource/modules/*.
The new content is located in Classic Resource overview.

The section enables browsing the Cinema 4D resources to find a particular ID for a given parameter or possible values for a Cycle parameter.

Scene Node

Scene Nodes is a technology preview of Cinema 4D future.
Due to the scope of the project, an API to directly access the provided functionalities is not yet available.
As a temporary fallback, it's possible to request and create a Classic API representation of the Scene Nodes output adopting the code below:

// Export Scene Nodes data
BaseObject* scenenodesRoot = nullptr;
BaseSceneHook* scenenodes = doc->FindSceneHook(Int32(SCENENODES_IDS::SCENEHOOK_ID));
if (scenenodes == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// Request reference to Neutron objects before scene hook execution is done.
scenenodes->Message(Int32(SCENENODES_IDS::MSGUPDATE_LEGACYOBJ_ID), &scenenodesRoot);
if (scenenodesRoot == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// Do anything with the sceneNodeRoot object. It's similar than BaseDocument::GetFirstObject(), but for the Scene Node Root.

For the time being, Scene Nodes Classic API representation only output PolygonObject, Null, LineObject and InstanceObject in Multi-Instances mode.
Material applied via any Material node, will result in the creation of a TextureTag. Vertex Map will result in the creating of a VertexMapTag.
Dirty bit for these Classic API objects should be reliable. They also have unique hashes:

  • Each Null in the hierarchy sets up the BaseObject::GetUniqueIP value to be a hash, but because that's only 32 bit, a collision is likely to occur for 2**16 clones (birthday paradox).
    The UInt64 PERSISTENT_HASH_LOW(SCENENODES_IDS::PERSISTENT_HASH_LOW_ID) is available in the data container to reduce the chances of collision.
  • Multi-Instances (only available for Scene Node-created multi-instance) get a 128-bit hash for each instance that can be query by InstanceObject::GetInstancePersistentHashes.

It's worth to mention the activeobject.cpp example has been adapted to display Scene Nodes Classic API representation (see Project Hooks->Scene Nodes-> "CLASSIC_REPRESENTATION" within the plugin).

Execution Priorities

The EXECUTIONPRIORITY_SCENENODE has been added and it establishes a priority level higher than EXECUTIONPRIORITY_GENERATOR.


A new maxon::Array template interface has been introduced. This new Array support COW (Copy-On-Write) reference and it allows to wrap any existing array-like implementation (maxon::BaseArray, maxon::BlockArray).

Scene Nodes uses this interface to access arrays (some PORT_BUNDLE have been replaced from BaseArray to Array).
However, rest assured the use of maxon::BaseArray, maxon::BlockArray is supported by Scene Nodes and conversion to the maxon::Array is granted using the maxon::ArrayFactory.


The maxon::SqMat2, maxon::SqMat3 and maxon::SqMat4 structs have been renamed in maxon::SqrMat2, maxon::SqrMat3 and maxon::SqrMat4. This renaming does not affect the class member variables named "sqmat".


The maxon::Limit<>::MAX and maxon::Limit<>::MIN constants have been added for types in which they were missing and maxon::Limit<>::Max() and maxon::Limit<>::Min() have been replaced by the former two for types in which they were existing.


Most of MAXON API elements such as maxon::MAXON_DATATYPE or Interface have now a GetHashCode method used to perform efficient comparison.
In R23 the implementation must return a maxon::HashInt and while, at the current time, a Uint64 is used, this may change to 128bits in the future without breaking compatibility.

The new DefaultHash class has a Combine function which allows combining HashInt values.

maxon::HashInt GetHashCode() const
for (const DescLevel& d : _subids)
return hash;
// return maxon::DefaultHash::EMPTY_HASH in case of error.

This code shall be used instead of hash = hash * 31 + value which was previously suggested.
The macro MAXON_HASHCODE(value) can also be used to compute the hash code of the arguments based on DefaultCompare::GetCombinedHashCode.

Finally the old hash mechanism is still available via the macro MAXON_HASHCODE_LEGACY(value).


Within the Release 23, Python version was updated from 2.7.14 to 3.7.7.
This is a significant internal change within Python although if the python.framework was previously used, porting the code to Python 3 should be rather easy.

  • Python 2 namespace is removed: maxon::py27 namespace changed to maxon::py37.
  • Python 2 VM is removed: Python 3 VM shall be used.
  • Raw Python 2 header (cpython27_raw.h) is removed: Raw Python 3 header (cpython37_raw.h) shall be used.
  • String is removed, and unicode shall be used: PyString shall be replaced by PyUnicode.
  • Int is removed, and long shall be used: PyInt shall be replaced by PyLong.

If the deprecated Python Library (lib_py.h) is used, the only change needed is:

  • Registered methods in a PythonMethodData structure need to adapt their flags from PYFN_FLAGS::KEYWORDS to PYFN_FLAGS::KEYWORDS | PYFN_FLAGS::VARARGS. PYFN_FLAGS::NOARGS doesn't need to be adapted.


  • String/Char are internally remapped to Python 3 string (unicode), so nothing to change, e.g. PyTuple::AppendChar append a PyUnicode;
  • In/Uint are internally remapped to Python 3 long, so nothing to change, e.g. PyTuple::AppendInt32 append a PyLong.

Various Changes

API Changes in R23.008

See API Changes in R23.008 for the detailed list.

Definition: c4d_baseobject.h:224
Definition: hash.h:11
maxon::CompareTemplate< false >::GetHashCode
static MAXON_ATTRIBUTE_FORCE_INLINE HashInt GetHashCode(UInt32 h)
Definition: compare.h:71
Definition: memoryallocationbase.h:66
void Combine(HashInt value)
Definition: hash.h:52
Represents a level within a DescID.
Definition: lib_description.h:286
Definition: c4d_basedocument.h:43
Legacy Objects Update Message ID.
maxon::Int32 Int32
Definition: ge_sys_math.h:58
Bool Message(Int32 type, void *data=nullptr)
Definition: c4d_baselist.h:1394
UInt HashInt
Definition: apibase.h:322
SceneHook ID.