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

    QuickTabCustomGui.GetData() is None

    Cinema 4D SDK
    r20 python
    3
    7
    1.6k
    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.
    • M
      mike
      last edited by

      Hi,
      i am confuse about BaseCustomGui.GetData(), my_QuickTabCustomGui.GetData() always return None and SetData() always return False, anyone could tell me how to use it?
      hope yout help!

      1 Reply Last reply Reply Quote 0
      • r_giganteR
        r_gigante
        last edited by

        Hi @mike, thanks for reaching out us.

        With regard to your question, I encourage to have a look at the cinema4dsdk on Github examples where on the customgui_string.cpp both methods are properly implemented (see here).

        If the example isn't enough to bring you on the right direction, please provide us with some more details (code?) in order to look at your implementation.

        Best, Riccardo

        M 1 Reply Last reply Reply Quote 0
        • M
          mike @r_gigante
          last edited by

          @r_gigante thank you for your answer,i m misunderstand what it means. And is there any way to get and reset customgui data? return a basecontainer and reset setting,looks like node.setparameter( )?

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

            Hi @mike G/SetData come from the BaseCustomGui class and in fact offer only a way to define as low level, most of the time used for the tristate stuff so I would say for most of the time it's does not do what you expect.

            Most of the time to manage a CustomGui you have to use directly the method from your custom GUI (in your case QuickTabCustomGui).

            May I ask you what you really want to do?
            Cheers,
            Maxime.

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

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

              @m_adam actually i want get my QuickTabCustomGui String count and name str,also reset ,but in Python sdk, only have appendstring() and ClearStrings(),so,i think maybe i can get the cutomgui data (basecontainer or other )and reset data by myself?

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

                Actually, you are right and you have to handle this by yourself.
                Here is an example how it could work.

                """
                Copyright: MAXON Computer GmbH
                Author: Maxime Adam
                
                Description:
                    - Creates a Modal Dialog displaying a different SubDialog according to the selected entry of the QuickTab.
                    - Demonstrates how to adds, flushes, removes tab interactively.
                
                Class/method highlighted:
                    - c4d.gui.QuickTabCustomGui
                    - QuickTabCustomGui.ClearStrings()
                    - QuickTabCustomGui.AppendString()
                    - c4d.gui.GeDialog
                    - GeDialog.CreateLayout()
                    - GeDialog.InitValues()
                    - GeDialog.Command()
                    - GeDialog.HideElement()
                    - GeDialog.RemoveElement()
                    - c4d.gui.SubDialog
                
                Compatible:
                    - Win / Mac
                    - R19, R20
                """
                import c4d
                
                # Ids used in our Dialog
                ID_MAINGROUP = 100000  # ID used for the Group that holds all the other group representing the tab content
                ID_QUICKTAB_BAR = 110000  # ID for the quicktab customGui
                ID_QUICKTAB_BASE_GROUP = 120000  # Base ID for each SubDialog
                
                BUTTON_PRINT_TEXT = 1200  # ID used for the Print text Button
                BUTTON_PRINT_SELECTED = 1201  # ID used for the Print Selected Button
                BUTTON_FLUSH_ALL = 1203  # ID used for the Flush All Button
                BUTTON_ADD = 1204  # ID used for the Add Button
                BUTTON_REMOVE = 1205  # ID used for the Remove Button
                
                # Id used in our SubDialog
                CUSTOM_GROUP_ID_TEXT_BASE = 100000  # Defines the ID for the string to be displayed
                
                
                class CustomGroup(c4d.gui.SubDialog):
                    """
                    A SubDialog to display the passed string, its used as example for the actual content of a Tab
                    """
                    def __init__(self, data):
                        self._data = data
                
                    def CreateLayout(self):
                        for i, data in enumerate(self._data):
                            self.AddStaticText(CUSTOM_GROUP_ID_TEXT_BASE + i, c4d.BFH_SCALEFIT, name=data)
                        return True
                
                
                class QuickTabDialogExample(c4d.gui.GeDialog):
                
                    def __init__(self):
                        self._quickTab = None  # Stores the quicktab custom GUI
                        self._tabList = {}  # Stores the TabName and the SubDialog that represents each tab of the QuickTab
                
                    def _DrawQuickTabGroup(self):
                        """
                        Creates and draws all the SubDialog for each tab, take care it does not hide these according to a selection state.
                
                        :return: True if success otherwise False.
                        """
                
                        # Checks if the quicktab is defined
                        if self._quickTab is None:
                            return False
                
                        # Flush the content of the group that holds all ours SubDialogs
                        self.LayoutFlushGroup(ID_MAINGROUP)
                
                        # Iterates over the number of tab to create and attach the correct SubDialog
                        for tabId, (tabName, tabGui) in enumerate(self._tabList.iteritems()):
                            self.AddSubDialog(ID_QUICKTAB_BASE_GROUP + tabId, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0)
                            self.AttachSubDialog(tabGui, ID_QUICKTAB_BASE_GROUP + tabId)
                
                        # Notifies the content of the MainGroup has changed
                        self.LayoutChanged(ID_MAINGROUP)
                
                        return True
                
                    def GetActiveTab(self):
                        """
                        Retrieves the current selected tab from the self._quickTab.
                
                        :return: The tab Id (from the dict) and the name of the selected tab
                        :rtype: (int, str) or (False, False) if fail.
                        """
                        # Checks if the quicktab is defined
                        if self._quickTab is None:
                            return False, False
                
                        for tabId, (tabName, tabGui) in enumerate(self._tabList.iteritems()):
                            if self._quickTab.IsSelected(tabId):
                                return tabId, tabName
                
                        return False, False
                
                    def DisplayCorrectGroup(self):
                        """
                        Hides all unused groups and display the correct one.
                
                        :return: True if success otherwise False.
                        """
                        # Retrieves the selected tab
                        activeId, activeName = self.GetActiveTab()
                        if activeId is False:
                            return False
                
                        # Iterates each CustomGui and defines if they are hidden or not
                        for tabId in xrange(len(self._tabList)):
                            toHide = activeId == tabId
                            self.HideElement(ID_QUICKTAB_BASE_GROUP + tabId, not toHide)
                
                        # Notifies the content of the MainGroup has changed
                        self.LayoutChanged(ID_MAINGROUP)
                        return True
                
                    def AppendTab(self, tabName, content, active=True):
                        """
                        Appends a tab to the current quicktab with the associated content to be displayed.
                
                        :param tabName: The name the tab should have.
                        :type tabName: str
                        :param content: The SubDialog to be drawn/linked when the tab is selected.
                        :type content: c4d.gui.SubDialog
                        :param active: If True, the inserted tab will be selected
                        :type active: bool
                        :return: True if success otherwise False.
                        """
                        # Checks if the quicktab is defined
                        if self._quickTab is None:
                            return False
                
                        # Adds the tab entry n the quicktab
                        self._quickTab.AppendString(len(self._tabList), tabName, False)
                
                        # Updates our current tabList with tabName and the Subdialog to be linked
                        self._tabList.update({tabName: content})
                
                        # Retrieves the current selected tab
                        previousActiveId, previousActiveName = self.GetActiveTab()
                
                        # Draws the quicktab SubDialog (in order to have the new one drawn)
                        self._DrawQuickTabGroup()
                
                        # Defines which tab should be active
                        if active:
                            self._quickTab.Select(len(self._tabList) - 1, True)
                        else:
                            self._quickTab.Select(previousActiveId, True)
                
                        # Display only the selected tab and hides all others
                        self.DisplayCorrectGroup()
                
                        return True
                
                    def FlushAllTabs(self):
                        """
                        Removes all tabs and their content from the GUI.
                
                        :return: True if success otherwise False.
                        """
                        # Checks if the quicktab is defined
                        if self._quickTab is None:
                            return False
                
                        # Removes all the tabs
                        self._quickTab.ClearStrings()
                
                        # Removes all the customGui
                        for tabId in xrange(len(self._tabList)):
                            self.RemoveElement(ID_QUICKTAB_BASE_GROUP + tabId)
                
                        # Reinitializes the stored tablist to an empty dict
                        self._tabList = {}
                
                        # Notifies the content of the MainGroup has changed
                        self.LayoutChanged(ID_MAINGROUP)
                
                        return True
                
                    def RemoveTab(self, tabNameToRemove):
                        """
                        Removes a tab by its name
                
                        :param tabNameToRemove: The tab to remove.
                        :type tabNameToRemove: str
                        :return: True if success otherwise False.
                        """
                        # Checks if the quicktab is defined
                        if self._quickTab is None:
                            return False
                
                        # Copies the tabList
                        newDict = dict(self._tabList)
                
                        # Removes teh entry we want to delete
                        del newDict[tabNameToRemove]
                
                        # Removes all groups
                        self.FlushAllTabs()
                
                        # Re-adds all the one from our copy
                        for tabName, tabGui in newDict.iteritems():
                            self.AppendTab(tabName, tabGui)
                
                        return True
                
                    def CreateLayout(self):
                        """
                        This Method is called automatically when Cinema 4D Create the Layout (display) of the Dialog.
                        """
                
                        # Creates a QuickTab Custom Gui
                        bc = c4d.BaseContainer()
                        bc.SetBool(c4d.QUICKTAB_BAR, False)
                        bc.SetBool(c4d.QUICKTAB_SHOWSINGLE, True)
                        bc.SetBool(c4d.QUICKTAB_NOMULTISELECT, True)
                        self._quickTab = self.AddCustomGui(ID_QUICKTAB_BAR, c4d.CUSTOMGUI_QUICKTAB, '',
                                                           c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, bc)
                
                        # Creates a group that will contain all the group representing each tab
                        self.GroupBegin(ID_MAINGROUP, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, '', 0)
                        self.GroupEnd()
                
                        # Creates a group with 5 button in order to do some operation with the QuickTab CustomGUI
                        if self.GroupBegin(0, c4d.BFH_SCALEFIT, 5, 1, '', 0):
                            self.AddButton(BUTTON_PRINT_TEXT, c4d.BFH_SCALEFIT, name="Print text")
                            self.AddButton(BUTTON_PRINT_SELECTED, c4d.BFH_SCALEFIT, name="Print Selected")
                            self.AddButton(BUTTON_FLUSH_ALL, c4d.BFH_SCALEFIT, name="Flush All")
                            self.AddButton(BUTTON_ADD, c4d.BFH_SCALEFIT, name="Add")
                            self.AddButton(BUTTON_REMOVE, c4d.BFH_SCALEFIT, name="Remove")
                        self.GroupEnd()
                        return True
                
                    def InitValues(self):
                        """
                        This Method is called automatically after the GUI is initialized.
                        """
                        # Creates the first Tab
                        cg1 = CustomGroup(["This is the first Tab", "Just dummy text here"])
                        self.AppendTab("First Tab", cg1, False)
                
                        # Creates the second Tab
                        cg2 = CustomGroup(["This is the second Tab", "Just another dummy text here"])
                        self.AppendTab("Second Tab", cg2, False)
                        return True
                
                    def Command(self, id, msg):
                        """
                         This Method is called automatically when the user clicks on a gadget and/or changes its value this function will be called.
                         It is also called when a string menu item is selected.
                
                        :param id: The ID of the gadget that triggered the event.
                        :param msg: The original message container
                        :return: False if there was an error, otherwise True.
                        """
                
                        # If the user interacts with the quicktab, we make sure to display the CustomGUI linked to the active one
                        if id == ID_QUICKTAB_BAR and self._quickTab:
                            self.DisplayCorrectGroup()
                            return True
                
                        # Displays all the Tab name
                        if id == BUTTON_PRINT_TEXT:
                            print [key for key in self._tabList]
                            return True
                
                        # Displays the ID and name of the selected tab
                        if id == BUTTON_PRINT_SELECTED:
                            print self.GetActiveTab()
                
                        # Removes all tabs
                        if id == BUTTON_FLUSH_ALL:
                            self.FlushAllTabs()
                
                        # Adds a new Tab to the quicktab
                        if id == BUTTON_ADD:
                            cg3 = CustomGroup(["This is the third Tab"])
                            self.AppendTab("Third Tab", cg3, False)
                
                        # Removes the first tab of the quicktab
                        if id == BUTTON_REMOVE:
                            self.RemoveTab("First Tab")
                
                        return True
                
                
                # Main function
                def main():
                    # Initializes a QuickTabDialogExample Dialog
                    diag = QuickTabDialogExample()
                
                    # Opens the Dialog in modal mode
                    diag.Open(dlgtype=c4d.DLG_TYPE_MODAL, defaultw=400, defaulth=400)
                
                
                # Execute main()
                if __name__ == '__main__':
                    main()
                
                

                If you have any question on the previous code, please let me know.
                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                M 1 Reply Last reply Reply Quote 2
                • M
                  mike @m_adam
                  last edited by

                  @m_adam thank you for your answer😊 from the code, it similar to what i already try, but this way looks like not a perfect solution. actually after read most c4d gui sdk and write some examples, i think maybe c4d should update gui model? sometimes it not flexible. just my personal thoughts, don't mind : ) expect python 3.x and pyside2 coming : )

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