Undo loses stored data
On 23/10/2015 at 08:03, xxxxxxxx wrote:
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"].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.
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?
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 (
Changed in version R17.032: An alias translator is passed.
An optional alias translator for the operation.
An alias translator for the operation.
- trn (
On 26/10/2015 at 03:24, xxxxxxxx wrote:
can you show us what exactly you are doing in your CopyTo() and Read(), Write() functions? What exactly does crash?
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.
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.
On 27/10/2015 at 09:28, xxxxxxxx wrote:
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,