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

    Blank appearing dropdown cycle

    Cinema 4D SDK
    python macos
    2
    5
    764
    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
      HerrMay
      last edited by

      Hi guys,

      I have a problem with filling a dropdown cycle dynamically with options. Right now I’m doing this with userdata for the sake of simplicity. But in the end I want to use it in a Tag Plugin…

      So, the setup is as follows. I have a cube (just to have a dummy host object to test the code with) that holds a python tag. The python tag holds the userdata dropdown cycle with the options I want to choose from. Inside the code I swap out the entries of the dropdown cycle based on the condition whether the fillet switch of the cube is active.
      So the endgame here is to react to changes of the host object.

      While this is all nice and dandy I encounter a problem I can’t seem to resolve. When ever I switch the fillet of the cube the dropdown cycle entries are changed accordingly BUT after the switch the dropdown cycle somehow seems to remember the last selected index and tries to set an entry with this remembered index as the "selected" one. This obviously fails if the entries being switched are of different length. So the entries are there but the dropdown cycle appears so to speak blank.

      So question here is, how can I tell the dropdown cycle after the switch to select from the "new" indices. I’m probably missing something simple here.

      Cheers,
      Sebastian

      import c4d
      #Welcome to the world of Python
      
      def main():
          
          options1 = [
              "Option 1",
              "Option 2"
          ]
          
          options2 = [
              "Option 1",
              "Option 2",
              "Option 3",
              "Option 4"
          ]
          
          cube = op.GetObject()
          fillet = cube[c4d.PRIM_CUBE_DOFILLET]
          
          bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
          bc.SetString(c4d.DESC_NAME, "Options")
          bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
          
          cycle = c4d.BaseContainer()
          
          if not fillet:
              for i, option in enumerate(options1):
                  cycle.SetString(i, option)
          else:
              for i, option in enumerate(options2):
                  cycle.SetString(i, option)
          
          bc.SetContainer(c4d.DESC_CYCLE, cycle)
          op.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
          
          print op[c4d.ID_USERDATA,1]
      
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @HerrMay the issue is that the value defined for your dropdown is over the available option.
        When you do a cycle.SetString(i, option) This means the first parameter is equal to 0 but if your value for the user data is 4 and you create a DropDown that has only the value 0 and 1 then nothing will be displayed.

        To fix your issue the best way is to set the value of the dropdown (op[c4d.ID_USERDATA,1] = 0 to set the first value).
        But you need to do it only when something changed. In your case, you are rebuilding the UI each time the python script is executed, which may be not optimized at all.
        To save the state of the fillet we will use a global variable since they are frame-independent.

        import c4d
        
        global filletValue
        filletValue = None
        
        def main():
            global filletValue
            options1 = [
                "Option 1",
                "Option 2"
            ]
        
            options2 = [
                "Option 1",
                "Option 2",
                "Option 3",
                "Option 4"
            ]
        
            cube = op.GetObject()
            newFillet = cube[c4d.PRIM_CUBE_DOFILLET]
            if newFillet != filletValue:
        
                bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_LONG)
                bc.SetString(c4d.DESC_NAME, "Options")
                bc.SetInt32(c4d.DESC_CUSTOMGUI, c4d.CUSTOMGUI_CYCLE)
        
                cycle = c4d.BaseContainer()
        
                if not newFillet:
                    for i, option in enumerate(options1):
                        cycle.SetString(i, option)
                else:
                    for i, option in enumerate(options2):
                        cycle.SetString(i, option)
        
                bc.SetContainer(c4d.DESC_CYCLE, cycle)
                op.SetUserDataContainer([c4d.ID_USERDATA, 1], bc)
        
                if newFillet:
                    op[c4d.ID_USERDATA, 1] = 0
                else:
                    op[c4d.ID_USERDATA, 1] = 1
        
                filletValue = newFillet
                print op[c4d.ID_USERDATA,1]
        

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • H
          HerrMay
          last edited by

          Hi @m_adam ,

          of course, stupid me. 🤦 I knew it was something simple I’m missing here. Seems I didn’t see the elephant in the room. 😄

          This works like a charm now. Thank you!

          Allow one follow up question though. If I now want to translate this code to a TagData Plugin I’m pretty sure I don’t wanna use a global variable, do I? Would it be sufficient to make that variable a member variable inside of def __init__(self) of the Tag Plugin class?

          Cheers,
          Sebastian

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

            Yes it will 🙂

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • H
              HerrMay
              last edited by

              @m_adam alrighty got it working. 😃
              Thanks again. You can close this thread if you like.

              Cheers,
              Sebastian

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