Explains how to update a Cinema 4D 2026 plugin so that it compiles with the 2027.0 SDK.
The 2027 SDK keeps the ABI of the 2026 SDK (see ABI Compatibility). Plugins compiled with the 2026 SDK do not have to be recompiled and will work in all releases of Cinema 4D 2027. This manual is only relevant when you want to compile your plugin sources with the 2027 SDK. The shared ABI only guarantees that binaries keep working, not that source code keeps compiling. The frameworks have changed in places where 2026 plugin code must be adapted. These changes are mostly small and the best way to find them is to compile your plugin against the 2027 SDK and to fix the errors one by one. The changes below have been derived by comparing the 2026 and 2027 SDK examples and by building the unmodified 2026 examples with the 2027 frameworks (MSVC and ClangCL, Windows x64). Not every change is exercised by the examples; changes that are only visible in the framework headers are marked as such.
| Change | Type | Description |
|---|---|---|
| Project definitions | Major | Legacy projectdefinition.txt files can be converted once during CMake configuration, see Project Definitions. |
iferr_ignore | Major | The macro no longer returns the value of the ignored Result and only accepts a const char* reason. This breaks most Alloc() implementations of the form NewObj(...) iferr_ignore(...), see Changes to iferr_ignore. |
| Asset type components | Major | The method AssetTypeInterface::GetAssetDataType has been renamed to DeprecatedGetAssetDataType, see Asset Type Components. |
| Asset API | Major | Several methods have been renamed, deprecated, or have changed their signature or return type, see Asset API. |
| Custom data types | Major | CustomDataTypeClass gained the method GetHashCode, see Custom Data Types. |
Block initialization | Minor | Block can no longer be initialized from an initializer list, see Initializing Blocks. |
| Deprecations | Minor | Several methods are now deprecated and produce warnings, see Deprecations. |
| Compiler warnings | Minor | ClangCL treats implicit integer to float conversions as errors, and more MSVC warnings are reported, see Compiler Warnings. |
| Removed symbols | Minor | A few symbols have been removed or renamed, see Removed and Renamed Symbols. |
In 2026, iferr_ignore("reason") was a macro which expanded to .UncheckedGetValue(). The reason was not used, and the macro returned the value of the Result it was applied to. In 2027, the macro expands to .IfErrIgnore("reason"), a method which only accepts a const char* and returns void. This has three consequences for existing code:
iferr_ignore cannot be used anymore. Statements such as return NewObj(MyObject) iferr_ignore("..."); or auto ref = Foo::Create() iferr_ignore("..."); do not compile anymore."reason"_s does not compile anymore.The most common case are the Alloc() functions of plugin classes. NewObj returns a ResultMemT<T*>, and GetPointer() returns the contained pointer, which is nullptr when the allocation failed. This is what the previous code implicitly did, and what the 2027 SDK examples do:
When you need the value of a Result and cannot ignore a failure, handle the error explicitly with iferr or iferr_return. The MorphMixerObject example for instance used the value of a Create() call and now branches to its error handler:
When the result is not used, only the string literal must be adapted:
MAXON_IFERRIGNORE_LEGACY_HANDLING for your module (e.g., before including any header or as a compile definition) to restore the old behavior of iferr_ignore, i.e., that it returns the value of the Result. The reason must then still be a plain string literal. We recommend to migrate your code instead.The asset type interface method AssetTypeInterface::GetAssetDataType has been renamed to DeprecatedGetAssetDataType and is marked as [[deprecated("will be removed without replacement")]]. The rename has been done with an annotation which binds the new name to the old method identifier, i.e., the interface is binary identical. But source code which implements the method under its old name does not compile anymore. This affects every component which implements an asset type, such as the preset asset type in the example.assets plugin. The source processor reports this as:
You have two options. The 2027 version of the example.assets plugin simply removes the override from the declaration and the definition of the asset type component:
If you want to keep implementing the method, for example because your binary must also load in Cinema 4D 2026 where the method is still part of the interface, rename it instead:
The following changes to the Asset API do not affect the SDK examples, except for the repository creation in example.assets which is shown in detail. They are visible in the framework headers (mostly assets.h, asset_databases.h, and urlassetrepository.h).
| 2026 | 2027 |
|---|---|
AssetTypeInterface::CopyWithEncryption | Renamed to CopyWithProtection, signature unchanged (annotation bound). |
Result<Tuple<Data, Bool>> AssetTypeInterface::ComputeMetaData | Returns Result<Tuple<Data, AssetMetaDataInterface::KIND>> (annotation bound), see below. |
AssetRepositoryInterface::CopyAsset(aid, source, addEncryption, overwrite) | The old overload is now DeprecatedCopyAsset (annotation bound). The new CopyAsset(aid, source, addProtection, overwrite, encryption) has an additional optional CryptoKey argument; calls with up to four arguments still compile. |
AssetInterface::CreateRepositoryFromUrl | Deprecated, use UrlAssetRepositoryFactory::CreateStandardRepository, see below. |
AssetRepositoryTypes::AssetDatabase, AssetRepositoryTypes::WatchFolder | Deprecated, use the factories in UrlAssetRepositoryFactories. |
AssetInterface::GetUserPrefsRepository returns const UpdatableAssetRepositoryRef& | Returns const AssetRepositoryRef& (annotation bound). |
UpdatableAssetRepositoryRef available through maxon/assets.h | Only forward declared in maxon/assets.h. Include maxon/updatable_asset.h to use the type. |
AssetDatabaseInterface::SetDatabases(const Block<AssetDatabaseStruct>&) | Takes a const Block<const AssetDatabaseStruct>& (annotation bound). |
URLFLAGS::ASSETREPOSITORYTYPE | Replaced by URLFLAGS::ASSETREPOSITORYFACTORY. New is also URLFLAGS::ASSETREPOSITORYWRITABLE. |
AddAssetDepencendyStruct::AddDependency(const AssetDescription&) | Requires an additional ASSET_UPDATE_POLICY argument, there is no overload without it. |
AssetMetaDataInterface::KIND::STORAGELOCATION_DB, _USER, _DERIVED, _MASK | Removed. New are DERIVED_FALLBACK, USER_FALLBACK, and COPY_AS_PERSISTENT. |
The second tuple element is now a flag enum instead of a Bool. Return KIND::NONE where you returned false, KIND::DERIVED where you returned true and the value should be cached in memory, and KIND::PERSISTENT (or KIND::DERIVED | KIND::PERSISTENT) when the value should additionally be cached on disk.
AssetInterface::CreateRepositoryFromUrl has been deprecated in favor of the repository factories. The result of the factory is a UrlAssetRepositoryRef, which converts to an AssetRepositoryRef. Note that the arguments have been reordered and that their meaning has changed (e.g., derivedInPrefs is now derivedInRepository), so review each argument instead of just copying the old values. Also note that maxon/urlassetrepository.h now includes maxon/updatable_asset.h instead of maxon/assets.h.
Code which only included maxon/assets.h and uses UpdatableAssetRepositoryRef fails with an error such as ‘uses undefined class 'maxon::UpdatableAssetRepositoryRef’. Includemaxon/updatable_asset.hor switch toAssetRepositoryRef`.
CustomDataTypeClass has a new virtual method GetHashCode(const CustomDataType*). When MAXON_API_ABI_VERSION is at least 2027000 the method is pure virtual. In the 2027 SDK the ABI version is still 2026000, so that the method has a default implementation which stops execution with a CriticalStop() when it is called. This means that your 2026 plugin compiles unchanged, but fails at runtime as soon as the hash of one of your custom data values is requested. The Dots custom data type in example.assets and the Hybrid custom data type in example.nodes have been updated to implement the method and you should do the same for all your custom data types:
Block has lost its implicit constructor from an initializer list. The following code which compiled in 2026 now fails with ‘cannot convert from 'initializer list’ to 'maxon::Block<const maxon::Float32>'`:
For a local variable, store the values in an array and construct the block from that array, as the example.image plugin does now. For temporary function arguments, the new type maxon::TmpBlock can be used instead. It converts from initializer lists, but may only be used for temporary arguments, as it does not own its data:
The following APIs still compile but produce deprecation warnings (ClangCL) which you should fix. Some of these have been deprecated in the 2026 service releases (2026.2 and 2026.3), i.e., after the 2026.0.0 SDK, and might not yet be known to code written against it.
| Deprecated | Replacement |
|---|---|
Opt<T>::GetValue() (since 2026.3) | ToResult(), e.g., collection.FindValue(key).ToResult() iferr_return. |
Opt<T>::GetValueOrNull() (since 2026.2) | GetValueOrDefault(). |
Url::GetUrl() (since 2026.2) | ToString(), e.g., url.ToString(). |
AccessedObjectsCallback::MayAccessDeprecated | MayAccess2; pass CAMERA, TIME, or EXTERNAL in the masks when needed. |
ViewportSelect::PickMaterial overload with pickedObject | The overload without that parameter. |
AssignCopyConvert | AssignCopy. |
Id::Init(const InternedId&) in apibaseid.h | The assignment operator. |
DIRECT_PORT in nodesystem.h | EXPLICIT_PORT. |
The warning configuration of the SDK has been tightened. The warnings below can surface as errors or warnings in code which compiled without them in 2026:
-Werror=implicit-int-float-conversion is now enabled, where 2026 muted the warning. An implicit conversion of an integer to a floating point value, e.g., 0.415 * 4 / cnt where cnt is an Int, is now an error. Make the conversion explicit: 0.415 * 4 / (Float)cnt. The -Wtautological-compare family and -Wpointer-bool-conversion are now also enabled.g_random.Get01() > .5 ? 0.0 : 1.0 assigned to a float now produces a warning. Use float literals such as 0.0f.| 2026 | 2027 |
|---|---|
DrawRect<T>::GetBottomRigthPoint() in gfx_basictypes.h | Renamed to GetBottomRightPoint(); the misspelled name does not exist anymore. |
maxon::nodes::NODESPACE::DOCUMENTPATH in node_spaces.h | No longer declared. |
ASSET_MANAGER_SETTINGS::LIST_VIEW_ICON_SIZE_LEVEL and GRID_VIEW_ICON_SIZE_LEVEL (Int) in assetmanagerinterface.h | Replaced by LIST_VIEW_ICON_SIZE and GRID_VIEW_ICON_SIZE, which are Float values in the range [0, 1] and use the same string identifiers. |
The 2027 SDK uses native CMakeLists.txt files instead of projectdefinition.txt files. You do not have to convert your old project definitions by hand: configure the 2027 SDK once with MAXON_MIGRATE_LEGACY_PROJECTS=ON and the SDK generates a project/CMakeLists.txt for each module which only has a projectdefinition.txt. Review the generated files before you rely on them. See Migrating from projectdefinition.txt for the procedure and its limitations.
When you have questions about migrating your code, contact us via the Maxon Developer Portal.