While our game may be running without any issues in the editor or even in…
Creating a File Picker
In this post we’re going to see how to create a basic File Picker inside Unreal Engine. We’re going to use the built-in tools that the engine provides and read a text file.
[button size=”big” color=”black” link=”https://github.com/orfeasel/UE4-Cpp-Tutorials/tree/master/FilePicker”]Download the entire source code from my GitHub repo[/button]Adding the required Dependencies
For this post I have created a C++ project using the 4.20 version of the engine. Then, I added the SlateCore dependency in the public module names in the <MyProject>.Build.cs file:
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay","SlateCore" });Creating the file picker
Ideally, you will place the functionality of the file picker in a utility library so you can use it throughout your project. However I’ve added the code inside the character code just for demonstration purposes.
I have created two functions, one that is responsible for opening and displaying the file picker and one which is responsible for getting the contents of the selected file:
1 2 3 4 5 6 7 8 9 10 11 12 |
/* * Opens a file dialog for the specified data. Leave FileTypes empty to be able to select any files. * Filetypes must be in the format of: <File type Description>|*.<actual extension> * You can combine multiple extensions by placing ";" between them * For example: Text Files|*.txt|Excel files|*.csv|Image Files|*.png;*.jpg;*.bmp will display 3 lines for 3 different type of files. */ UFUNCTION(BlueprintCallable, Category = "FilePicker") void OpenFileDialog(const FString& DialogTitle, const FString& DefaultPath, const FString& FileTypes, TArray<FString>& OutFileNames); /*Prints the data of the given file*/ UFUNCTION(BlueprintCallable, Category = "FilePicker") void PrintData(const FString& File); |
Before implementing the logic for each function, make sure to include the following header files in your class:
1 2 3 |
//File picker includes #include "Developer/DesktopPlatform/Public/IDesktopPlatform.h" #include "Developer/DesktopPlatform/Public/DesktopPlatformModule.h" |
The reason we need to include them is so we can have access to the deskplatform code where the built-in file picker exists.
Here’s the implementation of each function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
void AFilePickerCharacter::OpenFileDialog(const FString& DialogTitle, const FString& DefaultPath, const FString& FileTypes, TArray<FString>& OutFileNames) { if (GEngine) { if (GEngine->GameViewport) { void* ParentWindowHandle = GEngine->GameViewport->GetWindow()->GetNativeWindow()->GetOSWindowHandle(); IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); if (DesktopPlatform) { //Opening the file picker! uint32 SelectionFlag = 0; //A value of 0 represents single file selection while a value of 1 represents multiple file selection DesktopPlatform->OpenFileDialog(ParentWindowHandle, DialogTitle, DefaultPath, FString(""), FileTypes, SelectionFlag, OutFileNames); } } } } void AFilePickerCharacter::PrintData(const FString& File) { //Parse the data into a string array TArray<FString> LoadedText; FFileHelper::LoadFileToStringArray(LoadedText, *File); //Print the contents for (int32 i = 0; i < LoadedText.Num(); i++) { GLog->Log(LoadedText[i]); } } |
After compiling my code, I created the following BP code to read the contents of the single file I selected:
Here is how the file dialog looks from within the engine:
It’s worth noting that depending on the files that you want to read your print/parse data function may differ from this post. If you want to be able to select any data type you can leave the file types string empty.
Do you know how to make sure that this works with a packaged product? For example, when packaging with UE4.19 for Windows 64 bit, your function gives me this error:
https://i.imgur.com/p3d2upy.png
But it works just fine in PIE!
Hey, I’ve not tested yet, but I think this is because of a missing module linkage. It’s weird that there is no compile time error actually.
I will try with
PublicDependencyModuleNames.AddRange(new string[] { “Core”, “CoreUObject”, “Engine”, “InputCore”, “DesktopPlatform” });
(SlateCore and HeadMountedDisplay are other modules, maybe useful for the author, but unnecessary for this tutorial)
I will let you know if this works
Hi, I’m having the same issue also with UE 19. Should I try a different version of ue?
Is there any chance you could compile this as a plugin? I’m not familiar with C++, so this would be a huge help. Thanks!
Hey, thank you for this it is really helpful! Right now I only have it working in PIE, do you know how I could modify this to work in the editor? Trying to build out some fool proof UI for getting different URI’s
hey, package shipping filed error,
UATHelper: Packaging (Windows(64位)): ERROR: Missing precompiled manifest for ‘DesktopPlatform’. This module was most likely not flagged for being included in a precompiled build – set ‘PrecompileForTargets = PrecompileTargetsType.Any;’ in DesktopPlatform.build.cs to override.
Can You know how to setting ? Thanks for you
Is it possible to select folder paths?, not a file.
For anyone else who reads this: look into PromptUserForDirectory. Not sure if it supports multiple filepath selection, though.
The DesktopPlatform module is a Developer module, the EULA version of the engine does not include Developer modules for Shipping builds. An Epic employee recommends building a custom UMG/Slate file picker that relies on IPlatformFile system instead.
Very useful. Just a note, rather than declaring a specific windows handle, which didn’t seem to work for me in 4.24, let Slate handle that by using this code as the first argument in the OpenFileDialogue:
FSlateApplication::Get().FindBestParentWindowHandleForDialogs(nullptr)
Daniel, thank you a million times,
I’ve been trying to get a viewport window handle in the editor for a couple hours now and your SlateApplication WindowHandle get worked like a charm. Cheers!
Thanks for the example! Successfully works on UE5!