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
    • Register
    • Login

    Using AddCustomGui for primitive controls

    Cinema 4D SDK
    python r23
    5
    4
    735
    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.
    • CairynC
      Cairyn
      last edited by

      Hello;
      using AddCustomGui for complex controls like Quicktab or Linkbox seems easy enough, as you get a specific class derived from BaseCustomGui. However, in the description for GeDialog::AddCustomGui there are numerous "Symbol ID"s listed that do not have a specific class but result in a BaseCustomGui being returned: CUSTOMGUI_REAL, CUSTOMGUI_STATICTEXT, CUSTOMGUI_TIME, etc.

      Mostly they seem to correspond with certain primitives (which already have their own dedicated Add functions, e.g. CUSTOMGUI_REALSLIDER and AddEditSlider), but sometimes there is no separate Add function, as e.g. for CUSTOMGUI_PROGRESSBAR or CUSTOMGUI_MATRIX.

      I have no idea how to work with these.

      For complex controls, I just create the GUI:

      self.customcontrol = self.AddCustomGui(ID_CUSTOM, c4d.CUSTOMGUI_QUICKTAB, 
      name="A quick tab", 
      flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30, 
      customdata=bc)
      

      and work from there with the returned class. No issues here.

      If I try the same for a primitive control like CUSTOMGUI_REALSLIDER, no GUI appears in the dialog at all (the return value is BaseCustomGui, not None, so the call did not fail at least). I cannot find any documentation on parameters to be set through the passed BaseContainer, if that's the issue.

      You may say "use AddEditSlider" but there is no AddTime or AddProgressBar so I would expect AddCustomGui to work.

      I seem to overlook something important. What do these "Symbol ID"s document, and how do I use them?

      J 1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        Hi,

        you have function to retrieve the custom datatype corresponding to the custom gui you are adding. But not all gadgets works the same.

        for CUSTOMGUI_PROGRESSBAR , you must send a message. DateTime you can either use the returned gadget or use FindCustomGui to update its data. CUSTOMGUI_QUICKTAB you can define the tabs in the CreateLayout function etc etc.

        as FindCustomData says:

        The method returns a BaseCustomGui when there is no class available for the custom GUI.
        This allows to interact with any custom GUI, calling for instance BaseCustomGui.GetData()/SetData().
        

        You can find this manual about the DateTime control/datatype.

        Some gadgets could be restricted to Description and looks bad or not work in a GeDialog.

        I wrote a plugin to test different cases and show how to use some gadgets.

        
        import c4d
        import collections
        import os
        from datetime import datetime
        
        # Be sure to use a unique ID obtained from www.plugincafe.com
        PLUGIN_ID = 9025250
        
        
        
        class MemoryViewerDialog(c4d.gui.GeDialog):
        
            def CreateLayout(self):
                """
                This Method is called automatically when Cinema 4D Create the Layout (display) of the Dialog.
                """
                self.GroupBegin(0, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 1)
                self.dateTimeControl = self.AddCustomGui(1000, c4d.DATETIME_GUI, name="date time", 
                flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30)
        
                quickTabGadgetBC = c4d.BaseContainer()
                quickTabGadgetBC.SetBool(c4d.QUICKTAB_SHOWSINGLE, True)
                quickTabGadgetBC.SetBool(c4d.QUICKTAB_NOMULTISELECT, False)
                self.quickTabGadget = self.AddCustomGui(1001, c4d.CUSTOMGUI_QUICKTAB, name="quick tab", 
                flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30, customdata = quickTabGadgetBC)
                self.quickTabGadget.AppendString(0, "First Tab", False)
                self.quickTabGadget.AppendString(0, "Second Tab Selected", True)
        
                self.AddButton(2000, c4d.BFH_SCALEFIT, 0, 0, "click me")
                self.progressBarGadget = self.AddCustomGui(1002, c4d.CUSTOMGUI_PROGRESSBAR, name="", 
                flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT, minw=120, minh=30)
                self.GroupEnd()
        
                return True
        
            def Command(self, id, msg):
                print (id)
                if id == 2000:
                    timeDataType = self.FindCustomGui(1000, c4d.DATETIME_GUI)
                    print("this is timedata", timeDataType, self.dateTimeControl )
                    # Parse the time string
                    dt = datetime.strptime('16.07.2011 03:37:12',"%d.%m.%Y %H:%M:%S")
                    dtd = c4d.DateTimeData()
                    # Fills the Data object with the DateTime object
                    dtd.SetDateTime(dt)
                    timeDataType.SetDateTime(dtd, True, True)
        
                    progressMessage = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR)
                    progressMessage.SetData(c4d.BFM_STATUSBAR_TXT , "this is displayed in the status bar")
                    self.SendMessage(1002, progressMessage)
                    
                    
                return True
           
        
        class MemoryViewerCommandData(c4d.plugins.CommandData):
        
            dialog = None
        
            def Execute(self, doc):
                """
                Called when the user Execute the command (CallCommand or a clicks on the Command from the plugin menu)
                :param doc: the current active document
                :type doc: c4d.documents.BaseDocument
                :return: True if the command success
                """
                # Creates the dialog if its not already exists
                if self.dialog is None:
                    self.dialog = MemoryViewerDialog()
        
                # Opens the dialog
                return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaulth=400, defaultw=400)
        
            def RestoreLayout(self, sec_ref):
                """
                Used to restore an asynchronous dialog that has been placed in the users layout.
                :param sec_ref: The data that needs to be passed to the dlg (almost no use of it).
                :type sec_ref: PyCObject
                :return: True if the restore success
                """
                # Creates the dialog if its not already exists
                if self.dialog is None:
                    self.dialog = MemoryViewerDialog()
        
                # Restores the layout
                return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
        
        
        if __name__ == "__main__":
            # Retrieves the icon path
            directory, _ = os.path.split(__file__)
            fn = os.path.join(directory, "res", "mviewer.tif")
        
            # Creates a BaseBitmap
        
        
            # Registers the Command plugin
            c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID,
                                              str="Py-MemoryViewer 2",
                                              help="Show the current mem usage of Cinema 4D.",
                                              info=0,
                                              dat=MemoryViewerCommandData(),
                                              icon=None)
        

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        CairynC 1 Reply Last reply Reply Quote 0
        • CairynC
          Cairyn @Manuel
          last edited by

          @manuel Thanks for the notes, there seems to be a lot that requires additional explanation beyond the API description. I may ask more specific questions later...

          Regarding the DateTime, I got a weird error when I try to show the extended GUI: the clock and calendar fields get duplicated:

          20221124__05__Screenshot_DateTime_04.jpg

          This happens upon calling

          self.dateTimeControl.SetLayoutMode(c4d.LAYOUTMODE_MAXIMIZED)

          or if you like the full script,

          import c4d
          from c4d import gui
          from datetime import datetime
          
          ID_BUTTON_CLOSE = 1001
          ID_DATETIME = 1002
          
          class CustomDialog(c4d.gui.GeDialog):
          
              def __init__(self):
                  self.customcontrol = None
          
              def CreateLayout(self):
                  self.SetTitle("Custom Control Test")
                  self.GroupBorderSpace(10, 10, 10, 10)
          
                  if self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT, cols=1, title="", groupflags=0):
          
                      bc = c4d.BaseContainer()
                      bc[c4d.DATETIME_TIME_CONTROL] = True
                      bc[c4d.DATETIME_DATE_CONTROL] = True
          
                      self.dateTimeControl = self.AddCustomGui(ID_DATETIME, c4d.DATETIME_GUI,
                              name="DateTime",
                              flags = c4d.BFH_SCALEFIT | c4d.BFV_FIT,
                              minw=10, minh=10, customdata=bc)
                      self.dateTimeControl.SetLayoutMode(c4d.LAYOUTMODE_MAXIMIZED)
                      dt = datetime.strptime('16.07.2011 03:37:12',"%d.%m.%Y %H:%M:%S")
                      dtd = c4d.DateTimeData()
                      dtd.SetDateTime(dt)
                      self.dateTimeControl.SetDateTime(dtd)
                      self.GroupEnd()
          
                  if self.GroupBegin(id=0, flags=c4d.BFH_CENTER, cols=2, title="", groupflags=0):
                      self.GroupBorderSpace(0, 20, 0, 0)
                      self.AddButton(ID_BUTTON_CLOSE, c4d.BFH_SCALEFIT, name="Close")
                      self.GroupEnd()
          
                  return True
          
              def Command(self, messageId, bc):
                  if messageId == ID_BUTTON_CLOSE:
                      self.Close()
                  return True
          
          def main():
          
              dlg = CustomDialog()
              dlg.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE)
              dt = dlg.dateTimeControl.GetDateTime().GetDateTime()
              print (dt.year, dt.month, dt.day)
              print (dt.hour, dt.minute, dt.second)
          
          if __name__=='__main__':
              main()
          

          (and no, it doesn't work in a CommandData plugin either...)
          I am still on R23.1 and have no current access to more recent versions, so this may actually be an error that has already been corrected, and it's no longer a valid question...

          1 Reply Last reply Reply Quote 0
          • J
            jana @Cairyn
            last edited by

            Hello @Cairyn ,

            without further questions or postings, we will consider this topic as solved by Friday 11th of august 2023 and flag it accordingly.

            Thank you for your understanding,
            Maxon SDK Group

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