Updating Attributes Question

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

On 29/12/2009 at 07:31, xxxxxxxx wrote:

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

---------
I was following the thread that was posted previously about updating the attributes manager.  In my plugin, I want the user to be able to click a button and to insert two new link elements in to the attributes manager.   Here is the code I am using.

  
  
Bool Planet::Message(GeListNode *node, LONG type, void *t_data)  
{      
  BaseObject* op = static_cast<BaseTag*>(node)->GetObject();  
  
   if (!node)     return FALSE;  
  DescriptionCommand *dc = (DescriptionCommand* ) t_data;  
    
  switch (type)  
  {  
      case MSG_DESCRIPTION_COMMAND:  
      {  
            
          if (dc->id[0].id==ADD_ORBIT_OBJECT)  
          {  
              GePrint("Adding an OBJECT");  
              BaseList2D *op = (BaseList2D* ) node;  
              BaseDocument *doc = op->GetDocument(); if (!doc) return FALSE;  
              BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;  
              BaseContainer *main = bc->GetContainerInstance(ID_PLANET_OBJECT); if (!main) return FALSE;  
  
              doc->StartUndo();  
  
              doc->AddUndo(UNDO_CHANGE_SMALL,node);  
  
              main->SetLong(ORBIT_OBJ_CNT, main->GetLong(ORBIT_OBJ_CNT,0)+1);  
              main->SetLong(ORBIT_PTH_CNT, main->GetLong(ORBIT_PTH_CNT,0)+1);  
  
              doc->EndUndo();  
  
              op->Message(MSG_CHANGE);  
          }  
  
      }  
  
      case MSG_DESCRIPTION_CHECKUPDATE:  
      {  
          //Update Planet  
          GePrint("UPDATED");  
          return UpdatePlanet(static_cast<BaseObject*>(node), static_cast<GeListNode*>(node));  
          
      }  
  }  
     
   if (planetCreated <1)  
   {  
       CreatePlanet(op,node);  
   }  
  
   return TRUE;  
}  
  
Bool Planet::GetDDescription(GeListNode *node, Description *description,LONG &flags)  
{  
  
   if (!description->LoadDescription(node->GetType())) return FALSE;  
  
  // important to check for speedup c4d!  
  const DescID *singleid = description->GetSingleDescID();  
  
  LONG index1 = ORBIT_INDEX1;  
  LONG index2 = ORBIT_INDEX2;  
  
  BaseObject *op = (BaseObject* )node;  
  BaseContainer *data = op->GetDataInstance();  
  BaseContainer *main = data->GetContainerInstance(ID_PLANET_OBJECT);  
  
  LONG i,cnt = main->GetLong(ORBIT_OBJ_CNT,0);  
  LONG j,cnt1 = main->GetLong(ORBIT_PTH_CNT,0);  
  
  Bool initbc2 = FALSE;  
  Bool initbc3 = FALSE;  
  BaseContainer bc2;  
  BaseContainer bc3;  
  
  for (i=0; i<cnt; i++)  
  {   
      DescID cid = DescLevel(index1,DTYPE_BOOL,0);  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc2)  
          {  
              initbc2 = TRUE;  
              bc2 = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);  
              bc2.SetLong(DESC_ANIMATE,DESC_ANIMATE_ON);  
              bc2.SetBool(DESC_REMOVEABLE,FALSE);  
                
          }  
  
          bc2.SetString(DESC_NAME,"Orbiting Object " +LongToString(i));  
          bc2.SetString(DESC_SHORT_NAME,"Orbiting Object "+LongToString(i));  
          if (!description->SetParameter(cid,bc2,DescLevel(ID_ORBITOPTIONS_TAB))) return FALSE;  
            
      }  
  
      index1++;  
  }  
  
      for (j=0; j<cnt1; j++)  
  {   
      DescID cid = DescLevel(index2,DTYPE_BOOL,0);  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc3)  
          {  
              initbc3 = TRUE;  
              bc2 = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);  
              bc2.SetLong(DESC_ANIMATE,DESC_ANIMATE_ON);  
              bc2.SetBool(DESC_REMOVEABLE,FALSE);  
                
          }  
  
          bc2.SetString(DESC_NAME,"Orbit Path " +LongToString(i));  
          bc2.SetString(DESC_SHORT_NAME,"Orbit Path "+LongToString(i));  
          if (!description->SetParameter(cid,bc2,DescLevel(ID_ORBITOPTIONS_TAB))) return FALSE;  
            
      }  
  
      index2++;  
  }  
    
  flags |= DESCFLAGS_DESC_LOADED;  
  
  //return Planet::GetDDescription(node,description,flags);  
  return TRUE;  
}  
  

Everything works well the first time the user clicks the button.  It inserts two different link elements with two different names.    However, the second time, the user clicks the button, it only adds the PATH link.   Could you tell me what I am doing wrong with this?

THanks,

~SHawn

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

On 29/12/2009 at 07:32, xxxxxxxx wrote:

PS:    this is the enum above..

#define ID_PLANET_OBJECT 1024532

enum
{
  ORBIT_PTH_CNT = 1200,
  ORBIT_OBJ_CNT = 1300,
  ORBIT_INDEX1,
  ORBIT_INDEX2,
};

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

On 29/12/2009 at 14:09, xxxxxxxx wrote:

Any thoughts on this?

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

On 30/12/2009 at 06:30, xxxxxxxx wrote:

With each button click you have to add a new link item to the object's subcontainer. Then in GetDDescription() iterate through the subcontainer and display the elements accordingly. How is your interface supposed to look like? If you have several elements per dynamic inteface line I would recommend to add for each interface line an own subcontainer to the object's subcontainer.

cheers,
Matthias

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

On 30/12/2009 at 06:48, xxxxxxxx wrote:

This is what I have so far...    with this code I am able to insert two link elements but they are inserted separate from one another so all of the "OBJECT" links stay together and all the "PATH" links stay together.  I would like for the final interface to insert 2 links, 2 reals, a bool, and a long..     which will amount to 2 link boxes, to sliders, a check box, and a drop down menu with 2 elements inside of that.    I would like all of these elements to be inserted between 2 spearators so as to show that they are all a group.   Right now I am experimenting with the link elements but I am not getting the desired results.

Could you possibly give me a little snippet example of how I would created an entire group of the elements I just mentioned.

Here's what I have:

  
Bool Planet::Message(GeListNode *node, LONG type, void *t_data)  
{      
  BaseObject* op = static_cast<BaseTag*>(node)->GetObject();  
  
   if (!node)     return FALSE;  
  DescriptionCommand *dc = (DescriptionCommand* ) t_data;  
    
  switch (type)  
  {  
      case MSG_DESCRIPTION_COMMAND:  
      {  
            
          if (dc->id[0].id==ADD_ORBIT_OBJECT)  
          {  
              GePrint("Adding an OBJECT");  
              BaseList2D *op = (BaseList2D* ) node;  
              BaseDocument *doc = op->GetDocument(); if (!doc) return FALSE;  
              BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;  
              BaseContainer *main = bc->GetContainerInstance(ID_PLANET_OBJECT); if (!main) return FALSE;  
  
              doc->StartUndo();  
  
              doc->AddUndo(UNDO_CHANGE_SMALL,node);  
              GePrint("Insert OBJ");  
              main->SetLong(ORBIT_OBJ_CNT, main->GetLong(ORBIT_OBJ_CNT,0)+1);  
              GePrint("Insert PTH");  
              main->SetLong(ORBIT_PTH_CNT, main->GetLong(ORBIT_PTH_CNT,0)+1);  
  
              doc->EndUndo();  
  
              op->Message(MSG_CHANGE);  
          }  
      }  
  
      case MSG_DESCRIPTION_CHECKUPDATE:  
      {  
          //Update Planet  
          GePrint("UPDATED");  
          return UpdatePlanet(static_cast<BaseObject*>(node), static_cast<GeListNode*>(node));  
          
      }  
  }  
     
   if (planetCreated <1)  
   {  
       CreatePlanet(op,node);  
   }  
  
   return TRUE;  
}  
  
Bool Planet::GetDDescription(GeListNode *node, Description *description,LONG &flags)  
{  
   if (!description->LoadDescription(node->GetType())) return FALSE;  
  
  // important to check for speedup c4d!  
  const DescID *singleid = description->GetSingleDescID();  
  
  LONG index1 = ORBIT_INDEX1;  
  LONG index2 = ORBIT_INDEX2;  
  
  BaseObject *op = (BaseObject* )node;  
  BaseContainer *data = op->GetDataInstance();  
  BaseContainer *main = data->GetContainerInstance(ID_PLANET_OBJECT);  
  
  LONG i,cnt = main->GetLong(ORBIT_OBJ_CNT,0);  
  LONG j,cnt1 = main->GetLong(ORBIT_PTH_CNT,0);  
  
  Bool initbc2 = FALSE;  
  Bool initbc3 = FALSE;  
  BaseContainer bc2;  
  BaseContainer bc3;  
  
  for (i=0; i<cnt; i++)  
  {   
      DescID cid = DescLevel(index1,DTYPE_BASELISTLINK,0);  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc2)  
          {  
              GePrint("OBJ 1");  
              initbc2 = TRUE;  
              bc2 = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);  
              bc2.SetLong(DESC_ANIMATE,DESC_ANIMATE_ON);  
              bc2.SetBool(DESC_REMOVEABLE,TRUE);      
          }  
          GePrint("OBJ 2");  
          bc2.SetString(DESC_NAME,"Orbiting Object " +LongToString(i));  
          bc2.SetString(DESC_SHORT_NAME,"Orbiting Object "+LongToString(i));  
          if (!description->SetParameter(cid,bc2,DescLevel(ID_ORBITOPTIONS_TAB))) return FALSE;  
            
      }  
      GePrint("OBJ 3");  
      index1++;  
      GePrint("Index 1 = " + LongToString(index1));  
  }  
  
      for (j=0; j<cnt1; j++)  
  {   
      DescID cid1 = DescLevel(index2,DTYPE_BASELISTLINK,0);  
      if (!singleid || cid1.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc3)  
          {  
              GePrint("PTH 1");  
              initbc3 = TRUE;  
              bc2 = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);  
              bc2.SetLong(DESC_ANIMATE,DESC_ANIMATE_ON);  
              bc2.SetBool(DESC_REMOVEABLE,TRUE);  
                
          }  
          GePrint("PTH 2");  
          bc2.SetString(DESC_NAME,"Orbit Path " +LongToString(j));  
          bc2.SetString(DESC_SHORT_NAME,"Orbit Path "+LongToString(j));  
          if (!description->SetParameter(cid1,bc2,DescLevel(ID_ORBITOPTIONS_TAB))) return FALSE;  
            
      }  
      GePrint("PTH 3");  
      index2++;  
      GePrint("Index 2 = " + LongToString(index2));  
  }  
    
  flags |= DESCFLAGS_DESC_LOADED;  
  
  //return Planet::GetDDescription(node,description,flags);  
  return TRUE;  
}  

Thanks,
~Shawn

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

On 30/12/2009 at 06:53, xxxxxxxx wrote:

Maybe you can post a screenshot of how it should look like?

cheers,
Matthias

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

On 30/12/2009 at 06:57, xxxxxxxx wrote:

I'll grab one now.

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

On 30/12/2009 at 07:06, xxxxxxxx wrote:

Here is a pic of what I mean.   The elements between the red lines were added again in photoshop to show what I would like to happen when the user presses the button.   ..  minus the Add button..    I accidentally included it in the copy but I don't want the button to be added again.   I am going to throw a sperator in there to block that off..


~Shawn

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

On 30/12/2009 at 15:40, xxxxxxxx wrote:

Does that make sense?

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

On 31/12/2009 at 05:15, xxxxxxxx wrote:

I did not had the time to look at it yet. There are holidays over here in Germany. Will post back after the weekend.

cheers,
Matthias

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

On 01/01/2010 at 15:42, xxxxxxxx wrote:

Thank you .  I appreciate your help very much.

~Shawn

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

On 04/01/2010 at 12:56, xxxxxxxx wrote:

Any info on this?    Thanks,

~Shawn

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

On 05/01/2010 at 05:38, xxxxxxxx wrote:

Here is the complete code of a simple example of a generator (doing nothing) with a dynamic description similar to what you want. The elements for each dynamic decription group are saved in a respective sub-subcontainer. Please check the comments within the sorce code for more details.

  
/////////////////////////////////////////////////////////////  
// CINEMA 4D SDK                                           //  
/////////////////////////////////////////////////////////////  
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //  
/////////////////////////////////////////////////////////////  
  
// generator object example (with no input objects)  
  
#include "c4d.h"  
#include "c4d_symbols.h"  
#include "oroundedtube.h"  
  
  
#define MY_SUBCONTAINER 1024882        //unique ID for the main-subcontaioner  
#define MY_SUBCONTAINER_CNT 1024883    //unique ID for storing the IDs of the sub-subcontainers  
  
  
class RoundedTube : public ObjectData  
{  
  INSTANCEOF(RoundedTube,ObjectData)  
  
  public:  
      virtual Bool Init(GeListNode *node);  
      virtual BaseObject* GetVirtualObjects(PluginObject *op, HierarchyHelp *hh);  
      virtual Bool Message(GeListNode *node, LONG type, void *data);  
      virtual Bool GetDDescription(GeListNode *node, Description *description, LONG &flags);  
  
      static NodeData *Alloc(void) { return gNew RoundedTube; }  
};  
  
Bool RoundedTube::Init(GeListNode *node)  
{  
  BaseContainer *data = ((BaseList2D* )node)->GetDataInstance(); if (!data) return FALSE;  
  
  BaseContainer main;  
  
  data->InsData(MY_SUBCONTAINER, main);        //insert the main-subcontainer  
  data->SetLong(MY_SUBCONTAINER_CNT, 1000);    //store the intial ID for the sub-subcontainers  
  
  return TRUE;  
}  
  
Bool RoundedTube::Message(GeListNode *node, LONG type, void *data)  
{  
  switch (type)  
  {  
      case MSG_DESCRIPTION_COMMAND:  
      {  
          DescriptionCommand *dc = (DescriptionCommand* )data;  
          if (dc->id[0].id == MY_BUTTON)  
          {  
              BaseList2D *op = (BaseList2D* )node;  
              BaseDocument *doc = op->GetDocument(); if (!doc) return FALSE;  
              BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;  
              BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return FALSE;  
  
              doc->StartUndo();  
  
              BaseContainer object;  
              object.SetLink(MY_LINK, NULL);  
              object.SetReal(MY_VALUE, 0.0);  
  
              doc->AddUndo(UNDO_CHANGE_SMALL, node);  
  
              main->InsData(bc->GetLong(MY_SUBCONTAINER_CNT), object);    //insert the sub-subcontainer  
              bc->SetLong(MY_SUBCONTAINER_CNT, bc->GetLong(MY_SUBCONTAINER_CNT)+1);    //increase the sub-subcontainer ID  
  
              doc->EndUndo();  
          }  
      }  
  }  
  
  return     SUPER::Message(node,type,data);  
}  
  
Bool RoundedTube::GetDDescription(GeListNode *node, Description *description, LONG &flags)  
{  
  if (!description->LoadDescription(node->GetType())) return FALSE;  
  
  // important to check for speedup c4d!  
  const DescID *singleid = description->GetSingleDescID();  
  
  BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;  
  BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return FALSE;  
  BaseDocument *doc = ((BaseList2D* )node)->GetDocument();  
  
  Bool initbc1 = FALSE;  
  Bool initbc2 = FALSE;  
  Bool initbc3 = FALSE;  
  BaseContainer bc1, bc2, bc3;  
  
  BrowseContainer brw(main);  
  GeData *data = NULL;  
  LONG id;  
  while (brw.GetNext(&id,&data))    //browse through the main-subcontainer  
  {  
      if (data->GetType() != DA_CONTAINER) continue;  
      BaseContainer *object = data->GetContainer(); if (!object) continue;    //get the sub-subcontainer  
  
      //read out the sub-subcontainer and accordingly add the elements to the description  
      //MY_LINK, MY_VALUE and MY_SEPARATOR are defined along with the button ID (MY_BUTTON) in the header file  
  
      DescID cid = DescID(DescLevel(MY_LINK,DTYPE_SUBCONTAINER,0), DescLevel(id,DTYPE_BASELISTLINK,0));  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc1)  
          {  
              initbc1 = TRUE;  
              bc1 = GetCustomDataTypeDefault(DTYPE_BASELISTLINK);  
              bc1.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_LINKBOX);  
              bc1.SetLong(DESC_ANIMATE, DESC_ANIMATE_ON);  
              bc1.SetBool(DESC_REMOVEABLE, FALSE);  
          }  
          bc1.SetString(DESC_NAME, "Link");  
          bc1.SetString(DESC_SHORT_NAME, "Link");  
          if (!description->SetParameter(cid,bc1,DescLevel(ID_OBJECTPROPERTIES))) return FALSE;  
      }  
  
      cid = DescID(DescLevel(MY_VALUE,DTYPE_SUBCONTAINER,0), DescLevel(id,DTYPE_REAL,0));  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc2)  
          {  
              initbc2 = TRUE;  
              bc2 = GetCustomDataTypeDefault(DTYPE_REAL);  
              bc2.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_REALSLIDER);  
              bc2.SetReal(DESC_MIN,0.0);  
              bc2.SetReal(DESC_MAX,1.0);  
              bc2.SetReal(DESC_STEP,0.01);  
              bc2.SetLong(DESC_UNIT,DESC_UNIT_PERCENT);  
              bc2.SetLong(DESC_ANIMATE, DESC_ANIMATE_ON);  
              bc2.SetBool(DESC_REMOVEABLE, FALSE);  
          }  
          bc2.SetString(DESC_NAME, "Value");  
          bc2.SetString(DESC_SHORT_NAME, "Value");  
          if (!description->SetParameter(cid,bc2,DescLevel(ID_OBJECTPROPERTIES))) return FALSE;  
      }  
  
      cid = DescID(DescLevel(MY_SEPARATOR,DTYPE_SUBCONTAINER,0), DescLevel(id,DTYPE_SEPARATOR,0));  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc3)  
          {  
              initbc3 = TRUE;  
              bc3 = GetCustomDataTypeDefault(DTYPE_SEPARATOR);  
              bc3.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_SEPARATOR);  
              bc3.SetBool(DESC_SEPARATORLINE, TRUE);  
              bc3.SetLong(DESC_ANIMATE, DESC_ANIMATE_OFF);  
              bc3.SetBool(DESC_REMOVEABLE, FALSE);  
          }  
          bc3.SetString(DESC_NAME, "");  
          bc3.SetString(DESC_SHORT_NAME, "");  
          if (!description->SetParameter(cid,bc3,DescLevel(ID_OBJECTPROPERTIES))) return FALSE;  
      }  
  }  
  
  flags |= DESCFLAGS_DESC_LOADED;  
  
  return SUPER::GetDDescription(node,description,flags);  
}  
  
BaseObject *RoundedTube::GetVirtualObjects(PluginObject *op, HierarchyHelp *hh)  
{  
  return NULL;  
}  
  
  
// be sure to use a unique ID obtained from www.plugincafe.com  
#define ID_ROUNDEDTUBEOBJECT 1001157  
  
Bool RegisterRoundedTube(void)  
{  
  // decide by name if the plugin shall be registered - just for user convenience  
  String name=GeLoadString(IDS_ROUNDED_TUBE); if (!name.Content()) return TRUE;  
  return RegisterObjectPlugin(ID_ROUNDEDTUBEOBJECT,name,OBJECT_GENERATOR,RoundedTube::Alloc,"Oroundedtube","roundedtube.tif",0);  
}  

hope that helps

cheers,
Matthias

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

On 17/01/2010 at 17:16, xxxxxxxx wrote:

Thanks for your help Matthias .   I have another question about this.   I am able to add the new dynamic decription elements to my attributes manager,   Now how do I access the data from these new elements?  I would like to be able to draw from the new links and sliders..

THanks,

~Shawn

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

On 17/05/2010 at 05:54, xxxxxxxx wrote:

sorry for digging out this old thread.

I'm also using the example above and changed it slightly to fit my puropse. Now I also don't understand where the new values (in my case just the REAL value) are stored and how I can access them?

In GetDDescription I tried: 
object->GetReal(MY_VALUE);  
main->GetReal(MY_VALUE);
bc2.GetReal(MY_VALUE); 
bc->GetReal(MY_VALUE);

a.s.o.

so far it's try and error hoping to get the correct value by chance 😕

Would be nice if someone could help out and explain where the values are stored and how I could access the new REAL value set in the attributes manager.

Thanks.

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

On 19/05/2010 at 08:13, xxxxxxxx wrote:

Hey, no one here who could give me a hint? 
I'm not an experienced programmer I'm doing this plugin for a students project and I spent hours trying to figur out this problem. Any help would be appreciated.

What I got so far: 
If I press the Button

in Message () 
I create an new (Sub-Sub-) BaseContainer and insert it in the main SubContainer.

BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;
BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return FALSE;
BaseContainer object;
object.SetReal(MY_VALUE, 0.0);
main->InsData(bc->GetLong(MY_SUBCONTAINER_CNT), object);    //insert the sub-subcontainer

then in GetDDescription()
the main SubContainer ist fetched and with it a BrowseContainer is created. 
With the BrowseContainer I browse through all the BaseContainer in the main Container and a new BaseContainer (bc2) with the Decription of the Parameters is created and added to the Description.

while (brw.GetNext(&id,&data))    //browse through the main-subcontainer
    {
        if (data->GetType() != DA_CONTAINER) continue;
        BaseContainer *object = data->GetContainer(); if (!object) continue;    //get the sub-subcontainer
  
        //read out the sub-subcontainer and accordingly add the elements to the description
        //MY_LINK, MY_VALUE and MY_SEPARATOR are defined along with the button ID (MY_BUTTON) in the header file
 DescID cid = scID(DescLevel(MY_VALUE,DTYPE_SUBCONTAINER,0), DescLevel(id,DTYPE_REAL,0));
        if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!
        {
            if (!initbc2)
            {
                initbc2 = TRUE;
                bc2 = GetCustomDataTypeDefault(DTYPE_REAL);
                bc2.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_REALSLIDER);
                bc2.SetReal(DESC_MIN,0.0);
                bc2.SetReal(DESC_MAX,1.0);
                bc2.SetReal(DESC_STEP,0.01);
                bc2.SetLong(DESC_UNIT,DESC_UNIT_PERCENT);
                bc2.SetLong(DESC_ANIMATE, DESC_ANIMATE_ON);
                bc2.SetBool(DESC_REMOVEABLE, FALSE);
            }
            bc2.SetString(DESC_NAME, "Value");
            bc2.SetString(DESC_SHORT_NAME, "Value");
            if (!description->SetParameter(cid,bc2,DescLevel(ID_OBJECTPROPERTIES))) return FALSE;
        }

Now I'm able to access the the Values stored in the SubContainer (the DESC_NAME...)

But unfortuntaly I can't get the values I enter in the REAL Box in the C4D Parameter Dialog. It seems that they are not stored in my object Sub-Sub- Container as I would've expected . 
I just can't figure out where there are stored and how I'm able to access them.

Thanks for taking the time.

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

On 19/05/2010 at 09:27, xxxxxxxx wrote:

I will look into this tomorrow.

cheers,
Matthias

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

On 20/05/2010 at 23:48, xxxxxxxx wrote:

thanks that would be ace.

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

On 25/05/2010 at 12:08, xxxxxxxx wrote:

Hi Matthias, did you had the chance to look into it?
I don't want to bug you but I'm really desperate 😉

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

On 26/05/2010 at 02:11, xxxxxxxx wrote:

There was some small but important thing missing in my example. You have to overload the SetD/GetDParameter methods because we are storing dynamic elements in sub-containers.

Here is the complete code for a example with dynamic slider elements. In the overloaded GetVirtualObjects method you can see how to read out the values.

  
/////////////////////////////////////////////////////////////  
// CINEMA 4D SDK                                           //  
/////////////////////////////////////////////////////////////  
// (c) 1989-2004 MAXON Computer GmbH, all rights reserved  //  
/////////////////////////////////////////////////////////////  
  
// generator object example (with no input objects)  
  
#include "c4d.h"  
#include "c4d_symbols.h"  
#include "oroundedtube.h"  
  
  
#define MY_SUBCONTAINER 1024882        //unique ID for the main-subcontaioner  
#define MY_SUBCONTAINER_CNT 1024883    //unique ID for storing the IDs of the sub-subcontainers  
  
  
class RoundedTube : public ObjectData  
{  
  INSTANCEOF(RoundedTube,ObjectData)  
  
  public:  
      virtual Bool Init(GeListNode *node);  
      virtual BaseObject* GetVirtualObjects(PluginObject *op, HierarchyHelp *hh);  
      virtual Bool Message(GeListNode *node, LONG type, void *data);  
      virtual Bool GetDDescription(GeListNode *node, Description *description, LONG &flags);  
      virtual Bool GetDParameter(GeListNode *node, const DescID &id, GeData &t_data, LONG &flags);  
      virtual Bool SetDParameter(GeListNode *node, const DescID &id, const GeData &t_data, LONG &flags);  
  
      static NodeData *Alloc(void) { return gNew RoundedTube; }  
};  
  
Bool RoundedTube::Init(GeListNode *node)  
{  
  BaseContainer *data = ((BaseList2D* )node)->GetDataInstance(); if (!data) return FALSE;  
  
  BaseContainer main;  
  
  data->InsData(MY_SUBCONTAINER, main);        //insert the main-subcontainer  
  data->SetLong(MY_SUBCONTAINER_CNT, 1000);    //store the intial ID for the sub-subcontainers  
  
  return TRUE;  
}  
  
Bool RoundedTube::Message(GeListNode *node, LONG type, void *data)  
{  
  switch (type)  
  {  
      case MSG_DESCRIPTION_COMMAND:  
      {  
          DescriptionCommand *dc = (DescriptionCommand* )data;  
          if (dc->id[0].id == MY_BUTTON)  
          {  
              BaseList2D *op = (BaseList2D* )node;  
              BaseDocument *doc = op->GetDocument(); if (!doc) return FALSE;  
              BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;  
              BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return FALSE;  
  
              doc->StartUndo();  
  
              BaseContainer object;  
              object.SetReal(MY_VALUE, 0.0);  
  
              doc->AddUndo(UNDO_CHANGE_SMALL, node);  
  
              main->InsData(bc->GetLong(MY_SUBCONTAINER_CNT), object);    //insert the sub-subcontainer  
              bc->SetLong(MY_SUBCONTAINER_CNT, bc->GetLong(MY_SUBCONTAINER_CNT)+1);    //increase the sub-subcontainer ID  
  
              doc->EndUndo();  
          }  
      }  
  }  
  
  return SUPER::Message(node,type,data);  
}  
  
Bool RoundedTube::GetDDescription(GeListNode *node, Description *description, LONG &flags)  
{  
  if (!description->LoadDescription(node->GetType())) return FALSE;  
  
  // important to check for speedup c4d!  
  const DescID *singleid = description->GetSingleDescID();  
  
  BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); if (!bc) return FALSE;  
  BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return FALSE;  
  BaseDocument *doc = ((BaseList2D* )node)->GetDocument();  
  
  Bool initbc1 = FALSE;  
  BaseContainer bc1;  
  
  BrowseContainer brw(main);  
  GeData *data = NULL;  
  LONG id;  
  while (brw.GetNext(&id,&data))    //browse through the main-subcontainer  
  {  
      if (data->GetType() != DA_CONTAINER) continue;  
      BaseContainer *object = data->GetContainer(); if (!object) continue;    //get the sub-subcontainer  
  
      //read out the sub-subcontainer and accordingly add the elements to the description  
      //MY_LINK, MY_VALUE and MY_SEPARATOR are defined along with the button ID (MY_BUTTON) in the header file  
  
      DescID cid = DescID(DescLevel(MY_VALUE,DTYPE_SUBCONTAINER,0), DescLevel(id,DTYPE_REAL,0));  
      if (!singleid || cid.IsPartOf(*singleid,NULL)) // important to check for speedup c4d!  
      {  
          if (!initbc1)  
          {  
              initbc1 = TRUE;  
              bc1 = GetCustomDataTypeDefault(DTYPE_REAL);  
              bc1.SetLong(DESC_CUSTOMGUI, CUSTOMGUI_REALSLIDER);  
              bc1.SetReal(DESC_MIN,0.0);  
              bc1.SetReal(DESC_MAX,1.0);  
              bc1.SetReal(DESC_STEP,0.01);  
              bc1.SetLong(DESC_UNIT,DESC_UNIT_PERCENT);  
              bc1.SetLong(DESC_ANIMATE, DESC_ANIMATE_ON);  
              bc1.SetBool(DESC_REMOVEABLE, FALSE);  
          }  
          bc1.SetString(DESC_NAME, "Value");  
          bc1.SetString(DESC_SHORT_NAME, "Value");  
          if (!description->SetParameter(cid,bc1,DescLevel(ID_OBJECTPROPERTIES))) return FALSE;  
      }  
  }  
  
  flags |= DESCFLAGS_DESC_LOADED;  
  
  return SUPER::GetDDescription(node,description,flags);  
}  
  
static BaseContainer *GetPose(GeListNode *node, LONG id)  
{  
  BaseContainer *bc = ((BaseObject* )node)->GetDataInstance(); if (!bc) return NULL;  
  BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return NULL;  
  
  if (main->GetType(id)!=DA_CONTAINER) return NULL;  
  return main->GetContainerInstance(id);  
}  
  
Bool RoundedTube::GetDParameter(GeListNode *node, const DescID &id, GeData &t_data, LONG &flags)  
{  
  BaseContainer *pose=NULL;  
  
  switch (id[0].id)  
  {  
      case MY_VALUE:  
      {  
          pose = GetPose(node,id[1].id); if (!pose) return FALSE;  
          t_data = pose->GetReal(MY_VALUE); flags |= DESCFLAGS_PARAM_GET;  
      }  
      break;  
  }  
  
  return SUPER::GetDParameter(node,id,t_data,flags);  
}  
  
Bool RoundedTube::SetDParameter(GeListNode *node, const DescID &id, const GeData &t_data, LONG &flags)  
{  
  BaseContainer *pose=NULL;  
  
  switch (id[0].id)  
  {  
      case MY_VALUE:  
      {  
          pose = GetPose(node,id[1].id); if (!pose) return FALSE;  
          pose->SetReal(MY_VALUE,t_data.GetReal()); flags |= DESCFLAGS_PARAM_SET;  
      }  
      break;  
  }  
  
  return SUPER::SetDParameter(node,id,t_data,flags);  
}  
  
BaseObject *RoundedTube::GetVirtualObjects(PluginObject *op, HierarchyHelp *hh)  
{  
  BaseContainer *bc = op->GetDataInstance(); if (!bc) return FALSE;  
  BaseContainer *main  = bc->GetContainerInstance(MY_SUBCONTAINER); if (!main) return FALSE;  
  
  BrowseContainer brw(main);  
  GeData *data = NULL;  
  LONG id;  
  while (brw.GetNext(&id,&data))    //browse through the main-subcontainer  
  {  
      if (data->GetType() != DA_CONTAINER) continue;  
      BaseContainer *object = data->GetContainer(); if (!object) continue;    //get the sub-subcontainer  
  
      GePrint("Value "+RealToString(object->GetReal(MY_VALUE)));        //print the value of each dynamic description element  
  }  
  
  return NULL;  
}  
  
  
// be sure to use a unique ID obtained from www.plugincafe.com  
#define ID_ROUNDEDTUBEOBJECT 1001157  
  
Bool RegisterRoundedTube(void)  
{  
  // decide by name if the plugin shall be registered - just for user convenience  
  String name=GeLoadString(IDS_ROUNDED_TUBE); if (!name.Content()) return TRUE;  
  return RegisterObjectPlugin(ID_ROUNDEDTUBEOBJECT,name,OBJECT_GENERATOR,RoundedTube::Alloc,"Oroundedtube","roundedtube.tif",0);  
}  

hope this helps

cheers,
Matthias