[Py4D] SubDialogs in ToolData plugins



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 30/01/2012 at 08:24, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:    
    Platform:      
    Language(s) :

    ---------
    When using a SubDialog to display a settings-dialog for a ToolData plugin, make sure to save the options somewhere while the user is changin them. As soon as the user selects another object/tag or alike, the options-dialog will disappear. This will cause any call's to GetReal, GetLong, etc. to freeze Cinema 4D. Actually, I had a long time to figure this out as it isn't any remark about this in the documentation.

    Here is an example that easen's the use of a SubDialog:

      
    import c4d  
    import copy  
      
    class PreparedSubDialog(c4d.gui.SubDialog) :  
      
      BASEDATA = dict()  
      data     = None  
      
      def __init__(self, data = None) :  
          if not data:  
              self.data = copy.deepcopy(self.BASEDATA)  
          elif isinstance(data, PreparedSubDialog) :  
              self.data = data.data  
          else:  
              self.data = data  
      
      def __getattr__(self, name) :  
          item = self.data.get(name, None)  
          if not item:  
              raise AttributeError('No such dialog-element %r.' %name)  
          id, type, value, min, max = item  
          return value  
      
      # ---- overwritten from ``c4d.gui.GeDialog`` -------------------------------  
      
      def InitValues(self) :  
          for name, (id, type, default, min, max) in self.data.iteritems() :  
              if type == 'str':  
                  self.SetString(id, default)  
              elif type == 'm':  
                  self.SetMeter(id, default, min, max)  
              elif type == 'p':  
                  self.SetPercent(id, default, min, max)  
              elif type == 'b':  
                  self.SetBool(id, default)  
              elif type == 'l':  
                  self.SetLong(id, default, min, max)  
              elif type == 'r':  
                  self.SetReal(id, default, min, max)  
              elif type == 'd':  
                  self.SetDegree(id, default, min, max)  
              elif type == 't':  
                  self.SetTime(id, default, min, max)  
              elif type == 'f':  
                  self.SetFilename(id, default)  
              else:  
                  raise ValueError('Unknown element-type %r.' % type)  
          return True  
      
      def Command(self, id, msg) :  
          # save the values  
          for name, v in self.data.iteritems() :  
              if v[0] == id:  
                  v[2] = self.__getattr__(name)  
                  break  
          return True
    

    A possible subclass could look like this:

    class MySubDialog(PreparedSubDialog) :  
      
      ID_MYREAL   = 1001  
      ID_MYSTRING = 1002  
      ID_MYMETER  = 1003  
      ID_MYBOOL   = 1004  
      
      BASEDATA    = dict( myreal   = [ID_MYREAL, 'r', 0, 0, 1000],  
                          mystring = [ID_MYSTRING, 's', 'String here', None, None],  
                          mymeter  = [ID_MYMETER, 'm', 100, -500, 500],  
                          mybool   = [ID_MYBOOL, 'b', True, None, None] )  
      
      def CreateLayout(self) :  
          self.AddStaticString(self.ID_MYSTRING, c4d.BFH_FIT)  
          self.AddEditNumberArrows(self.ID_MYREAL, c4d.BFH_FIT)  
          self.AddEditNumberArrows(self.ID_MYMETER, c4d.BFH_FIT)  
          self.AddCheckbox(self.ID_MYBOOL, c4d.BFH_FIT)
    

    And used like this:

    class MyToolPlugin(c4d.plugins.ToolData) :  
      
      dlg = None  
      
      def MouseInput(self, doc, data, bd, win, msg) :  
          myreal   = self.dlg.myreal  
          mystring = self.dlg.mystring  
          mymeter  = self.dlg.mymeter  
          mybool   = self.dlg.mybool  
      
          # ...  
      
      def AllocSubDialog(self, bc) :  
          self.dlg = MySubDialog(self.dlg)  
          return self.dlg
    

    Any problems understanding the code? Ask. 🙂

    Greetz, Niklas


Log in to reply