Open/Save File dialog at runtime

I’m working on an app that allows users to load in 3D models. Therefore, a file dialog of sorts is needed. When I made something similar back in Unity, I had to create my own file browser widget. It’s a lot of work and has some unavoidable limitations, so this time, I’m basically looking for any other alternatives before I attempt to do the same with Blueprints.

Option 1
Somehow expose the unreal editor file dialog code to allow runtime use. I have no idea how to do this, but I do remember reading about how Rama’s color picker is based a similar approach. Of course, it did mention that the color picker was deliberately exposed to the runtime code in unreal’s source.

Option 2
Access the native file explorer of the runtime platform through C++. Also no idea how to do it. Just wanna know if it’s even possible in the first place.

Option 3
Create a small companion app for each platform I intend to support. This companion app would invoke the native file manager of the platform and at the end, send back the filepath through a socket to the unreal app.

Option 4
The last resort, design a file explorer in unreal using UMG and blueprints. I’ve already written some blueprint nodes to help me with file and directory operations. In Unity, instantiating UI widgets (eg for each file/directory) did have some very noticeable performance issues. Am I likely to have the same problems here?

2 Likes

I’ve got the same problem. Right now the user has to put the files in a folder in the Game Root Directory. There i can access them and fill a combobox with the names.
But this cant be the final solution.
The only solution i found so far looks like your option 4 ( A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums )
I’ve tried also a Drag n Drop Tutorial without success: (https://headcrash.industries/reference/hooking-into-the-windows-message-queue-in-ue4/ )

I will work on your Option 2 and answer back, if i come to a solution.

Good to know I’m not the only one looking for this. I did a some experimentation with option 4. To my surprise, it doesn’t appear to have the performance issues I faced with Unity even when opening a folder with lots of files.

In the long run, I think I might stick with that option. I’m a high level coder and C++ can be very frustrating to understand with all those pointers and weird constructs. It’s the option with the least amount of C++. But I’d love to see what possibilities the C++ wizards out there can unlock.

I’m very interested in Option 2. Good luck!

So i managed to get a Dialog working that gives me the path of the selected file.
Right now only for Windows.
I used the Code from the 2nd comment of Emiliarge from here

I needed to edit the included Files in the header.
i include:
#include “WindowsApplication.h”
#include “Windows/WindowsSystemIncludes.h”
#include “AllowWindowsPlatformTypes.h”
#include Commdlg.h

Iam not sure if this is a good and save way, or if i need to include other files…
But its working, as far as I could test it. Even after i made a shipping packed version.
I will keep you up to date if there are some problems that i missed…

I’m also loading 3D Models at runtime. Can i ask you, how your procedure for that import is?

That’s a very good find. I’ll definitely give it a shot, thank you.
It may not be a multiplatform solution, but it’s a start at least. I’ll see if I can replicate that.

For the 3D models, I use Assimp as explained by Moddingear https://wiki.unrealengine.com/Assimp_for_Unreal
It works really well but may need some tweaks depending on your use case. For example, my UVs were flipped on the Y axis maybe because I exported from Blender. And I’ll need to expand on it to support materials as well.

1 Like

I am also working with assimp and Procedural Mesh Components. Getting good results so far :slight_smile:

Me too. One minor issue I have with Assimp so far is that it’s not async. The whole app freezes for a second until the model is loaded.

I tried your file dialog method. Works like magic! I wish it could be done for other platforms as well. Mobile looks to be out of the question since they don’t run on C++, but I could be wrong.

Yeah i need the file dialog also at least for mac. I will take a look at that soon.
I don’t have experience with mobile development, but this will maybe also become a task for me.
I also have the async problem here. There is a Wiki for loading images async, maybe there is a way to combine this with assimp…

Why not execute the model loading process in it’s own thread?

As long as you follow basic thread safety rules, I don’t think there’d be any problems.

Just be sure not to do any custom rendering stuff from that thread, since it executes within the game thread and not the rendering thread.

Did you guys make any progress?

I had some success with windows. The file dialog works as a blueprint, but does not allow for parameterizing the file type filters. So I ended up making a hardcoded blueprint node for every file dialog type my application uses. Weirdly, it worked at one point here. I haven’t tried with other platforms.
I also tried option 4. It works quite well, but it’s considerably more work. You’ll have to implement all of the interaction logic yourself, like double-click to select, and so on. If you have the time, I definitely recommend this method.

Sure. You can generate a sample blueprint function library c++ class from the unreal editor. Once you’ve done that, it will create the header (.h) and the .cpp file. My .cpp file looks like this. My header file has this as the function declaration. Then you’ll need to create another header file (FileDialog.h) in the same folder as your library’s header file and paste this into it. Then (you guessed it) its FileDialog.cpp file in the same folder as your library’s .cpp file and paste this into it.

If you follow the links in the discussion in the comments, you’ll see where all this came from. Good luck!

Any chance you can share your successes?

Thanks.
I thought this was to be a blueprint endeavor?
I’m a total noob in case you haven’t already guessed :slight_smile: not ready for C++

Revisiting this issue, I was able to come up with a much neater solution. It uses the amazing [UnrealEnginePython][1] plugin. Besides unlocking the full power and comfort of Python, it has the added benefit of eliminating the need for C++ in this case. After setting up the plugin, simply pip install any Python GUI framework and call its file dialog functions. Since the GUI frameworks are crossplatform, I believe this method should work on Linux and other supported platforms as well. But I’ve only tried with Windows. Please let me know how it goes with other platforms.

Mini Example

Download a suitable embedded version of UnrealEnginePython and add to the Plugins folder of your project, and enable it in your Plugins settings. To install PySide2, a Python binding of the popular QT framework, run the following command from the Python folder in the plugin (…MyProject/Plugins/UnrealEnginePython/Binaries/Win64/).

./python.exe -m pip install --target . pyside2

With that done, create a PyActor blueprint class and set up its variables like so

248477-ue-fd-vars.png

Then set up the actor like so

248479-ue-fd-actor.png

We then create a file_dialog.py in the Project/Scripts folder and paste the following in it.

from PySide2 import QtCore, QtWidgets, QtGui
import unreal_engine as ue
from PySide2.QtWidgets import QFileDialog
from unreal_engine import FSlateApplication
#this import initializes our qt app
from ueqt import inst as ueqt


class DummyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

class FileDialogManager:
    # this is called on game start
    def begin_play(self):
        ue.log("File Dialog:::Start")
        
    def open(self):
        widget = DummyWidget()
        # widget.resize(800, 600)
        # widget.show()

        # get the active top level window
        top_window = FSlateApplication.get_active_top_level_window()
        top_window.set_as_owner(widget.winId())

        f = QFileDialog.getOpenFileName(
            widget, #parent
            self.uobject.Title, #title
            self.uobject.InitialDir, #initial dir
            ";;".join(self.uobject.FileTypeFilters), #filters
            self.uobject.FileTypeFilters[self.uobject.SelectedFileTypeFilter] #selected filter
        )
        if len(f[0]) < 1:
            ue.log("Open File Dialog:::Canceled")
            self.uobject.call_function('OnCancel')
            return
        ue.log("Open File Dialog:::Confirmed")
        ue.log(f)
        widget.close()
        self.uobject.Filepath = f[0]
        self.uobject.call_function('OnOpen')
        
    # this is called at every 'tick'
    def tick(self, delta_time):
        pass
    
    # this is called at the end
    def end_play(self, reason=None):
        ue.log("File Dialog:::Quit")
        ue.log(reason)

Then we create a ueqt.py script

import sys
import unreal_engine as ue
import PySide2
from PySide2 import QtWidgets

class UEQT:
    app = None

    def __init__(self):
        self.app = QtWidgets.QApplication(sys.argv)

inst = UEQT()
ue.set_brutal_finalize(True)

That’s all the coding we need. Head back to our PyActor and create a function called Open and another called OnOpen. Then create an event dispatcher called OnFileOpen with a single string input.

248480-ue-fd-open.png

248491-ue-fd-on-open.png

Then to open a dialog when you need to, simply spawn the actor, bind the OnFileOpen event and call Open.

If you get stuck, check out this repo on Bitbucket Bitbucket. It was created following this example. You can study its blueprint classes and python files for a better understanding.

Note: At the time of writing, only the latest code from the UnrealEnginePython repo supports attaching the file dialog to the unreal window. You should build the plugin from source (following the instructions on their page) if this is needed. Or comment out the lines of code with “top_window”. It will still open the file dialog, but it will not be attached to the unreal window. Or just wait for them to update the releases :slight_smile:

hi khlibloo can show me some thing that how its working i am making the same thing

thanks thats what i want i am going to do that i will let you know if get any problem and some how can you make simple project of this and share it?will help alot

Ok, I’ll try writing a wiki page as soon as someone can confirm that this method does work for other platforms

I’m not sure what you mean. It’s a regular native file dialog. I’ve attached a screenshot of a test I did in a packaged unreal app running on windows. A side-effect I found was that including a gui framework in a packaged app increases package size. Pyside2 added around 40mb after stripping down its unnecessary files.

can you help me installing pyside2 for python?like from where to run the command. i run it from python.exe in plugins but it says syntax error