How can I make a simple input form for my Python script?

Hello,
I'm new about Python and Cinema 4D scripting. I've done many part of my script but I could not achieve to make a simple form that will get

  1. 3 string values
  2. 2 check box values.
  3. a directory path (I need to get a target folder path)

could anyone help me about making this form please?

thank you

... while the Team probalby will ask you to provide more context / detail ... have you looked at the sdk examples ?

https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/scripts/03_application_development/gui/dialog

kind regards

Hello @delizade,

thank you for reaching out to us. I am a bit confused when you say:

I'm new about Python and Cinema 4D scripting.

You have more than 20 postings in your account, asking Python questions which I would hardly classify as being new? Nonetheless, windows or 'input forms' are called dialogs in Cinema 4D and represented by the type c4d.gui.GeDialog. There is also another form of GUI definitions called descriptions, but they are tied to classic API nodes, e.g., a Cube object or a Noise shader. Dialogs can be modal and non-modal. In a 'Script [Manager script]' you are bound to modal dialogs, i.e., the user can only interact with the dialog until the dialog has been closed.

We also have a series of GeDialog related example scripts on GitHub. I also provided a small example which probably does some things you want to do.

Cheers,
Ferdinand

The result:
simple_dialog.gif

The code:

"""Simple example for a custom dialog in Cinema 4D.

The example will contain a file selection element and a button, as well as a multiline text box.
Pressing the button will load the content of a selected file into the text box.

Windows are represented by the class c4d.gui.GeDialog in Cinema 4D. There are two ways to define
dialogs, programmatically, as shown here, or with the help of something which is called a resource file.
Resource files work similarly to other GUI markups, as for example XAML for C# or QT-XML for QT. The
dialog raised here is modal, i.e., the user must focus on the dialog. For async, i.e., non-modal
dialogs you must write a plugin and cannot use a script (there are ways to wiggle around that 
restriction, but it is not recommended to do that.)

For more information, see the Python and C++ documentation of Cinema 4D on dialogs and dialog 
ressources.
"""

import c4d
import os

class MyDialog(c4d.gui.GeDialog):
    """Defines a dialog.
    """
    ID_TEXT = 1000
    ID_CHECKBOX = 1001
    ID_FILENAME = 1002
    ID_MULTILINE = 1003
    ID_BUTTON = 1004

    ID_GROUP = 10000

    def CreateLayout(self) -> bool:
        """Called by Cinema 4D to populate the dialog with gadgets.
        """
        # Set the title of the dialog.
        self.SetTitle("My Dialog")

        # Open a container to put other elements into.
        self.GroupBegin(id=MyDialog.ID_GROUP, flags=c4d.BFH_SCALEFIT, cols=1)
        self.GroupSpace(spacex=5, spacey=5)

        # Add a text box and a check box.
        self.AddEditText(id=MyDialog.ID_TEXT, flags=c4d.BFH_SCALEFIT)
        self.AddCheckbox(id=MyDialog.ID_CHECKBOX, flags=c4d.BFH_SCALEFIT, 
                         initw=0, inith=0, name="Check")
        
        # A Filename, i.e., an interface to select a file is a bit more fringe and must be added
        # over its custom GUI.
        self.AddCustomGui(id=MyDialog.ID_FILENAME, 
                          pluginid=c4d.CUSTOMGUI_FILENAME, 
                          name="Path", 
                          flags=c4d.BFH_SCALEFIT, 
                          minw=0, minh=0, 
                          customdata=c4d.BaseContainer())

        # Add text box spanning multiple lines (that is set to read only mode).
        self.AddMultiLineEditText(id=MyDialog.ID_MULTILINE, flags=c4d.BFH_SCALEFIT, 
                                  inith=50, style=c4d.DR_MULTILINE_READONLY)
        # Add a button.
        self.AddButton(id=MyDialog.ID_BUTTON, flags=c4d.BFH_SCALEFIT, name="Run")

        # Close the lyaout group.
        self.GroupEnd()
        
        return super().CreateLayout()

    def InitValues(self) -> bool:
        """Called by Cinema 4D to initialize a layout.
        """
        self.SetString(MyDialog.ID_TEXT, "Hello World!")
        self.SetBool(MyDialog.ID_CHECKBOX, True)
        self.SetFilename(MyDialog.ID_FILENAME, "")
        self.SetString(MyDialog.ID_MULTILINE, "")
        return super().InitValues()

    @staticmethod
    def ReadFile(filename: str) -> str:
        """Custom static function to read the content of a file into a string.
        """
        if not os.path.exists(filename):
            raise OSError("Could not access file.")

        try:
            with open(filename, mode="rt") as f:
                return f.read()
        except Exception as e:
            raise OSError(f"Could not read access file {filename}.")


    def Command(self, mid: int, msg: c4d.BaseContainer) -> bool:
        """Called by Cinema 4D when the user interacts with one of the gadgets in the dialog.
        """
        # The "Run" button has been pressed.
        if mid == MyDialog.ID_BUTTON:
            # Read the content of the file if it has been selected and put it into the multiline
            # text box, otherwise open an error dialog.
            filename = self.GetFilename(MyDialog.ID_FILENAME)
            if filename:
                self.SetString(MyDialog.ID_MULTILINE, MyDialog.ReadFile(filename))
            else:
                c4d.gui.MessageDialog("Please select a file first.")
            
        return super().Command(mid, msg)

def main():
    """Opens the dialog.
    """
    # Instantiate the dialog.
    dialog = MyDialog()
    # Open the dialog in modal mode, i.e., it will be the only thing the user can focus on.
    dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=400, xpos=-2, ypos=-2)

if __name__=='__main__':
    main()