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.

    81e6e0e2-ca35-4835-b5fe-56384e1ff9b6-image.png

    a3e58a1b-42bc-4966-a40a-7761373d8725-image.png
    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 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.

    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 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.

    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


Log in to reply