Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Parameters in predefined functions

    SDK Help
    0
    4
    388
    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

      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

      On 02/02/2007 at 02:47, xxxxxxxx wrote:

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

      ---------
      I got a little problem understanding the parameter handling in functions. In some functions there are parameters like BaseDocument* doc, BaseObject* op or Description *description. It seems to me that Cinema4d "knows" that 'doc' is this document or 'op' is the object the function belongs to. But what how can i manually call functions with these standart parameters?
      I want to create someting like the Mocca Pose Mixer Tag Interface. If you click on "Add Pose" a new line in the description file will be created.
      I thought i have to combine a Message and a GetDDescription function like this:
      There is my GetDDesctiption function which is able to create some entries in a descrtipion file:

          
          
           Bool TagCone::GetDDescription(GeListNode *node, Description *description, LONG &flags) 
      

      and there is my Message function which controls the buttons in the description file.

          
          
          
          
          Bool TagCone::Message(GeListNode *node, LONG type, void *data)
          
          
          
          
          {
          
          
          
          
            switch (type)
          
          
          
          
            {
          
          
          
          
               case MSG_DESCRIPTION_COMMAND:
          
          
          
          
              {
          
          
          
          
                 DescriptionCommand *dc = (DescriptionCommand* ) data;
          
          
          
          
                 Bool TagCone::Message(GeListNode *node, LONG type, void *data)
          
          
          
          
                 {
          
          
          
          
                   GePrint("Yeah hit me again!!!");
          
          
          
          
                   GetDDescription(node,???,???);
          
          
          
          
                 }
          
          
          
          
          .... 
      

      How you can see I want to call the GetDDescription Function out of my Message Function. The parameter node is used in both functions so i can pass it to the GetDDescription Function. But i don't know how i can pass the parameter "description" to the GetDDescription Function, cause the Message Function has no parameter "description". (And i don't know what i should do with this LONG &flags)
       
      Can someone tell me what i should do or tell me if there is another maybe simpler way (with only one function) to get an interface like in the Mocca Pose Mixer Tag ...

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

        THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

        On 02/02/2007 at 12:07, xxxxxxxx wrote:

        GetDDescription() is called *fairly* often (sarcasm). If you add GePrint("GetDDescription"); to the top of your GetDDescription() function call and open C4D's Console, you'll see just how frequently is it indeed called.

        That said, you should never have to call this function directly. A good way to 'kick' your plugin to call GetDDescription() is to send a Message(MSG_CHANGE) for the plugin - node->Message(MSG_CHANGE);. You may also try node->GetDescription(desc,0);. Description* desc will need to be allocated/freed each time.

        For example, you add your dynamic description elements using GetD(ynamic)Description(). These are description elements not stored statically in the description .res file for the plugin. They need their own IDs that don't conflict with the static ones.

        MSG_DESCRIPTION_COMMAND is sent when a description button is clicked. If you are wanting to add dynamic elements on a button click, then you are heading in the correct direction. But instead of trying to call GetDDescription from there, get the node and do node->Message(MSG_CHANGE). In the GetDDescription() function is where you are going to assemble the dynamic elements - that is its purpose.

        // NodeData.GetDDescription - Descriptions and Parameters  
        //*---------------------------------------------------------------------------*  
        Bool IPPBase::GetDDescription(GeListNode* node, Description* description, LONG& flags)  
        //*---------------------------------------------------------------------------*  
        {  
             if (!(node && description))               return FALSE;  
             if (!description->LoadDescription(node->GetType())) return FALSE;  
          
             // Get Object containing Dials  
             BaseDocument*     baseDoc =               node->GetDocument();  
             if (!baseDoc)     return FALSE;  
             BaseObject*          obj =                    static_cast<BaseObject*>(node);  
             if (!obj)          return FALSE;  
             BaseContainer*     opBC =                    obj->GetDataInstance();  
             if (!opBC)          return FALSE;  
          
             // Add dial tags  
             BaseContainer*     pbc;  
             DescID               descID;  
             String               dname;  
             ULONG               type;  
             ULONG               tsf;  
             LONG               index;  
             BOOL               hideZero =               opBC->GetBool(IPP_HIDE_ZERODIALS);  
             BOOL               hide;  
             Real               value;  
          
             // Initialize BaseContainer static values  
             BaseContainer sliderBC =                    GetCustomDataTypeDefault(DTYPE_REAL);  
             sliderBC.SetLong(DESC_ANIMATE,               DESC_ANIMATE_ON);  
             sliderBC.SetBool(DESC_REMOVEABLE,          FALSE);  
             sliderBC.SetLong(DESC_CUSTOMGUI,          CUSTOMGUI_REALSLIDER);     // _REAL, _REALSLIDERONLY  
             sliderBC.SetReal(DESC_MIN,                    MINREAL);  
             sliderBC.SetReal(DESC_MAX,                    MAXREAL);  
        #ifdef     C4D_R85  
             sliderBC.SetBool(DESC_SCALEH,               TRUE);  
        #endif  
          
             BaseContainer editBC =                         GetCustomDataTypeDefault(DTYPE_BUTTON);  
             editBC.SetString(DESC_SHORT_NAME,          "Edit");  
             editBC.SetLong(DESC_CUSTOMGUI,               CUSTOMGUI_BUTTON);  
             editBC.SetLong(DESC_ANIMATE,               DESC_ANIMATE_OFF);  
             editBC.SetBool(DESC_REMOVEABLE,               FALSE);  
          
             // Filter visible body part dial groups  
             for (BaseTag* pt = obj->GetFirstTag(); pt; pt = pt->GetNext())  
             {  
                  if (!pt->IsInstanceOf(ID_IPPDIALTAG))     continue;  
                  pbc =          pt->GetDataInstance();  
                  if (!pbc)     continue;  
          
                  // Dial Index  
                  index =          pbc->GetLong(IPPDIAL_INDEX);  
          
                  // Dial Slider  
                  dname =          pbc->GetString(IPPDIAL_DIALNAME);  
                  sliderBC.SetString(DESC_NAME,          dname);  
                  value =          pbc->GetReal(IPPDIAL_CURRENTVALUE);  
                  tsf =          (ULONG)pbc->GetLong(IPPDIAL_TYPESUBFLAGS);  
                  type =          tsf & 0x000000FFL;  
                  hide =          tsf & DIAL_FLAGS_HIDDEN;  
                  // Transforms  
                  if          (tsf & DIAL_FLAGS_TRANSFORM)     descID =     DescID(DescLevel(GROUP_TRANSFORM));  
                  // Morphs  
                  else if (type == CHAN_TYPE_TARGETGEOM)  
                  {  
                       if (hideZero && (value == 0.0f))     hide =     TRUE;  
                       descID =     DescID(DescLevel(GROUP_MORPH));  
                  }  
                  // Other  
                  else  
                  {  
                       if ((type == CHAN_TYPE_VALUEPARM) && hideZero && (value == 0.0f))     hide = TRUE;  
                       descID =     DescID(DescLevel(GROUP_OTHER));  
                  }  
          
                  if (hide)  
                  {  
                       // - Set display state to hide  
                       sliderBC.SetBool(DESC_HIDE,               TRUE);  
                       editBC.SetBool(DESC_HIDE,               TRUE);  
                  }  
                  else  
                  {  
                       sliderBC.SetString(DESC_SHORT_NAME, pt->GetName());  
                       sliderBC.SetLong(DESC_UNIT,               chanTypeParams[type].unit);  
                       // - Set Min/Max/Step for Slider  
                       sliderBC.SetReal(DESC_MINSLIDER,     pbc->GetReal(IPPDIAL_MIN));  
                       sliderBC.SetReal(DESC_MAXSLIDER,     pbc->GetReal(IPPDIAL_MAX));  
                       sliderBC.SetReal(DESC_STEP,               pbc->GetReal(IPPDIAL_STEP));  
                       // - Set display state to show  
                       sliderBC.SetBool(DESC_HIDE,               FALSE);  
                       editBC.SetBool(DESC_HIDE,               FALSE);  
                       editBC.SetString(DESC_NAME,               dname);  
                       // -- Set Master-Slave button to show whether dial is Master and/or Slave  
                       if          (tsf & DIAL_FLAGS_SLAVES)  
                       {  
                            if (tsf & DIAL_FLAGS_VALUEOP)     editBC.SetString(DESC_SHORT_NAME,     "Edit M/S");  
                            else                                   editBC.SetString(DESC_SHORT_NAME,     "Edit M/_");  
                       }  
                       else  
                       {  
                            if (tsf & DIAL_FLAGS_VALUEOP)     editBC.SetString(DESC_SHORT_NAME,     "Edit _/S");  
                            else                                   editBC.SetString(DESC_SHORT_NAME,     "Edit _/_");  
                       }  
                  }  
                  // Dial Slider  
                  if (!description->SetParameter(DescLevel(index,DTYPE_REAL,0),          sliderBC,     descID))     return FALSE;  
                  // Edit Button  
                  if (!description->SetParameter(DescLevel(index+1,DTYPE_BUTTON,0),     editBC,          descID))     return FALSE;  
                  opBC->SetReal(index,                    value);  
             }  
          
             flags |=     DESCFLAGS_DESC_LOADED|DESCFLAGS_DESC_RECURSIONLOCK;  
          
             return SUPER::GetDDescription(node,description,flags);  
        }
        

        Note that a set of tags is being used to set up a set of dynamic sliders and buttons on this plugin object.

        Your message would be something like:

        // NodeData.Message  
        //*---------------------------------------------------------------------------*  
        Bool IPPBase::Message(GeListNode* node, LONG type, void* data)  
        //*---------------------------------------------------------------------------*  
        {  
             if          (!node) return FALSE;  
             switch (type)  
             {  
                  // One of the Buttons  
                  case MSG_DESCRIPTION_COMMAND:  
                  {  
                       if (!data)     return TRUE;  
                       LONG id = ((DescriptionCommand* )data)->id[0].id;  
                       switch (id)  
                       {  
                            // Force update of Attributes Manager descriptions  
                            // This will also force a call to GetDDescription()  
                            case DIALGROUP_KICK:  
                                 AutoAlloc<Description>     desc;  
                                 if (desc)     node->GetDescription(desc,0);  
                                 break;  
                            ...  
                       }  
                       break;  
                  }  
             }  
             return TRUE;  
        }
        

        If the AutoAlloc<> doesn't work with Description, you'll need to do it this way:

        Description* desc =     Description::Alloc();  
        if (desc)  
        {  
             node->GetDescription(desc,0);  
             Description::Free(desc);  
        }
        
        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

          On 02/02/2007 at 14:08, xxxxxxxx wrote:

          GetDDescription will be called for every change of the description elements, except button clicks, you have to catch these within Message and change the description's container. Haven't looked through Robert's code but will do so after the weekend and will try to post another example.

          cheers,
          Matthias

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

            THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

            On 06/02/2007 at 00:01, xxxxxxxx wrote:

            Thx a lot for this partricularized answer. I will try to solve my problem with this. When i got the solution i will post it here ...

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