Writing data to the .c4d file
-
@zipit Thanks for the explanation of the data structure (and the code for clarity).
I tried my best to get it working, but it's still not printing the data. I'm not sure if it was intentional, but I changed the line
print_container(doc.SetDocumentData(ID_MY_SECRET_COOKING_RECIPES))
as it was throwing an error for not passing a BaseContainer. Did you mean?
print_container(doc.GetDocumentData(ID_MY_SECRET_COOKING_RECIPES))
Regardless it's the same issue where it does see the BaseContainer in the print function, but cannot iterate through it.
import c4d ID_MY_SECRET_COOKING_RECIPES = 2999999 ID_TITLE = 1008 ID_DATA = 1009 ID_INSTRUCTIONS = 1010 def print_container(bc): for cid, value in bc: print cid, value if isinstance(value, c4d.BaseContainer): print_container(value) def main(): doc = c4d.documents.GetActiveDocument() # Your settings container bc = c4d.BaseContainer() # One level of your container, we treat this like a list/folder folder = c4d.BaseContainer() # One item in your folder recipe_1 = c4d.BaseContainer() # Another item in your folder recipe_2 = c4d.BaseContainer() bc[ID_TITLE] = 'My Cooking recipes' bc[ID_DATA] = folder folder[1000] = recipe_1 folder[1001] = recipe_2 recipe_1[ID_TITLE] = 'Choclate delight' recipe_1[ID_INSTRUCTIONS] = 'Lorem Ipsum ...' recipe_2[ID_TITLE] = 'Cheesekake' recipe_2[ID_INSTRUCTIONS] = 'Lorem Ipsum ...' doc.SetDocumentData(ID_MY_SECRET_COOKING_RECIPES, bc) print_container(doc.GetDocumentData(ID_MY_SECRET_COOKING_RECIPES)) if __name__=='__main__': main()
-
Not sure if this matters, but my ultimate goal would be to save JSON data in the BaseContainer.
-
Hello,
The function SetDocumentData can only be used to update the document settings.
It does accept an Int as a "type" but if you put something else than
DOCUMENTSETTINGS_GENERAL
DOCUMENTSETTINGS_MODELING
DOCUMENTSETTINGS_DOCUMENT
DOCUMENTSETTINGS_ANIMATIONSYSTEM
the function will simply do nothing. (and the last one is marked as private)BaseContainer is a tree system, you can see sub-BaseContainer just like a child object in the object manager.
So you can have (infinite ?) BaseContainer inside BaseContainer.If you want to store json data, it's up to you. You can store all elements of your json data or simply store a string.
import c4d PLUGIN_ID = 1234567 MyUniqueId = 456789 def main(): #retrieves the document baseContainer docBC = doc.GetDataInstance() #create a sub-BaseContainer subBc = c4d.BaseContainer() subBc[1000] = "hello" subBc[2000] = "world!" # Add the container to the "main" Container docBC.SetContainer(MyUniqueId, subBc) # Updates the document container doc.SetData(docBC) # Print the values stored in our container. for cid, value in doc.GetDataInstance().GetContainer(MyUniqueId): print cid, value # Print Hello World print doc[MyUniqueId][1000], doc[MyUniqueId][2000] if __name__=='__main__': main()
Cheers,
Manuel -
@m_magalhaes Hi Manuel and thank you for this contribution. This code's data, however, is not persisting when I do the following:
- run the script to set the data
- close and reopen the document.
- comment out the lines setting the data (lines 11-19)
- run the script to print the data
Instead I get this error for
doc[MyUniqueId]
:TypeError: 'NoneType' object has no attribute '__getitem__'
Also, is MyUniqueId supposed to be the PLUGIN_ID? Why is that not being used?
Thanks!
-
@blastframe For me, it works fine this way. Did you really "close and reopen" the document? Not "save", "close", "load"? Because if you just close the document, the data from the container is gone, which leads to your error message.
The Q regarding MyUniqueId vs. PLUGIN_ID is not relevant (probably typed in a hurry), you can use either. But the ID value should come from Maxon in the end, so you avoid collisions with existing IDs.
-
-
hi,
you could use the same ID, you just have to be sure that you are the only one to use that ID to store datas.
That's why we use plugin's ID.Cheers
Manuel. -
@m_magalhaes Thanks, Manuel.
How would I delete the data of an individual sub-BaseContainer in the case of your script?
I've tried several methods below but the
doc[MyUniqueId][1000]
still shows data in theprint
call.bc = doc.GetDataInstance().GetContainer(MyUniqueId) print bc.RemoveData(1000) # True print doc[MyUniqueId].RemoveData(1000) # True doc[MyUniqueId].FlushAll() print doc[MyUniqueId][1000] #hello
I was able to delete all of the data this way, but what if I want to keep the data in
subBc[2000]
?docBC.RemoveData(MyUniqueId)
Thank you!
-
hello,
there's a difference between GetContainer and GetContainerInstance
The first return a copy of the container the second the original link.
So either you retrieve a copy and set back the container to the parent withSetData
and/orSetContainer
or you retrieve the original link and the changes are reflected immediately.You can also use
del
that is pythonicbc = doc.GetDataInstance().GetContainerInstance(MyUniqueId) bc.RemoveData(2000) #del (bc[2000])
Cheers,
Manuel -
@m_magalhaes said in Writing data to the .c4d file:
You can also use
del
that is pythonicbc = doc.GetDataInstance().GetContainerInstance(MyUniqueId) bc.RemoveData(2000) #del (bc[2000])
Wonderful, @m_magalhaes , thank you so much!