Storing node data in a Tag plugin
-
I try to save an object (using IsolateObjects()) using the Tag plugins Write() function.
Here the code:
class EDITABLECLEANTAG(plugins.TagData): myData = None def Write(self, node, HFfile): print "WRITE myData: ", self.myData # Store the size HFfile.WriteInt32(self.myData[1]) # Store the data itself if HFfile.WriteMemory(self.myData[0]) is False: raise ValueError("can't write the file") return True def Message(self, tag, type, data): doc = tag.GetDocument() id = GetMessageID(data) if id == CLICK_EDITABLECLEAN: # If this Gizmo is activated # using a MemoryFileStructure to store a document mfs = c4d.storage.MemoryFileStruct() mfs.SetMemoryWriteMode() IsolateObject = tag.GetObject() print "IsolateObject: ", IsolateObject newdoc = c4d.documents.IsolateObjects(doc , [IsolateObject]) # Save the document to the MemoryFileStructure c4d.documents.SaveDocument(newdoc, mfs, c4d.SAVEDOCUMENTFLAGS_NONE, c4d.FORMAT_C4DEXPORT) #Retrieve the data and store it somewhere, here in self.myData self.myData = mfs.GetData() print "Data saved: ", self.myData
When a button is clicked in the tag UI, I do an IsolateObjects(), and then store the resulting newdoc in myData.
Later on, when the scene file is saved, the Write() function is called automatically and the data is saved.However, it looks to me that c4d.documents.SaveDocument() also calls Write().
If so, myData is not filled yet, and an error occurs.
What am I doing wrong? -
Hi,
well, you answered your question yourself. You are trying to index
myData
with the bracket syntax (i.e. invoke__getitem__
) which causes an excpetion whenmyData
isNone
. You have to test first, if the class dictionary ofmyData
contains__getitem__
, or more straight forward - if it is not of typeNone
.Cheers
zipit -
hello,
as @zipit said, you have to check your data before trying to write them on the HF.
Another thing, in your code you are trying to isolate the object, don't forget it will isolate your tag also.
You should use a command data that will- isolate the hierarchy,
- retrieve a polygon object from it and insert it in your document.
- add the tag to your object that will store the old hierarchy
Even if i still think a generator should work better.
Cheers
Manuel -
@zipit, The strange thing is the sequence of things / of messages in the console.
In the code I do:
- print "IsolateObject: ", IsolateObject
- c4d.documents.SaveDocument(newdoc, mfs, c4d.SAVEDOCUMENTFLAGS_NONE, c4d.FORMAT_C4DEXPORT)
- self.myData = mfs.GetData() and print "Data saved: ", self.myData
So, in the console I would expect:
- "IsolateObject: ", IsolateObject
- "Data saved: ", self.myData
But what I get in the console is:
- "IsolateObject: ", IsolateObject
- "WRITE myData: ", self.myData !!! This tells me that the Write function is called?
And because the write function is called before the statement self.myData = mfs.GetData(), self.myData is None! - "Data saved: ", self.myData
So the question is, why is the Write function called?
I guess it is called by c4d.documents.SaveDocument()? -
hello,
As i said, when you are isolating the object you are also isolating your tag with it.
you save the new document where your object is isolated (with a copy of your tag).
So, this "second" tag is calling the write function.if your print out the "self" you should see two different instances of your tag.
That's why you should use a
CommandData
to store the hierarchy in your tag.
And the tag to "restore" the hierarchy.Cheers,
Manuel -
@m_magalhaes, Aha, clear.
I will convert it to a Command plugin.
However, I find an issue with Isolate().
I will open another thread for that one.
Basically it is that when I isolate a Cloner, the effector is not 'copied'.For now let's close this thread.
Thanks for all the information and your patience.-Pim
-
Hi,
@m_magalhaes already explained the reason for your problem, I would just like to point out a more general misconception which does not only apply to this specific problem.
You assumption is that
NodeData.Write()
is being called once you are "ready", i.e. the user has clicked the button in the interface (I assume that message ID is a button), i.e. after a call toNodeData.Message()
. You cannot make this assumption in general with SDKs that let you interface with complex objects. Things might get called not in an order you would consider consecutive, multiple times for no apparent reason, or in the oddest situations you do not really anticipate at all. So you have to check all your inputs and outputs every time.Cheers
zipit -
@zipit, thanks for this extra information!
Indeed my assumption is / was that Write is only called, when you save the scene file.-Pim