Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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
    • Recent
    • Tags
    • Users
    • Login

    Populate Userdata via Python - Please Help!

    Scheduled Pinned Locked Moved PYTHON Development
    9 Posts 0 Posters 858 Views
    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.
    • H Offline
      Helper
      last edited by

      On 08/06/2015 at 00:17, xxxxxxxx wrote:

      Hello, as a beginner of C4D Python Scripting, I'm trying to find out how to populate & dynamically a userdata (dropdown - cycle ). When user add new object/spline under specific Null - I want it automatically be added to dropdown userdata. (I'm going to use it as a Python Node in my Xpresso Setup )

      Here is my non-working terrible code;
      What I want is;

      Search null (Profiles) - Get its children names 
      Populate Userdata as Dropdown (Userdata is located in "Options" null) like 01;Profile1 02;Profile2 03;Profile3
      http://www.dropbox.com/s/9f5mwlosm6oy39v/modify_userdata.c4d?dl=0

      😢

      import c4d
      from c4d import gui
      from c4d import documents

      def GetChildren(node) :
          global names
          
          options = doc.SearchObject("Options") # This is where userdata located
          profiles = doc.SearchObject("Profiles") # Get names of children from this null 
          userdata = options.GetUserDataContainer() #The master UD container
          
          if options is None:
              print "main controls not found"
              return
          count = len(profiles.GetChildren())
          
          if (node.GetChildren() != []) :
              for child in node.GetChildren() :
                  GetChildren(child)
                  names = []
                  names = child.GetName()
                  print names
                  print count
                  nextID = len(options.GetUserDataContainer()) - 1
                  bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_STRING)
                  cc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_STRING)
                  bc[c4d.DESC_NAME] = 'Profiles'
                  bc[c4d.DESC_CUSTOMGUI] = c4d.CUSTOMGUI_CYCLE
                  #CUSTOMGUI_STRINGMULTI
                  options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
                  
      def main() :
          GetChildren(Object)

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 08/06/2015 at 08:42, xxxxxxxx wrote:

        Hi and welcome to the PluginCafe!

        Thanks for the example scene.

        What's you're missing is the initialization and the way to setup a user data container.
        If you want a dropdown cycle, this is an integer parameter. So you've to retrieve an integer default container (DTYPE_LONG). Then set the parameter to use  the CUSTOMGUI_CYCLE and initialize its values with DESC_CYCLE.
        Also, you seem to try to recursively call GetChildren() for each child of the input object. I'm not sure this is really wanted.

        Note in your XPresso Python node, 'node' and 'profiles' variables references the same object. This could lead to problems if the input object is changed in the XPresso setup.

        Here's how GetChildren() function would look like:

        def GetChildren(node) :
            global names
            
            options = doc.SearchObject("Options")     # This is where userdata located
            
            if options is None:
                print "main controls not found"
                return
            
            children = node.GetChildren()
            count = len(children)
            
            # Create and initialize user data container for an integer for the children
            bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
            bc.SetString(c4d.DESC_NAME, node.GetName())
            bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
            bc.SetInt32(c4d.DESC_MIN, 0)
            bc.SetInt32(c4d.DESC_MAX, count-1)
            
            # Create a container for the dropdown cycle values
            cycle = c4d.BaseContainer()
            
            for index in range(0, count) :
                child = children[index]
                cycle.SetString(index, child.GetName())
            
            # Set cycle values container
            bc.SetContainer(c4d.DESC_CYCLE, cycle)
            
            # Set container for children user data cycle parameter
            options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
            
            names = ""
        
        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 20/06/2015 at 12:49, xxxxxxxx wrote:

          Hello,
          Thanks for the answer, it worked:)

          But now I have realized that my specific userdata should be in another userdata group. 
          It changes default Userdata group automatically. But I could not find how to access another userdata group..
          Really searched on net but could not find any info. As I said I'm just a beginner:)

          Again my scene;
          https://www.dropbox.com/s/etmln6e7esvtnp1/modify_userdata_another_group.c4d?dl=0

          😢

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 17/07/2015 at 02:48, xxxxxxxx wrote:

            Hi,

            Sorry for the late reply.

            To set the parent group for a user data assign DESC_PARENTGROUP. This value in the description container accepts a DescID and has to be setup like this:

            parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(theGroupID, c4d.DTYPE_GROUP, 0))
            bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
            

            theGroupID is the ID number for the group (4 in your example scene).

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 17/07/2015 at 05:52, xxxxxxxx wrote:

              Hi Yannick,
              Thank you for your answer;
              (Sorry If I am asking so many question, trying to learn...)

              What I am doing wrong? I've added your last strings but still it's not working.

              Script By Yannick Puech

              import c4d
              from c4d import gui
              from c4d import documents

              def GetChildren(Object) :
                  global names
                  
                  options = doc.SearchObject("Options")     # This is where userdata located
                  
                  if options is None:
                      print "main controls not found"
                      return
                  
                  children = Object.GetChildren()
                  count = len(children)
                  
                  # Create and initialize user data container for an integer for the children
                  bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
                  bc.SetString(c4d.DESC_NAME, Object.GetName())
                  bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
                  bc.SetInt32(c4d.DESC_MIN, 0)
                  bc.SetInt32(c4d.DESC_MAX, count-1)
                  parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(4, c4d.DTYPE_GROUP, 0))
                  bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
                  # Create a container for the dropdown cycle values
                  cycle = c4d.BaseContainer()
                  
                  for index in range(0, count) :
                      child = children[index]
                      cycle.SetString(index, child.GetName())
                  
                  # Set cycle values container
                  bc.SetContainer(c4d.DESC_CYCLE, cycle)
                  
                  # Set container for children user data cycle parameter
                  options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
                  
                  names = ""
                  
              def main() :
                  GetChildren(Object)

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 17/07/2015 at 06:17, xxxxxxxx wrote:

                Hi I think I've done finally:)
                Thanks a lot Yannick, I have placed it inside Python Tag.
                And if anyone intrested ;

                Script By Yannick Puech

                import c4d
                from c4d import gui
                from c4d import documents

                def GetChildren() :
                    global names
                    profiles = doc.SearchObject("Profiles")   # Null name contains children objects
                    options = doc.SearchObject("Options")     # This is where userdata located   
                    if options is None:
                        print "main controls not found"
                        return
                    
                    children = profiles.GetChildren()
                    count = len(children)
                    
                    # Create and initialize user data container for an integer for the children
                    
                    bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
                    
                    bc.SetString(c4d.DESC_NAME, profiles.GetName())
                    bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
                    bc.SetInt32(c4d.DESC_MIN, 0)
                    bc.SetInt32(c4d.DESC_MAX, count-1)
                    parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(4, c4d.DTYPE_GROUP, 0))# 4 is my secondary Group ID
                    bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
                    # Create a container for the dropdown cycle values
                    cycle = c4d.BaseContainer()
                    for index in range(0, count) :
                        child = children[index]
                        cycle.SetString(index, child.GetName())
                    # Set cycle values container
                    bc.SetContainer(c4d.DESC_CYCLE, cycle)
                    # Set container for children user data cycle parameter
                    options.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
                    
                    names = ""
                    
                def main() :
                    
                    GetChildren()

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 17/07/2015 at 06:22, xxxxxxxx wrote:

                  Btw I've noticed that as I paste this code in my real project It deletes my current other options userdata. 
                  Is there a way to add or modify directly without deleting or recreating other userdatas ?

                  In my case my group ID is 2 and drop down list should be in userdata with ID 13 for example.

                  This is last step Yannick, please do me a favor last time:)))

                  Thanks a lot again.

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    On 17/07/2015 at 07:28, xxxxxxxx wrote:

                    To add a user data use BaseList2D.AddUserData().
                    To modify a user data retrieve its description container with BaseList2D.GetUserDataContainer() and set it back with BaseList2D.SetUserDataContainer().

                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      On 17/07/2015 at 08:44, xxxxxxxx wrote:

                      I'm again confused, according to my previous example I tried to add getuserdatacontainer and setuserdatacontainer...But it's still not working...
                      (In this example my group ID is 1 and drop down cycle UD id is 13, I only need to modify it, it already exists...Sorry again as a beginner it's so confusing...)

                      Script By Yannick Puech

                      import c4d
                      from c4d import gui
                      from c4d import documents

                      def GetChildren() :
                          global names
                          profiles = doc.SearchObject("Profiles")   # Null name contains children objects
                          options = doc.SearchObject("Options")     # This is where userdata located   
                          if options is None:
                              print "main controls not found"
                              return
                          
                          children = profiles.GetChildren()
                          count = len(children)
                          
                          # Create and initialize user data container for an integer for the children
                          bc = options.GetUserDataContainer()
                          bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
                          
                          bc.SetString(c4d.DESC_NAME, profiles.GetName())
                          bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
                          bc.SetInt32(c4d.DESC_MIN, 0)
                          bc.SetInt32(c4d.DESC_MAX, count-1)
                          parentGroup = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(1, c4d.DTYPE_GROUP, 0))
                          bc.SetData(c4d.DESC_PARENTGROUP, parentGroup)
                          
                          cycle = c4d.BaseContainer()
                          for index in range(0, count) :
                              child = children[index]
                              cycle.SetString(index, child.GetName())
                          
                          bc.SetContainer(c4d.DESC_CYCLE, cycle)
                          # Set container for children user data cycle parameter
                          options.SetUserDataContainer([c4d.ID_USERDATA,13], bc)
                          
                          names = ""
                          
                      def main() :
                          
                          GetChildren()

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