Parameters in predefined functions

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 ...

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);  
}

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

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 ...