1388 lines
57 KiB
C#
1388 lines
57 KiB
C#
using System.Linq;
|
|
using UnityEngine;
|
|
using Crosstales.FB.Util;
|
|
using Crosstales.FB.Wrapper;
|
|
|
|
namespace Crosstales.FB
|
|
{
|
|
/// <summary>Native file browser various actions like open file, open folder and save file.</summary>
|
|
[ExecuteInEditMode]
|
|
[DisallowMultipleComponent]
|
|
[HelpURL("https://www.crosstales.com/media/data/assets/FileBrowser/api/class_crosstales_1_1_f_b_1_1_file_browser.html")]
|
|
public class FileBrowser : Crosstales.Common.Util.Singleton<FileBrowser>
|
|
{
|
|
#region Variables
|
|
|
|
[Header("Custom Wrapper"), Tooltip("Custom wrapper for File Browser."), SerializeField] private BaseCustomFileBrowser customWrapper;
|
|
|
|
[Tooltip("Enable or disable the custom wrapper (default: false)."), SerializeField] private bool customMode;
|
|
|
|
[Header("Titles")] [Tooltip("Title for the 'Open File'-dialog."), SerializeField] private string titleOpenFile = "Open File";
|
|
[Tooltip("Title for the 'Open Files'-dialog."), SerializeField] private string titleOpenFiles = "Open Files";
|
|
[Tooltip("Title for the 'Open Folder'-dialog."), SerializeField] private string titleOpenFolder = "Select Folder";
|
|
[Tooltip("Title for the 'Open Folders'-dialog."), SerializeField] private string titleOpenFolders = "Select Folders";
|
|
[Tooltip("Title for the 'Save File'-dialog."), SerializeField] private string titleSaveFile = "Save File";
|
|
|
|
[Header("Labels")] [Tooltip("Text for 'All Files'-filter (*)"), SerializeField] private string textAllFiles = "All Files";
|
|
[Tooltip("Default name of the save-file."), SerializeField] private string nameSaveFile = "MySaveFile";
|
|
|
|
[UnityEngine.Serialization.FormerlySerializedAsAttribute("LegacyFolderBrowser")] [Header("Windows Settings"), Tooltip("Use the legacy folder browser under Windows (default: false)."), SerializeField]
|
|
private bool legacyFolderBrowser;
|
|
|
|
[Tooltip("Ask to overwrite existing file in save dialog (default: true)."), SerializeField] private bool askOverwriteFile = true;
|
|
|
|
[Header("UWP (WSA) Settings"), Tooltip("Always read the file data under UWP (default: false)."), SerializeField]
|
|
private bool alwaysReadFile;
|
|
|
|
private static string lastOpenSingleFile;
|
|
private static string[] lastOpenFiles;
|
|
private static string lastOpenSingleFolder;
|
|
private static string[] lastOpenFolders;
|
|
private static string lastSaveFile;
|
|
|
|
private WrapperHolder wrapperHolder;
|
|
|
|
#endregion
|
|
|
|
|
|
#region Properties
|
|
|
|
/// <summary>Custom wrapper for File Browser.</summary>
|
|
public BaseCustomFileBrowser CustomWrapper
|
|
{
|
|
get => customWrapper;
|
|
set
|
|
{
|
|
if (customWrapper == value) return;
|
|
|
|
customWrapper = value;
|
|
|
|
wrapperHolder = new WrapperHolder();
|
|
}
|
|
}
|
|
|
|
/// <summary>Enables or disables the custom wrapper.</summary>
|
|
public bool CustomMode
|
|
{
|
|
get => customMode;
|
|
set
|
|
{
|
|
if (customMode == value) return;
|
|
|
|
customMode = value;
|
|
|
|
wrapperHolder = new WrapperHolder();
|
|
}
|
|
}
|
|
|
|
/// <summary>Use the legacy folder browser (Windows).</summary>
|
|
public bool LegacyFolderBrowser
|
|
{
|
|
get => legacyFolderBrowser;
|
|
set => legacyFolderBrowser = value;
|
|
}
|
|
|
|
/// <summary>Ask to overwrite existing file in save dialog (Windows).</summary>
|
|
public bool AskOverwriteFile
|
|
{
|
|
get => askOverwriteFile;
|
|
set => askOverwriteFile = value;
|
|
}
|
|
|
|
/// <summary>Always read the file data (UWP).</summary>
|
|
public bool AlwaysReadFile
|
|
{
|
|
get => alwaysReadFile;
|
|
set => alwaysReadFile = value;
|
|
}
|
|
|
|
/// <summary>Title for the 'Open File'-dialog.</summary>
|
|
public string TitleOpenFile
|
|
{
|
|
get => titleOpenFile;
|
|
set => titleOpenFile = value;
|
|
}
|
|
|
|
/// <summary>Title for the 'Open Files'-dialog.</summary>
|
|
public string TitleOpenFiles
|
|
{
|
|
get => titleOpenFiles;
|
|
set => titleOpenFiles = value;
|
|
}
|
|
|
|
/// <summary>Title for the 'Open Folder'-dialog.</summary>
|
|
public string TitleOpenFolder
|
|
{
|
|
get => titleOpenFolder;
|
|
set => titleOpenFolder = value;
|
|
}
|
|
|
|
/// <summary>Title for the 'Open Folders'-dialog.</summary>
|
|
public string TitleOpenFolders
|
|
{
|
|
get => titleOpenFolders;
|
|
set => titleOpenFolders = value;
|
|
}
|
|
|
|
/// <summary>Title for the 'Save File'-dialog.</summary>
|
|
public string TitleSaveFile
|
|
{
|
|
get => titleSaveFile;
|
|
set => titleSaveFile = value;
|
|
}
|
|
|
|
/// <summary>Text for 'All Files'-filter (*).</summary>
|
|
public string TextAllFiles
|
|
{
|
|
get => textAllFiles;
|
|
set => textAllFiles = value;
|
|
}
|
|
|
|
/// <summary>Default name of the save-file.</summary>
|
|
public string NameSaveFile
|
|
{
|
|
get => nameSaveFile;
|
|
set => nameSaveFile = value;
|
|
}
|
|
|
|
/// <summary>Returns the file from the last "OpenSingleFile"-action.</summary>
|
|
/// <returns>File from the last "OpenSingleFile"-action.</returns>
|
|
public string CurrentOpenSingleFile
|
|
{
|
|
get => wrapperHolder?.PlatformWrapper?.CurrentOpenSingleFile;
|
|
set => wrapperHolder.PlatformWrapper.CurrentOpenSingleFile = value;
|
|
}
|
|
|
|
/// <summary>Returns the file name (without path) from the last "OpenSingleFile"-action.</summary>
|
|
/// <returns>File name from the last "OpenSingleFile"-action.</returns>
|
|
public string CurrentOpenSingleFileName => getNameFromPath(CurrentOpenSingleFile);
|
|
|
|
/// <summary>Returns the array of files from the last "OpenFiles"-action.</summary>
|
|
/// <returns>Array of files from the last "OpenFiles"-action.</returns>
|
|
public string[] CurrentOpenFiles
|
|
{
|
|
get => wrapperHolder?.PlatformWrapper?.CurrentOpenFiles;
|
|
set => wrapperHolder.PlatformWrapper.CurrentOpenFiles = value;
|
|
}
|
|
|
|
/// <summary>Returns the folder from the last "OpenSingleFolder"-action.</summary>
|
|
/// <returns>Folder from the last "OpenSingleFolder"-action.</returns>
|
|
public string CurrentOpenSingleFolder
|
|
{
|
|
get => wrapperHolder?.PlatformWrapper?.CurrentOpenSingleFolder;
|
|
set => wrapperHolder.PlatformWrapper.CurrentOpenSingleFolder = value;
|
|
}
|
|
|
|
/// <summary>Returns the folder name (without path) from the last "OpenSingleFolder"-action.</summary>
|
|
/// <returns>Folder name from the last "OpenSingleFolder"-action.</returns>
|
|
public string CurrentOpenSingleFolderName => getNameFromPath(CurrentOpenSingleFolder);
|
|
|
|
/// <summary>Returns the array of folders from the last "OpenFolders"-action.</summary>
|
|
/// <returns>Array of folders from the last "OpenFolders"-action.</returns>
|
|
public string[] CurrentOpenFolders
|
|
{
|
|
get => wrapperHolder?.PlatformWrapper?.CurrentOpenFolders;
|
|
set => wrapperHolder.PlatformWrapper.CurrentOpenFolders = value;
|
|
}
|
|
|
|
/// <summary>Returns the file from the last "SaveFile"-action.</summary>
|
|
/// <returns>File from the last "SaveFile"-action.</returns>
|
|
public string CurrentSaveFile
|
|
{
|
|
get => wrapperHolder?.PlatformWrapper?.CurrentSaveFile;
|
|
set => wrapperHolder.PlatformWrapper.CurrentSaveFile = value;
|
|
}
|
|
|
|
/// <summary>Returns the file name (without path) from the last "SaveFile"-action.</summary>
|
|
/// <returns>File name from the last "SaveFile"-action.</returns>
|
|
public string CurrentSaveFileName => getNameFromPath(CurrentSaveFile);
|
|
|
|
/// <summary>Returns the data of the file from the last "OpenSingleFile"-action.</summary>
|
|
/// <returns>Data of the file from the last "OpenSingleFile"-action.</returns>
|
|
public byte[] CurrentOpenSingleFileData => wrapperHolder?.PlatformWrapper?.CurrentOpenSingleFileData;
|
|
|
|
/// <summary>The data for the "SaveFile"-action.</summary>
|
|
public byte[] CurrentSaveFileData
|
|
{
|
|
get => wrapperHolder?.PlatformWrapper?.CurrentSaveFileData;
|
|
set => wrapperHolder.PlatformWrapper.CurrentSaveFileData = value;
|
|
}
|
|
|
|
#region Wrapper delegates
|
|
|
|
/// <summary>Indicates if this wrapper can open a file.</summary>
|
|
/// <returns>Wrapper can open a file.</returns>
|
|
public bool canOpenFile => wrapperHolder?.PlatformWrapper.canOpenFile ?? false;
|
|
|
|
/// <summary>Indicates if this wrapper can open a folder.</summary>
|
|
/// <returns>Wrapper can open a folder.</returns>
|
|
public bool canOpenFolder => wrapperHolder?.PlatformWrapper.canOpenFolder ?? false;
|
|
|
|
/// <summary>Indicates if this wrapper can save a file.</summary>
|
|
/// <returns>Wrapper can save a file.</returns>
|
|
public bool canSaveFile => wrapperHolder?.PlatformWrapper.canSaveFile ?? false;
|
|
|
|
/// <summary>Indicates if this wrapper can open multiple files.</summary>
|
|
/// <returns>Wrapper can open multiple files.</returns>
|
|
public bool canOpenMultipleFiles => wrapperHolder?.PlatformWrapper.canOpenMultipleFiles ?? false;
|
|
|
|
/// <summary>Indicates if this wrapper can open multiple folders.</summary>
|
|
/// <returns>Wrapper can open multiple folders.</returns>
|
|
public bool canOpenMultipleFolders => wrapperHolder?.PlatformWrapper.canOpenMultipleFolders ?? false;
|
|
|
|
/// <summary>Indicates if this wrapper is supporting the current platform.</summary>
|
|
/// <returns>True if this wrapper supports current platform.</returns>
|
|
public bool isPlatformSupported => wrapperHolder?.PlatformWrapper.isPlatformSupported ?? true;
|
|
|
|
/// <summary>Indicates if this wrapper is working directly inside the Unity Editor (without 'Play'-mode).</summary>
|
|
/// <returns>True if this wrapper is working directly inside the Unity Editor.</returns>
|
|
public bool isWorkingInEditor => wrapperHolder?.PlatformWrapper.isWorkingInEditor ?? false;
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
|
|
#region Events
|
|
|
|
[Header("Events")] public OnOpenFilesCompleted OnOpenFilesCompleted;
|
|
public OnOpenFoldersCompleted OnOpenFoldersCompleted;
|
|
public OnSaveFileCompleted OnSaveFileCompleted;
|
|
|
|
public delegate void OpenFilesStart();
|
|
|
|
public delegate void OpenFilesComplete(bool selected, string singleFile, string[] files);
|
|
|
|
public delegate void OpenFoldersStart();
|
|
|
|
public delegate void OpenFoldersComplete(bool selected, string singleFolder, string[] folders);
|
|
|
|
public delegate void SaveFileStart();
|
|
|
|
public delegate void SaveFileComplete(bool selected, string file);
|
|
|
|
/// <summary>An event triggered whenever "OpenFiles" is started.</summary>
|
|
public event OpenFilesStart OnOpenFilesStart;
|
|
|
|
/// <summary>An event triggered whenever "OpenFiles" is completed.</summary>
|
|
public event OpenFilesComplete OnOpenFilesComplete;
|
|
|
|
/// <summary>An event triggered whenever "OpenFolders" is started.</summary>
|
|
public event OpenFoldersStart OnOpenFoldersStart;
|
|
|
|
/// <summary>An event triggered whenever "OpenFolders" is completed.</summary>
|
|
public event OpenFoldersComplete OnOpenFoldersComplete;
|
|
|
|
/// <summary>An event triggered whenever "SaveFile" is started.</summary>
|
|
public event SaveFileStart OnSaveFileStart;
|
|
|
|
/// <summary>An event triggered whenever "SaveFile" is completed.</summary>
|
|
public event SaveFileComplete OnSaveFileComplete;
|
|
|
|
#endregion
|
|
|
|
|
|
#region MonoBehaviour methods
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
|
|
//if (!Helper.isEditorMode && DontDestroy && CustomMode && CustomWrapper != null)
|
|
// CustomWrapper.transform.parent = transform;
|
|
|
|
wrapperHolder = new WrapperHolder();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (lastOpenFiles != CurrentOpenFiles || lastOpenSingleFile != CurrentOpenSingleFile)
|
|
{
|
|
lastOpenFiles = CurrentOpenFiles;
|
|
lastOpenSingleFile = CurrentOpenSingleFile;
|
|
bool selected = false;
|
|
string singleFile = null;
|
|
|
|
if (lastOpenFiles?.Length > 0)
|
|
{
|
|
selected = true;
|
|
singleFile = lastOpenFiles[0];
|
|
}
|
|
|
|
onOpenFilesComplete(selected, singleFile, lastOpenFiles);
|
|
}
|
|
|
|
if (lastOpenFolders != CurrentOpenFolders || lastOpenSingleFolder != CurrentOpenSingleFolder)
|
|
{
|
|
lastOpenFolders = CurrentOpenFolders;
|
|
lastOpenSingleFolder = CurrentOpenSingleFolder;
|
|
|
|
bool selected = false;
|
|
string singleFolder = null;
|
|
|
|
if (lastOpenFolders?.Length > 0)
|
|
{
|
|
selected = !string.IsNullOrEmpty(lastOpenFolders[0]);
|
|
singleFolder = lastOpenFolders[0];
|
|
}
|
|
|
|
onOpenFoldersComplete(selected, singleFolder, lastOpenFolders);
|
|
}
|
|
|
|
if (lastSaveFile != CurrentSaveFile)
|
|
{
|
|
lastSaveFile = CurrentSaveFile;
|
|
bool selected = !string.IsNullOrEmpty(lastSaveFile);
|
|
|
|
onSaveFileComplete(selected, lastSaveFile);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region Public methods
|
|
|
|
/// <summary>Open native file browser for a single file.</summary>
|
|
/// <param name="extension">Allowed extension, e.g. "png" (optional)</param>
|
|
/// <returns>Returns a string of the chosen file. Empty string when cancelled</returns>
|
|
public string OpenSingleFile(string extension = "*")
|
|
{
|
|
return OpenSingleFile(string.Empty, string.Empty, string.Empty, getFilter(extension));
|
|
}
|
|
|
|
/// <summary>Open native file browser for a single file.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns a string of the chosen file. Empty string when cancelled</returns>
|
|
public string OpenSingleFile(string title, string directory, string defaultName, params string[] extensions)
|
|
{
|
|
return OpenSingleFile(title, directory, defaultName, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Open native file browser for a single file.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns a string of the chosen file. Empty string when cancelled</returns>
|
|
public string OpenSingleFile(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return "disabled";
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'OpenSingleFile' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenSingleFile' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (canOpenFile)
|
|
{
|
|
onOpenFilesStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenSingleFile(string.IsNullOrEmpty(title) ? titleOpenFile : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), defaultName, extensions);
|
|
|
|
return CurrentOpenSingleFile;
|
|
}
|
|
|
|
Debug.LogWarning("'OpenSingleFile' is currently not supported for the current platform!", this);
|
|
return null;
|
|
}
|
|
|
|
/// <summary>Open native file browser for multiple files.</summary>
|
|
/// <param name="extension">Allowed extension, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
public string[] OpenFiles(string extension = "*")
|
|
{
|
|
return OpenFiles(string.Empty, string.Empty, string.Empty, getFilter(extension));
|
|
}
|
|
|
|
/// <summary>Open native file browser for multiple files.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
public string[] OpenFiles(string title, string directory, string defaultName, params string[] extensions)
|
|
{
|
|
return OpenFiles(title, directory, defaultName, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Open native file browser for multiple files.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
public string[] OpenFiles(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return null;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'OpenFiles' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenFiles' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (canOpenFile)
|
|
{
|
|
onOpenFilesStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFiles(string.IsNullOrEmpty(title) ? titleOpenFiles : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), defaultName, true, extensions);
|
|
|
|
return CurrentOpenFiles;
|
|
}
|
|
|
|
Debug.LogWarning("'OpenFiles' is currently not supported for the current platform!", this);
|
|
return null;
|
|
}
|
|
|
|
/// <summary>Open native folder browser for a single folder.</summary>
|
|
/// <returns>Returns a string of the chosen folder. Empty string when cancelled</returns>
|
|
public string OpenSingleFolder()
|
|
{
|
|
return OpenSingleFolder(string.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open native folder browser for a single folder.
|
|
/// NOTE: Title is not supported under Windows and UWP (WSA)!
|
|
/// </summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory (default: current, optional)</param>
|
|
/// <returns>Returns a string of the chosen folder. Empty string when cancelled</returns>
|
|
public string OpenSingleFolder(string title, string directory = "")
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return "disabled";
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenSingleFolder' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (canOpenFolder)
|
|
{
|
|
onOpenFoldersStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenSingleFolder(string.IsNullOrEmpty(title) ? titleOpenFolder : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false));
|
|
|
|
return CurrentOpenSingleFolder;
|
|
}
|
|
|
|
Debug.LogWarning("'OpenSingleFolder' is currently not supported for the current platform!", this);
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open native folder browser for multiple folders.
|
|
/// NOTE: Title and multiple folder selection are not supported under Windows and UWP (WSA)!
|
|
/// </summary>
|
|
/// <returns>Returns array of chosen folders. Zero length array when cancelled</returns>
|
|
public string[] OpenFolders()
|
|
{
|
|
return OpenFolders(string.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open native folder browser for multiple folders.
|
|
/// NOTE: Title and multiple folder selection are not supported under Windows and UWP (WSA)!
|
|
/// </summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory (default: current, optional)</param>
|
|
/// <returns>Returns array of chosen folders. Zero length array when cancelled</returns>
|
|
public string[] OpenFolders(string title, string directory = "")
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return null;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenFolders' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (canOpenFolder)
|
|
{
|
|
onOpenFoldersStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFolders(string.IsNullOrEmpty(title) ? titleOpenFolders : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), true);
|
|
|
|
return CurrentOpenFolders;
|
|
}
|
|
|
|
Debug.LogWarning("'OpenFolders' is currently not supported for the current platform!", this);
|
|
return null;
|
|
}
|
|
|
|
/// <summary>Open native save file browser.</summary>
|
|
/// <param name="defaultName">Default file name (optional)</param>
|
|
/// <param name="extension">File extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
public string SaveFile(string defaultName = "", string extension = "*")
|
|
{
|
|
return SaveFile(string.Empty, string.Empty, defaultName, getFilter(extension));
|
|
}
|
|
|
|
/// <summary>Open native save file browser.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name</param>
|
|
/// <param name="extensions">File extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
public string SaveFile(string title, string directory, string defaultName, params string[] extensions)
|
|
{
|
|
return SaveFile(title, directory, defaultName, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Open native save file browser</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
public string SaveFile(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return "disabled";
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'SaveFile' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'SaveFile' dialog!", this);
|
|
return null;
|
|
}
|
|
|
|
if (canSaveFile)
|
|
{
|
|
onSaveFileStart();
|
|
|
|
wrapperHolder.PlatformWrapper.SaveFile(string.IsNullOrEmpty(title) ? titleSaveFile : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), string.IsNullOrEmpty(defaultName) ? NameSaveFile : defaultName, extensions);
|
|
|
|
return CurrentSaveFile;
|
|
}
|
|
|
|
Debug.LogWarning("'SaveFile' is currently not supported for the current platform!", this);
|
|
return null;
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native file browser for a single file.</summary>
|
|
/// <param name="extension">Allowed extension, e.g. "png" (optional)</param>
|
|
/// <returns>Returns a string of the chosen file. Empty string when cancelled</returns>
|
|
public void OpenSingleFileAsync(string extension = "*")
|
|
{
|
|
OpenSingleFileAsync(string.Empty, string.Empty, string.Empty, getFilter(extension));
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native file browser for a single file.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns a string of the chosen file. Empty string when cancelled</returns>
|
|
public void OpenSingleFileAsync(string title, string directory, string defaultName, params string[] extensions)
|
|
{
|
|
OpenSingleFileAsync(title, directory, defaultName, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native file browser for a single file.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns a string of the chosen file. Empty string when cancelled</returns>
|
|
public void OpenSingleFileAsync(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'OpenSingleFileAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenSingleFileAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canOpenFile)
|
|
{
|
|
onOpenFilesStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFilesAsync(string.IsNullOrEmpty(title) ? titleOpenFile : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), defaultName, false, extensions, resetOpenFiles);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'OpenSingleFileAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native file browser for multiple files.</summary>
|
|
/// <param name="multiselect">Allow multiple file selection (default: true, optional)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
public void OpenFilesAsync(bool multiselect = true, params string[] extensions)
|
|
{
|
|
OpenFilesAsync(string.Empty, string.Empty, string.Empty, multiselect, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native file browser for multiple files.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="multiselect">Allow multiple file selection (default: true, optional)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
public void OpenFilesAsync(string title, string directory, string defaultName, bool multiselect = true, params string[] extensions)
|
|
{
|
|
OpenFilesAsync(title, directory, defaultName, multiselect, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native file browser for multiple files.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="multiselect">Allow multiple file selection (default: true, optional)</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
public void OpenFilesAsync(string title, string directory, string defaultName, bool multiselect = true, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'OpenFilesAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenFilesAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canOpenFile)
|
|
{
|
|
onOpenFilesStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFilesAsync(string.IsNullOrEmpty(title) ? multiselect ? titleOpenFiles : titleOpenFile : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), defaultName, multiselect, extensions, resetOpenFiles);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'OpenFilesAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native folder browser for a single folder.</summary>
|
|
/// <returns>Returns a string of the chosen folder. Empty string when cancelled</returns>
|
|
public void OpenSingleFolderAsync()
|
|
{
|
|
OpenSingleFolderAsync(string.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Asynchronously opens native folder browser for a single folder.
|
|
/// NOTE: Title is not supported under Windows and UWP (WSA)!
|
|
/// </summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory (default: current, optional)</param>
|
|
/// <returns>Returns a string of the chosen folder. Empty string when cancelled</returns>
|
|
public void OpenSingleFolderAsync(string title, string directory = "")
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenSingleFolderAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canOpenFolder)
|
|
{
|
|
onOpenFoldersStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFoldersAsync(string.IsNullOrEmpty(title) ? titleOpenFolder : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), false, resetOpenFolders);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'OpenSingleFolderAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native folder browser for multiple folders.</summary>
|
|
/// <param name="multiselect">Allow multiple folder selection (default: true, optional)</param>
|
|
/// <returns>Returns array of chosen folders. Zero length array when cancelled</returns>
|
|
public void OpenFoldersAsync(bool multiselect = true)
|
|
{
|
|
OpenFoldersAsync(string.Empty, string.Empty, multiselect);
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native folder browser for multiple folders.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory (default: current, optional)</param>
|
|
/// <param name="multiselect">Allow multiple folder selection (default: true, optional)</param>
|
|
/// <returns>Returns array of chosen folders. Zero length array when cancelled</returns>
|
|
public void OpenFoldersAsync(string title, string directory = "", bool multiselect = true)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenFoldersAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canOpenFolder)
|
|
{
|
|
onOpenFoldersStart();
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFoldersAsync(string.IsNullOrEmpty(title) ? multiselect ? titleOpenFolders : titleOpenFolder : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), multiselect, resetOpenFolders);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'OpenFoldersAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native save file browser.</summary>
|
|
/// <param name="defaultName">Default file name (optional)</param>
|
|
/// <param name="extension">File extension, e.g. "png" (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
public void SaveFileAsync(string defaultName = "", string extension = "*")
|
|
{
|
|
SaveFileAsync(string.Empty, string.Empty, defaultName, getFilter(extension));
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native save file browser.</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name</param>
|
|
/// <param name="extensions">File extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
public void SaveFileAsync(string title, string directory, string defaultName, params string[] extensions)
|
|
{
|
|
SaveFileAsync(title, directory, defaultName, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Asynchronously opens native save file browser (async)</summary>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
public void SaveFileAsync(string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'SaveFileAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'SaveFileAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canSaveFile)
|
|
{
|
|
onSaveFileStart();
|
|
|
|
wrapperHolder.PlatformWrapper.SaveFileAsync(string.IsNullOrEmpty(title) ? titleSaveFile : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), string.IsNullOrEmpty(defaultName) ? NameSaveFile : defaultName, extensions, paths => resetSaveFile(paths));
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'SaveFileAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Find files inside a path.</summary>
|
|
/// <param name="path">Path to find the files</param>
|
|
/// <param name="isRecursive">Recursive search</param>
|
|
/// <param name="extensions">List of extension filters for the search (optional)</param>
|
|
/// <returns>Returns array of the found files inside the path. Zero length array when an error occured.</returns>
|
|
public string[] GetFiles(string path, bool isRecursive, params ExtensionFilter[] extensions)
|
|
{
|
|
return Crosstales.Common.Util.FileHelper.GetFiles(path, isRecursive, extensions.SelectMany(extensionFilter => extensionFilter.Extensions).ToArray());
|
|
}
|
|
|
|
#region Legacy
|
|
|
|
/// <summary>Find files inside a path.</summary>
|
|
/// <param name="path">Path to find the files</param>
|
|
/// <param name="isRecursive">Recursive search (default: false, optional)</param>
|
|
/// <param name="extensions">Extensions for the file search, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of the found files inside the path (alphabetically ordered). Zero length array when an error occured.</returns>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.GetFiles' instead.")]
|
|
public string[] GetFiles(string path, bool isRecursive = false, params string[] extensions)
|
|
{
|
|
return Crosstales.Common.Util.FileHelper.GetFiles(path, isRecursive, extensions);
|
|
}
|
|
|
|
/// <summary>Find folders inside.</summary>
|
|
/// <param name="path">Path to find the directories</param>
|
|
/// <param name="isRecursive">Recursive search (default: false, optional)</param>
|
|
/// <returns>Returns array of the found directories inside the path. Zero length array when an error occured.</returns>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.GetDirectories' instead.")]
|
|
public string[] GetFolders(string path, bool isRecursive = false)
|
|
{
|
|
return Crosstales.Common.Util.FileHelper.GetDirectories(path, isRecursive);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Find all logical drives.
|
|
/// </summary>
|
|
/// <returns>Returns array of the found drives. Zero length array when an error occured.</returns>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.GetDrives' instead.")]
|
|
public string[] GetDrives()
|
|
{
|
|
return Crosstales.Common.Util.FileHelper.GetDrives();
|
|
}
|
|
|
|
/// <summary>Copy or move a file.</summary>
|
|
/// <param name="sourceFile">Source file path</param>
|
|
/// <param name="destFile">Destination file path</param>
|
|
/// <param name="move">Move file instead of copy (default: false, optional)</param>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.CopyFile' instead.")]
|
|
public static void CopyFile(string sourceFile, string destFile, bool move = false)
|
|
{
|
|
Crosstales.Common.Util.FileHelper.CopyFile(sourceFile, destFile, move);
|
|
}
|
|
|
|
/// <summary>Copy or move a folder.</summary>
|
|
/// <param name="sourcePath">Source folder path</param>
|
|
/// <param name="destPath">Destination folder path</param>
|
|
/// <param name="move">Move folder instead of copy (default: false, optional)</param>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.CopyDirectory' instead.")]
|
|
public static void CopyFolder(string sourcePath, string destPath, bool move = false)
|
|
{
|
|
Crosstales.Common.Util.FileHelper.CopyDirectory(sourcePath, destPath, move);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the location of a file (or folder) in OS file explorer.
|
|
/// NOTE: only works on standalone platforms
|
|
/// </summary>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.ShowFile' instead.")]
|
|
public static void ShowFile(string file)
|
|
{
|
|
Crosstales.Common.Util.FileHelper.ShowFile(file);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the location of a folder (or file) in OS file explorer.
|
|
/// NOTE: only works on standalone platforms
|
|
/// </summary>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.ShowPath' instead.")]
|
|
public static void ShowFolder(string path)
|
|
{
|
|
Crosstales.Common.Util.FileHelper.ShowPath(path);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Opens a file with the OS default application.
|
|
/// NOTE: only works for standalone platforms
|
|
/// </summary>
|
|
/// <param name="file">File path</param>
|
|
[System.Obsolete("Please use 'Crosstales.Common.Util.FileHelper.OpenFile' instead.")]
|
|
public static void OpenFile(string file)
|
|
{
|
|
Crosstales.Common.Util.FileHelper.OpenFile(file);
|
|
}
|
|
|
|
/// <summary>Open native file browser for multiple files.</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="multiselect">Allow multiple file selection (default: true, optional)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void OpenFilesAsync(System.Action<string[]> cb, bool multiselect = true, params string[] extensions)
|
|
{
|
|
OpenFilesAsync(cb, multiselect ? titleOpenFiles : titleOpenFile, string.Empty, string.Empty, multiselect, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Open native file browser for multiple files.</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="multiselect">Allow multiple file selection (default: true, optional)</param>
|
|
/// <param name="extensions">Allowed extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void OpenFilesAsync(System.Action<string[]> cb, string title, string directory, string defaultName, bool multiselect = true, params string[] extensions)
|
|
{
|
|
OpenFilesAsync(cb, title, directory, defaultName, multiselect, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Open native file browser for multiple files (async).</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name (currently only supported under Windows standalone)</param>
|
|
/// <param name="multiselect">Allow multiple file selection (default: true, optional)</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns array of chosen files. Zero length array when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void OpenFilesAsync(System.Action<string[]> cb, string title, string directory, string defaultName, bool multiselect = true, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (cb != null)
|
|
{
|
|
if (canOpenFile)
|
|
{
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'OpenFiles' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenFiles' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
wrapperHolder.PlatformWrapper.OpenFilesAsync(string.IsNullOrEmpty(title) ? titleOpenFiles : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), defaultName, multiselect, extensions, cb);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'OpenFilesAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'cb' (callback)is null - can not show dialog!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Open native folder browser for multiple folders (async).</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="multiselect">Allow multiple folder selection (default: true, optional)</param>
|
|
/// <returns>Returns array of chosen folders. Zero length array when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void OpenFoldersAsync(System.Action<string[]> cb, bool multiselect = true)
|
|
{
|
|
OpenFoldersAsync(cb, titleOpenFolders, string.Empty, multiselect);
|
|
}
|
|
|
|
/// <summary>Open native folder browser for multiple folders (async).</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory (default: current, optional)</param>
|
|
/// <param name="multiselect">Allow multiple folder selection (default: true, optional)</param>
|
|
/// <returns>Returns array of chosen folders. Zero length array when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void OpenFoldersAsync(System.Action<string[]> cb, string title, string directory = "", bool multiselect = true)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (cb != null)
|
|
{
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'OpenFolders' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canOpenFolder)
|
|
{
|
|
wrapperHolder.PlatformWrapper.OpenFoldersAsync(string.IsNullOrEmpty(title) ? titleOpenFolders : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), multiselect, cb);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'OpenFoldersAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'cb' (callback) is null - can not show dialog!", this);
|
|
}
|
|
}
|
|
|
|
/// <summary>Open native save file browser</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="defaultName">Default file name (optional)</param>
|
|
/// <param name="extension">File extension, e.g. "png" (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void SaveFileAsync(System.Action<string> cb, string defaultName = "", string extension = "*")
|
|
{
|
|
SaveFileAsync(cb, titleSaveFile, string.Empty, defaultName, getFilter(extension));
|
|
}
|
|
|
|
/// <summary>Open native save file browser</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name</param>
|
|
/// <param name="extensions">File extensions, e.g. "png" (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void SaveFileAsync(System.Action<string> cb, string title, string directory, string defaultName, params string[] extensions)
|
|
{
|
|
SaveFileAsync(cb, title, directory, defaultName, getFilter(extensions));
|
|
}
|
|
|
|
/// <summary>Open native save file browser (async).</summary>
|
|
/// <param name="cb">Callback for the async operation.</param>
|
|
/// <param name="title">Dialog title</param>
|
|
/// <param name="directory">Root directory</param>
|
|
/// <param name="defaultName">Default file name</param>
|
|
/// <param name="extensions">List of extension filters (optional)</param>
|
|
/// <returns>Returns chosen file. Empty string when cancelled</returns>
|
|
//[System.Obsolete("This method is deprecated, please use it without the callback.")]
|
|
public void SaveFileAsync(System.Action<string> cb, string title, string directory, string defaultName, params ExtensionFilter[] extensions)
|
|
{
|
|
if (this != null && !isActiveAndEnabled)
|
|
return;
|
|
|
|
if (cb != null)
|
|
{
|
|
if (Crosstales.Common.Util.FileHelper.HasFileInvalidChars(defaultName))
|
|
{
|
|
Debug.LogWarning("'defaultName' contains invalid characters - can not show 'SaveFileAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (Crosstales.Common.Util.FileHelper.HasPathInvalidChars(directory))
|
|
{
|
|
Debug.LogWarning("'directory' contains invalid characters - can not show 'SaveFileAsync' dialog!", this);
|
|
return;
|
|
}
|
|
|
|
if (canSaveFile)
|
|
{
|
|
wrapperHolder.PlatformWrapper.SaveFileAsync(string.IsNullOrEmpty(title) ? titleSaveFile : title, Crosstales.Common.Util.FileHelper.ValidatePath(directory, true, false), string.IsNullOrEmpty(defaultName) ? NameSaveFile : defaultName, extensions, cb);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'SaveFileAsync' is currently not supported for the current platform!", this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("'cb' (callback) is null - can not show dialog!", this);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
|
|
#region Private methods
|
|
|
|
private string getNameFromPath(string path) //TODO move to BaseHelper?
|
|
{
|
|
if (string.IsNullOrEmpty(path))
|
|
return null;
|
|
|
|
int nameIndex = path.LastIndexOf("/");
|
|
|
|
if (nameIndex < 0)
|
|
nameIndex = path.LastIndexOf(@"\");
|
|
|
|
if (nameIndex < 0)
|
|
nameIndex = -1;
|
|
|
|
return path.Substring(nameIndex + 1);
|
|
}
|
|
|
|
private void resetOpenFiles(params string[] paths)
|
|
{
|
|
//do nothing
|
|
//lastOpenFiles = System.Array.Empty<string>();
|
|
//lastOpenSingleFile = string.Empty;
|
|
}
|
|
|
|
private void resetOpenFolders(params string[] paths)
|
|
{
|
|
//do nothing
|
|
//lastOpenFolders = System.Array.Empty<string>();
|
|
//lastOpenSingleFolder = string.Empty;
|
|
}
|
|
|
|
private void resetSaveFile(params string[] paths)
|
|
{
|
|
//do nothing
|
|
//lastSaveFile = string.Empty;
|
|
}
|
|
|
|
private ExtensionFilter[] getFilter(params string[] extensions)
|
|
{
|
|
if (extensions?.Length > 0)
|
|
{
|
|
if (extensions.Length == 1 && "*".Equals(extensions[0]))
|
|
return null;
|
|
|
|
ExtensionFilter[] filter = new ExtensionFilter[extensions.Length];
|
|
|
|
for (int ii = 0; ii < extensions.Length; ii++)
|
|
{
|
|
string extension = string.IsNullOrEmpty(extensions[ii]) ? "*" : extensions[ii];
|
|
|
|
if (extension.Equals("*"))
|
|
{
|
|
filter[ii] = new ExtensionFilter(TextAllFiles, Helper.isMacOSEditor ? string.Empty : extension);
|
|
}
|
|
else
|
|
{
|
|
filter[ii] = new ExtensionFilter(extension, extension);
|
|
}
|
|
}
|
|
|
|
if (Config.DEBUG)
|
|
Debug.Log($"getFilter: {filter.CTDump()}", this);
|
|
|
|
return filter;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region Event-trigger methods
|
|
|
|
private void onOpenFilesStart()
|
|
{
|
|
if (Config.DEBUG)
|
|
Debug.Log("onOpenFilesStart", this);
|
|
|
|
lastOpenFiles = CurrentOpenFiles = null;
|
|
lastOpenSingleFile = CurrentOpenSingleFile = null;
|
|
|
|
OnOpenFilesStart?.Invoke();
|
|
}
|
|
|
|
private void onOpenFilesComplete(bool selected, string singleFile, string[] files)
|
|
{
|
|
if (Config.DEBUG)
|
|
Debug.Log($"onOpenFilesComplete: {selected} - {singleFile} - {CurrentOpenSingleFileData?.Length}", this);
|
|
|
|
if (!Helper.isEditorMode)
|
|
{
|
|
string fileList = files?.Length > 0 ? string.Join(";", files) : null;
|
|
|
|
OnOpenFilesCompleted?.Invoke(selected, singleFile, fileList);
|
|
}
|
|
|
|
OnOpenFilesComplete?.Invoke(selected, singleFile, files);
|
|
}
|
|
|
|
private void onOpenFoldersStart()
|
|
{
|
|
if (Config.DEBUG)
|
|
Debug.Log("onOpenFoldersStart", this);
|
|
|
|
lastOpenFolders = CurrentOpenFolders = null;
|
|
lastOpenSingleFolder = CurrentOpenSingleFolder = null;
|
|
|
|
OnOpenFoldersStart?.Invoke();
|
|
}
|
|
|
|
private void onOpenFoldersComplete(bool selected, string singleFolder, string[] folders)
|
|
{
|
|
if (Config.DEBUG)
|
|
Debug.Log($"onOpenFoldersComplete: {selected} - {singleFolder}", this);
|
|
|
|
if (!Helper.isEditorMode)
|
|
{
|
|
string folderList = folders?.Length > 0 ? string.Join(";", folders) : null;
|
|
|
|
OnOpenFoldersCompleted?.Invoke(selected, singleFolder, folderList);
|
|
}
|
|
|
|
OnOpenFoldersComplete?.Invoke(selected, singleFolder, folders);
|
|
}
|
|
|
|
private void onSaveFileStart()
|
|
{
|
|
if (Config.DEBUG)
|
|
Debug.Log("onSaveFileStart", this);
|
|
|
|
lastSaveFile = CurrentSaveFile = null;
|
|
|
|
OnSaveFileStart?.Invoke();
|
|
}
|
|
|
|
private void onSaveFileComplete(bool selected, string file)
|
|
{
|
|
if (Config.DEBUG)
|
|
Debug.Log($"onSaveFileComplete: {selected} - {file} - {CurrentSaveFileData?.Length}", this);
|
|
|
|
if (selected && (!Helper.isWebPlatform || Helper.isEditor) && CurrentSaveFileData != null)
|
|
{
|
|
try
|
|
{
|
|
Crosstales.Common.Util.FileHelper.WriteAllBytes(file, CurrentSaveFileData);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
//if (Config.DEBUG)
|
|
Debug.LogWarning($"Could not write file: {file} - {ex}", this);
|
|
}
|
|
}
|
|
|
|
if (!Helper.isEditorMode)
|
|
OnSaveFileCompleted?.Invoke(selected, file);
|
|
|
|
OnSaveFileComplete?.Invoke(selected, file);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>Filter for extensions.</summary>
|
|
public struct ExtensionFilter
|
|
{
|
|
public string Name;
|
|
public string[] Extensions;
|
|
|
|
public ExtensionFilter(string filterName, params string[] filterExtensions)
|
|
{
|
|
Name = filterName;
|
|
Extensions = filterExtensions;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
System.Text.StringBuilder result = new System.Text.StringBuilder();
|
|
|
|
result.Append(GetType().Name);
|
|
result.Append(Constants.TEXT_TOSTRING_START);
|
|
|
|
result.Append("Name='");
|
|
result.Append(Name);
|
|
result.Append(Constants.TEXT_TOSTRING_DELIMITER);
|
|
|
|
result.Append("Extensions='");
|
|
result.Append(Extensions.CTDump());
|
|
result.Append(Constants.TEXT_TOSTRING_DELIMITER_END);
|
|
|
|
result.Append(Constants.TEXT_TOSTRING_END);
|
|
|
|
return result.ToString();
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class OnOpenFilesCompleted : UnityEngine.Events.UnityEvent<bool, string, string>
|
|
{
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class OnOpenFoldersCompleted : UnityEngine.Events.UnityEvent<bool, string, string>
|
|
{
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class OnSaveFileCompleted : UnityEngine.Events.UnityEvent<bool, string>
|
|
{
|
|
}
|
|
|
|
internal class WrapperHolder
|
|
{
|
|
#region Variables
|
|
|
|
public IFileBrowser PlatformWrapper { get; private set; }
|
|
|
|
#endregion
|
|
|
|
|
|
#region Constructor
|
|
|
|
public WrapperHolder()
|
|
{
|
|
bool useCustom = FileBrowser.Instance.CustomWrapper != null && FileBrowser.Instance.CustomMode && FileBrowser.Instance.CustomWrapper.enabled;
|
|
|
|
if (useCustom)
|
|
{
|
|
PlatformWrapper = FileBrowser.Instance.CustomWrapper;
|
|
}
|
|
else
|
|
{
|
|
#if UNITY_EDITOR_WIN
|
|
if (Helper.isEditor && !Config.NATIVE_WINDOWS)
|
|
#else
|
|
if (Helper.isEditor)
|
|
#endif
|
|
{
|
|
#if UNITY_EDITOR
|
|
PlatformWrapper = new FileBrowserEditor();
|
|
#endif
|
|
}
|
|
#if UNITY_STANDALONE_OSX && !UNITY_EDITOR_WIN
|
|
else if (Helper.isMacOSPlatform)
|
|
{
|
|
PlatformWrapper = new FileBrowserMac();
|
|
}
|
|
#endif
|
|
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
|
|
else if (Helper.isWindowsPlatform || Helper.isWindowsEditor)
|
|
{
|
|
PlatformWrapper = new FileBrowserWindows();
|
|
}
|
|
#endif
|
|
#if UNITY_STANDALONE_LINUX && !UNITY_EDITOR_WIN
|
|
else if (Helper.isLinuxPlatform)
|
|
{
|
|
PlatformWrapper = new FileBrowserLinux();
|
|
}
|
|
#endif
|
|
#if UNITY_WSA && !UNITY_EDITOR && ENABLE_WINMD_SUPPORT
|
|
else if (Helper.isWSAPlatform)
|
|
{
|
|
PlatformWrapper = new FileBrowserWSA();
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
PlatformWrapper = new FileBrowserGeneric();
|
|
}
|
|
}
|
|
|
|
if (Config.DEBUG)
|
|
Debug.Log(PlatformWrapper);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|
|
// © 2017-2023 crosstales LLC (https://www.crosstales.com) |