Core Nodes Implementation

About

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.

Implementation

A simple custom core node is implemented as follows:

// This example shows
// core node class
class MaximumComponentCoreNode
{
public:
// input port "colora"
// input port "colorb"
// output port "result"
{
public:
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
ports.result.Update(resultColor);
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");

Description

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 "net.maxon.node.base.group.inputs" or "net.maxon.node.base.group.outputs"
  • 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)
{
const maxon::LanguageRef language = maxon::LanguageRef();
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()
{
{
err.CritStop();
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;
return maxon::OK;
}
// free description
static void HandleFreeModule()
{
g_coreNodeDescriptions.Reset();
}
MAXON_INITIALIZATION(HandleInitializeModule, HandleFreeModule);

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

Further Reading

maxon::DataDescriptionDefinitionDatabaseInterface::RegisterDatabaseWithUrl
static MAXON_METHOD Result< void > RegisterDatabaseWithUrl(const Id &databaseId, const Url &url)
maxon::DataDescriptionDatabaseInterface::LoadDescription
static MAXON_METHOD Result< DataDescription > LoadDescription(const Id &category, const LanguageRef &language, const Id &dataType)
maxon::Col4::b
T b
Definition: col4.h:35
MAXON_ATTRIBUTE_FORCE_INLINE
#define MAXON_ATTRIBUTE_FORCE_INLINE
Definition: apibase.h:105
maxon::Col4::r
T r
Definition: col4.h:33
maxon::LiteralId::IsPopulated
Bool IsPopulated() const
Definition: apibaseid.h:146
maxon::Tuple
Definition: tuple.h:569
maxon::DataDescriptionDefinitionDatabaseInterface::GetRegisteredDescriptions
static MAXON_METHOD Result< BaseArray< IdAndVersion > > GetRegisteredDescriptions(const Id &databaseId, const Id &category, const LanguageRef &language)
maxon::OK
return OK
Definition: apibase.h:2462
maxon::Id
Definition: apibaseid.h:273
maxon::APPLICATION_URLTYPE::CURRENT_MODULE_RESOURCE_DIR
@ CURRENT_MODULE_RESOURCE_DIR
Resource directory of the module that invoked this call.
iferr_return
#define iferr_return
Definition: resultbase.h:1419
MAXON_PORT_INPUT
#define MAXON_PORT_INPUT(T, name)
Definition: micronodes_ports.h:58
maxon::corenodes
Definition: corenodes.h:9
maxon::BaseArray
Definition: basearray.h:366
maxon::Url
Definition: url.h:819
MAXON_INITIALIZATION
#define MAXON_INITIALIZATION(...)
Definition: module.h:731
maxon::DATADESCRIPTION_CATEGORY_DATA
const Id DATADESCRIPTION_CATEGORY_DATA
Definition: datadescriptiondatabase.h:17
maxon::Col4
A color consisting of three components R, G, B and an alpha.
Definition: col4.h:14
maxon::Result< void >
maxon::BaseArray::Append
MAXON_ATTRIBUTE_FORCE_INLINE ResultRef< T > Append()
Definition: basearray.h:569
maxon::Classes::Get
const Class< R > & Get(const Id &cls)
Definition: objectbase.h:1881
iferr_scope
#define iferr_scope
Definition: resultbase.h:1328
maxon::Col4::a
T a
Definition: col4.h:36
maxon::GenericData
Definition: genericdata.h:19
MAXON_CORENODE_REGISTER_PURE
#define MAXON_CORENODE_REGISTER_PURE(CLS, id,...)
Definition: corenodes.h:975
iferr_scope_handler
#define iferr_scope_handler
Definition: resultbase.h:1346
maxon::Application::GetUrl
static MAXON_FUNCTION Result< Url > GetUrl(APPLICATION_URLTYPE urlType)
maxon::Col4::g
T g
Definition: col4.h:34
MAXON_PORT_OUTPUT
#define MAXON_PORT_OUTPUT(T, name)
Definition: micronodes_ports.h:209
maxon::BaseArray::Reset
void Reset()
Deletes all elements (calls destructors and frees memory).
Definition: basearray.h:495
maxon::Max
constexpr MAXON_ATTRIBUTE_FORCE_INLINE X Max(X a, X b)
Calculates the maximum of two values and return it.
Definition: apibasemath.h:363
maxon::corenodes::BasicMicroNode
Definition: micronodes.h:205
micronodes.h
maxon::LiteralId::Get
const Id & Get() const
Definition: apibaseid.h:183