Solved Drag and Drop external image in a gui Edit Text box with Python

I have a gui.GeDialog with a few Edit Text boxes and I wanted to drop textures from my Windows Explorer on there and get the full path of each texture, just like in the texture field on a material.

I found a couple of useful posts approaching the same question, but the solution seems to be directed to more experienced Python users, as they have only parts of code, not a full working example.

I'd appreciate if someone could share an example on how to do that in this dialog here:

import c4d

class MyDialog(c4d.gui.GeDialog):

    def CreateLayout(self):
        
        self.AddEditText(1000, c4d.BFH_SCALEFIT, initw=0, inith=0)
        self.AddEditText(1001, c4d.BFH_SCALEFIT, initw=0, inith=0)
        self.AddEditText(1002, c4d.BFH_SCALEFIT, initw=0, inith=0)
        self.AddEditText(1003, c4d.BFH_SCALEFIT, initw=0, inith=0)
        return True

def main():
    dialog = MyDialog()
    dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=500, defaulth=500)

if __name__ == '__main__':
    main()

Hi @danielsian,

thank you for reaching out to us. To replicate the BitmapShader behaviour you have to use a FilenameCustomGui. It comes with drag and drop support out of the box. Below is an example showcasing how to create such an element in a GeDialog and how to interact with drag and drop events.

Cheers,
Ferdinand

the code:

"""Example for creating a CUSTOMGUI_FILENAME in a GeDialog and how to handle
drag and drop events.

As discussed in:
    plugincafe.maxon.net/topic/13240

References:
    [1] developers.maxon.net/docs/Cinema4DCPPSDK/html/class_filename_custom_gui.html
"""

import c4d

ID_FILE_LINK_1 = 1000


class MyDialog(c4d.gui.GeDialog):

    def CreateLayout(self):
        """
        """
        # Add a filename custom GUI to the dialog. You can read more about it
        # in the C++ documentation [1]. The type itself has not been wrapped
        # for Python, but you can interact with it as a BaseCustomGui.
        self.AddCustomGui(ID_FILE_LINK_1, c4d.CUSTOMGUI_FILENAME, "",
                          c4d.BFH_SCALEFIT, 0, 0, c4d.BaseContainer())

        return True

    def Message(self, msg, result):
        """
        """
        # When the message id is BFM_ACTION.
        if msg.GetId() == c4d.BFM_ACTION:
            # An action send from the filename GUI ID_FILE_LINK_1.
            if msg[c4d.BFM_ACTION_ID] == ID_FILE_LINK_1:
                # The newly set file path value.
                filePath = msg[c4d.BFM_ACTION_VALUE]
                print(filePath)
                # You can also access the directly element like so:
                filePath = self.GetString(ID_FILE_LINK_1)
                print (filePath)

        return c4d.gui.GeDialog.Message(self, msg, result)

DIALOG = None

def main():
    global DIALOG
    DIALOG = MyDialog()
    DIALOG.Open(dlgtype=c4d.DLG_TYPE_ASYNC,
                defaultw=500, defaulth=500)


if __name__ == '__main__':
    main()

Its behaviour:
1.gif

MAXON SDK Specialist
developers.maxon.net

Hi @danielsian,

thank you for reaching out to us. To replicate the BitmapShader behaviour you have to use a FilenameCustomGui. It comes with drag and drop support out of the box. Below is an example showcasing how to create such an element in a GeDialog and how to interact with drag and drop events.

Cheers,
Ferdinand

the code:

"""Example for creating a CUSTOMGUI_FILENAME in a GeDialog and how to handle
drag and drop events.

As discussed in:
    plugincafe.maxon.net/topic/13240

References:
    [1] developers.maxon.net/docs/Cinema4DCPPSDK/html/class_filename_custom_gui.html
"""

import c4d

ID_FILE_LINK_1 = 1000


class MyDialog(c4d.gui.GeDialog):

    def CreateLayout(self):
        """
        """
        # Add a filename custom GUI to the dialog. You can read more about it
        # in the C++ documentation [1]. The type itself has not been wrapped
        # for Python, but you can interact with it as a BaseCustomGui.
        self.AddCustomGui(ID_FILE_LINK_1, c4d.CUSTOMGUI_FILENAME, "",
                          c4d.BFH_SCALEFIT, 0, 0, c4d.BaseContainer())

        return True

    def Message(self, msg, result):
        """
        """
        # When the message id is BFM_ACTION.
        if msg.GetId() == c4d.BFM_ACTION:
            # An action send from the filename GUI ID_FILE_LINK_1.
            if msg[c4d.BFM_ACTION_ID] == ID_FILE_LINK_1:
                # The newly set file path value.
                filePath = msg[c4d.BFM_ACTION_VALUE]
                print(filePath)
                # You can also access the directly element like so:
                filePath = self.GetString(ID_FILE_LINK_1)
                print (filePath)

        return c4d.gui.GeDialog.Message(self, msg, result)

DIALOG = None

def main():
    global DIALOG
    DIALOG = MyDialog()
    DIALOG.Open(dlgtype=c4d.DLG_TYPE_ASYNC,
                defaultw=500, defaulth=500)


if __name__ == '__main__':
    main()

Its behaviour:
1.gif

MAXON SDK Specialist
developers.maxon.net

Hey Ferdinand, thank you very much for your time. I really appreciate that!

A custom GUI is so much easier, that I think my whole script is gonna be much shorter and with a pretty nice new functionality.

Cheers

Hi,

I am glad that it works for you, @m_magalhaes also pointed out that the custom gui flags (you have to write them into the BaseContainer passed an argument to the AddCustomGui call) might be helpful to you in case you want the gui to look more like a text box. The flag NOSELECT will make the ... button disappear. You can play around with the flags in the user data manager.

Cheers,
Ferdinand

The user data manager with a Filename element and its flags:
09dfb5db-3b80-4bc4-853d-35e47a134997-image.png

MAXON SDK Specialist
developers.maxon.net

Great!
Cheers!