I try to save an object (using IsolateObjects()) using the Tag plugins Write() function.
Here the code:
myData = None
def Write(self, node, HFfile):
print "WRITE myData: ", self.myData
# Store the size
# Store the data itself
if HFfile.WriteMemory(self.myData) is False:
raise ValueError("can't write the file")
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()
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?
well, you answered your question yourself. You are trying to index myData with the bracket syntax (i.e. invoke __getitem__) which causes an excpetion when myData is None. You have to test first, if the class dictionary of myData contains __getitem__, or more straight forward - if it is not of type None.
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
Even if i still think a generator should work better.
@zipit, The strange thing is the sequence of things / of messages in the console.
In the code I do:
So, in the console I would expect:
But what I get in the console is:
So the question is, why is the Write function called?
I guess it is called by c4d.documents.SaveDocument()?
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.
@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.
@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 to NodeData.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.
@zipit, thanks for this extra information!
Indeed my assumption is / was that Write is only called, when you save the scene file.