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

    Collapsing/Foldable Groups in Python?

    PYTHON Development
    0
    5
    661
    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
      Helper
      last edited by

      On 17/11/2013 at 18:53, xxxxxxxx wrote:

      I seem to remember being told this wasn't possible in Python, but now I'm wanting to double check this.

      When doing User Data, if you put something in a new group, that group can be foldable/collapsable.

      Is there any way to do this in a GeDialog in Python?

      To see what I mean create a cube, look in the Coords tab. The Freeze Transformation can be collapses. I'm looking to be able to do that in my GeDialog plugin.

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

        On 18/11/2013 at 04:05, xxxxxxxx wrote:

        Hi Bret,

        unfortunately the groupflag which makes the group foldable is broken. It is however possible by using a
        button/userarea widget and the GeDialog.HideElement() function.

        Here's a quick example:

         

        >
        > import c4d
        > import weakref
        >
        > class FoldUa(c4d.gui.GeUserArea) :
        >
        > def __init__(self, dlg, wid, parent_id, state_1=None, state_2=None) :
        > super(FoldUa, self).__init__()
        > self.dlg = weakref.ref(dlg)
        > self.wid = wid
        > self.parent_id = parent_id
        > self.hidden = False
        >
        > if not state_1: state_1 = c4d.RESOURCEIMAGE_PLUS
        > if not state_2: state_2 = c4d.RESOURCEIMAGE_SUBGROUP
        > self.state_1 = state_1
        > self.state_2 = state_2
        > print self.state_1, self.state_2
        >
        > def Toggle(self, notify=True) :
        > self.hidden = not self.hidden
        > self.SetState(self.hidden, notify)
        >
        > def SetState(self, hidden, notify=True) :
        > self.hidden = bool(hidden)
        > self.dlg().HideElement(self.wid, self.hidden)
        > if notify:
        > self.LayoutChanged()
        > self.dlg().LayoutChanged(self.parent_id)
        >
        > def GetStateIcon(self) :
        > if self.hidden:
        > icon = self.state_1
        > else:
        > icon = self.state_2
        >
        > if isinstance(icon, int) :
        > icon = c4d.gui.GetIcon(icon)
        > elif isinstance(icon, dict) :
        > pass
        > elif isinstance(icon, c4d.bitmaps.BaseBitmap) :
        > w, h = icon.GetSize()
        > icon = {'x': 0, 'y': 0, 'w': w, 'h': h, 'bmp': icon}
        > elif not icon:
        > pass
        > else:
        > raise TypeError('Expected int, dict or BaseBitmap for state field.')
        >
        > return icon
        >
        > def DrawMsg(self, x1, y1, x2, y2, msg) :
        > self.DrawSetPen(c4d.COLOR_BG)
        > self.DrawRectangle(x1, y1, x2 - 1, y2 - 1)
        >
        > icon = self.GetStateIcon()
        > if not icon: return
        > self.DrawBitmap(icon['bmp'], 0, 0, icon['w'], icon['h'],
        > icon['x'], icon['y'], icon['w'], icon['h'],
        > c4d.BMP_ALLOWALPHA)
        >
        > def InputEvent(self, msg) :
        > device = msg.GetLong(c4d.BFM_INPUT_DEVICE)
        > channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
        > if device == c4d.BFM_INPUT_MOUSE and channel == c4d.BFM_INPUT_MOUSELEFT:
        > self.Toggle()
        > return True
        >
        > def GetMinSize(self) :
        > icon = self.GetStateIcon()
        > if icon:
        > return (icon['w'], icon['h'])
        > else:
        > return (0, 0)
        >
        > class Dialog(c4d.gui.GeDialog) :
        >
        > GRP_FOLDABLE = 1000
        > EDT_SOMEFIELD = 1001
        >
        > def __init__(self) :
        > super(Dialog, self).__init__()
        > self.__foldindex = 10000
        > self.__folduas = {}
        >
        > def GroupBeginFoldable(self, id, flags, *args, **kwargs) :
        > self.GroupBegin(self.__foldindex, flags, 0, 1)
        > ua = FoldUa(self, id, self.__foldindex)
        > self.__foldindex += 1
        >
        > self.AddUserArea(self.__foldindex, 0)
        > self.AttachUserArea(ua, self.__foldindex)
        > self.__folduas[self.__foldindex] = ua
        > self.__foldindex += 1
        >
        > return self.GroupBegin(id, flags, *args, **kwargs)
        >
        > def GroupEndFoldable(self) :
        > self.GroupEnd()
        > self.GroupEnd()
        >
        > # c4d.gui.GeDialog
        >
        > def CreateLayout(self) :
        > if self.GroupBeginFoldable(self.GRP_FOLDABLE, c4d.BFH_SCALEFIT, 0, 1) :
        > self.AddStaticText(0, 0, name="Field")
        > self.AddEditSlider(self.EDT_SOMEFIELD, c4d.BFH_SCALEFIT)
        > self.GroupEndFoldable()
        >
        > self.AddDlgGroup(c4d.DLG_CANCEL)
        > return True
        >
        > def Command(self, wid, msg) :
        > if wid == c4d.DLG_CANCEL:
        > self.Close()
        > return True
        >
        > dlg = Dialog()
        > dlg.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE)

        Best,
        -Niklas

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

          On 18/11/2013 at 07:30, xxxxxxxx wrote:

          Is there a way though to make it so it will display the group name still?

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

            On 18/11/2013 at 11:17, xxxxxxxx wrote:

            Requires a bit more hacky approach using a 2-level group call.

            import c4d
            import weakref
              
            class FoldUa(c4d.gui.GeUserArea) :
              
                minsize = (10, 10)
              
                def __init__(self, dlg, wid, parent_id, state_1=None, state_2=None) :
                    super(FoldUa, self).__init__()
                    self.dlg = weakref.ref(dlg)
                    self.wid = wid
                    self.parent_id = parent_id
                    self.hidden = False
              
                    if not state_1: state_1 = c4d.RESOURCEIMAGE_PLUS
                    if not state_2: state_2 = c4d.RESOURCEIMAGE_SUBGROUP
                    self.state_1 = state_1
                    self.state_2 = state_2
              
                def Toggle(self, notify=True) :
                    self.hidden = not self.hidden
                    self.SetState(self.hidden, notify)
              
                def SetState(self, hidden, notify=True) :
                    self.hidden = bool(hidden)
                    self.dlg().HideElement(self.wid, self.hidden)
                    if notify:
                        self.LayoutChanged()
                        self.dlg().LayoutChanged(self.parent_id)
              
                def GetStateIcon(self) :
                    if self.hidden:
                        icon = self.state_1
                    else:
                        icon = self.state_2
              
                    if isinstance(icon, int) :
                        icon = c4d.gui.GetIcon(icon)
                    elif isinstance(icon, dict) :
                        pass
                    elif isinstance(icon, c4d.bitmaps.BaseBitmap) :
                        w, h = icon.GetSize()
                        icon = {'x': 0, 'y': 0, 'w': w, 'h': h, 'bmp': icon}
                    elif not icon:
                        pass
                    else:
                        raise TypeError('Expected int, dict or BaseBitmap for state field.')
              
                    return icon
              
                def DrawMsg(self, x1, y1, x2, y2, msg) :
                    self.DrawSetPen(c4d.COLOR_BGFOCUS)
                    self.DrawRectangle(x1, y1, x2 - 1, y2 - 1)
              
                    icon = self.GetStateIcon()
                    if not icon: return
              
                    x = (self.GetWidth() - icon['w']) / 2
                    y = (self.GetHeight() - icon['h']) / 2
                    self.DrawBitmap(icon['bmp'], x, x, icon['w'], icon['h'],
                                    icon['x'], icon['y'], icon['w'], icon['h'],
                                    c4d.BMP_ALLOWALPHA)
              
                def InputEvent(self, msg) :
                    device = msg.GetLong(c4d.BFM_INPUT_DEVICE)
                    channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL)
                    if device == c4d.BFM_INPUT_MOUSE and channel == c4d.BFM_INPUT_MOUSELEFT:
                        self.Toggle()
                    return True
              
                def GetMinSize(self) :
                    icon = self.GetStateIcon()
                    if icon:
                        return tuple(map(max, zip(self.minsize, (icon['w'], icon['h']))))
                    else:
                        return tuple(self.minsize)
              
            class Dialog(c4d.gui.GeDialog) :
              
                GRP_FOLDABLE = 1000
                EDT_SOMEFIELD = 1001
              
                def __init__(self) :
                    super(Dialog, self).__init__()
                    self.__foldindex = 10000
                    self.__folduas = {}
              
                def GroupBeginFoldable(self, id, flags, rows=0, cols=0, title="",
                            groupflags=0, initw=0, inith=0) :
                    id_ua = self.__foldindex
                    id_group = self.__foldindex + 1
                    self.__foldindex += 2
              
                    self.GroupBegin(id, flags, 2, 0, title, groupflags, initw, inith)
                    self.__continue_data = (id, flags, rows, cols, title, groupflags,
                            initw, inith, id_ua, id_group)
              
                    return True
              
                def GroupContinueFoldable(self) :
                    if not self.__continue_data:
                        raise RuntimeError('No foldable group opened.')
              
                    (id, flags, rows, cols, title, groupflags,
                            initw, inith, id_ua, id_group) = self.__continue_data
                    self.__continue_data = None
              
                    # Column 1: User Area
                    ua = FoldUa(self, wid=id_group, parent_id=id)
                    self.__folduas[id_ua] = ua
                    self.AddUserArea(id_ua, 0)
                    self.AttachUserArea(ua, id_ua)
              
                    # Column 2: The inner group.
                    self.GroupBegin(id_group, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT,
                            rows, cols, title, groupflags, initw, inith)
              
                    return True
              
                def GroupEndFoldable(self) :
                    self.GroupEnd()
                    self.GroupEnd()
              
                # c4d.gui.GeDialog
              
                def CreateLayout(self) :
                    if self.GroupBeginFoldable(self.GRP_FOLDABLE, c4d.BFH_SCALEFIT, 0, 1,
                                               title="Foldable Group") :
                        self.GroupBorder(c4d.BORDER_GROUP_TOP | c4d.BORDER_WITH_TITLE)
                        self.GroupContinueFoldable()
              
                        self.AddStaticText(0, 0, name="Field")
                        self.AddEditSlider(self.EDT_SOMEFIELD, c4d.BFH_SCALEFIT)
                        self.GroupEndFoldable()
              
                    self.AddDlgGroup(c4d.DLG_CANCEL)
                    return True
              
                def Command(self, wid, msg) :
                    if wid == c4d.DLG_CANCEL:
                        self.Close()
                    return True
              
            dlg = Dialog()
            dlg.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE)
            
            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 19/11/2013 at 02:20, xxxxxxxx wrote:

              I think one thing worth mentioning in that context is also, that GeDialog.LoadDialogRessource 
              does not overwrite the dialogs ressources, but appends the IDs content to the dialog.

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