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

    Update in UD link does not update object in Volume Builder Object List

    Cinema 4D SDK
    python r20
    2
    5
    1.3k
    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.
    • SwinnS
      Swinn
      last edited by

      I am trying to automatically update the object list in a Volume Builder. I am using a User Data link. When I drop a new object in the UD link field, the object in the Volume Builder list does not update. Is there a way to do this? Below is the code I am using:

      import c4d
      from c4d.modules import volume
      import pprint
      from c4d import documents
      from c4d import utils
      
      
      Bake_Button = 240
      
      obj = op.GetObject()
      #obj = doc.SearchObject("Spritz 4.0")
      UD = obj.GetUserDataContainer()
      
      bottle = obj[c4d.ID_USERDATA,5]
      set_bottle = 242
      delete_bottle = 243
      
      document = op.GetDocument()
      settings = c4d.BaseContainer()
      selected = doc.GetActiveObjects(0)
      taglist = doc.GetActiveTags()
      
      presets = obj[c4d.ID_USERDATA,13]
      drop_name = obj[c4d.ID_USERDATA,197]
      
      
      
      
      def set_delete_UD_object():
      
          vol_build = doc.SearchObject("VB Drops")
          vol_build_drip_1 = doc.SearchObject("VB Drip 1")
      
          if obj[c4d.ID_USERDATA, set_bottle] == 1:
              vol_build.AddSceneObject(bottle, index = 0)
              vol_build.SetBoolMode(0, 2)
              vol_build_drip_1.AddSceneObject(bottle, index = 0)
              vol_build_drip_1.SetBoolMode(0, 2)
      
              obj[c4d.ID_USERDATA, set_bottle] = False
              for descId, container in UD: # SET Object hide
                  if descId[1].id == 266:
                      container[c4d.DESC_HIDE] = True
                      obj.SetUserDataContainer(descId, container)
      
              for descId, container in UD: # DELETE Object show
                  if descId[1].id == 267:
                      container[c4d.DESC_HIDE] = False
                      obj.SetUserDataContainer(descId, container)
      
      
          if obj[c4d.ID_USERDATA, delete_bottle] == 1:
                  vol_build.RemoveObject(0)
                  vol_build_drip_1.RemoveObject(0)
      
                  obj[c4d.ID_USERDATA, delete_bottle] = False
                  for descId, container in UD: # SET Object show
                      if descId[1].id == 267:
                          container[c4d.DESC_HIDE] = True
                          obj.SetUserDataContainer(descId, container)
      
                  for descId, container in UD: # DELETE Object hide
                      if descId[1].id == 266:
                          container[c4d.DESC_HIDE] = False
                          obj.SetUserDataContainer(descId, container)
      
      def main():
      
          set_delete_UD_object()
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @Swinn no worries, but please make sure to use Q&A functionality 😉.

        According to your description, I made my own setup, with a Null which gets a userData link. Then I attach a python script to this Null object.
        I also created a Volume Builder called Volume Builder. Using the following code it's working as expected.

        import c4d
        from c4d.modules import volume
        
        def main():
            # Get the host object and the linked obj from the user data
            obj = op.GetObject()
            linkedObj = obj[c4d.ID_USERDATA,1]
            if not linkedObj: return
        
            # Get the volume builder
            vBuilder = doc.SearchObject("Volume Builder")
            if not vBuilder and not vBuilder.CheckType(c4d.Ovolumebuilder): return
        
            # Check if our object is not already in the list
            allowedObj = [linkedObj] # Maybe you got some other object you don't want to delete
            alreadyIn = False
            for i in xrange(0, vBuilder.GetListEntryCount()):
                o = vBuilder.GetInputObject(i)
        
                # If is not in our list of allowed objects we remove it
                if o not in allowedObj:
                    vBuilder.RemoveObject(i)
                
                # If our linked object is already in the list
                if o == linkedObj:
                    alreadyIn = True
                
            # Only add if the object is not already in the list
            if not alreadyIn:
                vBuilder.AddSceneObject(linkedObj)
                vBuilder.SetBoolMode(0, 2)
        

        Maybe you can try to reduce your code. Moreover, it looks like you are adding and deleting the bottle at the same time.

        Additionally, I would not recommend you to define variables in global space of the script but rather in local space of your function.

        if you have any question, please me know!
        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • SwinnS
          Swinn
          last edited by m_adam

          This is starting to work but it now adds 2 user data objects. As well, do I need to add an event to get a refresh? Also, I am trying to move the linked user data object to the top of the hierarchy but it doesn't want to go there. And finally, MIST Cloner and SMALL DROPS Cloner keep switching places.

          import c4d
          from c4d.modules import volume
          
          def main():
              # Get the host object and the linked obj from the user data
              obj = op.GetObject()
              linkedObj = obj[c4d.ID_USERDATA,5]
              if not linkedObj: return
          
              # Get the volume builder
              vBuilder = doc.SearchObject("VB Drops")
              if not vBuilder and not vBuilder.CheckType(c4d.Ovolumebuilder): return
          
              # Check if our object is not already in the list
              allowedObj = [linkedObj] # Maybe you got some other object you don't want to delete
              alreadyIn = False
              for i in xrange(0, vBuilder.GetListEntryCount()):
                  o = vBuilder.GetInputObject(i)
          
                  # If is not in our list of allowed objects we remove it
                  if o not in allowedObj:
                      vBuilder.RemoveObject(i)
          
                  # If our linked object is already in the list
                  if o == linkedObj:
                      alreadyIn = True
          
              # Only add if the object is not already in the list
              if not alreadyIn:
                  vBuilder.AddSceneObject(linkedObj, index = 0)
                  vBuilder.SetBoolMode(0, 2)
          

          I have added index = 0 to your code but it doesn't seem to work.

          0_1539033606921_CINEMA 4DScreenSnapz008.jpg

          0_1539033625748_CINEMA 4DScreenSnapz009.jpg

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

            Hi @Swinn, if you add another object through another UserData link, then you have to properly insert it, and keep track of it inside the volume builder as well and handle the "refresh" yourself as I demonstrated in my previous example.
            Since you are doing it for more than one object, in my previous example I used a variable called alreadyIn, to keep track of my object. But it was a very simple example.
            If you are switching to multiple objects, it may be worth making a data structure where you hold the objects, and if these are already inserted or not, in order to be able to track your objects properly.

            In the end this is probably more an algorithmic problem, and not that much API related. Thus we as the SDK Team can only give advice and suggest a direction.

            Moreover, in your code, I don't see any link to the new UserData link. And you are still deleting 'BIG DROPS CLONER' and all others custom cloners you have in your image. Are you sure you use the same code than the one you posted?

            Furthermore vBuilder.AddSceneObject(linkedObj, index = 0) respects the order, with index parameter set to zero linkedObj will be correctly inserted at the top of the list.

            Cheers,
            Maxime!

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            SwinnS 1 Reply Last reply Reply Quote 1
            • SwinnS
              Swinn @m_adam
              last edited by

              @m_adam Cool. Thank-you for your time and patience. ☺

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