Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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
    • Recent
    • Tags
    • Users
    • Login

    Dialogs attached to ToolData plugins never freed ?

    Scheduled Pinned Locked Moved PYTHON Development
    8 Posts 0 Posters 606 Views
    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 Offline
      Helper
      last edited by

      On 26/05/2013 at 14:54, xxxxxxxx wrote:

      Hi,

      Is it true that a GeDialog attached to a ToolData instance is never freed ? While AllocSubDialog()
      is called each time the tool is raised I could not manage to get __del__ being called for my
      GeDialog instance. I of course made sure that I do not store a reference to the dialog in
      my tools instance, like you do it normally.

      def AllocSubDialog(self, startbc) :
      	# might look funny but is the same as - return someclass.__init__()
              return self.DialogType(host = self)
      

      Also AskClose() and DestroyWindow are never called, it seems that dialog continues to
      exists internally. Normally you might prefer this behaviour or do not care about it, but
      for me it is currently a bit annoying. I just need to fetch the moment when dialog is 
      closing.

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

        On 26/05/2013 at 15:53, xxxxxxxx wrote:

        I don't know why it is not called (I also didn't test it), but you can override
        ToolData.FreeTool().

        -Nik

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

          On 26/05/2013 at 17:21, xxxxxxxx wrote:

          This is the second time you've said that "ToolData plugins have a GeDialog attached to them".
          But what I see in the docs is that ToolData plugins have a sub dialog you can use with them: AllocSubDialog(self, bc)
          Not a GeDialog.

          Where did you get the idea that a ToolData plugin has a Gedialog attached to it?
          I'm not seeing that in the docs.

          -ScottA

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

            On 27/05/2013 at 01:02, xxxxxxxx wrote:

            SubDialog is a subclass of GeDialog. And it doesn't implement anything new.

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

              On 27/05/2013 at 03:06, xxxxxxxx wrote:

              Originally posted by xxxxxxxx

              I don't know why it is not called (I also didn't test it), but you can override
              ToolData.FreeTool().

              -Nik

              the problem is, you can close a tools dialog without closing (freeing) the tool. if you try
              then to invoke methods on the tools dialog, c4d  crashes (even if you do make the dialog
              a tools class member to keep it alive).

              not sure about the internal reasons for that, but at least GeDialog.DestroyWindow()
              should be called on closing tool dialogs (as the cpp docs imply).

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

                On 27/05/2013 at 03:27, xxxxxxxx wrote:

                Ah yes, I remember this when I implemented a Python tool! I'm not sure how I got to know when

                the dialog was not visible anymore back then, but what I know is, that the reference to the dialog
                was not valid anymore and therefore Cinema crashed or you got invalid data. I cached the parameters
                using a small tool I wrote, and now I have it implemented in c4dtools.misc.dialog. Maybe you want
                to check it out, it is very useful. It enables you to retrieve all values of a dialog in a BaseContainer or
                a dictionary, and also allows you to set the values back via a  BaseContainer or dictionary.

                Here's an excerpt from a plugin where I used it in. In this code, I used it to save and load the
                parameters of the dialog to keep the configuration even when you restarted Cinema. You can
                use this to cache your symbols of course.

                import c4d
                import c4dtools
                  
                from c4dtools.misc.dialog import DefaultParameterManager
                  
                res, _ = c4dtools.prepare()
                  
                class MainDialog(c4d.gui.GeDialog) :
                  
                    def __init__(self) :
                        super(MainDialog, self).__init__()
                        self.params = DefaultParameterManager()
                  
                        # Initialize the Parameter Manager.
                        p = self.params
                  
                        p.add('reset_axes', res.CHK_RESETAXES, 'b', True)
                        p.add('optimize', res.CHK_OPTIMIZE, 'b', True)
                        p.add('optimize_tolerance', res.EDT_OPTIMIZE_TOLERANCE, 'm', 0.01)
                        p.add('set_phong_angle', res.CHK_SETPHONGANGLES, 'b', True)
                        p.add('phong_angle', res.EDT_PHONGANGLE, 'd', math.radians(21))
                        p.add('untri', res.CMB_UNTRIANGULATE, 'i', res.CMB_UNTRIANGULATE_NGONS)
                  
                        p.add('remove_empty', res.CHK_REMOVEEMPTYNULLS, 'b', True)
                        p.add('preserve_names', res.CHK_PRESERVENAMES, 'b', True)
                        p.add('remove_normaltags', res.CHK_REMOVENORMALTAGS, 'b', True)
                        p.add('remove_uvwtags', res.CHK_REMOVEUVWTAGS, 'b', True)
                        p.add('align_normals', res.CHK_ALIGNNORMALS, 'b', True)
                        p.add('norm_projection', res.CHK_NORMALIZEPROJECTION, 'b', True)
                  
                    # Just a helper I used, I could now access parameters using
                    # self.v_optimize to get the value associated with the name "optimize"
                    # in the DefaultParameterManager.
                    def __getattr__(self, name) :
                        if name.startswith('v_') :
                            name = name[2:]
                            return self.params.get(self, name)
                        else:
                            return getattr(super(MainDialog, self), name)
                  
                    def CreateLayout(self) :
                        return self.LoadDialogResource(res.DLG_MAIN)
                  
                    def InitValues(self) :
                        self.params.set_defaults(self)
                  
                        # Load a BaseContainer with all the parameters of the dialog.
                        config = load_dialog_config()
                        self.params.load_container(self, config)
                  
                        return True
                  
                    def DestroyWindow(self) :
                        config = self.params.to_container(self)
                        save_dialog_config(config)
                

                -Nik

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

                  On 27/05/2013 at 03:44, xxxxxxxx wrote:

                  the problem is not accessing dialog parameters, my dialog base class has already bc based 
                  parameter solution it is passing on each update to its host, the ToolData instance. the problem 
                  was invoking methods on the dialog from outside of the dialog, but i have solved it now using 
                  core messages and keeping all calls on the dialog inside the dialog.

                  but i think the crashing and DestroyWindow() problem should be fixed in python.

                  edit : thanks for your help 🙂 i tend to be a bit grumpy on mondays, so please excuse my grumpy 
                  tone 🙂

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

                    On 27/05/2013 at 08:51, xxxxxxxx wrote:

                    Originally posted by xxxxxxxx

                    SubDialog is a subclass of GeDialog. And it doesn't implement anything new.

                    Yes. But that does not mean that a GeDialog is "attached" to a ToolData plugin.
                    A SubDialog is available in a ToolData plugin because it was specifically added to it in the SDK by the developers. And was tested by them. The GeDialog was not.

                    Sure we can spawn a GeDialog and force it to work using special messages. We can do that in other types of plugins too. But that's not the way the developers intended us to use the ToolData class.
                    And while it's fun to create our own custom hacks and workarounds for things not in the SDK.
                    I just think its wrong (and dangerous) to say that a GeDialog is attached to a ToolData plugin.

                    -ScottA

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