Adds plugins

This commit is contained in:
2021-11-18 15:24:24 +01:00
parent 748b0804b8
commit b94590ab4f
529 changed files with 10429 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
using UnrealBuildTool;
public class EasyFileDialog : ModuleRules
{
public EasyFileDialog(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}

View File

@@ -0,0 +1,266 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#include "EFDCore.h"
#include "shlobj.h"
#include <Runtime\Core\Public\HAL\FileManager.h>
#include <Runtime\Core\Public\Misc\Paths.h>
#include <Runtime\Core\Public\Windows\COMPointer.h>
#define MAX_FILETYPES_STR 4096
#define MAX_FILENAME_STR 65536 // This buffer has to be big enough to contain the names of all the selected files as well as the null characters between them and the null character at the end
bool EFDCore::OpenFileDialogCore(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray< FString >& OutFilenames)
{
// Calling the FileDialogShared function using save parameter with false.
int OutFilterIndex=0;
return FileDialogShared(false, nullptr, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames,OutFilterIndex);
}
bool EFDCore::SaveFileDialogCore(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray< FString >& OutFilenames)
{
// Calling the FileDialogShared function using save parameter.
int OutFilterIndex = 0;
return FileDialogShared(true, nullptr, DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames, OutFilterIndex);
}
bool EFDCore::OpenFolderDialogCore(const FString& DialogTitle, const FString& DefaultPath, FString& OutFoldername)
{
// Calling the main open folder dialog function.
return OpenFolderDialogInner(NULL, DialogTitle, DefaultPath, OutFoldername);
}
bool EFDCore::FileDialogShared(bool bSave, const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray<FString>& OutFilenames, int32& OutFilterIndex)
{
#pragma region Windows
//FScopedSystemModalMode SystemModalScope;
#if PLATFORM_WINDOWS
WCHAR Filename[MAX_FILENAME_STR];
FCString::Strcpy(Filename, MAX_FILENAME_STR, *(DefaultFile.Replace(TEXT("/"), TEXT("\\"))));
// Convert the forward slashes in the path name to backslashes, otherwise it'll be ignored as invalid and use whatever is cached in the registry
WCHAR Pathname[MAX_FILENAME_STR];
FCString::Strcpy(Pathname, MAX_FILENAME_STR, *(FPaths::ConvertRelativePathToFull(DefaultPath).Replace(TEXT("/"), TEXT("\\"))));
// Convert the "|" delimited list of filetypes to NULL delimited then add a second NULL character to indicate the end of the list
WCHAR FileTypeStr[MAX_FILETYPES_STR];
WCHAR* FileTypesPtr = NULL;
const int32 FileTypesLen = FileTypes.Len();
// Nicely formatted file types for lookup later and suitable to append to filenames without extensions
TArray<FString> CleanExtensionList;
// The strings must be in pairs for windows.
// It is formatted as follows: Pair1String1|Pair1String2|Pair2String1|Pair2String2
// where the second string in the pair is the extension. To get the clean extensions we only care about the second string in the pair
TArray<FString> UnformattedExtensions;
FileTypes.ParseIntoArray(UnformattedExtensions, TEXT("|"), true);
for (int32 ExtensionIndex = 1; ExtensionIndex < UnformattedExtensions.Num(); ExtensionIndex += 2)
{
const FString& Extension = UnformattedExtensions[ExtensionIndex];
// Assume the user typed in an extension or doesnt want one when using the *.* extension. We can't determine what extension they wan't in that case
if (Extension != TEXT("*.*"))
{
// Add to the clean extension list, first removing the * wildcard from the extension
int32 WildCardIndex = Extension.Find(TEXT("*"));
CleanExtensionList.Add(WildCardIndex != INDEX_NONE ? Extension.RightChop(WildCardIndex + 1) : Extension);
}
}
if (FileTypesLen > 0 && FileTypesLen - 1 < MAX_FILETYPES_STR)
{
FileTypesPtr = FileTypeStr;
FCString::Strcpy(FileTypeStr, MAX_FILETYPES_STR, *FileTypes);
TCHAR* Pos = FileTypeStr;
while (Pos[0] != 0)
{
if (Pos[0] == '|')
{
Pos[0] = 0;
}
Pos++;
}
// Add two trailing NULL characters to indicate the end of the list
FileTypeStr[FileTypesLen] = 0;
FileTypeStr[FileTypesLen + 1] = 0;
}
OPENFILENAME ofn;
FMemory::Memzero(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = (HWND)ParentWindowHandle;
ofn.lpstrFilter = FileTypesPtr;
ofn.nFilterIndex = 1;
ofn.lpstrFile = Filename;
ofn.nMaxFile = MAX_FILENAME_STR;
ofn.lpstrInitialDir = Pathname;
ofn.lpstrTitle = *DialogTitle;
if (FileTypesLen > 0)
{
ofn.lpstrDefExt = &FileTypeStr[0];
}
ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLESIZING | OFN_EXPLORER;
if (bSave)
{
ofn.Flags |= OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT | OFN_NOVALIDATE;
}
else
{
ofn.Flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
}
if (Flags & EEasyFileDialogFlags::Multiple)
{
ofn.Flags |= OFN_ALLOWMULTISELECT;
}
bool bSuccess;
if (bSave)
{
bSuccess = !!::GetSaveFileName(&ofn);
}
else
{
bSuccess = !!::GetOpenFileName(&ofn);
}
if (bSuccess)
{
// GetOpenFileName/GetSaveFileName changes the CWD on success. Change it back immediately.
//FPlatformProcess::SetCurrentWorkingDirectoryToBaseDir();
if (Flags & EEasyFileDialogFlags::Multiple)
{
// When selecting multiple files, the returned string is a NULL delimited list
// where the first element is the directory and all remaining elements are filenames.
// There is an extra NULL character to indicate the end of the list.
FString DirectoryOrSingleFileName = FString(Filename);
TCHAR* Pos = Filename + DirectoryOrSingleFileName.Len() + 1;
if (Pos[0] == 0)
{
// One item selected. There was an extra trailing NULL character.
OutFilenames.Add(DirectoryOrSingleFileName);
}
else
{
// Multiple items selected. Keep adding filenames until two NULL characters.
FString SelectedFile;
do
{
SelectedFile = FString(Pos);
new(OutFilenames) FString(DirectoryOrSingleFileName / SelectedFile);
Pos += SelectedFile.Len() + 1;
} while (Pos[0] != 0);
}
}
else
{
new(OutFilenames) FString(Filename);
}
// The index of the filter in OPENFILENAME starts at 1.
OutFilterIndex = ofn.nFilterIndex - 1;
// Get the extension to add to the filename (if one doesnt already exist)
FString Extension = CleanExtensionList.IsValidIndex(OutFilterIndex) ? CleanExtensionList[OutFilterIndex] : TEXT("");
// Make sure all filenames gathered have their paths normalized and proper extensions added
for (auto OutFilenameIt = OutFilenames.CreateIterator(); OutFilenameIt; ++OutFilenameIt)
{
FString& OutFilename = *OutFilenameIt;
OutFilename = IFileManager::Get().ConvertToRelativePath(*OutFilename);
if (FPaths::GetExtension(OutFilename).IsEmpty() && !Extension.IsEmpty())
{
// filename does not have an extension. Add an extension based on the filter that the user chose in the dialog
OutFilename += Extension;
}
FPaths::NormalizeFilename(OutFilename);
}
}
else
{
uint32 Error = ::CommDlgExtendedError();
if (Error != ERROR_SUCCESS)
{
//UE_LOG(LogDesktopPlatform, Warning, TEXT("Error reading results of file dialog. Error: 0x%04X"), Error);
}
}
return bSuccess;
#endif
#pragma endregion
#pragma region LINUX
#if PLATFORM_LINUX
return false;
#endif
#pragma endregion
return false;
}
bool EFDCore:: OpenFolderDialogInner(const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, FString& OutFolderName)
{
//FScopedSystemModalMode SystemModalScope;
bool bSuccess = false;
TComPtr<IFileOpenDialog> FileDialog;
if (SUCCEEDED(::CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&FileDialog))))
{
// Set this up as a folder picker
{
DWORD dwFlags = 0;
FileDialog->GetOptions(&dwFlags);
FileDialog->SetOptions(dwFlags | FOS_PICKFOLDERS);
}
// Set up common settings
FileDialog->SetTitle(*DialogTitle);
if (!DefaultPath.IsEmpty())
{
// SHCreateItemFromParsingName requires the given path be absolute and use \ rather than / as our normalized paths do
FString DefaultWindowsPath = FPaths::ConvertRelativePathToFull(DefaultPath);
DefaultWindowsPath.ReplaceInline(TEXT("/"), TEXT("\\"), ESearchCase::CaseSensitive);
TComPtr<IShellItem> DefaultPathItem;
if (SUCCEEDED(::SHCreateItemFromParsingName(*DefaultWindowsPath, nullptr, IID_PPV_ARGS(&DefaultPathItem))))
{
FileDialog->SetFolder(DefaultPathItem);
}
}
// Show the picker
if (SUCCEEDED(FileDialog->Show((HWND)ParentWindowHandle)))
{
TComPtr<IShellItem> Result;
if (SUCCEEDED(FileDialog->GetResult(&Result)))
{
PWSTR pFilePath = nullptr;
if (SUCCEEDED(Result->GetDisplayName(SIGDN_FILESYSPATH, &pFilePath)))
{
bSuccess = true;
OutFolderName = pFilePath;
FPaths::NormalizeDirectoryName(OutFolderName);
::CoTaskMemFree(pFilePath);
}
}
}
}
return bSuccess;
}

View File

@@ -0,0 +1,40 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#include "EFDFunctionLibrary.h"
bool UEFDFunctionLibrary::OpenFileDialog(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, EEasyFileDialogFlags Flags, TArray< FString >& OutFilenames)
{
// Calling the core class function for open file dialog
return EFDCore::OpenFileDialogCore(DialogTitle, DefaultPath, DefaultFile, FileTypes, Flags, OutFilenames);
}
bool UEFDFunctionLibrary::SaveFileDialog(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypeDescription, const FString& FileType, EEasyFileDialogFlags Flags, TArray<FString>& OutFilenames)
{
// Saving the file type and file type description to append and Removing . if user provides any
FString TempFileType = FileType.Replace(TEXT("."), TEXT(""));
FString TempFileTypeDescription = FileTypeDescription;
// Setting description if user did not provide any
if (TempFileTypeDescription.IsEmpty())
{
TempFileTypeDescription = TempFileType.ToUpper();
}
// Creating final file types by appending FileTypeDescription and FileType
const FString FinalFileType = TempFileTypeDescription.Append("|").Append(".").Append(TempFileType);
// Calling the core class function for save file dialog
return EFDCore::SaveFileDialogCore(DialogTitle, DefaultPath, DefaultFile, FinalFileType, Flags, OutFilenames);
}
bool UEFDFunctionLibrary::OpenFolderDialog(const FString& DialogTitle, const FString& DefaultPath, FString& OutFolderName)
{
// Calling the core class function for open folder dialog
return EFDCore::OpenFolderDialogCore(DialogTitle, DefaultPath, OutFolderName);
}

View File

@@ -0,0 +1,22 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#include "EasyFileDialog.h"
#define LOCTEXT_NAMESPACE "FEasyFileDialogModule"
void FEasyFileDialogModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FEasyFileDialogModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FEasyFileDialogModule, EasyFileDialog)

View File

@@ -0,0 +1,16 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#include "EasyFileDialogBPLibrary.h"
#include "EasyFileDialog.h"
UEasyFileDialogBPLibrary::UEasyFileDialogBPLibrary(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
float UEasyFileDialogBPLibrary::EasyFileDialogSampleFunction(float Param)
{
return -1;
}

View File

@@ -0,0 +1,40 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#pragma once
#pragma warning(disable : 4668)
// Flag Enum for saving multiple or single file's
UENUM(BlueprintType)
enum EEasyFileDialogFlags
{
Single = 0x00, // No flags
Multiple = 0x01 // Allow multiple file selections
};
#include "CoreMinimal.h"
/**
*
*/
class EASYFILEDIALOG_API EFDCore
{
public:
// Open file dialog core, called from the blueprint function library
static bool OpenFileDialogCore(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray< FString >& OutFilenames);
// Save file dialog core, called from the blueprint function library
static bool SaveFileDialogCore(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray< FString >& OutFilenames);
// Open folder dialog core, called from the blueprint function library
static bool OpenFolderDialogCore(const FString& DialogTitle, const FString& DefaultPath, FString& OutFolderName);
private:
// Both open file dialog and save file dialog using this same function with different save parameter.
static bool FileDialogShared(bool bSave, const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, uint32 Flags, TArray<FString>& OutFilenames, int32& OutFilterIndex);
// The main Open folder dialog functionalities
static bool OpenFolderDialogInner(const void* ParentWindowHandle, const FString& DialogTitle, const FString& DefaultPath, FString& OutFolderName);
};

View File

@@ -0,0 +1,30 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "EFDCore.h"
#include "EFDFunctionLibrary.generated.h"
/**
*
*/
UCLASS()
class EASYFILEDIALOG_API UEFDFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
// Open File Dialog
UFUNCTION(BlueprintCallable, Category = "EasyFileDialog")
static bool OpenFileDialog(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypes, EEasyFileDialogFlags Flags, TArray< FString >& OutFilenames);
// Save File Dialog
UFUNCTION(BlueprintCallable, Category = "EasyFileDialog")
static bool SaveFileDialog(const FString& DialogTitle, const FString& DefaultPath, const FString& DefaultFile, const FString& FileTypeDescription, const FString& FileType, EEasyFileDialogFlags Flags, TArray< FString >& OutFilenames);
// Open Folder Dialog
UFUNCTION(BlueprintCallable, Category = "EasyFileDialog")
static bool OpenFolderDialog(const FString& DialogTitle, const FString& DefaultPath, FString& OutFolderName);
};

View File

@@ -0,0 +1,14 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#pragma once
#include "Modules/ModuleManager.h"
class FEasyFileDialogModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

View File

@@ -0,0 +1,32 @@
// Copyright 2017-2020 Firefly Studio. All Rights Reserved.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "EasyFileDialogBPLibrary.generated.h"
/*
* Function library class.
* Each function in it is expected to be static and represents blueprint node that can be called in any blueprint.
*
* When declaring function you can define metadata for the node. Key function specifiers will be BlueprintPure and BlueprintCallable.
* BlueprintPure - means the function does not affect the owning object in any way and thus creates a node without Exec pins.
* BlueprintCallable - makes a function which can be executed in Blueprints - Thus it has Exec pins.
* DisplayName - full name of the node, shown when you mouse over the node and in the blueprint drop down menu.
* Its lets you name the node using characters not allowed in C++ function names.
* CompactNodeTitle - the word(s) that appear on the node.
* Keywords - the list of keywords that helps you to find node when you search for it using Blueprint drop-down menu.
* Good example is "Print String" node which you can find also by using keyword "log".
* Category - the category your node will be under in the Blueprint drop-down menu.
*
* For more info on custom blueprint nodes visit documentation:
* https://wiki.unrealengine.com/Custom_Blueprint_Node_Creation
*/
UCLASS()
class UEasyFileDialogBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Execute Sample function", Keywords = "EasyFileDialog sample test testing"), Category = "EasyFileDialogTesting")
static float EasyFileDialogSampleFunction(float Param);
};