Undo loses stored data

On 23/10/2015 at 08:03, xxxxxxxx wrote:

Hi everyone.

I have an ObjectData plugin which processes and stores about 10 million values when a button is pressed. Then, the values are referenced in GetVirtualObjects  (roughly 200 000 per frame). If I press undo, the stored values are lost. I've tried to use various AddUndo() etc commands but no success. I assume this is due to the values being stored in a standard list and not something C4D specific like a BaseContainer.

I can actually avoid this problem with a BaseContainer with many sub BaseContainers but unfortunately this seems to slow everything down a lot when reading it back every frame.

Does anyone know if I can keep my standard stored list method using an undo command configuration?  Or if I'm missing something obvious?

Here is a fragment of a really simplified version of my plugin:

class MyPlugin(plugins.ObjectData) :
    
  
    def Init(self, op) :
        
        # ---------------//  This is the data that disappears with an undo
        self.data = []
        
        return True
  
  
    def Message(self, op, type, data) :
  
  
        if type == c4d.MSG_DESCRIPTION_COMMAND:
	
            #---------------// If the update button is pressed, call the update data function
            if data["id"][0].id == UPDATE_DATA:
                self.Update_Data(op)
  
        return True
  
  
    def Update_Data(self, op) :
  
        #---------------// Here 's where I fill the array
        self.data.append(1)
        self.data.append(2)
        self.data.append(3)
  
        return True
  
  
    def GetVirtualObjects(self, op, hh) :
	
        #---------------// And here's where I do stuff with it
        for i in self.data:
            print i
  
        return None

On 24/10/2015 at 06:24, xxxxxxxx wrote:

Hi Adam, you need to implement NodeData.CopyTo(). This will allow you to copy the data to the internal
copy of the object that is being made when an undo step is created.

On 25/10/2015 at 10:28, xxxxxxxx wrote:

Thanks Niklas, that's exactly what I was looking for. I'm completely amazed that I've never actually needed that before.

Cheers,

Adam

On 25/10/2015 at 12:34, xxxxxxxx wrote:

Well I thought I was out of the woods but I guess I'm not yet. As soon as I introduce NodeData.CopyTo() into my plugin, it crashes at any attempted copying of the plugin object. Any ideas what might be doing that?

What I have tried so far is to implement the Read() & Write() methods correctly which I think I have managed to do as I can read the data back successfully after saving. I tried this as the documentation says that it's likely that I would need all three but I'm not sure if they get called on a copy command.

Even if the CopyTo function sits there empty it still crashes. What am I missing?

Thanks,

Adam

On 25/10/2015 at 13:15, xxxxxxxx wrote:

One more thing too add. This error does not occur in R16, only R17. I'm not sure if that means there is a bug or something I can't figure out about this:

  • trn  (AliasTrans) – 
    Changed in version R17.032: An alias translator is passed.
    An optional alias translator for the operation.
    An alias translator for the operation.

On 26/10/2015 at 03:24, xxxxxxxx wrote:

Hello,

can you show us what exactly you are doing in your CopyTo() and Read(), Write() functions? What exactly does crash?

Best wishes,
Sebastian

On 26/10/2015 at 03:53, xxxxxxxx wrote:

What exactly does Crash?

Cinema reports an application error and crashes and I have to execute a force quit. This error only occurs when the node is copied. e.g. I call a copy command(or press copy), I drop the object into a cloner etc.

What am I doing in my CopyTo(), Read() and Write()?

I'm passing a list from the old node to the new one in CopyTo(). Even if however, the CopyTo() function is completely empty and I pass nothing at all, Cinema still crashes. Again this only happens in R17 and not R16. The code works perfectly in R16.

Code below:

Here is the code:

  
  
    def Write(self, node, file) :
        
        self.num_frames  = len(self.data) 
        # Write the number of frames to the hf
        file.WriteInt32(self.num_frames)
  
  
        for i in xrange(self.num_frames) :
            # These are the lengths of each frame
            frame_length = int(len(self.data[i]))
            # Write frame lengths to file
            file.WriteInt32(frame_length)
            
  
  
        for i in self.data:
            for j in i:
                # Write each point
                file.WriteVector(j)
  
  
        return True
  
    def Read(self, node, file, level) :
    
  
        # Read back number of frames
        self.num_frames = file.ReadInt32()     
  
        # Read back the number of values for each frame
        frame_lengths = []
        for i in xrange(self.num_frames) :
            fl = file.ReadInt32()
            frame_lengths.append(fl)
  
  
        # Read back the values and apply them to the frame lists
        # And recreate the main list
        del self.data[:]
        for i in frame_length:
            frame = []
            for j in xrange(i) :
                pos = file.ReadVector()
                frame.append(pos)
  
            self.data.append(frame)
  
  
    def CopyTo(self, dest, snode, dnode, flags, trn) :
  
        dest.data = self.data
  
        return True
  
  
  

Saving and loading of data sees to be right in Read() and Write(), I've done a few tests.

Thanks,

Adam

On 27/10/2015 at 09:28, xxxxxxxx wrote:

Hello,

it seems that there is indeed a bug with CopyTo(). We are currently working on fixing this bug and try to provide a fix as soon as possible.

Thanks and best wishes,
Sebastian