Multiple NodeData Descriptions [SOLVED]



  • On 19/03/2016 at 05:23, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   17 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hello everybody,

    is it possible to instantiate a NodeData class and load a different description from a res file?
    Currently, I'm inheriting a NodeData, Alloc it to a BaseList2D and this works fine.
    However, I want to create another instance of it, this time with different description elements, defined in another description resource.

    Some more Info: The NodeData plugin should act as a simple options gui where every node carries their own description parameters.
    This NodeData is represented in a DescriptionCustomGui and should become visible if user selects them in a list view.

    Is this even the right approach?

    Thanks in advance. :)



  • On 19/03/2016 at 18:11, xxxxxxxx wrote:

    Hey mp5gosu,

    sounds like a reasonable approach. The Multipass system actually does it that way. There is only one
    plugin for Multipasses (Zmultipass, the ones you see under the "Multipass" section in the Render
    Settings). The actual parameters you can see in the description are based on the
    MULTIPASSOBJECT_TYPE parameter.

    So in GetDDescription(), you could do something like this:

    BaseList2D* op = static_cast<BaseList2D*>(node);
    BaseContainer* bc = op->GetDataInstance();
    Int32 type = bc->GetInt32(MYPLUGIN_TYPE);
      
    switch (type) {
    case MYPLUGIN_TYPE_A:
    case MYPLUGIN_TYPE_B:
    case MYPLUGIN_TYPE_C:
    case MYPLUGIN_TYPE_D:
      // Assuming that these symbols have Plugin IDs as their values
      // that you used with RegisterDescription().
      if (desc->LoadDescription(type))
        flags |= DESCFLAGS_DESC_LOADED;
      break;
    }
    

    Cheers!
    -Niklas



  • On 20/03/2016 at 02:39, xxxxxxxx wrote:

    Thanks a lot, got it working! :)
    This could however need an example in the SDK, imho.



  • On 21/03/2016 at 00:00, xxxxxxxx wrote:

    One more question:
    Is the animatable state of a parameter depending on the context?
    Now I have no possibility to set keyframes for my params, which is ok.
    But I just want to understand why there are no animation gadgets in front of the params. I guess, the object has to be in document context?



  • On 21/03/2016 at 02:51, xxxxxxxx wrote:

    Hello,

    actually you can find an extensive example how to use GetDDescription in the example project and on GitHub.

    What exactly do you mean with "animation state" and "document context"? Can you post some example code on what you are doing? How do you display your plugin parameters?

    Best wishes,
    Sebastian



  • On 21/03/2016 at 03:17, xxxxxxxx wrote:

    Hello Sebastian,

    thanks for pointing out the GitHub example, totally forgot about that. Seems like I forgot something to implement, that will explain my confusion about the animation state (I mean the little circles in front of the object's parameters, they aren't visible, although param is set to ANIM ON explicitly).
    I will post some example code within the next days.



  • On 21/03/2016 at 13:00, xxxxxxxx wrote:

    Here's the test code I'm using so far.
    I'd expect, that MY_STRING would be animatable, but it isn't.
    I assume that is because the NodeData has not been inserted into the document.
    The DescriptionGui has to set its parameter OBJECTSNOTINDOC to display the Node Descriptions. This is what I meant with "document context".
    Any explanation would be very welcome!

    Thanks again. :)

    main.h/main.cpp

      
    #ifndef MAIN_H__   
    #define MAIN_H__   
      
      
    Bool RegisterMyCommandPlugin();   
    Bool RegisterMyNodeDataPlugin();   
      
    #endif // MAIN_H__   
      
    #####################   
      
    #include "c4d.h"   
      
    #include "main.h"   
      
    #define NPID 1000007   
      
    Bool PluginStart(void)   
    {   
         if (!RegisterMyCommandPlugin())   
              return false;   
         if (!RegisterMyNodeDataPlugin())   
              return false;   
      
         return true;   
    }   
      
    void PluginEnd(void)   
    {   
    }   
      
    Bool PluginMessage(Int32 id, void* data)   
    {   
         if (id == C4DPL_INIT_SYS)   
         {   
              resource.Init();   
              RegisterDescription(NPID, "my_type_a", resource.Get());   
              return false;   
         }   
         return false;   
    }   
    

    CommandData.cpp:

      
    #include "c4d.h"   
      
    #include "mydialog.h"   
      
    #define PID 1000006   
      
    class MyCommandData : public CommandData   
    {   
    public:   
         virtual Bool Execute(BaseDocument* doc) override;   
         virtual Bool RestoreLayout(void* secret) override;   
    private:   
         MyDialog mainDialog;   
         BaseContainer* settings;   
    };   
      
      
    Bool MyCommandData::Execute(BaseDocument* doc)   
    {   
         return mainDialog.Open(DLG_TYPE_ASYNC, PID, -1, -1, 400, 200);   
    }   
      
    Bool MyCommandData::RestoreLayout(void* secret)   
    {   
         return mainDialog.RestoreLayout(PID, 0, secret);   
    }   
      
    Bool RegisterMyCommandPlugin()   
    {   
         return RegisterCommandPlugin(PID, "My Plugin", 0, 0, NULL, NewObjClear(MyCommandData));   
    }   
    

    MyDialog.h/MyDialog.cpp

      
    #ifndef MYDIALOG_H   
    #define MYDIALOG_H   
      
      
    #include "c4d.h"   
      
    class MyDialog : public GeDialog   
    {   
    public:   
         virtual Bool CreateLayout(void) override;   
    };   
    #endif   
      
    #####################   
      
    #include "mydialog.h"   
    #include "c4d_symbols.h"   
      
    #define NPID 1000007   
      
    Bool MyDialog::CreateLayout(void)   
    {   
         Bool res = GeDialog::CreateLayout();   
         res = LoadDialogResource(DLG_MYDIALOG, nullptr, 0);   
      
         BaseList2D* node = BaseList2D::Alloc(NPID);   
         BaseList2D* op = static_cast<BaseList2D*>(node);   
         BaseContainer* bc = op->GetDataInstance();   
      
         bc->SetInt32('type', MY_TYPE_A);   
      
      
         DescriptionCustomGui* descGui = static_cast<DescriptionCustomGui*>(FindCustomGui(IDC_DESCGUI, CUSTOMGUI_DESCRIPTION));   
         descGui->SetObject(node);   
      
         return res;   
    }   
    

    Dialog resource:

      
    // C4D-DialogResource   
      
    DIALOGSTRINGS DLG_MYDIALOG   
    {   
    IDS_DIALOG "Dialog";   
    }   
      
    

    MyNodeData.cpp:

      
    #include "c4d.h"   
      
    #include "c4d_symbols.h"   
    #define NPID 1000007   
      
      
    class MyNodeData : public NodeData   
    {   
    public:   
         static NodeData* Alloc() {   
              return NewObjClear(MyNodeData);   
         }   
      
         virtual Bool GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags) override;   
    };   
      
    Bool MyNodeData::GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags)   
    {   
         BaseList2D* op = static_cast<BaseList2D*>(node);   
         BaseContainer* bc = op->GetDataInstance();   
         Int32 type = bc->GetInt32('type');   
      
         switch (type) {   
         case MY_TYPE_A:   
              if (description->LoadDescription(type))   
                   flags |= DESCFLAGS_DESC_LOADED;   
              break;   
         }   
         return NodeData::GetDDescription(node, description, flags);   
    }   
      
    Bool RegisterMyNodeDataPlugin()   
    {   
         return RegisterNodePlugin(NPID, "My NodeData", PLUGINFLAG_HIDE, MyNodeData::Alloc, NULL, 0, NULL);   
    }   
    

    c4d_symbols.h

      
    enum   
    {   
         _FIRST_ELEMENT_ = 10000,   
         // Dialog definitions of DLG_MYDIALOG start here   
         DLG_MYDIALOG,   
         IDC_DESCGUI,   
         // Dialog definitions of DLG_MYDIALOG end here   
      
         MY_TYPE_A = 100009,   
         MY_STRING = 10008,   
         MY_LABEL,   
      
         // End of symbol definition   
         _DUMMY_ELEMENT_   
    };   
      
    

    Description resource my_type_a.h / my_type_a.res:

      
    #ifndef MY_TYPE_A_H   
    #define MY_TYPE_A_H   
      
    enum   
    {   
         MY_STRING = 10010,   
         MY_LABEL,   
    };   
      
    #endif   
      
    ########################   
      
    CONTAINER my_type_a   
    {        
         NAME my_type_a;   
      
         GROUP   
         {             
              COLUMNS 2;   
      
              STATICTEXT MY_LABEL { NAME STR_MY_LABEL; }   
              STRING MY_STRING { ANIM ON; }   
      
         }   
    }   
    

    String resource MY_TYPE_A:

      
    STRINGTABLE my_type_a   
    {   
         my_type_a     "My Type A";   
         STR_MY_LABEL     "My Test Label";   
    }   
    

    Dialog resource:

      
    // C4D-DialogResource   
    DIALOG DLG_MYDIALOG   
    {   
    NAME IDS_DIALOG; SCALE_V; SCALE_H;   
      
      
    DESCRIPTION IDC_DESCGUI   
    {   
          SCALE_V; SCALE_H;   
          OBJECTSNOTINDOC;   
    }   
    }   
    

    String resource DLG_MYDIALOG:

      
    // C4D-DialogResource   
      
    DIALOGSTRINGS DLG_MYDIALOG   
    {   
    IDS_DIALOG "Dialog";   
    }   
      
    


  • On 22/03/2016 at 03:00, xxxxxxxx wrote:

    Hello,

    indeed, the keyframe button is only displayed if the Node is part of a document. This makes sense because if the Node is not part of a document one cannot create a keyframe for the "current frame" of the document.

    The GUI element checks the document by accessing GeListNode::GetDocument(). So you could return a BaseDocument by implementing NodeData::GetDocument(). But depending on what you do this could lead to instability.

    Best wishes,
    Sebastian



  • On 22/03/2016 at 03:52, xxxxxxxx wrote:

    Thanks Sebastian,

    nice to know. :)

    This thread can be marked as solved then...


Log in to reply