Core Nodes Implementation


A core node is a basic node of Cinema 4D's node material system. It represents a basic functionality that can be used in a node material.

The relevant interfaces needed to implement custom core nodes are found in the corenodes.framework.


A simple custom core node is implemented as follows:

// This example shows
// core node class
class MaximumComponentCoreNode
// input port "colora"
// input port "colorb"
// output port "result"
MAXON_ATTRIBUTE_FORCE_INLINE maxon::Result<void> Process(const Ports<colora, colorb, result>& ports) const
// access input port color
const maxon::ColorA& inputColorA = ports.colora();
const maxon::ColorA& inputColorB = ports.colorb();
// invert color
maxon::ColorA resultColor;
resultColor.r = maxon::Max(inputColorA.r, inputColorB.r);
resultColor.g = maxon::Max(inputColorA.g, inputColorB.g);
resultColor.b = maxon::Max(inputColorA.b, inputColorB.b);
resultColor.a = maxon::Max(inputColorA.a, inputColorB.a);
// store in result port
return maxon::OK;
static maxon::Result<void> Init(const maxon::corenodes::MicroNodeGroupRef& group)
return group.AddChild<Impl>();
using namespace maxon::corenodes;
// we choose pure registration, because the node has no lazy evaluation (and is evaluated from left to right).
MAXON_CORENODE_REGISTER_PURE(MaximumComponentCoreNode, "net.maxonexample.corenodes.examplenode");
Definition: micronodes.h:209
Definition: corenodes.h:1033
Definition: apibase.h:111
return OK
Definition: apibase.h:2620
Calculates the maximum of two values and return it.
Definition: apibasemath.h:349
#define MAXON_PORT_INPUT(T, name)
Definition: micronodes_ports.h:60
#define MAXON_PORT_OUTPUT(T, name)
Definition: micronodes_ports.h:221
This namespace contains the API of the nodes framework.
Definition: corenodes.h:10
#define iferr_scope
Definition: resultbase.h:1374
A color consisting of three components R, G, B and an alpha.
Definition: col4.h:16
T r
Definition: col4.h:33
T g
Definition: col4.h:34
T a
Definition: col4.h:36
T b
Definition: col4.h:35


The description of the core node must be created with the Resource Editor.The new data type must have the ID of the core node.

The data type properties are:

  • Classification: "node"
  • Description Processor: "CoreNodeDescriptionProcessor"
  • Processor Parameters: The core node ID.
  • Menu Category: Select a category for the node.

The core node needs a new attribute:

  • Command: "include"
  • Identifier: "net.maxon.node.base"
  • Include: "net.maxon.node.base"

The name of the node is set with net.maxon.node.base.

Port descriptions are created with new attributes:

  • Command: "attribute"
  • Identifier: the port ID
  • Datatype: The port data type
  • Classification: "input" or "output"
  • Gui Type Id: The proper UI for that data type
  • Group Id: The proper group, either "" or ""
  • String: The name displayed in the UI.

Description Handling

The description of the core node must be loaded and handled properly:

// This example loads and handles the description database containing the core node description.
static maxon::BaseArray<maxon::GenericData> g_coreNodeDescriptions;
// the ID of the database storing the core node's description
static maxon::Id g_corenodesDatabaseId = maxon::Id { "net.maxonexample.corenodes" };
// function to process the description
// static maxon::Result<void> HandleCoreNodeDescriptions(const maxon::Id& databaseId)
// iferr_scope;
// const maxon::Id catData = maxon::DATADESCRIPTION_CATEGORY_DATA;
// const maxon::LanguageRef language = maxon::LanguageRef();
// maxon::BaseArray<maxon::IdAndVersion> ids = maxon::DataDescriptionDefinitionDatabaseInterface::GetRegisteredDescriptions(g_corenodesDatabaseId, catData, language) iferr_return;
// for (const maxon::IdAndVersion& id : ids)
// {
// maxon::DataDescription description = maxon::DataDescriptionDatabaseInterface::LoadDescription(maxon::DATADESCRIPTION_CATEGORY_DATA, maxon::LanguageRef(), id.first) iferr_return;
// maxon::DataDictionary info = description.GetInfo();
// maxon::Id builderId = info.Get(maxon::DESCRIPTION::DATA::INFO::PROCESSOR, maxon::Id());
// if (builderId.IsPopulated())
// {
// const maxon::DescriptionProcessor& processor = maxon::DescriptionProcessors::Get(builderId);
// if (processor)
// {
// maxon::GenericData d = processor.Process(id.first, description) iferr_return;
// g_coreNodeDescriptions.Append(std::move(d)) iferr_return;
// }
// }
// }
// return maxon::OK;
// load description
static maxon::Result<void> HandleInitializeModule()
return err;
// get plugin "res" folder
// get "nodes" folder within the "res" folder
const maxon::Url coreNodesResourceUrl = pluginDir.Append("nodes"_s) iferr_return;
// register database
// handle the core node description
//HandleCoreNodeDescriptions(g_corenodesDatabaseId) iferr_return; // commented out due to duplication in DB registration occurred because of the line above
return maxon::OK;
// free description
static void HandleFreeModule()
MAXON_INITIALIZATION(HandleInitializeModule, HandleFreeModule);
Definition: basearray.h:413
void Reset()
Deletes all elements (calls destructors and frees memory).
Definition: basearray.h:542
static MAXON_METHOD Result< void > RegisterDatabaseWithUrl(const Id &databaseId, const Url &url)
Definition: apibaseid.h:251
Definition: url.h:876
Definition: module.h:750
Resource directory of the module that invoked this call.
#define iferr_scope_handler
Definition: resultbase.h:1392
#define iferr_return
Definition: resultbase.h:1465

This is an extended version of the typical procedure to load MAXON API descriptions. See Loading Data Descriptions.

Further Reading