Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    How to dynamically add description elements?

    SDK Help
    0
    5
    576
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 21/02/2014 at 20:14, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   13,14,15 
      Platform:   Windows  ;   
      Language(s) :     C++  ;

      ---------
      Hi, I have searched the web now for almost two hours, and cannot find a single example on how to do this:

      I want to dynamically (when the users presses a button) to add several Real Sliders to a specific group in my tag plugin. I really don't want to use a RES file. Well, I hope I do not need to..
      The amount of sliders needed can be up to a 100, maybe more.

      So the criteria is:
      Add to a specific description group
      Apply the sliders below existing GUI elements.

      What I could do, is to use a RES file with 100 or more sliders and hide them as needed, so that I always get the number of sliders I want. But I would prefer to do it dynamically! Are there drawbacks of doing it dynamically, I might want to use the RES file after all. But it is not the way I am used to do things in when programming, in general.

      TIA

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 22/02/2014 at 06:46, xxxxxxxx wrote:

        Override GetDDescription() in your TagData derived class.  Do an Advanced search here for more information on it.  Note that you never call GetDDescription() directly.  It is called frequently, especially on parameter changes.  Basically, when the user clicks the button, add to your overriden Message() a check for DESCRIPTION_MESSAGE_COMMAND.

        Here is a basic example:

        // NodeData.GetDDescription - Descriptions and Parameters  
        //*---------------------------------------------------------------------------*  
        Bool UnfurlTag::GetDDescription(GeListNode* node, Description* description, DESCFLAGS_DESC& flags)  
        //*---------------------------------------------------------------------------*  
        {  
          if (!(node && description))  
              return ErrPrt("UnfurlTag.GetDDescription.node/description");  
          // Load Static Resources from .res  
          if (!description->LoadDescription(node->GetType()))  
              return ErrPrt("UnfurlTag.GetDDescription.LoadDescription");  
          
          flags |=    DESCFLAGS_DESC_LOADED|DESCFLAGS_DESC_RECURSIONLOCK;  
          
          // *************************  
          // Add Dynamic Descriptions  
          // *************************  
          
          // Get the default container for the data type  
          // and then set relevant description options associated with it  
          BaseContainer    cp_id =                    GetCustomDataTypeDefault(DTYPE_STATICTEXT);  
          cp_id.SetBool(DESC_ANIMATE,                DESC_ANIMATE_OFF);  
          cp_id.SetBool(DESC_SCALEH,                FALSE);  
          cp_id.SetBool(DESC_REMOVEABLE,            FALSE);  
          
          BaseContainer    cp_value =                GetCustomDataTypeDefault(DTYPE_REAL);  
          cp_value.SetBool(DESC_ANIMATE,            DESC_ANIMATE_OFF);  
          cp_value.SetBool(DESC_HIDE,                FALSE);  
          cp_value.SetBool(DESC_SCALEH,            FALSE);  
          cp_value.SetBool(DESC_REMOVEABLE,        FALSE);  
          cp_value.SetReal(DESC_MIN,                0.0);  
          cp_value.SetReal(DESC_MAX,                1.0);  
          cp_value.SetReal(DESC_STEP,                0.01);  
          cp_value.SetLong(DESC_UNIT,                DESC_UNIT_PERCENT);  
          cp_value.SetLong(DESC_CUSTOMGUI,        CUSTOMGUI_REAL);  
          cp_value.SetString(DESC_SHORT_NAME,        "Unfurled at");  
          
          BaseContainer    cp_show =                GetCustomDataTypeDefault(DTYPE_BOOL);  
          cp_show.SetBool(DESC_ANIMATE,            DESC_ANIMATE_OFF);  
          cp_show.SetBool(DESC_HIDE,                FALSE);  
          cp_show.SetBool(DESC_SCALEH,            FALSE);  
          cp_show.SetBool(DESC_REMOVEABLE,        FALSE);  
          cp_show.SetString(DESC_SHORT_NAME,        "Show");  
          
          BaseContainer    cp_remove =                GetCustomDataTypeDefault(DTYPE_BUTTON);  
          cp_remove.SetString(DESC_SHORT_NAME,    "Remove");  
          cp_remove.SetLong(DESC_CUSTOMGUI,        CUSTOMGUI_BUTTON);  
          cp_remove.SetLong(DESC_ANIMATE,            DESC_ANIMATE_OFF);  
          cp_remove.SetBool(DESC_REMOVEABLE,        FALSE);  
          cp_remove.SetBool(DESC_SCALEH,            FALSE);  
          
          BaseContainer    cp_index =                GetCustomDataTypeDefault(DTYPE_LONG);  
          cp_index.SetBool(DESC_ANIMATE,            DESC_ANIMATE_OFF);  
          cp_index.SetBool(DESC_HIDE,                TRUE);  
          cp_index.SetBool(DESC_SCALEH,            FALSE);  
          cp_index.SetBool(DESC_REMOVEABLE,        FALSE);  
          cp_index.SetString(DESC_SHORT_NAME,        "Gradient Index");  
          
          LONG            c =                        0L;  
          
          // Like your count that should incremented when the user clicks the button  
          // and stored like: opBC->SetLong(TUNFURL_POLYGON_COUNT, opBC->GetLong(TUNFURL_POLYGON_COUNT)++);  
          LONG            gcnt =                    opBC->GetLong(TUNFURL_POLYGON_COUNT);  
          
          // Count controls to see if we hide "Gradient Dir" or not  
          for (LONG i = 0L; i != gcnt; ++i)  
          {  
              if (gradients[i].control)            ++c;  
          }  
          if (c > 1L)  
          {  
              BaseContainer    cp_mix =                GetCustomDataTypeDefault(DTYPE_STATICTEXT);  
              cp_mix.SetBool(DESC_ANIMATE,            DESC_ANIMATE_OFF);  
              cp_mix.SetBool(DESC_HIDE,                FALSE);  
              cp_mix.SetBool(DESC_SCALEH,                FALSE);  
              cp_mix.SetBool(DESC_REMOVEABLE,            FALSE);  
              cp_mix.SetString(DESC_SHORT_NAME,        ".");  
              NeighborPoly*    g =                        NULL;  
              c =                                        0L;  
              for (LONG i = 0L; i != gcnt; ++i)  
              {  
                  g =                                    &gradients[i];  
                  if (!g->control)                    continue;  
                  if (c >= 2048L)                        break;  
          
                  cp_id.SetString(DESC_SHORT_NAME,    LongToString(c+1L)+"  ("+LongToString(i)+")");  
                  // description->SetParameter(...) adds the dynamic description and assigns a DescID UNIQUE within your resources  
                  // - I typically set a start for each set by enumeration (as you see) and increment the value  
                  // - if these descriptions can also be deleted/rearranged and there is special correlation to something  
                  // - else, you may also need to maintain that correlation between DescID and whatever expects that particular one.  
                  if (!description->SetParameter(DescLevel(TUNFURL_CONTROL_ID+c,        DTYPE_STATICTEXT,0L),    cp_id,        DescLevel(TUNFURL_GROUP_CONTROLS)))  
                      continue;  
                  // Control Polygon Gradation Direction - Static Text (see below)  
                  if (!description->SetParameter(DescLevel(TUNFURL_CONTROL_MIX+c,        DTYPE_STATICTEXT,0L),    cp_mix,        DescLevel(TUNFURL_GROUP_CONTROLS)))  
                      continue;  
                  // Control Polygon Value - Real  
                  if (!description->SetParameter(DescLevel(TUNFURL_CONTROL_VALUE+c,    DTYPE_REAL,0L),            cp_value,    DescLevel(TUNFURL_GROUP_CONTROLS)))  
                      continue;  
                  // Control Polygon Highlight - Bool  
                  if (!description->SetParameter(DescLevel(TUNFURL_CONTROL_SHOW+c,    DTYPE_BOOL,0L),            cp_show,    DescLevel(TUNFURL_GROUP_CONTROLS)))  
                      continue;  
                  // Control Polygon Remove - Button  
                  if (!description->SetParameter(DescLevel(TUNFURL_CONTROL_REMOVE+c,    DTYPE_BUTTON,0L),        cp_remove,    DescLevel(TUNFURL_GROUP_CONTROLS)))  
                      continue;  
                  // Control Polygon Index - LONG  
                  if (!description->SetParameter(DescLevel(TUNFURL_CONTROL_INDEX+c,    DTYPE_LONG,0L),            cp_index,    DescLevel(TUNFURL_GROUP_CONTROLS)))  
                      continue;  
          
                  ++c;  
              }  
          }  
          // Always call this at the end!  
          return SUPER::GetDDescription(node,description,flags);  
        }  
        // NodeData.Message  
        //*---------------------------------------------------------------------------*  
        Bool UnfurlTag::Message(GeListNode* node, LONG type, void* data)  
        //*---------------------------------------------------------------------------*  
        {  
          if (!node)    return FALSE;  
          if (type == MSG_DESCRIPTION_COMMAND)            return MsgCommand(static_cast<DescriptionCommand*>(data), static_cast<BaseTag*>(node));  
          
          return SUPER::Message(node,type,data);  
        }  
        // UnfurlTag.MsgCommand  
        //*---------------------------------------------------------------------------*  
        Bool UnfurlTag::MsgCommand(DescriptionCommand* dc, BaseTag* tag)  
        //*---------------------------------------------------------------------------*  
        {  
          // IMPORTANT: Buttons need to change the BaseContainer to have GetDDescription called!  
          if (!dc)                return TRUE;  
          BaseContainer*    tbc =    tag->GetDataInstance();  
          if (!tbc)                return FALSE;  
          LONG            id =    dc->id[0].id;  
          // Individual Control Actions  
          // - Remove Control Polygon  
          if ((id >= TUNFURL_CONTROL_REMOVE) && (id < TUNFURL_CONTROL_REMOVE_END))  
              ControlPoly_Remove(tag, id-TUNFURL_CONTROL_REMOVE);  
          return TRUE;  
        }  
        // UnfurlTag.ControlPoly_Remove  
        //*---------------------------------------------------------------------------*  
        Bool UnfurlTag::ControlPoly_Remove(BaseTag* tag, const LONG& id)  
        //*---------------------------------------------------------------------------*  
        {  
          BaseContainer*    tbc =    tag->GetDataInstance();  
          if (!tbc)                return ErrPrt("UnfurlTag.ControlPoly_Remove.tbc");  
          NeighborPoly*    g =        &gradients[tbc->GetLong(TUNFURL_CONTROL_INDEX+id)];  
          g->control =            FALSE;  
          g->show =                FALSE;  
          g->value =                0.0;  
          g->ctrlValue =            0.0;  
          // Mark as "Not-Applied"  
          tbc->SetBool(TUNFURL_APPLIED,    FALSE);  
          // These assure that GetDDescription() gets called and the AM/View are updated  
          tbc->SetLong(TUNFURL_DIRTY,        ++dirty);  
          tag->Message(MSG_CHANGE);  
          return TRUE;  
        }
        
        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 22/02/2014 at 06:53, xxxxxxxx wrote:

          Thanks!!
          I will look at it a little later today, just a quick question (haven't looked much at the code yet), can I add the GUI elements to a certain Group?

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 22/02/2014 at 07:03, xxxxxxxx wrote:

            The DescLevel() at the end of SetParameter() is the group to which to add the description.  The group must either exist in the static resource file or be dynamically created as well.

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 22/02/2014 at 15:08, xxxxxxxx wrote:

              Hi Robert,
              I have this comment: 👍

              It works like a dream! Great post of yours, it exactly what I needed, thank you so much!

              1 Reply Last reply Reply Quote 0
              • First post
                Last post