C++ Missing Information

  • On 03/07/2013 at 05:56, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:    
    Language(s) :

    Hei folks,

    I find myself annoyed about missing information in the SDK documentation very often recently,
    because I had to invest a lot of time figuring out these tings myself. I want to post things here
    that I couldn't find in the documentation and was able to figure out myself or from information
    collected from other threads. You are welcome to join!

    I'll try to update the Table of Contents regularly. If you post, please make it one post for each
    topic. If you have to add information or update the post, just do it. I'd also like to ask you to
    not respond to this thread, but if any questions occure, create a new thread with a link to the
    topic in this post. This way the thread stays focues on the actual topic: collecting information
    missing from the SDK docs in one place. Thanks

    Table of Contents:


  • On 03/07/2013 at 05:59, xxxxxxxx wrote:

    EffectorData - Drawing of C4D_Falloff does not follow the Effector object

    Description : The EffectorData class has a C4D_Falloff member. Necessary calls are automatically
    forwarded to it (eg. C4D_Falloff::Draw() from EffectorData::Draw()). Though, there's one
    problem one might experience while developing an effector: When the effector object is not
    attached to any object (eg. effector list in a cloner, serving as a deformer), the visuals of the falloff
    in the viewport stay at the position the effector was last invoked from.

    Solution : Register the EffectorData plugin with the OBJECT_CALL_ADDEXECUTION flag. The
    implementation of EffecorData::Execute() will automatically update the internal C4D_Falloff object
    causing it to be drawn at the correct location.

    Example :


    Source : cinema4dsdk/source/object/dropeffector.cpp

  • On 03/07/2013 at 06:52, xxxxxxxx wrote:

    GvOperatorData - Simple graph-view calculation example

    While I tried to figure this out, an example would have been more than I could have ever dreamt
    of. Remo was so kind to hand one over to me, which helped me figuring out a few things. Here is
    an example of mine:

    class MyOperatorData : public GvOperatorData {

    typedef GvOperatorData super;


    //| GvOperatorData Overrides

    virtual Bool InitCalculation(GvNode* node, GvCalc* calc, GvRun* run) {
                if (!node || !calc || !run) return FALSE;
                if (!GvBuildValuesTable(node, m_values, calc, run, GV_EXISTING_PORTS)) {
                    return FALSE;
                return super::InitCalculation(node, calc, run);

    virtual void FreeCalculation(GvNode* node, GvCalc* calc) {
                GvFreeValuesTable(node, m_values);
                super::FreeCalculation(node, calc);

    virtual Bool Calculate(GvNode* node, GvPort* outPort, GvRun* run, GvCalc* calc) {
                if (!node || !run || !calc) return FALSE;
                if (!GvCalculateInValuesTable(node, run, calc, m_values)) {
                    return FALSE;

    Bool index = 0;
                GvPort* indexPort = node->GetInPortFirstMainID(ID_MYPORT_INDEX);
                if (indexPort && indexPort->GetInteger(&index, run)) ;
                else {
                    // Either work with index = 0 or stop calculation. Returning FALSE
                    // will make the XPresso Node turn yellow!

    // Limit the index.
                LONG count = GetFooBarArrayCountFromSomewhere();
                if (index < 0) index = 0;
                else if (index >= count) index = count - 1;

    if (!outPort) {
                    // If your node is an initiator, handle this step here. Eg. when
                    // your input-ports should be directed to values on an object or
                    // similar, you can retrieve the values here and fill in the object.
                    // Example (imagine an array of objects that can be addressed via
                    // via the index retrieved above) :

    Real value = 0.0;
                    GvPort* valuePort = node->GetInPortFirstMainID(ID_MYPORT_VALUE);
                    if (valuePort && valuePort->GetReal(&value, run)) ;
                    else {
                        // The port does either not exist or is not connected. If
                        // the port is described as an INPORT in the operator
                        // description resource, the value can even be retrieved when
                        // the port is not connected (since the value is defined in
                        // the Attributes Manager).
                        return FALSE;

    Real* data = GetFooBarArrayFromSomewhere();
                    data[index] = value;
                    return TRUE;
                else {
                    // Set the data for an output port.
                    switch (outPort->GetMainID()) {
                        case ID_MYPORT_COUNT:
                            return outPort->SetInteger(count, run);

    // If we reached this statement, something went wrong.
                return FALSE;


    GvValuesInfo m_values;


  • On 03/07/2013 at 06:57, xxxxxxxx wrote:

    GeDialog - Be careful with modal dialogs (platform differences)

    Especially interesting for developers working on Windows only and giving the code away for
    compilation or developers of Python plugins.

    On OSX, a modal dialog does not have a close button in the title bar, unlike the windows modal
    dialog! If you open a modal dialog on OSX without a hand-made close-button (simply add a Button
    widget), you have to force quit Cinema since there is no way to close the window.

  • On 03/07/2013 at 09:10, xxxxxxxx wrote:

    For modal dialogs, use the AddDlgGroup() with any of the following options OR'd together: DLG_OK and DLG_CANCEL.  And then handle them in the Command() method.  I know that this isn't the best solution, but it makes it easier to handle that bad situation in OSX.

  • On 14/07/2013 at 12:58, xxxxxxxx wrote:

    MSVC vs. Clang : Differences

    I thought I'd put things here that I came across while compiling plugins for Mac, written on Windows.
    Though most of them might not be related to the C4D SDK at all, I think it is useful if you have at least
    heard about them.

    Context Macros :

    The macros __FUNCTION__ and __PRETTY_FUNCTION__ are treated like string literals in MSVC and
    GCC 3.3 (and earlier), but as of GCC 3.4, they are treated like variables. In MSVC and GCC 3.3, this
    was possible:

    GePrint(__FUNCTION__": something went wrong!");

    This is not valid in GCC 3.4 any longer. (Clang is based on GCC)

Log in to reply