Symbols¶
A symbols represents the name of a constant value in the Cinema 4D SDK. Symbol should always be used rather than the direct constant value, as value may change between 2 Cinema 4D releases. As an example Ocube is a symbols representing the constant value 5159. This symbol represent the Plugin ID used to register the Cube Object, other built-in symbols are listed in the Types and Symbols List documents.
Internal Creation Process¶
This section explain the internal process to create symbols. This is relevant to understand the static nature of them.
First, during Cinema 4D compilation i.e the creation of Cinema 4D, symbols and their associated constants values are extracted from the Cinema 4D C++ SDK. They are saved to a file shipped with Cinema 4D. During the first Cinema 4D startup, this cache file and all descriptions resource files are loaded by Python. Python will parse theses files to expose symbols and their value to you, 3rd party plugin developers. This parsing is cached to speedup next Cinema 4D startup. The cache consist of a file named “symbolcache” and updated only when a resource files is added, removed or modified.
The symbolcache file is located in :
(Mac) e.g: ‘/Users/UserName/Library/Preferences/MAXON/Maxon Cinema 4D R25_C333CB6C/prefs/symbolcache’
(Windows) e.g: ‘C:\Users\UserName\AppData\Roaming\Maxon\Maxon Cinema 4D R25_C333CB6C\prefs\symbolcache’
Symbols Parser Usage¶
With Cinema 4D R25, a new parser was introduced to extract symbols and their values from C++ files and description resource files. To have symbols and their values automatically in your Python plugins, the parser is exposed within the symbol_parser Python module.
-
symbol_parser.
parse_and_export_in_caller
(input_directory)¶ Parse all .h files recursively from *input_directory to find define, enum and static const int (read Symbols Parser Features for more information). They are then exported as a Python variable in the caller locals.
- Parameters
input_directory (integer or None) – The directories
Find bellow an example given c4d_symbols.h
enum
{
My_Symbol = 1000,
My_Syml = 1001,
_DUMMY_ELEMENT_
};
To automatically have My_Symbol and My_Syml symbol with their respective associated value in Python use the next
import os
import symbol_parser
# Parse recursively all header files and parse enums and define
c4d_symbol_dir = os.path.dirname("c4d_symbols.h")
symbol_parser.parse_and_export_in_caller(c4d_symbol_dir)
# Values are accessible directly
print(My_Symbol)
>>> 1000
print(My_Syml)
>>> 1001
Symbols Parser Features¶
Supported Values¶
For the moment Cinema 4D, can only ingest Int32 value when reading the cached symbolcache files. However, the parser, understand and parse correctly all POD including string.
Integer value¶
Integer value are parsed, all bit operations are supported, even simple arithmetic.
C++ Input |
Python Output |
---|---|
#define LEGACY_DRAW_FLAGS_DEPTH_TEST_ALWAYS (1 << 10) |
LEGACY_DRAW_FLAGS_DEPTH_TEST_ALWAYS == 1024 |
#define COLORMODE_MAXCOLOR ((1 << 6) - 1) |
COLORMODE_MAXCOLOR == 63 |
#define HUDCONTROL_FLAG_KEYVALUE_CHANGED (1ULL << 32ULL) Note UL/LL/ULL are removed only if the previous char is a number, otherwise it’s kept to not break symbols like BASEDRAW_DISPLAYFILTER_NULL. |
HUDCONTROL_FLAG_KEYVALUE_CHANGED == 4294967296 |
Hexadecimal value¶
Hexadecimal value are correctly parsed.
C++ Input |
Python Output |
---|---|
#define ZIP_FILE_FLAG_OWNER_R 0x01000000 |
ZIP_FILE_FLAG_OWNER_R == 16777216 |
Float value¶
Float32 value are correct parsed, supporting scientific notation.
C++ Input |
Python Output |
---|---|
#define MAXRANGE 1.0e20 |
ZIP_FILE_FLAG_OWNER_R == 1e+20 |
#define MIN_EPSILON 0.001 |
MIN_EPSILON == 0.001 |
Single Quote string¶
Single quote string, are directly converted to their corresponding integer value if their length == 3 or 4 otherwise they are treated as regular string.
C++ Input |
Python Output |
---|---|
#define QUICKTAB_BARTITLE ‘btit’ |
QUICKTAB_BARTITLE == 1651796340 |
CHAR_CONST32¶
CHAR_CONST32 are directly converted to their corresponding integer value.
C++ Input |
Python Output |
---|---|
#define FLAT_SETTINGS_MAGIC CHAR_CONST32(‘fflt’) |
FLAT_SETTINGS_MAGIC == 1717988468 |
C4D_FOUR_BYTE¶
C4D_FOUR_BYTE are directly converted to their corresponding integer value.
C++ Input |
Python Output |
---|---|
#define QUICKTAB_BAR C4D_FOUR_BYTE(0,’b’,’a’,’r’) |
QUICKTAB_BAR == 6447474 |
Double Quote string¶
Double quote string, are correctly parsed.
C++ Input |
Python Output |
---|---|
#define MENUCOMMAND “CMD” |
MENUCOMMAND == “CMD” |
Value referencing other value¶
Value referencing other value are correctly resolved.
C++ Input |
Python Output |
---|---|
#define POLY_TRIANG_NGON 32
#define POLY_TRIANG_FORCE_NGON (128 | POLY_TRIANG_NGON)
|
POLY_TRIANG_NGON == 32 POLY_TRIANG_FORCE_NGON == 160 Note The system is able to resolve any numbers of references (a reference which itself make a reference to another symbols, etc…). |
enum class HDIRTY_ID {RENDERSETTINGS = 7}
enum class HDIRTYFLAGS {RENDERSETTINGS = (1 << (UInt32)HDIRTY_ID::RENDERSETTINGS)}
|
HDIRTY_ID_RENDERSETTINGS == 7 HDIRTYFLAGS_RENDERSETTINGS == 128 |
Supported types¶
Define¶
Define expressing a value are parsed. Define expressing an expression/macro are not parsed.
C++ Input |
Python Output |
---|---|
#define CUSTOMGUI_TEXTURENAME 1000484 |
c4d.CUSTOMGUI_TEXTURENAME == 1000484 |
#define COLORBYTES_GRAYw (COLORBYTES_GRAY * sizeof(PIX_W)) // COLORBYTES_GRAY == 1, sizeof(PIX_W) == 2 |
c4d.COLORBYTES_GRAYw == 2 |
static const Int32¶
static const Int32 and only Int32 value are parsed and outputs using the current namespace/class.
C++ Input |
Python Output |
---|---|
C++ Input |
Python Output |
static const Int32 ID_CUSTOMDATA_TAG_LIB = 431000187; |
c4d.ID_CUSTOMDATA_TAG_LIB == 431000187 |
Enums¶
Enums value are properly incremented, starting from 0 if no value is defined otherwise, it take the previous enum value.
Unnamed Enums¶
Enums without name are expressed in Python with the current C++ namespace or class.
C++ Input |
Python Output |
---|---|
enum {Mcamera, Xyz, Mdrag} |
c4d.Mcamera == 0 c4d.Xyz == 1 c4d.Mdrag = 2 |
enum {Mcamera = 5, Xyz, Mdrag = 1000} |
c4d.Mcamera == 5 c4d.Xyz == 6 c4d.Mdrag = 1000 |
Named Enums¶
Enums with name are expressed in Python with the current C++ namespace or class, so their names are not took into consideration.
C++ Input |
Python Output |
---|---|
enum DA {DA_NIL= 0, DA_VOID = 14}; |
c4d.DA_NIL == 0 c4d.DA_VOID == 14 Note c4d.DA.DA_NIL does not exist |
Enums Struct/Class and MAXON_ENUM_LIST/MAXON_ENUM_FLAGS¶
Enums struct, class, MAXON_ENUM_LIST and MAXON_ENUM_FLAGS are expressed in Python with their scope name. Given a enum class XYZ with the value ABC will output XYZ_ABC.
C++ Input |
Python Output |
---|---|
enum class MDDIRTY
{
NONE = 0,
ARRAYCOUNT = (1 << 0)
} MAXON_ENUM_FLAGS(MDDIRTY);
|
c4d.MDDIRTY_NONE c4d.MDDIRTY_0 == 0 c4d.MDDIRTY_ARRAYCOUNT == 1 Note The MDDIRTY_0 value is added to Python, each time there is a NONE entry to not break API compatibility as older version of the API may still use it. |
enum class MD_TYPE
{
MD_NONE = DA_NIL,
MD_CHAR = 40000000,
} MAXON_ENUM_LIST(MD_TYPE);
|
c4d.MD_TYPE_MD_NONE = 0 c4d.MD_TYPE_MD_CHAR = 40000000 |