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

    How to pass a value from GeDialog to another class

    Cinema 4D SDK
    3
    5
    856
    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.
    • D
      danielsian
      last edited by

      This is probably a silly question, but I'm stuck and need some help so I can move forward in my plugin without using global dialog.
      The original dialog has much more checkboxes and edit texts to guide the whole processing, but I've been able to get a very simplified sample of my code with a similar structure.

      I have a class

      class processing
      

      that needs to retrieve data from the dialog in order to process the script, but I really don't know how to get it since the code below is returning this error:

      AttributeError: 'OptionsDialog' object has no attribute 'print_msg1'
      

      I have to keep the structure like it is at the moment.

      This the sample, any help would be awesome:

      import c4d
      
      pluginVersion = "v1.0.0"
      pluginName = "Get Value From Dialog"
      PLUGIN_ID = 1111222
      
      class OptionsDialog (c4d.gui.GeDialog):
          GROUP_OPTIONS = 1011
          CHKBX1 = 1007
          CHKBX2 = 1008
          CHKBX3 = 1009
          BTN_OK = 1010
          def __init__(self):
              self._hasBeenInitalized = False
              self._hasLayoutDone = False
      
          def Message(self, msg, result):
              if msg.GetId() == c4d.BFM_ACTION: msg[c4d.BFM_ACTION_VALUE]        
              return c4d.gui.GeDialog.Message(self, msg, result)
          
          def CreateLayout(self):
              self.SetTitle(pluginName + ' ' + pluginVersion)
              self.AddCheckbox(self.CHKBX1, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 1')
              self.AddCheckbox(self.CHKBX2, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 2')
              self.AddCheckbox(self.CHKBX3, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 3')
              if self.GroupBegin(self.GROUP_OPTIONS, c4d.BFH_CENTER, 1, 1):
                  self.AddButton(self.BTN_OK, c4d.BFH_SCALEFIT,  initw=500, inith=15,name='Go!')
              self.GroupEnd()
              self._hasLayoutDone = True
              self._hasBeenInitalized = False
              return True
      
          def Command(self, id, msg):
              if id==self.BTN_OK or id==c4d.IDC_OK:
                  self.print_msg1 = self.GetBool(self.CHKBX1)
                  self.print_msg2 = self.GetBool(self.CHKBX2)
                  self.print_msg3 = self.GetBool(self.CHKBX3)
                  self.Run()
              return True
      
          def InitValues(self):
              if self._hasBeenInitalized is True:
                  return True
              self.SetBool(self.CHKBX1, True)
              self._hasBeenInitalized = True
              return True
      
          def Run(self):
              message = processing().set_nice_message()
              print(message)
              c4d.EventAdd()
              return True
      
      class processing:
          dlg = OptionsDialog()
          def set_nice_message(self):
      
              """ how can I get values from OptionsDialog() ???
              """
              if self.dlg.print_msg1: result = 'Hello world 1'
              if self.dlg.print_msg2: result = 'Hello world 2'
              if self.dlg.print_msg3: result = 'Hello world 3'
              return result
      
      class DialogCommandData(c4d.plugins.CommandData):
          dlg = None
      
          def Execute(self, doc):
              if self.dlg is None:
                  self.dlg = OptionsDialog()
              return self.dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC,
                                       pluginid=PLUGIN_ID,
                                       xpos=-2, ypos=-2, defaultw=720, defaulth=50)
      
          def RestoreLayout(self, secret):
              if self.dlg is None:
                  self.dlg = OptionsDialog()
              return self.dlg.Restore(pluginid=PLUGIN_ID, secret=secret)
      
      
      if __name__ == '__main__':
          myPlugin = DialogCommandData()
          c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID,
                                      str=pluginName,
                                      info=0,
                                      icon=None,
                                      help=pluginName,
                                      dat=myPlugin)
      
      1 Reply Last reply Reply Quote 0
      • CairynC
        Cairyn
        last edited by

        First of all, your dialog in the class processing is never used. So, you never open it or pass it or receive it from somewhere else. It just is generated, and then ... exists. Thus, the attempts in set_nice_message to read the print_msg attributes must fail... as these attributes are only generated when you press the OK button, and the class's local dialog is not open.

        Remove the OptionsDialog() from the class processing.
        Pass the actual dialog in the parameter list of set_nice_message.
        Consequentially, remove the self.dlg from the body of that method, and replace it by the parameter.
        In Run(), pass self (the real, actual dialog that is currently open) to set_nice_message().

        D 1 Reply Last reply Reply Quote 0
        • D
          danielsian @Cairyn
          last edited by

          @cairyn thanks for your time and helpful answer.
          I was trying to retrieve the value of a variable from another class by calling it directly. This is why you could see OptionsDialog() within class processing. This is the source of my problems, because as far as I know, this is how a class variable should be called from another class.
          Probably I'm wrong or things are different when there's a dialog involved 😕

          Anyways, this is the working code, with your solution addressed:

          import c4d
          
          pluginVersion = "v1.0.0"
          pluginName = "Get Value From Dialog"
          PLUGIN_ID = 1111222
          
          class OptionsDialog (c4d.gui.GeDialog):
              GROUP_OPTIONS = 1011
              CHKBX1 = 1007
              CHKBX2 = 1008
              CHKBX3 = 1009
              BTN_OK = 1010
              def __init__(self):
                  self._hasBeenInitalized = False
                  self._hasLayoutDone = False
          
              def Message(self, msg, result):
                  if msg.GetId() == c4d.BFM_ACTION: msg[c4d.BFM_ACTION_VALUE]        
                  return c4d.gui.GeDialog.Message(self, msg, result)
              
              def CreateLayout(self):
                  self.SetTitle(pluginName + ' ' + pluginVersion)
                  self.AddCheckbox(self.CHKBX1, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 1')
                  self.AddCheckbox(self.CHKBX2, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 2')
                  self.AddCheckbox(self.CHKBX3, c4d.BFH_SCALEFIT, initw=1, inith=1, name='Checkbox 3')
                  if self.GroupBegin(self.GROUP_OPTIONS, c4d.BFH_CENTER, 1, 1):
                      self.AddButton(self.BTN_OK, c4d.BFH_SCALEFIT,  initw=500, inith=15,name='Go!')
                  self.GroupEnd()
                  self._hasLayoutDone = True
                  self._hasBeenInitalized = False
                  return True
          
              def Command(self, id, msg):
                  if id==self.BTN_OK or id==c4d.IDC_OK:
                      self.print_msg1 = self.GetBool(self.CHKBX1)
                      self.print_msg2 = self.GetBool(self.CHKBX2)
                      self.print_msg3 = self.GetBool(self.CHKBX3)
                      self.Run()
                  return True
          
              def InitValues(self):
                  if self._hasBeenInitalized is True:
                      return True
                  self.SetBool(self.CHKBX1, True)
                  self._hasBeenInitalized = True
                  return True
          
              def Run(self):
                  message = processing().set_nice_message(self.print_msg1, self.print_msg2, self.print_msg3)
                  print(message)
                  c4d.EventAdd()
                  return True
          
          class processing:
              def set_nice_message(self, msg1, msg2, msg3):
                  if msg1: result = 'Hello world 1'
                  if msg2: result = 'Hello world 2'
                  if msg3: result = 'Hello world 3'
                  return result
          
          class DialogCommandData(c4d.plugins.CommandData):
              dlg = None
          
              def Execute(self, doc):
                  if self.dlg is None:
                      self.dlg = OptionsDialog()
                  return self.dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC,
                                           pluginid=PLUGIN_ID,
                                           xpos=-2, ypos=-2, defaultw=720, defaulth=50)
          
              def RestoreLayout(self, secret):
                  if self.dlg is None:
                      self.dlg = OptionsDialog()
                  return self.dlg.Restore(pluginid=PLUGIN_ID, secret=secret)
          
          if __name__ == '__main__':
              myPlugin = DialogCommandData()
              c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID,
                                          str=pluginName,
                                          info=0,
                                          icon=None,
                                          help=pluginName,
                                          dat=myPlugin)
          
          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @danielsian
            last edited by ferdinand

            Hello @danielsian,

            Thank you for reaching out to us. It is good to hear that you have found a working solution. For future readers I want to emphasize however a few points.

            1. A GeDialog is a Python object like any other you can just pass it around. Either inside a method of that dialog and by passing out self, i.e., the instance of the dialog. Or in the place where you did instantiate/attached your dialog, i.e. DialogCommandData in your case.
            2. set_nice_message is only formally a method of processing as it does not make use of the object instance self. You should either make the method a module function (i.e., a function without a class) or add the @staticmethod decorator, so that you do not have to insatiate a processing instance every time you want to call it, e.g., here message = processing().set_nice_message(self.print_msg1, self.print_msg2, self.print_msg3) .

            Find below an example which briefly demonstrates both points.

            Cheers,
            Ferdinand

            The result:

            Ran <__main__.Processor object at 0x0000014E8F61CB10> for <__main__.MyDialog object at 0x0000014E8F828010>.
            Ran <__main__.Processor object at 0x0000014E8F61CAD0> for <__main__.MyDialog object at 0x0000014E8F828010>.
            Ran <__main__.Processor object at 0x0000014E8F61CA90> for <__main__.MyDialog object at 0x0000014E8F828010>.
            args: (42,), kwargs: {'object': <__main__.MyDialog object at 0x0000014E8F828010>, 'msg': "bob's your uncle."}
            >>> 
            

            The code:

            import c4d
            
            class Processor(object):
                """Your processor class
                """
                def Excecute(self, dialog):
                    """The execution function of a processor.
                    """
                    if not isinstance(dialog, c4d.gui.GeDialog):
                        raise RuntimeError(f"Expected GeDialog for 'dialog': {dialog}")
            
                    # Do stuff with the dialog ...
            
                    print (f"Ran {self} for {dialog}.")
            
            # Some global processor instances
            g_processors = [Processor(), Processor(), Processor()]
            
            class MyDialog(c4d.gui.GeDialog):
                """The dialog which passes itself to all processor executions.
                """
                
                def CallProcessors(self):
                    """ The function in the dialog which calls the processors and
                    passes the dialog itself.
                    """
                    # Call all processors.
                    for p in g_processors:
                        p.Excecute(dialog=self)
            
                    # Call the global function.
                    SomeGlobalFunction(42, object=self, msg="bob's your uncle.")
            
            
            def SomeGlobalFunction(*args, **kwargs):
                """Just prints its arguments.
                """
                print (f"args: {args}, kwargs: {kwargs}")
            
            def main():
                """Entry point.
                """
                dialog = MyDialog()
                dialog.CallProcessors()
            
            if __name__ == '__main__':
                main()
            

            MAXON SDK Specialist
            developers.maxon.net

            D 1 Reply Last reply Reply Quote 0
            • D
              danielsian @ferdinand
              last edited by

              @ferdinand Thank you for your awesome explanation!
              I will keep this post as a reference for my studies as your approach seems a bit complicated for my understanding at the moment.
              I'm learning a lot with your contribution in this forum, and in this case here it's not gonna be different.
              Cheers

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