Overview
- The Source Processor is a tool that automatically analyses the plugin source code and creates utility code.
- Debug messages can be written with ApplicationOutput() or DiagnosticOutput().
- The plugin code must handle error objects that are returned by sub-functions.
- It is also possible to return error object to report errors.
- Plugins using the "classic" API must implement PluginStart(), PluginMessage() and PluginEnd().
- The "classic" API allows to create new objects and tools by implementing plugin hooks like ObjectData etc.
- Most elements of the "classic" API are based on C4DAtom, GeListNode and BaseList2D.
- Parameters of Cinema 4D elements are accessed with C4DAtom::GetParameter() and C4DAtom::SetParameter(). The parameter IDs are represented with DescID objects.
- The MAXON API allows to create new components by implementing interfaces. These implementation are shared with registries or as published object.
Source Processor
The Source Processor is a Python script that is executed every time a MAXON API framework or plugin is build. The script checks the code for certain programming errors and creates additional code.
If a project file is created with the Project Tool, the script is automatically added to the build process. It is not needed to run it manually. The output console of the IDE will display which file or files are parsed and what errors the script has detected.
Printing Messages
To debug a program and to follow the program flow it is useful to print a statement to the IDE's console window. This can easily be done with DiagnosticOutput().
For more debug functions see Debug and Output Functions and Debugging.
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:176
static void PrintHelloWorld()
{
}
Definition: string.h:1235
Error System
The MAXON API includes a sophisticated error system. This system allows functions not only to return arbitrary values but also dedicated error objects. Such an error object contains information on what exactly went wrong within the function. For an overview see Error Handling.
This simple code snippet accesses the name of the host machine:
static MAXON_METHOD DataDictionary GetMachineInfo()
Definition: resultbase.h:766
PyObject PyObject * result
Definition: abstract.h:43
maxon::Application::GetMachineInfo() returns a DataDictionary that includes various system data. To access the data one can use maxon::DataDictionaryInterface::Get(). This function does not return a primitive value but a maxon::Result object. Such a maxon::Result object contains either the return value or an error object.
It is possible to manually handle the maxon::Result object. See also Error Result.
{
}
else
{
const maxon::Error& err =
result.GetError();
}
const char const char * name
Definition: abstract.h:195
return OK
Definition: apibase.h:2667
The preferred way of handling errors is to use various attributes. These attributes can be used to handle the program flow in the case of an error. E.g. ifnoerr() executes the given code only if no error occurred.
{
}
#define ifnoerr(...)
The opposite of iferr.
Definition: errorbase.h:393
Within a function that returns a maxon::Result one can return either a valid return value or an error object. Such an error object can be one of many build-in error types. See Error Types.
Within such a function one can also return the error returned by a sub-function. This is automatically done by using the attribute iferr_return. To use this macro one must prepare the scope using iferr_scope.
The attribute iferr_scope_handler allows to define some code that is invoked when an error is detected with iferr_return.
static void PrintMachineName()
{
{
};
}
#define iferr_scope_handler
Definition: resultbase.h:1392
#define iferr_return
Definition: resultbase.h:1465
{
return true;
return false;
}
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
#define iferr_scope
Definition: resultbase.h:1374
Classic API Foundations
Basic Plugin Functions
Every plugin that uses the classic API (linking to cinema.framework) must implement the global functions PluginStart(), PluginMessage() and PluginEnd(). This is typically done in a main.cpp file.
PluginStart() is used to register classic API plugins. PluginMessage() can receive various global messages. PluginEnd() is used to free data before the plugin in unloaded when Cinema 4D ends. See Plugin Functions Manual.
Classic plugins are created by implementing a plugin class e.g. ObjectData or TagData. Such an implementation must be registered in PluginStart() using a specific function like RegisterObjectPlugin(). See General Plugin Information Manual.
C4DAtom
C4DAtom is the base class for many elements of the classic API. It gives access to the element's type, its parameter Description, parameter values and dirty state. The class is also used to copy the element and send messages to it. See C4DAtom Manual.
if (clone == nullptr)
doc->InsertObject(objectClone,
nullptr,
nullptr);
Definition: c4d_baseobject.h:225
Definition: c4d_baselist.h:1377
C4DAtom * GetClone(COPYFLAGS flags, AliasTrans *trn)
Definition: c4d_baselist.h:1462
Definition: c4d_gedata.h:83
const Vector & GetVector(void) const
Definition: c4d_gedata.h:451
Py_ssize_t size
Definition: bytesobject.h:86
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:145
maxon::Int32 Int32
Definition: ge_sys_math.h:60
@ PRIM_CUBE_LEN
Definition: ocube.h:6
PyObject ** type
Definition: pycore_pyerrors.h:34
const char * doc
Definition: pyerrors.h:226
GeListNode
GeListNode is another frequently used base class. It allows to organize elements in lists and trees. It also gives access to the element's document and registration information. See GeListNode Manual.
{
}
Definition: c4d_basedocument.h:498
BaseObject * GetNext(void)
Definition: c4d_baseobject.h:256
BaseObject * GetDown(void)
Definition: c4d_baseobject.h:274
BaseDocument * GetDocument()
Definition: c4d_baselist.h:1960
#define PLUGINFLAG_HIDEPLUGINMENU
Hide the plugin's menu entry.
Definition: c4d_baseplugin.h:31
_Py_clock_info_t * info
Definition: pytime.h:197
BaseList2D
The base class BaseList2D provides functions to handle the element's name, animation tracks, internal data, bits, shaders, layers and IDs. See BaseList2D Manual.
if (newMaterial == nullptr)
doc->InsertMaterial(newMaterial);
newMaterial->
SetName(
"The new Material"_s);
if (noiseShader == nullptr)
if (root == nullptr)
if (newLayer == nullptr)
Bool SetLayerObject(LayerObject *layer)
void SetName(const maxon::String &name)
Definition: c4d_baselist.h:2369
void InsertShader(BaseShader *shader, BaseShader *pred=nullptr)
Definition: c4d_baselist.h:2573
Definition: c4d_basechannel.h:36
static BaseShader * Alloc(Int32 type)
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
Definition: c4d_baselist.h:2026
void InsertLast(GeListNode *bn)
Definition: c4d_baselist.h:2110
Definition: c4d_basedocument.h:253
static LayerObject * Alloc(void)
Definition: c4d_basematerial.h:241
static Material * Alloc()
#define Xnoise
Noise.
Definition: ge_prepass.h:1332
@ MATERIAL_COLOR_SHADER
Definition: mmaterial.h:272
Parameter IDs
The functions C4DAtom::GetParameter() and C4DAtom::SetParameter() allow to access the parameter values of objects, materials, tags etc. The ID of such a parameter is defined using a DescID object. Such a DescID object is composed of multiple DescLevel elements. The complete DescID is also needed when handling an animation track of a given parameter. See DescID Manual.
if (track == nullptr)
{
if (track == nullptr)
cubeObject->InsertTrackSorted(track);
}
PyObject * value
Definition: abstract.h:715
CTrack * FindCTrack(const DescID &id)
Definition: c4d_canimation.h:671
static CTrack * Alloc(BaseList2D *bl, const DescID &id)
Definition: lib_description.h:330
void PushId(const DescLevel &subid)
Float GetFloat(void) const
Definition: c4d_gedata.h:439
maxon::Float Float
Definition: ge_sys_math.h:66
@ DTYPE_VECTOR
Vector
Definition: lib_description.h:70
@ DTYPE_REAL
Float
Definition: lib_description.h:68
@ VECTOR_X
X component.
Definition: lib_description.h:269
Represents a level within a DescID.
Definition: lib_description.h:289
MAXON API Foundations
Interfaces
An interface is a public abstract declaration of a class. Such an interface can be implemented one or multiple times; such implementations are separated from the public interface declaration. This interface system is the base for most MAXON API classes. See MAXON API Interfaces.
{
public:
};
#include "simpleclass1.hxx"
MAXON_DECLARATION(SimpleClassRef, OtherSimpleClass,
"net.maxonexample.othersimpleclass");
#include "simpleclass2.hxx"
[interfaces_basic_virtual_interface]
Definition: simpleclass.h:15
MAXON_METHOD void SetNumber(maxon::Int number)
MAXON_INTERFACE(SimpleClassInterface, MAXON_REFERENCE_NORMAL, "net.maxonexample.interfaces.simpleclass")
MAXON_METHOD maxon::Int GetNumber() const
Definition: objectbase.h:709
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:188
#define MAXON_REFERENCE_NORMAL(FREEIMPL)
Definition: interfacebase.h:1173
#define MAXON_DECLARATION(T, Name, id,...)
Definition: module.h:847
#define MAXON_METHOD
Definition: interfacebase.h:1001
#define MAXON_INTERFACE_BASES(...)
Definition: objectbase.h:1062
class SimpleClassImplementation :
public maxon::Component<SimpleClassImplementation, SimpleClassInterface>
{
public:
{
_value = number;
}
{
return _value;
}
private:
};
Definition: objectbase.h:2651
#define MAXON_COMPONENT(KIND,...)
Definition: objectbase.h:2212
const maxon::Id id {
"net.maxonexample.class.somesimpleclass" };
const SimpleClassRef simpleClass = componentClass.Create()
iferr_return;
simpleClass.SetNumber(123);
const maxon::Int number = simpleClass.GetNumber();
Definition: apibaseid.h:253
References
The MAXON API makes heavy use of reference counting. New instances of a given class are typically handled as reference counted objects. The instance will be freed when all references using that object are deleted. See References.
{
vectorRef->y = 200.0f;
vectorRef->z = 300.0f;
}
#define MAXON_SCOPE
Definition: apibase.h:2818
#define NewObj(T,...)
Definition: newobj.h:108
Registries
A registry is used to store implementations of a given interface. Using such a registry it is possible to access all implementations of that interface. See Registries.
for (const auto& it : maxon::StreamConversions::GetEntriesWithId())
{
}
Published Objects
A published object gives access to a certain object. This can be any kind of object in memory; typically it is a class representing an implementation of an interface. See Published Objects.
const maxon::StreamConversionRef hexEncoder = maxon::StreamConversions::HexEncoder().Create()
iferr_return;
Definition: basearray.h:412
const Py_UNICODE * source
Definition: unicodeobject.h:54
char Char
signed 8 bit character
Definition: apibase.h:184