SOLVED Some basic questions on BaseContainer

Hi all,

I'd like to ask a few questions to establish the basics on using basecontainers.

  1. How to use the Unique ID? The SDK says if we store something in the Top Level we need it. Let's say want to store a value in an object's base container, is the following example correct?
uniqueID = 12345
bc = c4d.BaseContainer()
bc[12345] = "My new value"
obj.SetData(bc, True)

There's nothing really stopping anyone from overwriting this id, so I was wondering if this is how the unique id is being used.

  1. Are the types of values we can store in the base container limited? I tried to store a list, a tuple and a dictionary and it always fails. Here's an example:
bc = c4d.BaseContainer()
bc[12345] = (1,2,3,4,5)
    
obj.SetData(bc, True)
print (op.GetData())

This produces this error:

TypeError: could not convert 'tuple'
  1. In the SDK sub-containers are mentioned. Is the following code the correct way of using subcontainers?
bc = c4d.BaseContainer
subContainer = c4d.BaseContainer
subcontainer[0] = "My subcontainer value"

bc[12345] = subcontainer

Thanks in advance

Hi Orestis hope you are fine 🙂

  1. Unique ID are registered in plugincafe. The only purpose is to be sure to not override existing data, but it's true there is nothing in the API preventing any other developer to not read/override the value you defined. But it's a good practice that every developer follow.

  2. Correct only Cinema 4D Datatype can be used. To be more precise, only type registered with RegisterCustomDataType In C++. This registered type can then be stored within a GeData (GenericData) that can be handle by a BaseContainer.
    There is the method BaseContainer.GetType to inform you about the type of a value, and you can look at DTYPE enum to find some possible value, but again since any registered Custom Datatype can be used, this is not an exhaustive list.

  3. Correct 🙂

Cheers,
Maxime.

Hi @orestiskon,

From what I learnt recently, if you have more than one data to store, you can create a sub container of the base container identified by the pluginID.

I can't remember where I read that... just be careful I'm not an advanced C4D developer 😉

In a class for a BaseTag I use this like that,

        self.bcDATAS = c4d.BaseContainer()
        self.bcDATAS[ myData ] = "A string for example"
        # Be sure to use a unique ID obtained at https://plugincafe.maxon.net/c4dpluginid_cp
        myPLUGIN_ID = 0123456789 

        # Get the Document Settings BaseContainer
        self.bcDoc = doc.GetDocumentData( c4d.DOCUMENTSETTINGS_DOCUMENT )
        self.bcDoc[ myPLUGIN_ID ] = self.bcDATAS # Store plugin container inside the document container

        # Save the updated Document BC
        op.SetData( self.bcDoc )
        
        # To retrieve a data
        print ( op.GetData()[ myPLUGIN_ID ][ myData ] )

Cheers,

Christophe

@m_adam Thanks for the information Maxime.

@mocoloco interesting example, I didn't think about the document. I have a question:

# Save the updated Document BC
        op.SetData( self.bcDoc )

Shouldn't that be:

doc.SetData(bcDoc)

Also, any reason you're using "self" before each variable?

@orestiskon, self is used because the example is an extract of a class. In my case, those variables are defined in the def __init__ (self):, and belongs to the class object. They are not globals. Have a look there, https://docs.python.org/3/tutorial/classes.html you will understand it with a much better explanation than mine.

If you plan to do not use that inside a class, you can get rid of self of course. Just be careful of doc and op used here below as they are arguments of def Execute(self, tag, doc, op, bt, priority, flags): used in my BaseTag plugin.

Knowing this, I assume you can easily transpose this to your purpose as the following example won't work as it is 😉

bcDATAS = c4d.BaseContainer()
bcDATAS[ myData ] = "A string for example"
# Be sure to use a unique ID obtained at https://plugincafe.maxon.net/c4dpluginid_cp
myPLUGIN_ID = 0123456789 

# Get the Document Settings BaseContainer
bcDoc = doc.GetDocumentData( c4d.DOCUMENTSETTINGS_DOCUMENT )
bcDoc[ myPLUGIN_ID ] = bcDATAS # Store plugin container inside the document container

# Save the updated Document BC
op.SetData( bcDoc )
        
# To retrieve a data
print ( op.GetData()[ myPLUGIN_ID ][ myData ] )

Hello @orestiskon,

without any further replies or questions, we will consider this thread as solved by Thursday and flag it accordingly.

Thank you for your understanding,
Ferdinand

Thanks Ferdinand, I'll mark this as solved.

Hi @orestiskon,

thank you for flagging the topic as answered.

Cheers,
Ferdinand