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

    How to copy (and remove) userdata via python ?

    Cinema 4D SDK
    r19 python
    3
    8
    1.9k
    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.
    • R
      ruckzuck
      last edited by m_adam

      Hi,

      this is what I would like to achieve:

      1. copy userdata (only one vector element) from object 'b' to object 'a'
      2. remove all userdata elements from object 'a'
      3. copy userdata (only one float element) from object 'c' to object 'a'

      This is what works so far:

      Removing all userdata from object 'a':

      for id, bc in aObj.GetUserDataContainer():
         aObj.RemoveUserData(id)
      

      Copy userdata from object 'b' to 'a'

      for id, bc in bObj.GetUserDataContainer():
         aObj.SetUserDataContainer(id,bc)
      

      But here comes the problem: after I copied one userdata element (type: vector) from object 'b' to object 'a', I can't then just remove all userdata from object 'a' and then copy another userdata element (type: float) from object 'c' to (the apparently not entirely cleaned) object 'a'. It seems to me that even after the remove function the previous userdata type is still cached. As a result to this, I get this error when I try to enter any vector data to this userdata element:

      TypeError: __setitem__ expected c4d.Vector, not float
      

      When I remove all userdata manually from object 'a' using the GUI it works, but using code like "RemoveUserData" seems to be not the same. In other words: how can I replace a userdata element from type A by another element from type B using python ?

      I attached a file for testing:

      3 null objects:
      object 'b' has float userdata element
      object 'c' has vector userdata element
      object 'a' is the target object

      Select the python script tag and select the userdata tab. You can run these 3 functions:

      • remove all
      • b to a (float)
      • c to a (vector)
      1. run function "b to a (float)"
        -> float userdata element will be copied to object 'a'
      2. run function "remove all"
        -> userdata of object 'a' is gone
      3. run function "c to a (vector)"
        -> vector userdata structure is created on object 'a' but vector data can't be set:
      TypeError: __setitem__ expected float, not c4d.Vector
      
      1. check the userdata of object 'a': the gui shows the vector element but the "c to a" function can't set any vector data (?)
      2. remove the userdata of object 'a' manually and run function "c to a" again ... this time it works

      Really strange. Do I miss any additonal (update-) commands besides "RemoveUserData" in order to really remove any userdata and set new userdata types ?

      cheers,
      Jens

      0_1546388979560_userdata.c4d

      1 Reply Last reply Reply Quote 0
      • fwilleke80F
        fwilleke80
        last edited by

        My guess is (but I didn't check) that the user data entries on both objects, b and c, have the same ID. Therefore, you're copying the float value first, and then try to overwrite it with a vector. You probably have to check if a user data entry with that ID already exists, and then map the original user data id to a new one.

        www.frankwilleke.de
        Only asking personal code questions here.

        1 Reply Last reply Reply Quote 0
        • R
          ruckzuck
          last edited by ruckzuck

          I guess there is a misunderstanding: I'm not only copying the userdata values but the complete structure between the objects. And I'm doing this after I've removed ALL userdata (not only the values) from the target object before ... so there should be no reason for any mismatching types. When I'm doing the removing part manually it's working - so the question is: why is using the python command "RemoveUserData" not the same like just deleting all userdata manually via the GUI ?

          1. A is a simple null object without any userdata at all
          2. copy userdata float structure (ID=1) from B to A
            (now A has a userdata tab and a userdata float element)
          3. set float element on A (let's say to float value 10.0) ... is working
          4. removing ALL userdata elements on A (using "RemoveUserData")
            (now A should be empty like in step 1). If I check in the GUI there is no userdata anymore, the userdata tab is gone ... but my guess is that the previously existing float element is still cached internally)
          5. copy userdata vector structure (ID=1) from C to A
            (this is working and when I check in the GUI there is now a vector element in A's userdata ... BUT internally this element seems to be still a float and not a vector like the GUI is indicating)
          6. trying to set this userdata element to any vector value ... FAILED - caused by type mismatch (??)

          Again: the crucial step seems to be step 4). Removing all userdata structure manually via GUI results in no errors. But the python way via "RemoveUserData" caused the error in step 6) 😞

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by m_adam

            Hi @ruckzuck , first of all, I wish you a happy new year!

            Regarding your issue, I confirm there is an issue (I'm not sure exactly where it's located right now, either in our RemoveUserData function or either in the [] operator). I will investigate this.

            Anyway, use directly SetParameter make it works. I also did a quick rewrite of your code to clean it.

            import c4d
            
            def removeAll(obj):
                for id, bc in obj.GetUserDataContainer():
                    obj.RemoveUserData(id)
            
            def copyUserData(src, dst):
                for id, bc in src.GetUserDataContainer():
                    dst.SetUserDataContainer(id, bc)
                    dst.SetParameter(id, src[id], c4d.DESCFLAGS_SET_NONE)
            
            def main():
                a = doc.SearchObject("a")
                b = doc.SearchObject("b")
                c = doc.SearchObject("c")
                if not a or not b or not c: return
            
                copyUserData(b, a)
                removeAll(a)
                copyUserData(c, a)
            
                c4d.EventAdd()
            
            # Execute main()
            if __name__=='__main__':
                main()
            

            If you have any questions left, please let me know.
            Cheers,
            Maxime!

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            R 1 Reply Last reply Reply Quote 0
            • R
              ruckzuck @m_adam
              last edited by

              Hi @m_adam, I also wish you a happy new year!

              Thanks a lot for your workaround - this is working perfectly ☺ 👍

              Just one little correction: I guess, it's c4d.DESCFLAGS_SET_0 instead of c4d.DESCFLAGS_SET_NONE

              Cheers,
              Jens

              1 Reply Last reply Reply Quote 0
              • M
                m_adam
                last edited by

                No in R20 pretty all symbols were migrated from _0 to _NONE, for compatibility reason in python, _0 keep working as before but should be considered as deprecated.

                A note in the documentation will be added and all symbols will be updated for the R20 SP2 documentation

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 0
                • R
                  ruckzuck
                  last edited by

                  Ah ok, good to know, thanks for clarifying this - I've tested this in R19 ... but I forgot to mention that, sorry.

                  1 Reply Last reply Reply Quote 0
                  • M
                    m_adam
                    last edited by

                    Seems I also forget to mention but please use About Tags and Tagging like so you can mark a specific version.

                    MAXON SDK Specialist

                    Development Blog, MAXON Registered Developer

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