Multiple SubDialogs



  • On 07/04/2014 at 09:29, xxxxxxxx wrote:

    You're welcome, Scott.

    You can also find the code at the GitHub py-cinema4sdk repository under gui/restore-sub-dialog.pyp!
    Do also take a look at the respective readme file at gui/restore-sub-dialog.md.

    Best,
    -Niklas



  • On 07/04/2014 at 11:19, xxxxxxxx wrote:

    Thanks for the help guys, however I still have a few problems. Using Kiklas' method I got the SubDialogs to behave correctly when I re-open them while they are open and the window becomes active. I still get a Plugin not found while restoring a layout, I think this reason is due to having more than one sub dialog.

    here is the code:

    def Restore(self, PLUGIN_ID, secref) :
         if secref['subid'] == 1:
              return self.sub_dialog1.Restore(PLUGIN_ID,secref)
         elif secref['subid'] == 2:
              return self.sub_dialog2.Restore(PLUGIN_ID,secref)
         else:
              return super(MainDialog, self).Restore(PLUGIN_ID,secref)
    

    How do I correctly look for both subdialogs.



  • On 07/04/2014 at 11:23, xxxxxxxx wrote:

    How do you open the subdialogs?



  • On 07/04/2014 at 11:26, xxxxxxxx wrote:

    if id == 10017: # Get Render Time
         self.sub_dialog2.Open(c4d.DLG_TYPE_ASYNC, defaulth=200, defaultw=300, subid = 2)
    

    Oh wait, I think I just figured it out, This has to have the plugin ID as well correct?



  • On 07/04/2014 at 11:41, xxxxxxxx wrote:

    No that did not work. Here is what my @properties look like

    @property
    def sub_dialog1(self) :
         if not hasattr(self, '_sub_dialog1') :
              self._sub_dialog1 = ColorDialog()
         return self._sub_dialog1
    @property
    def sub_dialog2(self) :
         if not hasattr(self, '_sub_dialog2') :
              self._sub_dialog2 = RenderTimeDialog()
         return self._sub_dialog2
    


  • On 07/04/2014 at 11:58, xxxxxxxx wrote:

    Here is the code from your exaple made to have 2 sub dialogs: Same problem.

    import c4d
      
    PLUGIN_ID = 1000004 # Test ID
      
    class MainDialog(c4d.gui.GeDialog) :
      
        # Do not create the object on class-level, although it might
        # be unimportant since you do not open multiple objects of your
        # MainDialog, it is contradicting to have one instance of sub
        # dialog for all instances of the main dialog.
        # A property that creates the dialog on-demand is perfect for
        # this purpose.
      
        @property
        def sub_dialog(self) :
            if not hasattr(self, '_sub_dialog') :
                self._sub_dialog = SubDialog()
            return self._sub_dialog
        @property
        def sub_dialog2(self) :
            if not hasattr(self, '_sub_dialog2') :
                self._sub_dialog2 = SubDialog2()
            return self._sub_dialog2
        # c4d.gui.GeDialog
      
        def CreateLayout(self) :
            self.SetTitle('Main Dialog')
            self.AddButton(1000, 0, name="Open Sub-Dialog")
            return True
      
        def Command(self, param, bc) :
            if param == 1000:
                self.sub_dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=1)
                self.sub_dialog2.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=2)
            return True
      
        def Restore(self, pluginid, secref) :
            # We override this method so we don't have to handle the sub-
            # dialog from the CommandData plugin. THIS dialog is responsible
            # for the sub-dialog, do not split such management throughout
            # your program or it gets confusing.
            if secref['subid'] == 1:
                return self.sub_dialog.Restore(pluginid, secref)
            elif secref['subid'] == 2:
                return self.sub_dialog2.Restore(pluginid, secref)
            else:
                return super(MainDialog, self).Restore(pluginid, secref)
      
    class SubDialog(c4d.gui.GeDialog) :
      
        def CreateLayout(self) :
            self.SetTitle('Sub-Dialog')
            self.AddStaticText(1000, 0, name="This is the sub-dialog.")
            return True
    class SubDialog2(c4d.gui.GeDialog) :
      
        def CreateLayout(self) :
            self.SetTitle('Sub-Dialog2')
            self.AddStaticText(1000, 0, name="This is the sub-dialog2.")
            return True
      
    class Command(c4d.plugins.CommandData) :
      
        def Register(self) :
            return c4d.plugins.RegisterCommandPlugin(
                    PLUGIN_ID, "Sub-Dialog Docking Test", 0, None, "", self)
      
        @property
        def dialog(self) :
            if not hasattr(self, '_dialog') :
                self._dialog = MainDialog()
            return self._dialog
      
        # c4d.plugins.CommandData
      
        def Execute(self, doc) :
            return self.dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID)
      
        def RestoreLayout(self, secref) :
            return self.dialog.Restore(PLUGIN_ID, secref)
      
    if __name__ == '__main__':
        Command().Register()
    


  • On 07/04/2014 at 13:45, xxxxxxxx wrote:

    OK I got the example to work. 
    however I cannot get my plugin to work. could it be that my main window uses a .res file?

    import c4d
      
    PLUGIN_ID = 1000004 # Test ID
      
    class MainDialog(c4d.gui.GeDialog) :
      
        # Do not create the object on class-level, although it might
        # be unimportant since you do not open multiple objects of your
        # MainDialog, it is contradicting to have one instance of sub
        # dialog for all instances of the main dialog.
        # A property that creates the dialog on-demand is perfect for
        # this purpose.
      
        @property
        def sub_dialog(self) :
            if not hasattr(self, '_sub_dialog') :
                self._sub_dialog = SubDialog()
            return self._sub_dialog
        @property
        def sub_dialog2(self) :
            if not hasattr(self, '_sub_dialog2') :
                self._sub_dialog2 = SubDialog2()
            return self._sub_dialog2
        # c4d.gui.GeDialog
      
        def CreateLayout(self) :
            self.SetTitle('Main Dialog')
            self.AddButton(1000, 0, name="Open Sub-Dialog")
            return True
      
        def Command(self, param, bc) :
            if param == 1000:
                self.sub_dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=1)
                self.sub_dialog2.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=2)
            return True
      
        def Restore(self, pluginid, secref) :
            # We override this method so we don't have to handle the sub-
            # dialog from the CommandData plugin. THIS dialog is responsible
            # for the sub-dialog, do not split such management throughout
            # your program or it gets confusing.
            if secref['subid'] == 1:
                print "yes"
                return self.sub_dialog.Restore(pluginid, secref)
            if secref['subid'] == 2:
                return self.sub_dialog2.Restore(pluginid, secref)
            else:
                return super(MainDialog, self).Restore(pluginid, secref)
      
    class SubDialog(c4d.gui.GeDialog) :
      
        def CreateLayout(self) :
            self.SetTitle('Sub-Dialog')
            self.AddStaticText(1000, 0, name="This is the sub-dialog.")
            return True
            
    class SubDialog2(c4d.gui.GeDialog) :
      
        def CreateLayout(self) :
            self.SetTitle('Sub-Dialog2')
            self.AddStaticText(1000, 0, name="This is the sub-dialog2.")
            return True
      
    class Command(c4d.plugins.CommandData) :
      
        def Register(self) :
            return c4d.plugins.RegisterCommandPlugin(
                    PLUGIN_ID, "Sub-Dialog Docking Test", 0, None, "", self)
      
        @property
        def dialog(self) :
            if not hasattr(self, '_dialog') :
                self._dialog = MainDialog()
            return self._dialog
      
        # c4d.plugins.CommandData
      
        def Execute(self, doc) :
            return self.dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID)
      
        def RestoreLayout(self, secref) :
            return self.dialog.Restore(PLUGIN_ID, secref)
      
    if __name__ == '__main__':
        Command().Register()
    


  • On 08/04/2014 at 14:11, xxxxxxxx wrote:

    I think the problem with my plugin has something to do with the main command class, the "RestoreLayout" does not get called at all. I added some print functions to see and nothing. However the example prints just fine. Here is my main command code:

    class RenderBuddy(c4d.plugins.CommandData) :
      
        @property
        def RBdialog(self) :
            if not hasattr(self, '_RBdialog') :
                self._RBdialog = BuddyDialog()
            return self._RBdialog
            
        def Register(self) :
            return c4d.plugins.RegisterCommandPlugin(PLUGIN_ID, "Render Buddy (Beta)",0, bmp, "", self)
                    
        def Execute(self, doc) :
            return self.RBdialog.Open(c4d.DLG_TYPE_ASYNC,PLUGIN_ID)
            
        def RestorLayout(self, secref) :
            print "RB_Main"
            return self.RBdialog.Restore(PLUGIN_ID, secref)
        
    if __name__ == "__main__":
        
        path, fn = os.path.split(__file__)
        bmp = bitmaps.BaseBitmap()  
        bmp.InitWith(os.path.join(path, "res/icons/", "icon.tif"))
         
        RenderBuddy().Register()
    

    Everything seems to be right, but the RestoreLayout does not get called.



  • On 08/04/2014 at 14:14, xxxxxxxx wrote:

    Figured it out! After typing it out above I realized RestoreLayout() was misspelled. Thank you guys for all the help!

    *Edit there is a new problem the setup:

        def Restore(self, pluginid, secref) :
            if secref['subid'] == 1:
                print "Color"
                return self.RB_ColorDLG.Restore(pluginid,secref)
            if secref['subid'] == 2:
                print "Temp"
                return self.RB_TempDLG.Restore(pluginid,secref)
            else:
                print "Main"
                return super(BuddyDialog, self).Restore(pluginid,secref)
    

    This causes cinema to crash. I will restore the layout but if you launch the sub dialog again everything locks up. This happens with the Example as well. 



  • On 08/04/2014 at 16:01, xxxxxxxx wrote:

    Hi Shawn, I can reproduce the problems you have described. The Example I posted worked though,
    but funnily broke after a few more times testing it. I'll have to talk to a developer on this, I am pretty
    sure this is a bug. Especially this message is

    Traceback (most recent call last) :
      File "'restore-sub-dialog.pyp'", line 57, in CreateLayout
    SystemError: error return without exception set

    Best,
    -Niklas



  • On 08/04/2014 at 16:19, xxxxxxxx wrote:

    Thank you Niklas.

    -Shawn



  • On 08/04/2014 at 19:28, xxxxxxxx wrote:

    It seems to work just fine for me. No errors or problems at all.
    Maybe you're trying to do something different than I'm doing?

    Here is a complete example that works fine for me in R13.
    Save it as a .pyp file and put it in your plugins folder.
    The main dialog has buttons to open two other dialogs. And a button that will change the checkbox gizmo in dilaog1.
    All three dialogs can be docked into the UI and saved in a custom layout.

    #This is an example of a GeDialog plugin that opens three dialogs  
    #It also allows all three dialogs to be docked and saved in a custom layout  
      
    import c4d, os  
    from c4d import gui, plugins, bitmaps  
      
    PLUGIN_ID  = 1000004 #Testing ID  
    SUBDLG_ID1  = 1000005 #Testing ID  
    SUBDLG_ID2 = 1000006 #Testing ID  
      
    MAINDLG_BUTTON1_ID = 1000  
    MAINDLG_BUTTON2_ID = 1001  
    MAINDLG_BUTTON3_ID = 1002  
    SUBDLG_TEXT_ID     = 1003  
    SUBDLG_CHKBOX_ID   = 1004  
    SUBDLG_RESET_ID    = 1005  
      
    ############################  
    #The first sub dialog              
    class SubDialog1(c4d.gui.GeDialog) :  
      
      def CreateLayout(self) :  
          self.SetTitle('Sub-Dialog1')      
            
          self.GroupBeginInMenuLine()    
          self.AddCheckbox(SUBDLG_RESET_ID, c4d.BFH_RIGHT, 100, 20, name="Reset")  
          self.GroupEnd()          
            
          self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0, "MyGroup")  
          self.GroupBorderSpace(5, 5, 5, 5)  
          self.GroupBorder(c4d.BORDER_BLACK)  
          self.AddStaticText(SUBDLG_TEXT_ID, c4d.BFH_LEFT, 200, 20, "This is the sub-dialog1")  
          self.AddCheckbox(SUBDLG_CHKBOX_ID, c4d.BFH_LEFT, 20, 20, "myChkbox")  
          self.GroupEnd()   
            
          return True          
            
      def Command(self, id, msg) :  
          if id == SUBDLG_RESET_ID:  
              self.SetBool(SUBDLG_CHKBOX_ID, False)   
              self.SetBool(SUBDLG_RESET_ID, False)     
                
          return True         
            
            
    ############################  
    #The second sub dialog              
    class SubDialog2(c4d.gui.GeDialog) :  
      
      def CreateLayout(self) :  
          self.SetTitle('Sub-Dialog2')      
            
          self.GroupBeginInMenuLine()    
          self.AddCheckbox(SUBDLG_RESET_ID, c4d.BFH_RIGHT, 100, 20, name="Reset")  
          self.GroupEnd()          
            
          self.GroupBegin(0, c4d.BFH_SCALEFIT, 2, 0, "MyGroup")  
          self.GroupBorderSpace(5, 5, 5, 5)  
          self.GroupBorder(c4d.BORDER_BLACK)  
          self.AddStaticText(SUBDLG_TEXT_ID, c4d.BFH_LEFT, 200, 20, "This is the sub-dialog2")  
          self.AddCheckbox(SUBDLG_CHKBOX_ID, c4d.BFH_LEFT, 20, 20, "myChkbox")  
          self.GroupEnd()   
            
          return True          
            
      def Command(self, id, msg) :  
          if id == SUBDLG_RESET_ID:  
              self.SetBool(SUBDLG_CHKBOX_ID, False)   
              self.SetBool(SUBDLG_RESET_ID, False)     
                
          return True          
            
      
      
    ############################  
    #The main dialog  
    class MainDialog(c4d.gui.GeDialog) :   
      
      sub_dialog1 = SubDialog1()  
      sub_dialog2 = SubDialog2()          
      
      def CreateLayout(self) :  
          self.SetTitle('Main Dialog')  
          self.AddButton(MAINDLG_BUTTON1_ID, 0, name="Open Sub-Dialog1")  
          self.AddButton(MAINDLG_BUTTON2_ID, 0, name="Open Sub-Dialog2")  
          self.AddButton(MAINDLG_BUTTON3_ID, 0, name="Change Sub-Dialog1")  
          return True  
      
      def Command(self, id, msg) :  
          if id == MAINDLG_BUTTON1_ID:  
              self.sub_dialog1.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=SUBDLG_ID1)  
                
          if id == MAINDLG_BUTTON2_ID:  
              self.sub_dialog2.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=SUBDLG_ID2)              
                
          if id == MAINDLG_BUTTON3_ID:  
              self.sub_dialog1.SetBool(SUBDLG_CHKBOX_ID, True)              
                
          return True  
            
      #Restore the subdialog and the main dialog in the layout  
      def Restore(self, pluginid, secref) :  
          if secref['subid'] == SUBDLG_ID1:  
              return self.sub_dialog1.Restore(pluginid, secref)  
                
          if secref['subid'] == SUBDLG_ID2:  
              return self.sub_dialog2.Restore(pluginid, secref)              
                
          else:  
              return super(MainDialog, self).Restore(pluginid, secref)  
            
    ############################  
    #The Command Data section   
    class MainDialog_CD(c4d.plugins.CommandData) :  
      
      @property  
      def dialog(self) :  
          if not hasattr(self, '_dialog') :  
              self._dialog = MainDialog()  
          return self._dialog  
      
      def Execute(self, doc) :  
          return self.dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID)  
      
      def RestoreLayout(self, secref) :  
          return self.dialog.Restore(PLUGIN_ID, secref)  
      
    if __name__ == "__main__":  
      
      bmp = bitmaps.BaseBitmap()  
      dir, file = os.path.split(__file__)  
      fn = os.path.join(dir, "res", "icon.png")  
      bmp.InitWith(fn)  
      plugins.RegisterCommandPlugin(PLUGIN_ID, "Sub-Dialog Docking",0, bmp, "re-open", MainDialog_CD())
    

    -ScottA


Log in to reply