Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    GetUserDataContainer() and UserData Values

    Cinema 4D SDK
    3
    9
    1.4k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • indexofrefractionI
      indexofrefraction
      last edited by indexofrefraction

      Hi, this is about some basic undestanding...

      i can get a BaseList2D UserData Container like this
      udc = op.GetUserDataContainer()
      which is a list of DescID / BaseContainer tuples

      now... is it possible to get the actual UserData values out of this without having the BaseList2D?
      or are they not stored directly in these BaseContainers?

      background is that i save the udc to a HyperFile and restore/clone it back to different objects.

      best, Index

      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by ferdinand

        Hi,

        I am not sure that I do follow the question. What do you mean by `without having the BaseList2D'? When you can access the description of the node, you have access to the node, so I am a bit confused. But no, the description does not store the values, they are in the data container of the node.

        You can iterate over the description of a node with c4d.C4DAtom.GetDescription. GetUserDataContainer is basically just a thin wrapper around that, which skips all
        non-user data elements. To access all user data of a node (of unknown count) you can do this:

        import c4d
        
        # Goes over the first 1000 user data indices.
        for eid in range(1, 1001):
            try:
                print op[c4d.ID_USERDATA, eid]
            except AttributeError:
                # Will be raised when you try to access a non-existing element.
                pass
        

        Cheers,
        zipit

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • indexofrefractionI
          indexofrefraction
          last edited by indexofrefraction

          hi zipit,

          ok, so GetUserDataContainer() is only the Description, I already thought so.
          but what does it mean when you say about the values "they are in the data container of the node"?
          I know you get the value by op[c4d.ID_USERDATA, id] but are those values stored in the bc you get by op.GetData() ?
          Is there a way to get all values in a bc without iterating through the indexes?
          Where does c4d.ID_USERDATA point to?

          🙂 index

          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by

            hi,

            You can also use the function GetParameter to retrieve the value for the parameter.
            Using GetParameter/SetParameter assure you to retrieve the value. Not all value are stored in the BaseContainer of the object.

            def main():
                udc = op.GetUserDataContainer()
                for data in udc:
                    print (op.GetParameter(data[0] ,c4d.DESCFLAGS_GET_NONE ))
            

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • indexofrefractionI
              indexofrefraction
              last edited by indexofrefraction

              hm ok, I dont understand where they are stored, but it seems there is no bc on the baselist2d holding the values
              i have to fetch them by using the ids in the description, add them to a new bc and then save it along with the description
              (if i want a hyperfile holding the description and the values)

              1 Reply Last reply Reply Quote 0
              • indexofrefractionI
                indexofrefraction
                last edited by indexofrefraction

                ok, I think I figured it out :

                op[c4d.USERDATA, id] is the same as op.GetData()[c4d.USERDATA][id]

                the UserData values are stored in a sub BaseContainer of op.GetData() with the id c4d.USERDATA=700

                so to store all values of a BaseList2D into a HyperFile :
                hf.WriteContainer(op.GetData()[c4d.USERDATA])

                ... EDIT:
                interesting is that even though the UserData in the GUI shows 0 for a freshly added integer
                op.GetData()[c4d.USERDATA] doesnt have it unless you actually have pressed enter in the input field in the GUI.
                so op.GetData()[c4d.USERDATA] is NOT reliable to have all values
                for a freshly added id :
                op[c4d.USERDATA,17] # 0
                op.GetData()[c4d.USERDATA][17] # nuthin' 😕

                anyway, topic solved, i guess...
                (where can you set that yourself? its not in the topic tools)

                1 Reply Last reply Reply Quote 0
                • ManuelM
                  Manuel
                  last edited by Manuel

                  hi,

                  brackets are aliases to the function GetParameter, see getitem for a GeListNode
                  While op.GetData return a copy of the BaseContainer. (from BaseList2D)

                  (by the way it's c4d.ID_USERDATA that is equal to 700.

                  so op[c4d.ID_USERDATA, id] is NOT the same as op.GetData()[c4d.ID_USERDATA][id]

                  For what i see, for object, UserData are not stored in the object's BaseContainer but in some internal data.

                  Can you share a scene to let me understand why it's working on your case ?

                  about the forum:
                  you first need to mark this thread as "ask a question" to access the "mark as solved" or "mark this thread as then answer" option
                  See this thread for more information.

                  Cheers,
                  Manuel

                  MAXON SDK Specialist

                  MAXON Registered Developer

                  1 Reply Last reply Reply Quote 0
                  • indexofrefractionI
                    indexofrefraction
                    last edited by indexofrefraction

                    thanks, manuel,

                    right, c4d.ID_USERDATA .-)
                    but this works here, I just verified again :

                    create any object, add some userdata, lets say an integer with id = 1
                    op[c4d.ID_USERDATA, 1] # 0
                    op.GetData()[c4d.ID_USERDATA][1] #
                    op[c4d.ID_USERDATA, 1] = 123 # 123
                    op.GetData()[c4d.ID_USERDATA][1] # 123 <-- you need to set the value, first (by gui or code)

                    op.GetData() is a BaseContainer having a sub-BaseContainer with id=700,
                    so i suppose this is where the values are stored, after they have been set.
                    if they have not been set, op[c4d.ID_USERDATA, 1] seems to return the default value from the description.

                    but its kind of useless, because you need to iterate the description anyway to be sure to get all values
                    problem there is that if you iterate the description there are also ids for groups, separators (and other stuff?)
                    which are not (changeable) values, so you have to filter these out.

                    best, index

                    1 Reply Last reply Reply Quote 0
                    • ManuelM
                      Manuel
                      last edited by m_adam

                      hi,

                      ha, i was not setting any value. So yes, they are in the BaseContainer at id c4d.ID_USERDATA (=700)

                      to filter the groups or separator you just have to check the type in the descLevel and compare with DTYPE_SEPARATOR or DTYPE_GROUP or either use DescId.IsPartOf like:

                          for descId, parameterBc in op.GetUserDataContainer():
                              print(c4d.DESCID_DYNAMICSUB.IsPartOf(descId)) # Will print True for all of them
                      

                      Cheers,
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post