Open Search
    C4DAtom Manual

    About

    C4DAtom is the base class for many entities in the classic Cinema 4D API. Along with GeListNode and BaseList2D it implements the basic functionality of most classic entities. C4DAtomGoal is the extension of the C4DAtom class that allows to create safe references to an C4DAtom entity with a BaseLink.

    Access

    A pointer to a C4DAtom is typically provided by resolving a BaseLink to an entity. See BaseLink Manual.

    // This example gets the link of the given "Instance Object" and accesses the linked C4DAtom.
    GeData data;
    // read the "Reference Object" parameter
    if (!instanceObject->GetParameter(ConstDescID(DescLevel(INSTANCEOBJECT_LINK)), data, DESCFLAGS_GET::NONE))
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    const BaseLink* const link = data.GetBaseLink();
    if (link == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    const C4DAtom* const linkedAtom = link->GetLinkAtom(doc);
    if (linkedAtom != nullptr)
    {
    ApplicationOutput("Got linked C4DAtom"_s);
    }
    Definition: c4d_baselist.h:1522
    Definition: c4d_gedata.h:83
    const BaseLink * GetBaseLink() const
    Definition: c4d_gedata.h:529
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:67
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:210
    #define ConstDescID(...)
    Definition: lib_description.h:594
    @ INSTANCEOBJECT_LINK
    Definition: oinstance.h:6
    const char * doc
    Definition: pyerrors.h:226
    Represents a level within a DescID.
    Definition: lib_description.h:298

    C4DAtom pointers to any kind of entity are often stored in AtomArray objects. See AtomArray Manual.

    Allocation/Deallocation

    C4DAtom instances cannot be created directly. Only instances of C4DAtom based classes can be created.

    Type

    C4DAtom gives access to information about the type and class of the specific entity:

    // This example checks if the given C4DAtom is a BaseObject.
    // If so it checks if the atom is also a point object.
    // check the classification
    const Int32 classification = atom->GetClassification();
    if (classification == Obase)
    {
    const BaseObject* const baseObject = static_cast<BaseObject*>(atom);
    const Vector position = baseObject->GetMg().off;
    ApplicationOutput("Position: " + String::VectorToString(position));
    // check if it is an instance of a given class
    if (atom->IsInstanceOf(Opoint))
    {
    PointObject* const pointObject = static_cast<PointObject*>(atom);
    const Int32 pointCount = pointObject->GetPointCount();
    ApplicationOutput("Point Count: " + String::IntToString(pointCount));
    // check the specific type
    if (atom->GetType() == Offd)
    {
    // If this point object is a FFD object, change its grid size.
    }
    }
    }
    void EventAdd(EVENT eventflag=EVENT::NONE)
    Definition: c4d_baseobject.h:248
    Matrix GetMg() const
    Definition: c4d_baseobject.h:510
    Definition: c4d_baseobject.h:1564
    Int32 GetPointCount() const
    Definition: c4d_baseobject.h:1613
    static String IntToString(Int32 v)
    Definition: c4d_string.h:497
    static String VectorToString(const Vector32 &v, Int32 nnk=-1)
    Definition: c4d_string.h:573
    maxon::Vec3< maxon::Float64, 1 > Vector
    Definition: ge_math.h:145
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    #define atom
    Definition: graminit.h:72
    #define Offd
    FFD.
    Definition: ge_prepass.h:1049
    #define Opoint
    Point - PointObject.
    Definition: ge_prepass.h:1088
    #define Obase
    Base object - BaseObject.
    Definition: ge_prepass.h:1087
    @ FFDOBJECT_SIZE
    Definition: offd.h:6
    V off
    The translation vector.
    Definition: matrix.h:263
    Note
    C4DAtom::IsInstanceOf() can also be used to check the classification and element type.
    C4DAtom::GetType() can be used to get the ID of any entity that is not listed in the documentation.

    Copy

    C4DAtom based entities are easily copied and cloned:

    The copy flags are:

    The AliasTrans argument of these functions is optional. If an AliasTrans instance is provided it is used to update BaseLink parameters of the copied entities. If a BaseLink references an element that is also copied the BaseLink is changed to reference the copy of the originally referenced entity.

    // This example clones the objects defined in the given AtomArray.
    // The clones are created using an AliasTrans object.
    // So if an object is referenced by another object in the object list
    // this reference is redirected to the clone of the original object.
    // check if the AliasTrans was allocated
    // and can be initiated
    if (alias == nullptr || !alias->Init(doc))
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    doc->GetActiveObjects(objectSelection, GETACTIVEOBJECTFLAGS::NONE);
    const Int32 selectionCount = objectSelection->GetCount();
    if (selectionCount == 0)
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    for (Int32 i = 0; i < selectionCount; ++i)
    {
    BaseObject* const object = static_cast<BaseObject*>(objectSelection->GetIndex(i));
    if (object == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    BaseObject* const clone = static_cast<BaseObject*>(object->GetClone(COPYFLAGS::NONE, alias));
    if (clone == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    const String objectName = object->GetName();
    clone->SetName(objectName + " clone");
    doc->InsertObject(clone, nullptr, nullptr);
    }
    // this fixes links to elements that are not part of the given object selection
    alias->Translate(true);
    #define alias(a0, a1, a2)
    Definition: Python-ast.h:681
    Py_ssize_t i
    Definition: abstract.h:645
    Definition: ge_autoptr.h:37
    void SetName(const maxon::String &name, Bool setDirty=true)
    Definition: c4d_baselist.h:2544
    Definition: c4d_string.h:41
    @ NONE
    None.

    Disc I/O

    A C4DAtom based element can be read from and written to a HyperFile.

    If the entity is handled inside another read/write function (NodeData::Read() and NodeData::Write()) these functions must be used:

    Warning
    These functions are generally not recommended for third party plugins.

    Parameter Properties

    Parameter descriptions and IDs are managed with these functions:

    // This example prints the names of all parameters in the current parameter description.
    if (description == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // get the Description of the given object
    if (!object->GetDescription(description, DESCFLAGS_DESC::NONE))
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    void* handle = description->BrowseInit();
    const BaseContainer* bc = nullptr;
    DescID id, gid;
    // loop through all elements of the description
    while (description->GetNext(handle, &bc, id, gid))
    {
    ApplicationOutput("Parameter Name: " + bc->GetString(DESC_NAME));
    }
    description->BrowseFree(handle);
    Definition: c4d_basecontainer.h:48
    String GetString(Int32 id, const maxon::String &preset=maxon::String()) const
    Definition: c4d_basecontainer.h:432
    Definition: lib_description.h:355
    @ DESC_NAME
    String Name for standalone use.
    Definition: lib_description.h:91
    Definition: object.h:105

    Parameters

    The value of parameters should be changed with C4DAtom::GetParameter() and C4DAtom::SetParameter(). In this way one can be sure, the parameters are set correctly even if the entity does not store the data in its BaseContainer.

    Note
    Some parameters must be set with DESCFLAGS_SET::USERINTERACTION.
    // This example gets the active object of the given BaseDocument.
    // If it is a "Cube" its size is increased.
    BaseObject* const cube = doc->GetActiveObject();
    // check if the active object is a "Cube" object
    if (cube == nullptr || !cube->IsInstanceOf(Ocube))
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    GeData data;
    // read the "Size" parameter
    if (!cube->GetParameter(cubeLenID, data, DESCFLAGS_GET::NONE))
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    Vector size = data.GetVector();
    size = size + Vector { 100 };
    Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
    Bool GetParameter(const DescID &id, GeData &t_data, DESCFLAGS_GET flags) const
    Bool IsInstanceOf(Int32 id) const
    Definition: c4d_baselist.h:1563
    const Vector & GetVector() const
    Definition: c4d_gedata.h:486
    Py_ssize_t size
    Definition: bytesobject.h:86
    #define Ocube
    Cube.
    Definition: ge_prepass.h:1112
    @ PRIM_CUBE_LEN
    Definition: ocube.h:6
    Note
    Parameter IDs are defined with DescID objects. See DescID Manual.

    Dirty States

    The dirty status of an entity is a number that is increased every time the entity is changed.

    The dirty flags are:

    // This example checks the dirty states of the given BaseObject before and after an edit.
    // Get the current dirty checksums
    UInt32 dataDirtyStatus = baseObject->GetDirty(DIRTYFLAGS::DATA);
    UInt32 matrixDirtyStatus = baseObject->GetDirty(DIRTYFLAGS::MATRIX);
    ApplicationOutput("Data Status: " + String::UIntToString(dataDirtyStatus));
    ApplicationOutput("Martix Status: " + String::UIntToString(matrixDirtyStatus));
    // edit the object's data
    baseObject->SetName("New Name"_s);
    // Check the dirty checksums
    dataDirtyStatus = baseObject->GetDirty(DIRTYFLAGS::DATA);
    matrixDirtyStatus = baseObject->GetDirty(DIRTYFLAGS::MATRIX);
    ApplicationOutput("Data Status: " + String::UIntToString(dataDirtyStatus));
    ApplicationOutput("Martix Status: " + String::UIntToString(matrixDirtyStatus));
    UInt32 GetDirty(DIRTYFLAGS flags) const
    Definition: c4d_baselist.h:1745
    static String UIntToString(UInt32 v)
    Definition: c4d_string.h:513
    maxon::UInt32 UInt32
    Definition: ge_sys_math.h:61
    @ MATRIX
    Matrix changed.
    @ DATA
    Container changed.

    Hierarchy dirty (HDirty) states are used to check if the given entity or some child elements in the hierarchy were changed. Typically used with a BaseDocument or a GeListHead.

    The hierarchy dirty flags are:

    // Get the current dirty checksums
    UInt32 materialsDirtyState = doc->GetHDirty(HDIRTYFLAGS::MATERIAL);
    UInt32 objectsDirtyState = doc->GetHDirty(HDIRTYFLAGS::OBJECT);
    ApplicationOutput("Materials Status: " + String::UIntToString(materialsDirtyState));
    ApplicationOutput("Objects Status: " + String::UIntToString(objectsDirtyState));
    // edit a material
    BaseMaterial* const mat = doc->GetActiveMaterial();
    // check if the active material is a Cinema 4D standard material
    if (mat && mat->IsInstanceOf(Mmaterial))
    {
    }
    // check the dirty checksums
    materialsDirtyState = doc->GetHDirty(HDIRTYFLAGS::MATERIAL);
    objectsDirtyState = doc->GetHDirty(HDIRTYFLAGS::OBJECT);
    ApplicationOutput("Materials Status: " + String::UIntToString(materialsDirtyState));
    ApplicationOutput("Objects Status: " + String::UIntToString(objectsDirtyState));
    Definition: c4d_basematerial.h:28
    @ OBJECT
    Object data mask.
    @ MATERIAL
    Material data mask.
    #define Mmaterial
    Standard material.
    Definition: ge_prepass.h:1005
    @ MATERIAL_COLOR_COLOR
    Definition: mmaterial.h:56

    Messages

    Entities in Cinema 4D often communicate by sending messages to each other. Such a message can be used to inform the element about some event or to retrieve data from the element. A message can be sent to an entity with these functions:

    // This example gets the active object and checks if it is a point object.
    // If so its points are moved in object space.
    // The object itself is informed about this edit with the message MSG_UPDATE.
    BaseObject* const activeObject = doc->GetActiveObject();
    // check if the active object is a point object
    if (activeObject == nullptr || !activeObject->IsInstanceOf(Opoint))
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    PointObject* const pointObject = static_cast<PointObject*>(activeObject);
    Vector* const points = pointObject->GetPointW();
    if (points == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    const Int32 pointCount = pointObject->GetPointCount();
    for (Int32 i = 0; i < pointCount; ++i)
    points[i] = points[i] + Vector(0, 100, 0);
    pointObject->Message(MSG_UPDATE);
    Bool Message(Int32 type, void *data=nullptr)
    Definition: c4d_baselist.h:1584
    Vector * GetPointW()
    Definition: c4d_baseobject.h:1606
    #define MSG_UPDATE
    Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
    Definition: c4d_baselist.h:359

    See also NodeData::Message() Manual.

    Further Reading