Navigation

    • Register
    • Login
    • Search
    1. Home
    2. mogh
    3. Best
    • Profile
    • More
      • Following
      • Followers
      • Topics
      • Posts
      • Best
      • Groups

    Best posts made by mogh

    RE: How to setup c4d.utils.ViewportSelect() and GetNearestPoint to work

    @m_magalhaes

    This morning: uff more learning and work.
    This Afternoon lets try this code ... mind blown ... thank you !

    I'll mark this as solved hence I think ist a good way to close a thread with a working prototype for others to learn.

    Thank You again, @zipit & @m_magalhaes
    mogh

    posted in Cinema 4D SDK •
    RE: Table With TreeViewCustomGui with no Tree Icon

    @mikeudin

    In my case setting this to true hides them.

    customgui.SetBool(c4d.TREEVIEW_HIDE_LINES, True) # True if no lines should be drawn.

    kind regards
    mogh

    posted in Cinema 4D SDK •
    RE: Layers checker

    Beginner solution:
    If you do not need a certain layer you could also implement the call comand "Delete unused layers"
    Its not pretty but beats any convulated self written code if it is not called to often.

    c4d.CallCommand(100004760) # Remove unused layers

    cheers
    mogh

    posted in Cinema 4D SDK •
    RE: How can I make a simple input form for my Python script?

    ... while the Team probalby will ask you to provide more context / detail ... have you looked at the sdk examples ?

    https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/scripts/03_application_development/gui/dialog

    kind regards

    posted in Cinema 4D SDK •
    RE: Dialog Menu

    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

    posted in Cinema 4D SDK •
    RE: Quicktab SDK Example

    Here is my latest Example Code, I will check for R2023.1 on Monday.
    selecting FFFF and DDDD results in GUI weirdness ... on R20

    Update: Also on 2023.1 I get this UI glitch ... selecting KKKKK / LLLLLL (last ones)

    Update 2: fiddled a little bit with the IDs (the class has an offset now so the ids are unique) and Layoutchange() no updated on the glitch when selecting the KKKK + X elements.

    2023-03-27-Window_000269.png

    import c4d # pyright: ignore[reportMissingImports]
    import json
    import os
    from collections import OrderedDict
    
    DEBUG = True
    
    # Ids used in our Dialog
    ID_MAINGROUP = 1000  # ID used for the Group that holds all the other group representing the tab content
    ID_QUICKTAB_BAR = 1001  # ID for the quicktab customGui
    
    ID_LOADDEFAULT_MAT_ASIGN = 1003
    ID_CREATE_MATERIALS = 1004
    BUTTON_PRINT_TEXT = 1005  # ID used for the Print text Button
    BUTTON_PRINT_SELECTED = 1006  # ID used for the Print Selected Button
    BUTTON_FLUSH_ALL = 1007  # ID used for the Flush All Button
    BUTTON_ADD = 1008  # ID used for the Add Button
    BUTTON_REMOVE = 1009  # ID used for the Remove Button
    
    # Id used in our SubDialog
    ID_QUICKTAB_BASE_GROUP = 5000
    
    # Defines the ID for the string to be displayed
    CUSTOM_GROUP_ID_TEXT_BASE = 4000  
    
    DEFAULT_FLAGS = c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT
    DEFAULT_SPACE = (5, 5, 5, 5)
    DEFAULT_BORDER_STYLE =c4d.BORDER_NONE
    
    LAYOUT_DEBUG = True
    if LAYOUT_DEBUG is True:
        DEFAULT_BORDER_STYLE = c4d.BORDER_BLACK
    
    GENERATOR_START_ID = 2000
    def plusone_id():
        n = GENERATOR_START_ID
        while n < GENERATOR_START_ID+999:
            yield n
            n += 1
    
    some_json = '{"AAAAAAA 85": ["a part_num_1","a part_num_2","a part_num_3"],"BBBBB 40": ["b part_num_4","b part_num_5"],"CCCCCCC": ["c part_num_6","c part_num_7","c part_num_8","c part_num_9"],"DDDDDD": ["d part_num_6","d part_num_7","d part_num_8","d part_num_9"],"FFFFF": ["f Plane"],"GGGGGGG": ["g part_num_6","g part_num_7","g part_num_8","g part_num_9"],"HHHHHHHH": ["h part_num_6","h part_num_7","h part_num_8","h part_num_9"],"IIIIII": ["i part_num_6","i part_num_7","i part_num_8","i part_num_9"],"JJJJJJJJJ": ["j part_num_6","j part_num_7","j part_num_8","j part_num_9"],"KKKKKKKK": ["k part_num_6","k part_num_7","k part_num_8","k part_num_9"],"LLLLLLLLL": ["l part_num_6","l part_num_7","l part_num_8","l part_num_9"],"MMMMMM": ["m part_num_6","m part_num_7","m part_num_8","m part_num_9"]}'
    
    ### Json
    #####################################################################################
    
    def read_parts_json(json_file_path):
        #with open(json_file_path) as f: data = json.load(f)
        data = json.loads(some_json)
    
        materials = {}
        for material_id, part_numbers in data.items():
            materials[material_id] = part_numbers
        
        material_ids = list(data.keys())
        return material_ids, materials
    
    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, material, parts, offset):
    
            self._material = material
            self._parts = '\n'.join(parts)
            self.gui_id = CUSTOM_GROUP_ID_TEXT_BASE + offset
    
        def CreateLayout(self):
            
            self.GroupBegin(self.gui_id + 4, flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=1, rows=2, title=self.gui_id)
            self.GroupBorder(DEFAULT_BORDER_STYLE)
            self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
            self.AddStaticText(self.gui_id + 1 , flags=c4d.BFH_LEFT | c4d.BFV_TOP | c4d.BFH_FIT | c4d.BFV_FIT, name=self._material)
            #self.AddStaticText(self.gui_id + 2 , flags=c4d.BFH_LEFT | c4d.BFV_TOP | c4d.BFH_FIT | c4d.BFV_FIT, name=self.gui_id)
            self.AddMultiLineEditText(self.gui_id + 3, flags=c4d.BFH_LEFT | c4d.BFV_TOP | c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, initw=0, inith=0, style=0)
            self.SetString(self.gui_id + 3, value=self._parts)
            self.GroupEnd()
            #for i, parts in enumerate(self._parts):
            #    self.AddStaticText(self.gui_id + i, c4d.BFH_SCALEFIT, name=parts)
            return True
    
    
    class MyDialog(c4d.gui.GeDialog):
    
        def __init__(self, items=[]):
    
            # this is from the linkbox example from ferdinand
            super(MyDialog, self).__init__() 
    
            # will be link box
            self._items = [] 
            self._doc = None 
            self._hasCreateLayout = False
            self.Items = items
    
            self._quickTab = None  # Stores the quicktab custom GUI
            self._tabList = OrderedDict()  # 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.
    
            Returns: 
                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)
            #self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
    
            # Iterates over the number of tab to create and attach the correct SubDialog
            for tabId, (tabName, tabGui) in enumerate(self._tabList.items()):
                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 GetActiveTabs(self):
            """Retrieves two list of currently selected tabs from the self._quickTab.
    
            Returns:
                list(int), list(name): The first list, contains tabs Id (from self._quickTab the dict) and the second list contains all names of the selected tabs.
            """
            # Checks if the quicktab is defined
            if self._quickTab is None:
                return False, False
    
            returnIds = []
            returnNames = []
    
            for tabId, (tabName, tabGui) in enumerate(self._tabList.items()):
                if self._quickTab.IsSelected(tabId):
                    returnIds.append(tabId)
                    returnNames.append(tabName)
    
            return returnIds, returnNames
    
    
        def DisplayCorrectGroup(self):
            """Hides all unused groups and display the correct one.
    
            Returns: 
                True if success otherwise False.
            """
            # Retrieves the selected tab
            activeIds, activeNames = self.GetActiveTabs()
            
            print("Display Correct Group")
            print(activeIds)
    
            # Iterates each CustomGui and defines if they are hidden or not
            for tabId in range(len(self._tabList)):
                toDisplay = tabId in activeIds
                #print("activeIds: ", activeIds, "current: ", ID_QUICKTAB_BASE_GROUP, tabId, " -> toDisplay: ", toDisplay)
                self.HideElement(ID_QUICKTAB_BASE_GROUP + tabId, not toDisplay)
    
    
            # 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.
    
            Args:
                tabName (str): The name the tab should have.
                content (c4d.gui.SubDialog): The SubDialog to be drawn/linked when the tab is selected.
                active (bool, optional): If True, the inserted tab will be selected. Defaults to True.
    
            Returns:
                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, active)
    
            # Updates our current tabList with tabName and the Subdialog to be linked
            self._tabList.update({tabName: content})
    
            """ I uncommented below because it resulted in a lot of gui calls 
                It seems to work fine just calling self.DisplayCorrectGroup() at the right places
                not inside here hence this functionis called for each tab
            """
    
            # Retrieves the current selected tab
            #previousActiveId, previousActiveName = self.GetActiveTabs()
    
            # Draws the quicktab SubDialog (in order to have the new one drawn)
            #self._DrawQuickTabGroup()
    
            # Defines the just added tab according state
            #self._quickTab.Select(len(self._tabList) - 1, active)
    
            # Defines previous active tab
            #for tabId in previousActiveId: self._quickTab.Select(tabId, 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.
    
            Returns: 
                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 range(len(self._tabList)):
                self.RemoveElement(ID_QUICKTAB_BASE_GROUP + tabId)
    
            # Reinitializes the stored tablist to an empty dict
            self._tabList = OrderedDict()
    
            # Flush the content of the group that holds all ours SubDialogs
            self.LayoutFlushGroup(ID_MAINGROUP)
            # Notifies the content of the MainGroup has changed
            self.LayoutChanged(ID_MAINGROUP)
    
            return True
    
        def RemoveTab(self, tabNameToRemove):
            """Removes a tab by its name
    
            Args:
                tabNameToRemove (str): The tab to remove.
    
            Returns:
                True if success otherwise False.
            """
            # Checks if the quicktab is defined
            if self._quickTab is None:
                return False
    
            # Copies the tabList
            newDict = OrderedDict(self._tabList)
    
            # Checks if the entry exist
            if tabNameToRemove not in newDict:
                return True
    
            # Removes the 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.items():
                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.SetInt32(c4d.QUICKTAB_BAR, 0) # (0=off, 1=on, 2=non-bold, 3=special separator look)
            bc.SetString(c4d.QUICKTAB_BARTITLE, "Title")
            bc.SetBool(c4d.QUICKTAB_SPRINGINGFOLDERS, True) # if we can get link fields usefull
            bc.SetBool(c4d.QUICKTAB_SHOWSINGLE, False)
            bc.SetBool(c4d.QUICKTAB_NOMULTISELECT, False)
            bc.SetBool(c4d.QUICKTAB_SEPARATOR, True)
    
            self.GroupBegin(next(plusone_id()), c4d.BFH_SCALEFIT | c4d.BFV_TOP | c4d.BFV_FIT, 0, 0, 'ID_QUICKTAB_BAR', 0)
            #self.GroupBorderNoTitle(borderstyle=DEFAULT_BORDER_STYLE)
            self.GroupBorder(DEFAULT_BORDER_STYLE)
            self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
            self._quickTab = self.AddCustomGui(ID_QUICKTAB_BAR, c4d.CUSTOMGUI_QUICKTAB, 'the tabs', c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, bc)
            #self.AddStaticText(id=next(plusone_id()), flags=c4d.BFV_CENTER | c4d.BFV_SCALE | c4d.BFH_CENTER | c4d.BFH_SCALE, name="tabs")
            #print("layout cusrom gui: ", self._quickTab)
            self.GroupEnd()
    
            # Creates a group that will contain all the group representing each tab
            self.GroupBegin(ID_MAINGROUP, flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=10, rows=10, title='ID_MAINGROUP')
            #self.GroupBorderNoTitle(borderstyle=DEFAULT_BORDER_STYLE)
            self.GroupBorder(DEFAULT_BORDER_STYLE)
            self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
            self.AddStaticText(id=next(plusone_id()), flags=c4d.BFV_CENTER | c4d.BFV_SCALE | c4d.BFH_CENTER | c4d.BFH_SCALE, name="main")
            self.GroupEnd()
            
            # dummy group to spread vertically
            if self.GroupBegin(id=next(plusone_id()),  flags=c4d.BFH_FIT | c4d.BFV_FIT): #cols=1, rows=1,
                self.GroupBorderSpace(left=0, top=0, right=0, bottom=0)
                self.GroupBorderNoTitle(borderstyle=DEFAULT_BORDER_STYLE)
                self.AddStaticText(id=next(plusone_id()), flags=c4d.BFV_CENTER | c4d.BFV_SCALE | c4d.BFH_CENTER | c4d.BFH_SCALE, name="")
                self.GroupEnd()
    
            # Creates a group with button in order to do some operation with the QuickTab CustomGUI
            if self.GroupBegin(next(plusone_id()), c4d.BFH_SCALEFIT | c4d.BFV_BOTTOM, 4, 1, '', 0):
                self.AddButton(ID_LOADDEFAULT_MAT_ASIGN, c4d.BFH_SCALEFIT, name="Populate")
                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, True)
    
            # Creates the second Tab
            #cg2 = CustomGroup(["This is the second Tab", "Just another dummy text here"])
            #self.AppendTab("Second Tab", cg2, False)
            #return True
        
            return super(MyDialog, self).InitValues()
    
        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.
    
            Args:
                id: The ID of the gadget that triggered the event.
                msg: The original message container
    
            Returns:
                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:
                print("user interacted with tab")
                self.DisplayCorrectGroup()
                c4d.EventAdd()
                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.GetActiveTabs())
    
            # 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, True)
    
            # Removes the first tab of the quicktab
            if id == BUTTON_REMOVE:
                self.RemoveTab("First Tab")
            """
    
            if id == ID_LOADDEFAULT_MAT_ASIGN:
                self.Populate()
    
            return True
        
    
        def Populate(self):
            doc = c4d.documents.GetActiveDocument()
            directory, _ = os.path.split(__file__)
            poart_json_file = os.path.join(directory, "default_asignment.json")
            material_ids, materials_dict = read_parts_json(poart_json_file)
    
            self.FlushAllTabs() # clear the GUI
    
            print( str( material_ids))
            print("-"*80)
            
            offset=0
            
            for material_id in materials_dict:
                part_list = materials_dict[material_id]
    
                #print( str(material_id), str(part_list) )
    
                ### Tabs
                ##############################################
                
                tab_Content = CustomGroup(str(material_id), part_list, offset)
                self.AppendTab(str(material_id), tab_Content, True)
                offset += 10
            
            print("-"*80)
            self._DrawQuickTabGroup()
            c4d.EventAdd()    
          
    
    # Main function
    def main():
        
        if DEBUG:
            c4d.CallCommand(13957)  # clear console
        
        # Initializes a QuickTabDialogExample Dialog
        diag = MyDialog()
    
        # Opens the Dialog in modal mode
        diag.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=960, defaulth=600)
    
    
    # Execute main()
    if __name__ == '__main__':
        main()
    
    posted in Cinema 4D SDK •