SOLVED Tool plugin gui

Hi,
I want to create a gui interface similar to the Measure tool for my tool, but the gui is blank when my tool is running.
I read py-sculpt_grab_brush_r16 in github, but I still can't solve my problem

Here is my toolsscreenshot.h file

#ifndef TOOLSSCREENSHOT_H__
#define TOOLSSCREENSHOT_H__

enum
{

	SSCREENSHOT_GROUPTWO_CUTBUTTON = 1051,
};
#endif 

Here is my toolsscreenshot.res file

CONTAINER toolsscreenshot
{
    NAME toolsscreenshot;

    GROUP MDATA_MAINGROUP
    {
        SCALE_H;
        COLUMNS 1;
        BUTTON SSCREENSHOT_CUTBUTTON {}

    }
}

Here is my toolsscreenshot.str file

STRINGTABLE toolsscreenshot
{
    toolsscreenshot "S_ScreenShot";

	SSCREENSHOT_CUTBUTTON "Cut";
}


and the toolsscreenshot.pyp file

class S_ScreenShot(plugins.ToolData):
    

    def Draw(self, doc, data, bd, bh, bt, flags):
     
        return c4d.TOOLDRAW_NONE

    def MouseInput(self, doc, data, bd, win, msg):
        return True



if __name__ == "__main__":
    bmp = bitmaps.BaseBitmap()
    dir, file = os.path.split(__file__)
    fn = os.path.join(dir, "res", "S_PanZoom2D.tif")
    bmp.InitWith(fn)
    plugins.RegisterToolPlugin(id=PLUGIN_ID, str="S_ScreenShot",
                               info=0, icon=bmp,
                               help="",
                               dat=S_ScreenShot())

Thanks for any help

Hello @chuanzhen,

Thank you for reaching out to us. In short, the answer is that you are looking at the wrong example and therefore do not load your GUI, resulting in nothing being displayed. You must overwrite ToolData.AllocSubDialog() to show your tool dialog.

There are two ways to implement tools in the Cinema 4D API: ToolData plugins which base their GUI on dialog resources, and DescriptionToolData plugins which base their GUI on description resources, i.e., work for example similar to an ObjectData plugin.

In Python you can only implement directly ToolData plugins, i.e., plugins which are based on dialogs. There is however one caveat, as there is SculptBrushToolData, which is a specialization of DescriptionToolData for sculpting brushes. And SculptBrushToolData has been wrapped for Python, sculpt_grab_brush_r16.pyp is an example for that.

Python examples for ToolData plugins can be found in py-liquid_painter_r12.pyp and py-tooldata_ui_r15.pyp. Your class S_ScreenShot is not implementing AllocSubDialog and therefore cannot open that dialog. It must look something like this:

class MyToolDialog(c4d.gui.SubDialog):
    """Realizes a dialog for a tool hook.
    """
    def __init__(self, toolData: c4d.BaseContainer) -> None:
        """Not necessary, but IMHO advantageous to grab the tool data container.
        """
        self._toolData = toolData

    def CreateLayout(self) -> bool:
        """Adds gadgets to the dialog.

        Either populate the dialog manually or load a dialog resource.
        """
        return self.LoadDialogResource(*data)


class S_ScreenShot(plugins.ToolData):
    """Realizes a tool hook.
    """

    def AllocSubDialog(self, bc: c4d.BaseContainer) -> c4d.gui.SubDialog:  
        """Called by Cinema 4D to allocate the tool dialog.
        """
        return MyToolDialog(bc)

    ...

Cheers,
Ferdinand

Hello @chuanzhen,

Thank you for reaching out to us. In short, the answer is that you are looking at the wrong example and therefore do not load your GUI, resulting in nothing being displayed. You must overwrite ToolData.AllocSubDialog() to show your tool dialog.

There are two ways to implement tools in the Cinema 4D API: ToolData plugins which base their GUI on dialog resources, and DescriptionToolData plugins which base their GUI on description resources, i.e., work for example similar to an ObjectData plugin.

In Python you can only implement directly ToolData plugins, i.e., plugins which are based on dialogs. There is however one caveat, as there is SculptBrushToolData, which is a specialization of DescriptionToolData for sculpting brushes. And SculptBrushToolData has been wrapped for Python, sculpt_grab_brush_r16.pyp is an example for that.

Python examples for ToolData plugins can be found in py-liquid_painter_r12.pyp and py-tooldata_ui_r15.pyp. Your class S_ScreenShot is not implementing AllocSubDialog and therefore cannot open that dialog. It must look something like this:

class MyToolDialog(c4d.gui.SubDialog):
    """Realizes a dialog for a tool hook.
    """
    def __init__(self, toolData: c4d.BaseContainer) -> None:
        """Not necessary, but IMHO advantageous to grab the tool data container.
        """
        self._toolData = toolData

    def CreateLayout(self) -> bool:
        """Adds gadgets to the dialog.

        Either populate the dialog manually or load a dialog resource.
        """
        return self.LoadDialogResource(*data)


class S_ScreenShot(plugins.ToolData):
    """Realizes a tool hook.
    """

    def AllocSubDialog(self, bc: c4d.BaseContainer) -> c4d.gui.SubDialog:  
        """Called by Cinema 4D to allocate the tool dialog.
        """
        return MyToolDialog(bc)

    ...

Cheers,
Ferdinand

@ferdinand Thanks for your help!
My last version used dialog to implement gui, but due to some data transmission methods, I want to use res method to re-implement it, it seems that this is a limitation, I can only use dialog to achieve!
Use dialog:
b91d7819-49e8-49f4-bc9f-ffb2d4bbb5a7-image.png

Hello @chuanzhen,

I unfortunately do not fully understand what you want to say.

My last version used dialog to implement gui, but due to some data transmission methods, I want to use res method to re-implement

Both ToolData and DescriptionToolData allow defining their GUI using resources, one uses dialog resources, the other description resources.

it, it seems that this is a limitation, I can only use dialog to achieve!

I am not quite sure what you mean by limitation here. Not being able to implement a DescriptionToolData plugin in Python is a limitation, but that does not stop you from defining your tool plugin GUI in a resource.

If you really want a description-based tool, you must move to C++ there you would also have (more) direct viewport image buffer access, which would further incentivize doing this.

Cheers,
Ferdinand

@ferdinand yes,limition is python can not creat DescriptionToolData.
I'm not sure how to use resources to define the gui, in the above example also use function CreateLayout(), self.AddButton(), etc. to add elements.
There are related examples about defining their GUI uses dialog resources?
Thanks!

Hello @chuanzhen,

in the above example also use function CreateLayout(), self.AddButton(),

I am not sure to which example you refer, but if it is my mock-up, you will see that it does not use any of the methods for adding gadgets manually. But you of course still have to implement the dialog and CreateLayout.

def CreateLayout(self) -> bool:
    """Adds gadgets to the dialog.

    Either populate the dialog manually or load a dialog resource.
    """
    return self.LoadDialogResource(*data)

The example is a bit optimistic, usually you still must do some stuff in the dialog, like for example adjusting the title or populating its menu, but in principle you just have to call self.LoadDialogResource(*data) to load a dialog resource into a dialog. Note that you can also invoke the method in succession to load in multiple dialog fragements.

There is no dedicated Python documentation for this, but it all works in Python too, I have used it myself recently. I would recommend having a look at:

  • The C++ Resource Files Manual to understand how resources work in general (and that there are two types of resources: one for descriptions and one for dialogs),
  • the C++ Dialog Layout Manual to understand the fundamental design principle of a dialog (which you probably already do), and
  • the C++ Dialog Resource Manual which describes the syntax of dialog resource files. Which is very similar to the syntax of description resources but not identical to it.

As far as I am aware of, we have no Python examples for using GeDialog.LoadDialogResource but there are plenty of C++ examples. The Asset API Examples Dialog is for example partially being loaded from a dialog resource (in line 80).

Cheers,
Ferdinand

@ferdinand Thanks!