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

    Change UserData ID#?

    SDK Help
    0
    8
    456
    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 27/02/2013 at 13:14, xxxxxxxx wrote:

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

      ---------
      Hi,

      I'm adding and deleting UserData items in my plugin. But the way the ID#s stay local to each UD item. That is throwing everything out of sync when I delete them.
      In order to keep everything in sync in my plugin. I need to force the UserData items ID#s to always be in numerical order as they exist in the stack.

      How do we change the DescLevel() values of UserData items?

          BaseObject *obj = doc->GetActiveObject();    
        DynamicDescription *ud = obj->GetDynamicDescription();  
        
        DescID udEntry(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), DescLevel(3));  //<----I want to change this value from 3 to 2
      

      Also.
      What's the deal with GetDepth()?
      Instead of returning the stack position of each UD item. It gets stuck at 2. 😠

          DescID dscID;  
        const BaseContainer *bc;  
        void *dscHnd = ud->BrowseInit();                        //Initialize the Browse function  
        
        counter = 1;  
        
        while(ud->BrowseGetNext(dscHnd, &dscID, &bc))           //Loop through the UserData entries  
        {   
            DescID udEntry(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), DescLevel(counter));  
        
            LONG level = udEntry.GetDepth();  
        GePrint(LongToString(level));     <---- Prints 1, 2, 2, 2, 2, etc...  
        
            counter ++;  
        
        }  
        ud->BrowseFree(dscHnd); 
      

      ScottA

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

        On 27/02/2013 at 13:17, xxxxxxxx wrote:

        Not sure about ID numbering, but GetDepth() probably isn't getting what you think.  It is getting the number of levels of a DescID (subids, basically).

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

          On 28/02/2013 at 12:52, xxxxxxxx wrote:

          Maxon?...Yannick?
          Can we do this?
          Is there no SDK function to change the UD's position on the stack?

          If not.
          I figured out a possible way to maybe work around it by copying the user data entry. Then deleting the original.
          But this is an awful lot of work to do. Just to change a UD's levelID#.
          I.E. Change the UD position on the stack:

             //Get the object or tag the UserData is on  
            //Then get the master UserData container  
            BaseObject *obj = doc->GetActiveObject();    
            DynamicDescription *ud = obj->GetDynamicDescription();            //The master UD container  
            
            //Get the specific UD we want to copy  
            DescID udSource(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), DescLevel(3)); //The UD entry to copy  
            const BaseContainer *sourceBC = ud->Find(udSource);  
            GeData d;  
            obj->GetParameter(udSource, d, DESCFLAGS_GET_0);                  //Get the values for the gizmos in the source UD we want to copy and store them in d  
            String name = sourceBC->GetString(DESC_NAME);                     //Get the name of the source UD we want to copy  
            LONG type = sourceBC->GetLong(DESC_CUSTOMGUI);                    //Get the data type setting   
            LONG unit = sourceBC->GetLong(DESC_UNIT);                         //Get the units setting(Real, Percent. etc..)  
            LONG min = sourceBC->GetLong(DESC_MIN);                           //Get the min value  
            LONG max = sourceBC->GetLong(DESC_MAX);                           //Get the max value  
            GePrint(LongToString(max));              //<--always returns Zero!?  
            
            
            //Now we create a brand new UserData from scratch  
            //The copy the data from the source to the copy...Then delete the source  
            BaseContainer CopyBC;  
            DescID udCopy(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), DescLevel(2));    //The new ID level where the copy will end up  
            udCopy = ud->Alloc(CopyBC);                                                    //Create the new UD object in memory only  
            ud->FillDefaultContainer(CopyBC, type, name);                                  //Fill the UD with some basic information and use the source's name and data type  
            CopyBC.SetLong(DESC_UNIT, unit);                                               //Set the units value using the source's units value in memory only  
            CopyBC.SetLong(DESC_MIN, min);                                                 //Set the min value using the source's units value in memory only  
            CopyBC.SetLong(DESC_MAX, max);                                                 //Set the max value using the source's units value in memory only  
              
            ud->Set(udCopy, CopyBC, obj);                                                  //Execute the changes made to the UD from memory  
            
            obj->SetParameter(DescID(udCopy), GeData(d), DESCFLAGS_SET_0);                 //Copy the gizmo values from the source UD and copy them to this new UD  
            
            ud->Remove(DescID(DescLevel(ID_USERDATA),DescLevel(3)));                       //Delete the original(source) UserData entry  
            SendCoreMessage(COREMSG_CINEMA, BaseContainer(COREMSG_CINEMA_FORCE_AM_UPDATE));//Update the object the UD is on to reflect the deletion(mandatory when deleting UD)  
            if(obj->IsDirty(DIRTYFLAGS_DATA)) GePrint("Changed");                         //Sends a message that the UD was changed
          

          One small problem though. DESC_MIN & DESC_MAX are not working properly.
          I can't copy these values and set them in the new copy UD.
          How are we supposed to use these?

          -ScottA

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

            On 01/03/2013 at 01:04, xxxxxxxx wrote:

            Hi,

            Here's how you can simply change the ID of a user data:

            BaseObject *op = doc->GetActiveObject();
            if (op==NULL) return FALSE;
              
            DynamicDescription *dynDesc = op->GetDynamicDescription();
            if (dynDesc==NULL) return FALSE;
              
            DescID udEntry(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), 1);
              
            const BaseContainer *data = dynDesc->Find(udEntry);
            if (data!=NULL)
            {
                BaseContainer bc = *data->GetClone(COPYFLAGS_0, NULL);
              
                dynDesc->Remove(udEntry);
              
                // Get the ID sub-level and increment it
                DescLevel level = udEntry[1];
                level.id++;
                udEntry.PopId();
                udEntry.PushId(level);
              
                dynDesc->Set(udEntry, bc, NULL);
                EventAdd();
            }
            
            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 01/03/2013 at 07:24, xxxxxxxx wrote:

              Thank you sir. 🍺

              I was also having trouble figuring out how to use PopId() & PushId(). And your example answered my questions about them too.

              -ScottA

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

                On 01/03/2013 at 13:27, xxxxxxxx wrote:

                Uh Oh.
                I take it back. That code doesn't work properly.

                While it does change the level. It also deletes the current values in the fields. 😠

                -ScottA

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

                  On 01/03/2013 at 14:03, xxxxxxxx wrote:

                  Since the code Yannick posted wacks any previous UD values.
                  Here is an example that uses a combination of his code and mine. Which won't delete the UserData values when changing the level value:

                  //This example creates a copy of a specific UserData entry (ID#1) with a different ID# (ID#2) (DescLevel)  
                  //Then deletes the original UD entry (optional)  
                  //This version also copies the values from the old UD to the new UD  
                    
                    
                    BaseObject *op = doc->GetActiveObject();  
                    if (op==NULL) return FALSE;  
                    
                    DynamicDescription *dynDesc = op->GetDynamicDescription();           //The master UD container  
                    if (dynDesc==NULL) return FALSE;  
                    
                    DescID udEntry(DescLevel(ID_USERDATA, DTYPE_SUBCONTAINER, 0), 1);    //The ID is #1...The first UD item on the stack  
                    
                    const BaseContainer *data = dynDesc->Find(udEntry);                  //Get the data for this specific UD item  
                    if (data!=NULL)  
                    {  
                        BaseContainer bc = *data->GetClone(COPYFLAGS_0, NULL);           //Get a copy of the UD's BaseContainer  
                        GeData d;  
                        op->GetParameter(udEntry, d, DESCFLAGS_GET_0);                   //Get the values for the gizmos in the source UD we want to copy and store them in d  
                        String name = data->GetString(DESC_NAME);                        //Get the name of the source UD we want to copy  
                        LONG type = data->GetLong(DESC_CUSTOMGUI);                       //Get the data type setting   
                        LONG unit = data->GetLong(DESC_UNIT);                            //Get the units setting(Real, Percent. etc..)  
                    
                        dynDesc->Remove(udEntry);                                        //Delete the UD entry (Note: The UD's level is still there on the stack)   
                                                                                         //We have to handle the UD's level data(DescLevel) too  
                    
                        //Get the ID sub-level and increment it  
                        DescLevel level = udEntry[1];                                    //Gets the level of the UD item and assigns it to a variable  
                        level.id++;                                                      //Change the level to some other number  
                        udEntry.PopId();                                                 //Remove the UD's level data from the stack  
                        udEntry.PushId(level);                                           //Add the UD's new level data to the stack (this is what changes the ID#)  
                    
                        dynDesc->Set(udEntry, bc, NULL);                                 //Execute all these changes made to the UD from memory  
                        op->SetParameter(DescID(udEntry), GeData(d), DESCFLAGS_SET_0);   //Paste the gizmo values from the original UD to this new version of the UD  
                        EventAdd();  
                    }
                  

                  -ScottA

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

                    On 04/03/2013 at 01:26, xxxxxxxx wrote:

                    Thanks for sharing your code with the complete solution.

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