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

    Turn Off UNDOs?

    SDK Help
    0
    20
    1.3k
    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 13/03/2013 at 02:56, xxxxxxxx wrote:

      Hi Scott,

      Read() and Write() methods in CINEMA that make use of hyperfiles are only called when a scene with your tag is read and written.

      There's no issue here in fact. This is the normal way of the undo: the creation of your tag is undo'ed.
      To prevent this you have to build an undo list whenever a new pose is added:

      doc->StartUndo();
      doc->AddUndo(UNDOTYPE_CHANGE_SMALL, tag);
      ...
      doc->EndUndo();
      

      Also, you have to free the images array in the destructor of your tag.

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

        On 13/03/2013 at 07:28, xxxxxxxx wrote:

        Since I have no undo's at all in my code. It never occurred to me that adding them could actually prevent the mass extinction that happens to them all when an undo is executed.

        I'll give it try.
        Thanks,

        -ScottA

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

          On 13/03/2013 at 09:54, xxxxxxxx wrote:

          Originally posted by xxxxxxxx

          Also, you have to free the images array in the destructor of your tag.

          Ugh!
          I'm having a very, very hard time squashing the memory leaks in this plugin scenario.
          Every time I try to free things. It messes up the way the plugin works.
          The only place I can seem to safely do any memory freeing without hurting the plugin's operation is in the destructor. But nothing I do in the destructor kills all of the memory leaks

          StorageTag::~StorageTag()  
          {  
            BaseBitmap::Free(defaultImg);  
            BaseBitmap::Free(tagBitmap);  
            BaseBitmap::Free(render);            //Trying everything I can think of to free the Bitmaps & images array   
            GeFree(images);                         //But still getting memory leaks!!!   
            images.~GeDynamicArray();  
          }
          

          I admit it. I'm in over my head.
          This is such a cool new way to create plugins using tags as little databases. But I'm just not experienced enough to get it nailed down with proper memory freeing and undos.

          -ScottA

          Sorry for the rant.
          I've been working on this for a long time. And every time I think I've nailed it, I find a memory leak problem....C++ is beating me up.

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

            On 13/03/2013 at 12:14, xxxxxxxx wrote:

            GeDynamicArray.FreeArray() to free the memory of the array.

            You shouldn't have to ever free the GeDynamicArray itself!

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

              On 13/03/2013 at 13:23, xxxxxxxx wrote:

              OK. Thanks Robert.
              Even after using that in the destructor. I'm still getting leaks.
              If I free bitmaps after using them throught my code I can get rid of the leaks. But that messes up the way the plugin works.
              Images don't get created, updated, saved, etc.

              I didn't think about checking for memory leaks until I had written the entire plugin.
              That was a big mistake. Now I'm paying the price.

              -ScottA

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

                On 13/03/2013 at 14:40, xxxxxxxx wrote:

                Best thing to do is remove (comment out) things one section at a time and see where the leaks stop occurring. If you can, start at the stuff that runs latest and work your way back.

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

                  On 13/03/2013 at 15:04, xxxxxxxx wrote:

                  Yeah. I've been trying to do that. But it's hard to debug because I used so much dynamic creation stuff in it.
                  I think I'll have to start over and create a simpler version without the tree GUI and all the fancy dynamic stuff to figure out why the memory is leaking.
                  If I don't kill myself first.😉

                  What a total nightmare this project has been. Like pulling an elephant through a peephole.😂
                  Thanks for being patient with me and helping me with it.

                  -ScottA

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

                    On 14/03/2013 at 12:27, xxxxxxxx wrote:

                    Yannick,
                    I tried to use: doc->AddUndo(UNDOTYPE_CHANGE_SMALL, tag);
                    But I can't figure out where to use this. Because what I'm doing is so unusual.

                    I'm not trying to stop added tags from being deleted during an undo operation.
                    I'm trying to prevent my dynamically created bitmap buttons from getting deleted from the GeDialog.
                    The existence of those buttons are tied to an array in the tag's hyperfile.
                    The AsyncTest SDK example uses a variable called "row" to control the dynamically generated gizmos. But I'm using an array stored in the tag's hyperfile to do the same kind of thing.

                    What seems to be happening is that when an Undo operation is executed in C4D. One of the things it does is delete existing data from a tag's hyperfile. At least that's what looks like is  happening.
                    When the Undo occurs. The tag's hyperfile appears to be getting cleared, along with my array data. Which then has the final result of deleting my Bitmap buttons on the GeDialog.

                    I've never seen anyone use the hyperfile system so extensive like I'm using it.
                    So this could just be a case of trying to do things with it that it was never meant to handle.

                    -ScottA

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

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

                      You may need to implement CopyTo() if you haven't already.  Whenever an undo is stored, Init() and CopyTo() (among other things) are called.  When an undo is undone, Init() and CopyTo() are called.  With CopyTo(), you need to duplicate any relevant data that isn't stored directly in the object's BaseContainer (DataInstance).

                      It could be that when an undo is undone (Ctrl-Z), your bitmap array is not being recreated (or it was not stored in the undo in the first place), therefore you lose that data when undone.

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

                        On 14/03/2013 at 15:12, xxxxxxxx wrote:

                        Ok. I'll give it a try Robert.
                        I'm not very clear on how CopyTo() works. Your code is the only example I have on it. But I'll give it try.

                        BTW: I found where my memory leak was coming from.
                        It's coming from a function I was using to render the images

                        BaseBitmap *RenderDocument(BaseDocument *doc, LONG width, LONG height, Bool activeOnly)   
                        {  
                          if (!doc) return NULL;  
                          
                          BaseObject *bg = BaseObject::Alloc(Obackground);                             //Create a background object  
                          doc->InsertObject(bg, NULL, NULL);                                           //Add it to the OM  
                          bg->SetBit(BIT_ACTIVE);                                                      //Background object needs to be selected to work with the RenderActive option  
                          bg->SetParameter(ID_BASEOBJECT_USECOLOR, 2, DESCFLAGS_SET_0);                //Set the use color option to ON  
                          bg->SetParameter(ID_BASEOBJECT_COLOR, Vector(.32,.32, .32), DESCFLAGS_SET_0); //Set the color for the background  
                          
                          BaseBitmap *bmp = BaseBitmap::Alloc();  
                          if (!bmp) return NULL;  
                          bmp->Init(width, height);  
                          RenderData *renderData = doc->GetActiveRenderData();  
                          if(activeOnly) renderData->SetParameter(RDATA_ACTIVEOBJECTONLY, TRUE, DESCFLAGS_SET_0);  
                          else renderData->SetParameter(RDATA_ACTIVEOBJECTONLY, FALSE, DESCFLAGS_SET_0);  
                          BaseContainer container = renderData->GetData();          
                          container.SetLong(RDATA_XRES, width);  
                          container.SetLong(RDATA_YRES, height);  
                          container.SetLong(RDATA_RENDERENGINE, RDATA_RENDERENGINE_STANDARD);  
                          RenderDocument(doc, container, NULL, NULL, bmp, RENDERFLAGS_EXTERNAL, NULL);  
                          
                          renderData->SetParameter(RDATA_ACTIVEOBJECTONLY, FALSE, DESCFLAGS_SET_0);  
                          bg->Remove();  
                          BaseObject::Free(bg);  
                          
                          return bmp;
                        

                        This function gets called every time a new image is created.
                        And I think what was happening is every time it executed. A new Alloc was created but never freed.
                        I tried using BaseBitmap::Free(bmp) at the end of it. But it crashes.
                        I'm still trying to find a solution to freeing this code properly. I'm a newb at handling memory.

                        -ScottA

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

                          On 14/03/2013 at 15:26, xxxxxxxx wrote:

                          1. If your bmp allocation fails, you never free bg.

                          2. If you are returning the bmp to replace one that has already been allocated and stored in your tag, then, yes, you will need to free the old one before allocating a new one to replace it.  One way to do this safely would be to return the bmp to a local variable in the method calling RenderDocument() and if it is not null and the one being replaced is not null then free the one being replaced and set the pointer to the one returned and stored in the local variable.  Think of it as a swap sort of.

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

                            On 17/03/2013 at 10:05, xxxxxxxx wrote:

                            I'm trying to figure out how to use the CopyTo() method. But the docs only show how to copy a simple variable. Nothing as complex as bitmaps and arrays.

                            This is what I've got so far.
                            It doesn't crash. But it also doesn't solve my Undo problem. I have no idea if I'm doing this right because the docs don't show how to handle bitmaps and arrays.
                            I think I might be saving the array images to the tag. But not re-saving them back to the array?

                            class StorageTag : public TagData  
                            {  
                              INSTANCEOF(StorageTag,TagData)  
                              
                              public:  
                                  BaseBitmap *render;                      //<--The images that get saved into the images array  
                                  BaseBitmap *dbm;                         //<--The bitmap used to transfer the images in the array to the tag  
                                  LONG imagecount;  
                                  GeDynamicArray<BaseBitmap *> images;     //<--This is the array of images I want to CopyTo() the tag  
                              
                                  StorageTag();  
                                  ~StorageTag();  
                                  virtual Bool Init(GeListNode *node);  
                                  Bool Read(GeListNode* node, HyperFile* file, LONG level);  
                                  Bool Write(GeListNode* node, HyperFile* file);  
                                  virtual Bool CopyTo(NodeData* dest, GeListNode* snode, GeListNode* dnode, COPYFLAGS flags, AliasTrans* trn);  
                                  virtual Bool Message(GeListNode *node, LONG type, void *t_data);  
                                  virtual EXECUTIONRESULT Execute(BaseTag *tag, BaseDocument *doc, BaseObject *op, BaseThread *bt, LONG priority, EXECUTIONFLAGS flags);  
                                    
                                  static NodeData *Alloc(void) { return gNew StorageTag; }  
                            };  
                              
                            ...  
                              
                            Bool StorageTag::CopyTo(NodeData* dest, GeListNode* snode, GeListNode* dnode, COPYFLAGS flags, AliasTrans* trn)  
                            {  
                              StorageTag *dtag = (StorageTag* )dest;  
                              if (!dtag) return FALSE;  
                              
                              dtag->imagecount = imagecount;           //This works OK  
                              //dtag->render = render;                 //Crashes!!!   
                              //dtag->images = images;                 //Crashes!!!  
                              
                              dbm = BaseBitmap::Alloc();               //This works OK  
                              //render->CopyTo(dbm);                   //Crashes!!!  
                              //dtag->render = dbm;  
                              
                              for(LONG i=0; i<images.GetCount(); i++)  
                              {  
                                  images[i]->CopyTo(dbm);              //<----This doesn't crash...But it doesn't fix my Undo problem either  
                              }  
                              
                              return TRUE;  
                            }
                            

                            I need more information how to use the CopyTo() method with an array filled with bitmaps.
                            Please and thank you.

                            -ScottA

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

                              On 17/03/2013 at 10:57, xxxxxxxx wrote:

                              Bool StorageTag::CopyTo(NodeData* dest, GeListNode* snode, GeListNode* dnode, COPYFLAGS flags, AliasTrans* trn)  
                              {  
                                StorageTag *dtag = (StorageTag* )dest;  
                                if (!dtag) return FALSE;  
                                  
                                dtag->imagecount = imagecount;           //This works OK  
                                // You can't do this - you need copies, not just pointing to the originals!   
                                //dtag->render = render;                 //Crashes!!!   
                                //dtag->images = images;                 //Crashes!!!  
                                  
                                // could it be that render has not been allocated yet?  
                                if (render)  
                                {  
                                    // Only one bitmap has been allocated!  Corrected in for loop  
                                    dbm = BaseBitmap::Alloc();               //This works OK  
                                    if (!dbm)    return FALSE;  
                                    // Not sure if this is necessary but check it  
                                    dbm->Init(render->GetBw(), render->GetBh);  
                                    render->CopyTo(dbm);                   //Crashes!!!  
                                    dtag->render = dbm;  
                                }  
                                else GePrint("StorageTag.CopyTo.render == NULL");  
                                  
                                for(LONG i=0; i<images.GetCount(); i++)  
                                {  
                                    dbm = BaseBitmap::Alloc();  
                                    if (!dbm)    return FALSE;  
                                    // Not sure if this is necessary but check it  
                                    dbm->Init(images[i]->GetBw(), images[i]->GetBh);  
                                    // Might need a cast here (??), try it without but keep in mind  
                                    static_cast<BaseBitmap*>(images[i])->CopyTo(dbm);              //<----This doesn't crash...But it doesn't fix my Undo problem either  
                                    // the [] operator for GeDynamicArray is for access only.  Not sure if you can set to it.  Push() and Insert() exist for this purpose  
                                    dtag->images.Push(dbm);  
                                }  
                                  
                                return TRUE;  
                              }
                              
                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                On 17/03/2013 at 11:28, xxxxxxxx wrote:

                                It works!!!

                                I got compile errors for the Init() code parts. So I just commented them out and it seems to work fine without them.

                                I can't thank you enough for all your help Robert.🍺
                                You should be working for Maxon.

                                -ScottA

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