Solved Add normal button in a dialog that opens a dialog to select a folder

I need a button to open a dialog so the user can select a folder, and the button returns the path.
I know I can use

c4d.CUSTOMGUI_FILENAME

but I don't want an edit text box, but just the button. A normal button.
I can add a button with this

self.AddButton(1000, c4d.BFH_SCALEFIT,  initw=200, inith=20, name='Select Folder')

but I don't know how to select a directory on click.
According to the documentation, I can use the pluginid CUSTOMGUI_BUTTON

And that is what I was trying, but it doesn't work:

bc = c4d.BaseContainer()
bc[c4d.FILENAME_DIRECTORY] = True
self.AddCustomGui(1000, c4d.CUSTOMGUI_BUTTON, name="Select Folder", flags=c4d.BFH_SCALEFIT, minw=200, minh=200, customdata=bc)

Is it possible to add a normal button on a gui dialog so that I can pick a folder from there?

Hello @danielsian,

Thank you for reaching out to us. I am not quite sure that I understand your question correctly, but:

  • c4d.storage.LoadDialog opens the OS-native load-file dialog. With the flag FILESELECT_DIRECTORY you can make it so that the dialog behaves as directory selection dialog instead of a file selection dialog.
  • When you have added a button to a GeDialog, you would have to listen via GeDialog.Command for the button being clicked to add any logic to the event. The gedialog_modal_r13.py example demonstrates this, although it adds a AddDlgGroup instead of a AddButton, but the principle is the same.
  • You can technically also implement interactions directly via GeDialog.Message, listening for BFM_ACTION but that is more of an advanced technique.
  • A CUSTOMGUI_BUTTON gadget is just another type of UI element. Interactions are implemented in the same way as for other gadgets via .Command. Bitmap buttons have two bitmap states for their on/off state, can be tinted, and can also act as toggle buttons. They are the basis for the icons found in the palettes of Cinema 4D.
  • You can add a dedicated UI for selecting files or directories to a dialog with the data type Filename (which is represented as str in Python) and its associated GUI CUSTOMGUI_FILENAME. Find here and example.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Hello @danielsian,

Thank you for reaching out to us. I am not quite sure that I understand your question correctly, but:

  • c4d.storage.LoadDialog opens the OS-native load-file dialog. With the flag FILESELECT_DIRECTORY you can make it so that the dialog behaves as directory selection dialog instead of a file selection dialog.
  • When you have added a button to a GeDialog, you would have to listen via GeDialog.Command for the button being clicked to add any logic to the event. The gedialog_modal_r13.py example demonstrates this, although it adds a AddDlgGroup instead of a AddButton, but the principle is the same.
  • You can technically also implement interactions directly via GeDialog.Message, listening for BFM_ACTION but that is more of an advanced technique.
  • A CUSTOMGUI_BUTTON gadget is just another type of UI element. Interactions are implemented in the same way as for other gadgets via .Command. Bitmap buttons have two bitmap states for their on/off state, can be tinted, and can also act as toggle buttons. They are the basis for the icons found in the palettes of Cinema 4D.
  • You can add a dedicated UI for selecting files or directories to a dialog with the data type Filename (which is represented as str in Python) and its associated GUI CUSTOMGUI_FILENAME. Find here and example.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Thank you, @ferdinand, as always, very kind and helpful. You nailed it.

From your last example, when the button "Run" is pressed, the multiline edit text prints a list with the files from the given directory, and that is read-only.
Is there any way to have the same thing but with the ability to select some of the printed filenames from the list rather than only read them?

I know this is probably another question not directly related to the main query, but I'm just taking advantage of the fact that you provided a very nice example that happens to be another problem I'm trying to solve.

I wonder if I could achieve what I've just described by using an InExcludeData list, with the files listed there? If so, could you suggest another example?

Hello,

@danielsian said in Add normal button in a dialog that opens a dialog to select a folder:

I wonder if I could achieve what I've just described by using an InExcludeData list, with the files listed there? If so, could you suggest another example?

I am not quite sure I understand how you mean that? AnInExcludeData references GeListNode instances, so you cannot drag files into it. Or how do you mean that? I know that we have some specialized UIs which list multiple files/and or directories, but they are (a) not InExcludeData and its associated UI, and (b) also not part of the public API AFAIK. E.g., the plugin path field:

7a14abd2-b723-4076-8ba6-39281aafd478-image.png

On top of that, what you see here is not a dialog but a description, i.e., it is a whole other UI concept. If you want something like this, i.e., what is commonly known as a list box, you would have to implement it yourself for dialogs. Primarily because the cycle concept of Cinema 4D (which is closest to the concept of a list box) is always of type long. So, other than in the ListBox of Windows/WPF/WinForms, a cycle stores a selected int value and not a selected index (and whatever data you decided to store in the ListBox, usually a string).

When you want to have multiple file paths, I would simply add two buttons ("Add" and "Remove") and then dynamically rebuild the UI with the number of Filename UIs you need. I showed once here how to build a simple dynamic dialog UI.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Thanks again for clarifying my question, @ferdinand
By reading your reply and watching the example you provided, I think a TreeView could be a good way to try.

Instead of printing a list of filenames in a multiline edit text, it could instead feed a TreeView with the given folder being the parent and all files with subfolders as children, and so I could select the ones I need in order to perform another operation with those selected filenames.

Let me know please if this is something possible.
Cheers

Hey @danielsian,

Yes, a tree view could be another solution, another one could be a GeUserArea. I deliberately did not mention both options since they are more complex. Especially TreeViewFunctions, the underlying interface for tree views, tends to be overwhelming for newcomers. I would recommend the dynamic UI workflow hinted at above, as this will result in the least amount of code. But it will of course not be as beautiful as something truly custom.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net