Dialogs attached to ToolData plugins never freed ?

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


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 

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


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.


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

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

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


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).

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)
            return getattr(super(MainDialog, self), name)
    def CreateLayout(self) :
        return self.LoadDialogResource(res.DLG_MAIN)
    def InitValues(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)


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 :)

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.