ImGuiNET / ImGui.NET

An ImGui wrapper for .NET.
MIT License
1.89k stars 305 forks source link

Open File Dialog #22

Closed Sage-of-Mirrors closed 6 years ago

Sage-of-Mirrors commented 7 years ago

As our project relies on a lot input and output, most of it controlled by the user, ImGui presents a major issue since it has no "native" (read: already implemented) open file/directory dialog. If my understanding is correct, this is mostly due to the fact that it is difficult to create a reliable cross-platform open file dialog due to the differences between systems (Windows, Linux, iOS).

Ocornut had a discussion about it here, and it seems that the result of that thread was imguifilesystem. This, however, is for the original ImGui, in C++. There is the option of converting the C++ to C#, but the file is large with a lot of branches depending on the underlying system. Is there an easier way to integrate this pre-made ImGui add-on with ImGui-NET? Or would we be better off working out our own open file dialog?

mellinoe commented 7 years ago

I think the best and most manageable option here is to just write a custom control on top of ImGui.NET, rather than try to re-use the C++ implementation. It could simply be built on top of the file system types in the BCL (File, Directory, etc.), which already handle platform differences. By the way, I have done something like that in another side project. You can see the code here: https://github.com/mellinoe/synthapp/blob/master/src/synthapp/Widgets/FilePicker.cs. Disclaimer: it is extremely rough, and it is very ugly. But, it does work, for the most part.

Another option is to actually attempt to use native file picker dialogs, rather than implement one in a custom ImGui widget. You could try to create a PInvoke wrapper over something like this: https://github.com/mlabbe/nativefiledialog. It would give you a more "natural-feeling" file picker. Then again, it won't integrate as cleanly with the rest of your ImGui-based interface.

Sage-of-Mirrors commented 7 years ago

I see. Thank you for your input, I appreciate it. My partner and I did briefly suggest making a file picker using System.IO and ImGui. I think that's what we'll do. I'll have to get used to ImGui first, though. For example, I'm not entirely sure how to have the dialog open from the main window without hardcoding a check for if the dialog /should/ be open.

mellinoe commented 7 years ago

@Sage-of-Mirrors You can take a look at my example to see one possible way. Here is the important code:

if (ImGui.Button(label))
{
    ImGui.OpenPopup(FilePickerID);
}

bool result = false;
if (ImGui.BeginPopupModal(FilePickerID, WindowFlags.NoTitleBar))
{
    result = DrawFolder(ref selected, true);
    ImGui.EndPopup();
}
...
return result;

https://github.com/mellinoe/synthapp/blob/master/src/synthapp/Widgets/FilePicker.cs#L58

mellinoe commented 6 years ago

I don't have any plans on adding extra custom controls on top of what native ImGui supports. But if someone has a good file picker UI in C#, I'd be happy to start collecting them into a list or perhaps the wiki.

prime31 commented 5 years ago

Found this old thread and in case anyone else comes to it I made some mods to @mellinoe's FilePicker:

You can get it here: https://gist.github.com/prime31/91d1582624eb2635395417393018016e

Usage is like so for file picking:

            var isOpen = true;
            if (ImGui.BeginPopupModal("open-file", ref isOpen, ImGuiWindowFlags.NoTitleBar))
            {
                var picker = FilePicker.GetFilePicker(this, Path.Combine(Environment.CurrentDirectory, "Content/Atlases"), ".png|.atlas");
                if (picker.Draw())
                {
                    Console.WriteLine(picker.SelectedFile);
                    FilePicker.RemoveFilePicker(this);
                }
                ImGui.EndPopup();
            }

And like this for folder picking:

            var isOpen = true;
            if (ImGui.BeginPopupModal("save-file", ref isOpen, ImGuiWindowFlags.NoTitleBar))
            {
                var picker = FilePicker.GetFolderPicker(this, Path.Combine(Environment.CurrentDirectory));
                if (picker.Draw())
                {
                    Console.WriteLine(picker.SelectedFile);
                    FilePicker.RemoveFilePicker(this);
                }
                ImGui.EndPopup();
            }