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

    Dialog Menu

    Cinema 4D SDK
    python
    3
    6
    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.
    • J
      Joel
      last edited by

      Hi,
      I have two dialogs in different python scripts and I would like to join them in a single python script so the user via buttons can choose what dialog to show.

      I tried searching the forums as well as reading the documentation but I have not been able to find a starting guide to solve this issue.

      Does anyone have an idea how I could achieve a solution to this problem?

      Thanks so much for your time.

      ferdinandF 1 Reply Last reply Reply Quote 0
      • M
        mogh
        last edited by mogh

        EDIT:
        Sorry this was not what I thought I have a dual Dialog example somewhere but not at hand ...

        *This is an Subdialog Example from the SDK.

        Github Subdialog

        hope that is in line what you are searching.*
        Cheers mogh

        1 Reply Last reply Reply Quote 1
        • ferdinandF
          ferdinand @Joel
          last edited by ferdinand

          Hello @joel,

          thank you for reaching out to us. I am a bit confused about the nature of your question; when you have implemented two dialogs, you should be able to do this on your own.

          Interpreting your question in the most straight forward way, you have two dialogs A and B and want the user to be able to open either of them from a single script. You then must simply implement a dialog C with two buttons which open the respective dialogs. When you attach the dialog instances A and B to C you can also add some logic which would prevent users from opening multiple instances of A or B or opening A and B at the same time.

          Then there are multiple interpretations of your question which are less literal.

          • As pointed out by @mogh (thanks!), there is the concept of sub-dialogs in Cinema 4D. This effectively just means that the content of one ore multiple dialogs can be rendered within a hosting dialog. See GeDialog.AddSubDialog for a point of entry to the concept in the API. There are also two C++ and two Python code examples making use of this concept.
          • There is also the tab gadget with which you can structure larger groups of disjunct UI elements in a singular dialog. See GeDialog.TabGroupBegin for a point of entry. There exist only C++ Code examples for this gadget, although using it in Python is perfectly possible.
            3bb20552-58ca-4fce-b551-ff923ba3ab3a-image.png
          • You could also use three layout groups in a singular dialog, let's call them A, B, and C. A and B contain the layout of two dialogs as in the prior example. C also contains two buttons as in the prior example. You then add the groups in the order C, A, and B to a singular dialog. When the user presses a button in C, you hide and unhide the groups A and B using GeDialog.HideElement, so that the user sees only one of them at a time.
            • You can also dynamically rebuild the whole GUI at runtime, but that should not be necessary in this case. Find an example here.
          • This is more of an academic point, since it seems unlikely to me that you are using a dialog resource. But when you have defined two dialog resources RA and RB, nothing prevents you from (a.) loading them both into their seperate dialog but also (b.) into a singular dialog by simply calling GeDialog.LoadDialogResource twice in succession.
          ⚠ Script Manager scripts are not meant to have extensive GUIs. While one can make things work, it is easier and safer to wrap things into a CommandData plugin. You will need a plugin ID which you can get here on the forum with the plug icon in the top menu bar. The plugin itself is then straight forward, you can ignore the CommandData stuff and reuse the code in the dynamic dialog GUI example which I have posted above; the only thing you would have to change are the Plugin ID and the name of the plugin.

          Cheers,
          Ferdinand

          MAXON SDK Specialist
          developers.maxon.net

          1 Reply Last reply Reply Quote 0
          • J
            Joel
            last edited by

            I tried using the subdialog as the github example shows. If I just want to do one subdialog change the github example that @mogh posted works just find. However when I add another button so I can switch between the subdialogs the Dialog does not update.

            The code I used is a bit modified from the github but more or less the same:

            import c4d
            from c4d import gui
            
            ID_SUBDIALOG = 10000
            ID_Dialog1_BUTTON = 10001
            ID_Dialog2_BUTTON = 10002
            
            class Dialog1(c4d.gui.SubDialog):
                def CreateLayout(self):
                    self.AddStaticText(1, c4d.BFH_SCALEFIT, 0, 0, "Dialog 1")
                    return True
            
            class Dialog2(c4d.gui.SubDialog):
                def CreateLayout(self):
                    self.AddStaticText(1, c4d.BFH_SCALEFIT, 0, 0, "Dialog 2")
                    return True
            
            class MainDialog(c4d.gui.GeDialog):
                subDialog = Dialog1()
                
                def CreateLayout(self):
                    self.GroupBegin(0, c4d.BFH_SCALEFIT, 2)
                    self.AddButton(ID_Dialog1_BUTTON, c4d.BFH_SCALEFIT, name="Dialog1")
                    self.AddButton(ID_Dialog2_BUTTON, c4d.BFH_SCALEFIT, name="Dialog2")
                    self.GroupEnd()
                    
                    self.AddSubDialog(ID_SUBDIALOG, c4d.BFH_SCALEFIT, 100, 100)
                    self.AttachSubDialog(self.subDialog, ID_SUBDIALOG)
                    
                    return True
                
                def Command(self, mid, msg):
                    if mid == ID_Dialog1_BUTTON:
                        self.subDialog = Dialog1()
                        self.AttachSubDialog(self.subDialog, ID_SUBDIALOG)
                        print(self.LayoutChanged(ID_SUBDIALOG))
                    if mid == ID_Dialog2_BUTTON:
                        self.subDialog = Dialog2()
                        self.AttachSubDialog(self.subDialog, ID_SUBDIALOG)
                        print(self.LayoutChanged(ID_SUBDIALOG))
                    return True
            
            if __name__=='__main__':
                dlg = MainDialog()
                dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=900, xpos=-2, ypos=-2)
            

            When I click the buttons the first button click from either button the LayoutChanged returns True but on the second button click from either button returns False.

            What am I doing wrong?

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

              Hey @joel,

              you are running there in a fringe ownership error of the dialog object. You must create a dummy reference to the dialog before you overwrite the instance bound reference self.subDialog to avoid a race condition between the GC and C4D which is still using the dialog. Or what I would recommend - keep two dialog instances around, as this code looks then more sane to me.

              Find below a fix.

              Cheers,
              Ferdinand

              import typing
              import c4d
              from c4d import gui
              
              ID_SUBDIALOG = 10000
              ID_Dialog1_BUTTON = 10001
              ID_Dialog2_BUTTON = 10002
              
              class Dialog1(c4d.gui.SubDialog):
                  def CreateLayout(self):
                      self.AddStaticText(1, c4d.BFH_SCALEFIT, 0, 0, "Dialog 1")
                      return True
              
              class Dialog2(c4d.gui.SubDialog):
                  def CreateLayout(self):
                      self.AddStaticText(1, c4d.BFH_SCALEFIT, 0, 0, "Dialog 2")
                      return True
              
              class MainDialog(c4d.gui.GeDialog):
                  """
                  """
                  def __init__(self) -> None:
                      """
                      """
                      # You made your subDialog attribute class bound but then later used it as instance bound.
                      # I assume that was an oversight and you did not want the sub dialog to be class bound but
                      # instance bound.
                      self._dlg1: Dialog1 = Dialog1() # Dialog instance for type 1
                      self._dlg2: Dialog2 = Dialog2() # Dialog instance for type 2
              
                  def CreateLayout(self):
                      self.GroupBegin(0, c4d.BFH_SCALEFIT, 2)
                      self.AddButton(ID_Dialog1_BUTTON, c4d.BFH_SCALEFIT, name="Dialog1")
                      self.AddButton(ID_Dialog2_BUTTON, c4d.BFH_SCALEFIT, name="Dialog2")
                      self.GroupEnd()
                      self.AddSubDialog(ID_SUBDIALOG, c4d.BFH_SCALEFIT, 100, 100)
                      return True
              
                  def Command(self, mid, msg):
                      # Switch the dialog based on which button has been pressed.
                      if mid in (ID_Dialog1_BUTTON, ID_Dialog2_BUTTON):
                          self.AttachSubDialog(self._dlg1 
                                               if mid == ID_Dialog1_BUTTON
                                               else self._dlg2, ID_SUBDIALOG)
                          print(self.LayoutChanged(ID_SUBDIALOG))
                      return True
              
              if __name__=='__main__':
                  dlg = MainDialog()
                  dlg.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=900, xpos=-2, ypos=-2)
              

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • J
                Joel
                last edited by

                Creating an instance for each subdialog solved the issue thank you so much.

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