using System.Linq; using UnityEngine; namespace Crosstales.Common.Util { /// Base for various helper functions. #if UNITY_EDITOR [UnityEditor.InitializeOnLoad] #endif public abstract class BaseHelper { #region Variables public static readonly System.Globalization.CultureInfo BaseCulture = new System.Globalization.CultureInfo("en-US"); //TODO set with current user locale? protected static readonly System.Text.RegularExpressions.Regex lineEndingsRegex = new System.Text.RegularExpressions.Regex(@"\r\n|\r|\n"); //protected static readonly Regex cleanStringRegex = new Regex(@"([^a-zA-Z0-9 ]|[ ]{2,})"); protected static readonly System.Text.RegularExpressions.Regex cleanSpacesRegex = new System.Text.RegularExpressions.Regex(@"\s+"); protected static readonly System.Text.RegularExpressions.Regex cleanTagsRegex = new System.Text.RegularExpressions.Regex(@"<.*?>"); //protected static readonly System.Text.RegularExpressions.Regex asciiOnlyRegex = new System.Text.RegularExpressions.Regex(@"[^\u0000-\u00FF]+"); protected static readonly System.Random rnd = new System.Random(); protected const string file_prefix = "file://"; public static bool ApplicationIsPlaying = Application.isPlaying; private static string applicationDataPath = Application.dataPath; #endregion #region Properties /// Checks if an Internet connection is available. /// True if an Internet connection is available. public static bool isInternetAvailable { get { #if CT_OC if (OnlineCheck.OnlineCheck.Instance == null) { return Application.internetReachability != NetworkReachability.NotReachable; } else { return OnlineCheck.OnlineCheck.Instance.isInternetAvailable; } #else return Application.internetReachability != NetworkReachability.NotReachable; #endif } } /// Checks if the current platform is Windows. /// True if the current platform is Windows. public static bool isWindowsPlatform { get { #if UNITY_STANDALONE_WIN return true; #else return false; #endif } } /// Checks if the current platform is OSX. /// True if the current platform is OSX. public static bool isMacOSPlatform { get { #if UNITY_STANDALONE_OSX return true; #else return false; #endif } } /// Checks if the current platform is Linux. /// True if the current platform is Linux. public static bool isLinuxPlatform { get { #if UNITY_STANDALONE_LINUX return true; #else return false; #endif } } /// Checks if the current platform is standalone (Windows, macOS or Linux). /// True if the current platform is standalone (Windows, macOS or Linux). public static bool isStandalonePlatform => isWindowsPlatform || isMacOSPlatform || isLinuxPlatform; /// Checks if the current platform is Android. /// True if the current platform is Android. public static bool isAndroidPlatform { get { #if UNITY_ANDROID return true; #else return false; #endif } } /// Checks if the current platform is iOS. /// True if the current platform is iOS. public static bool isIOSPlatform { get { #if UNITY_IOS return true; #else return false; #endif } } /// Checks if the current platform is tvOS. /// True if the current platform is tvOS. public static bool isTvOSPlatform { get { #if UNITY_TVOS return true; #else return false; #endif } } /// Checks if the current platform is WSA. /// True if the current platform is WSA. public static bool isWSAPlatform { get { #if UNITY_WSA return true; #else return false; #endif } } /// Checks if the current platform is XboxOne. /// True if the current platform is XboxOne. public static bool isXboxOnePlatform { get { #if UNITY_XBOXONE return true; #else return false; #endif } } /// Checks if the current platform is PS4. /// True if the current platform is PS4. public static bool isPS4Platform { get { #if UNITY_PS4 return true; #else return false; #endif } } /// Checks if the current platform is WebGL. /// True if the current platform is WebGL. public static bool isWebGLPlatform { get { #if UNITY_WEBGL return true; #else return false; #endif } } /// Checks if the current platform is Web (WebPlayer or WebGL). /// True if the current platform is Web (WebPlayer or WebGL). public static bool isWebPlatform => isWebGLPlatform; /// Checks if the current platform is Windows-based (Windows standalone, WSA or XboxOne). /// True if the current platform is Windows-based (Windows standalone, WSA or XboxOne). public static bool isWindowsBasedPlatform => isWindowsPlatform || isWSAPlatform || isXboxOnePlatform; /// Checks if the current platform is WSA-based (WSA or XboxOne). /// True if the current platform is WSA-based (WSA or XboxOne). public static bool isWSABasedPlatform => isWSAPlatform || isXboxOnePlatform; /// Checks if the current platform is Apple-based (macOS standalone, iOS or tvOS). /// True if the current platform is Apple-based (macOS standalone, iOS or tvOS). public static bool isAppleBasedPlatform => isMacOSPlatform || isIOSPlatform || isTvOSPlatform; /// Checks if the current platform is iOS-based (iOS or tvOS). /// True if the current platform is iOS-based (iOS or tvOS). public static bool isIOSBasedPlatform => isIOSPlatform || isTvOSPlatform; /// Checks if the current platform is mobile (Android and iOS). /// True if the current platform is mobile (Android and iOS). public static bool isMobilePlatform => isAndroidPlatform || isIOSBasedPlatform; /// Checks if we are inside the Editor. /// True if we are inside the Editor. public static bool isEditor => isWindowsEditor || isMacOSEditor || isLinuxEditor; /// Checks if we are inside the Windows Editor. /// True if we are inside the Windows Editor. public static bool isWindowsEditor { get { #if UNITY_EDITOR_WIN return true; #else return false; #endif } } /// Checks if we are inside the macOS Editor. /// True if we are inside the macOS Editor. public static bool isMacOSEditor { get { #if UNITY_EDITOR_OSX return true; #else return false; #endif } } /// Checks if we are inside the Linux Editor. /// True if we are inside the Linux Editor. public static bool isLinuxEditor { get { #if UNITY_EDITOR_LINUX return true; #else return false; #endif } } /// Checks if we are in Editor mode. /// True if in Editor mode. public static bool isEditorMode => isEditor && !ApplicationIsPlaying; /// Checks if the current build target uses IL2CPP. /// True if the current build target uses IL2CPP. public static bool isIL2CPP { get { #if UNITY_EDITOR UnityEditor.BuildTarget target = UnityEditor.EditorUserBuildSettings.activeBuildTarget; UnityEditor.BuildTargetGroup group = UnityEditor.BuildPipeline.GetBuildTargetGroup(target); return UnityEditor.PlayerSettings.GetScriptingBackend(group) == UnityEditor.ScriptingImplementation.IL2CPP; #else #if ENABLE_IL2CPP return true; #else return false; #endif #endif } } /// Returns the current platform. /// The current platform. public static Model.Enum.Platform CurrentPlatform { get { if (isWindowsPlatform) return Model.Enum.Platform.Windows; if (isMacOSPlatform) return Model.Enum.Platform.OSX; if (isLinuxPlatform) return Model.Enum.Platform.Linux; if (isAndroidPlatform) return Model.Enum.Platform.Android; if (isIOSBasedPlatform) return Model.Enum.Platform.IOS; if (isWSABasedPlatform) return Model.Enum.Platform.WSA; return isWebPlatform ? Model.Enum.Platform.Web : Model.Enum.Platform.Unsupported; } } /// Returns the path to the the "Streaming Assets". /// The path to the the "Streaming Assets". public static string StreamingAssetsPath { get { if (isAndroidPlatform && !isEditor) return $"jar:file://{applicationDataPath}!/assets/"; if (isIOSBasedPlatform && !isEditor) return $"{applicationDataPath}/Raw/"; return $"{applicationDataPath}/StreamingAssets/"; } } #endregion #region Static block static BaseHelper() { //Debug.Log("Static block"); initialize(); } [RuntimeInitializeOnLoadMethod] private static void initialize() { //Debug.Log("initialize"); ApplicationIsPlaying = Application.isPlaying; applicationDataPath = Application.dataPath; if (!isEditorMode) { GameObject go = new GameObject("_HelperCT"); go.AddComponent(); GameObject.DontDestroyOnLoad(go); } } #endregion #region Public methods /// Opens the given URL with the file explorer or browser. /// URL to open /// True uf the URL was valid. public static bool OpenURL(string url) { if (isValidURL(url)) { Application.OpenURL(url); return true; } Debug.LogWarning($"URL was invalid: {url}"); return false; } /// Creates a string of characters with a given length. /// Characters to generate the string (if more than one character is used, the generated string will be a randomized result of all characters) /// Length of the generated string /// Generated string public static string CreateString(string replaceChars, int stringLength) { if (replaceChars != null) { if (replaceChars.Length > 1) { char[] chars = new char[stringLength]; for (int ii = 0; ii < stringLength; ii++) { chars[ii] = replaceChars[rnd.Next(0, replaceChars.Length)]; } return new string(chars); } return replaceChars.Length == 1 ? new string(replaceChars[0], stringLength) : string.Empty; } return string.Empty; } /// Determines if an AudioSource has an active clip. /// AudioSource to check. /// True if the AudioSource has an active clip. public static bool hasActiveClip(AudioSource source) { int timeSamples = source.timeSamples; return source != null && source.clip != null && (!source.loop && timeSamples > 0 && timeSamples < source.clip.samples - 256 || source.loop || source.isPlaying); } #if !UNITY_WSA || UNITY_EDITOR /// HTTPS-certification callback. public static bool RemoteCertificateValidationCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { bool isOk = true; // If there are errors in the certificate chain, look at each error to determine the cause. if (sslPolicyErrors != System.Net.Security.SslPolicyErrors.None) { foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus t in chain.ChainStatus.Where(t => t.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags .RevocationStatusUnknown)) { chain.ChainPolicy.RevocationFlag = System.Security.Cryptography.X509Certificates.X509RevocationFlag.EntireChain; chain.ChainPolicy.RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.Online; chain.ChainPolicy.UrlRetrievalTimeout = new System.TimeSpan(0, 1, 0); chain.ChainPolicy.VerificationFlags = System.Security.Cryptography.X509Certificates.X509VerificationFlags.AllFlags; isOk = chain.Build((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate); } } return isOk; } #endif /// Validates a given path and add missing slash. /// Path to validate /// Add delimiter at the end of the path (optional, default: true) /// Valid path public static string ValidatePath(string path, bool addEndDelimiter = true) { if (!string.IsNullOrEmpty(path)) { string pathTemp = path.Trim(); string result; if ((isWindowsBasedPlatform || isWindowsEditor) && !isMacOSEditor && !isLinuxEditor) { result = pathTemp.Replace('/', '\\'); if (addEndDelimiter) { if (!result.CTEndsWith(BaseConstants.PATH_DELIMITER_WINDOWS)) { result += BaseConstants.PATH_DELIMITER_WINDOWS; } } } else { result = pathTemp.Replace('\\', '/'); if (addEndDelimiter) { if (!result.CTEndsWith(BaseConstants.PATH_DELIMITER_UNIX)) { result += BaseConstants.PATH_DELIMITER_UNIX; } } } return string.Join(string.Empty, result.Split(System.IO.Path.GetInvalidPathChars())); } return path; } /// Validates a given file. /// File to validate /// Valid file path public static string ValidateFile(string path) { if (!string.IsNullOrEmpty(path)) { string result = ValidatePath(path); if (result.CTEndsWith(BaseConstants.PATH_DELIMITER_WINDOWS) || result.CTEndsWith(BaseConstants.PATH_DELIMITER_UNIX)) { result = result.Substring(0, result.Length - 1); } string fileName; if ((isWindowsBasedPlatform || isWindowsEditor) && !isMacOSEditor && !isLinuxEditor) { fileName = result.Substring(result.CTLastIndexOf(BaseConstants.PATH_DELIMITER_WINDOWS) + 1); } else { fileName = result.Substring(result.CTLastIndexOf(BaseConstants.PATH_DELIMITER_UNIX) + 1); } string newName = string.Join(string.Empty, fileName.Split(System.IO.Path .GetInvalidFileNameChars())); //.Replace(BaseConstants.PATH_DELIMITER_WINDOWS, string.Empty).Replace(BaseConstants.PATH_DELIMITER_UNIX, string.Empty); return result.Substring(0, result.Length - fileName.Length) + newName; } return path; } /// /// Find files inside a path. /// /// Path to find the files /// Recursive search (default: false, optional) /// Extensions for the file search, e.g. "png" (optional) /// Returns array of the found files inside the path (alphabetically ordered). Zero length array when an error occured. public static string[] GetFiles(string path, bool isRecursive = false, params string[] extensions) { if (isWebPlatform && !isEditor) { Debug.LogWarning("'GetFiles' is not supported for the current platform!"); } else if (isWSABasedPlatform && !isEditor) { #if CT_FB_PRO #if UNITY_WSA && !UNITY_EDITOR Crosstales.FB.FileBrowserWSAImpl fbWsa = new Crosstales.FB.FileBrowserWSAImpl(); fbWsa.isBusy = true; UnityEngine.WSA.Application.InvokeOnUIThread(() => { fbWsa.GetFiles(path, isRecursive, extensions); }, false); do { //wait } while (fbWsa.isBusy); return fbWsa.Selection.ToArray(); #endif #else Debug.LogWarning($"'GetFiles' under UWP (WSA) is supported in combination with 'File Browser PRO'. For more, please see: {BaseConstants.ASSET_FB}"); #endif } else { if (!string.IsNullOrEmpty(path)) { try { string _path = ValidatePath(path); if (extensions == null || extensions.Length == 0 || extensions.Any(extension => extension.Equals("*") || extension.Equals("*.*"))) { #if NET_4_6 || NET_STANDARD_2_0 return System.IO.Directory.EnumerateFiles(_path, "*", isRecursive ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly).ToArray(); #else return System.IO.Directory.GetFiles(_path, "*", isRecursive ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly); #endif } System.Collections.Generic.List files = new System.Collections.Generic.List(); foreach (string extension in extensions) { files.AddRange(System.IO.Directory.EnumerateFiles(_path, $"*.{extension}", isRecursive ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly)); } return files.OrderBy(q => q).ToArray(); } catch (System.Exception ex) { Debug.LogWarning($"Could not scan the path for files: {ex}"); } } } return new string[0]; } /// /// Find directories inside. /// /// Path to find the directories /// Recursive search (default: false, optional) /// Returns array of the found directories inside the path. Zero length array when an error occured. public static string[] GetDirectories(string path, bool isRecursive = false) { if (isWebPlatform && !isEditor) { Debug.LogWarning("'GetDirectories' is not supported for the current platform!"); } else if (isWSABasedPlatform && !isEditor) { #if CT_FB_PRO #if UNITY_WSA && !UNITY_EDITOR Crosstales.FB.FileBrowserWSAImpl fbWsa = new Crosstales.FB.FileBrowserWSAImpl(); fbWsa.isBusy = true; UnityEngine.WSA.Application.InvokeOnUIThread(() => { fbWsa.GetDirectories(path, isRecursive); }, false); do { //wait } while (fbWsa.isBusy); return fbWsa.Selection.ToArray(); #endif #else Debug.LogWarning($"'GetDirectories' under UWP (WSA) is supported in combination with 'File Browser PRO'. For more, please see: {BaseConstants.ASSET_FB}"); #endif } else { if (!string.IsNullOrEmpty(path)) { try { string _path = ValidatePath(path); #if NET_4_6 || NET_STANDARD_2_0 return System.IO.Directory.EnumerateDirectories(_path, "*", isRecursive ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly).ToArray(); #else return System.IO.Directory.GetDirectories(_path, "*", isRecursive ? System.IO.SearchOption.AllDirectories : System.IO.SearchOption.TopDirectoryOnly); #endif } catch (System.Exception ex) { Debug.LogWarning($"Could not scan the path for directories: {ex}"); } } } return new string[0]; } /// /// Find all logical drives. /// /// Returns array of the found drives. Zero length array when an error occured. public static string[] GetDrives() //TODO replace with "Util.Helper.GetDrives" in the next version { if (isWebPlatform && !isEditor) { Debug.LogWarning("'GetDrives' is not supported for the current platform!"); } else if (isWSABasedPlatform && !isEditor) { #if CT_FB_PRO #if UNITY_WSA && !UNITY_EDITOR && ENABLE_WINMD_SUPPORT Crosstales.FB.FileBrowserWSAImpl fbWsa = new Crosstales.FB.FileBrowserWSAImpl(); fbWsa.isBusy = true; UnityEngine.WSA.Application.InvokeOnUIThread(() => { fbWsa.GetDrives(); }, false); do { //wait } while (fbWsa.isBusy); return fbWsa.Selection.ToArray(); #endif #else Debug.LogWarning($"'GetDrives' under UWP (WSA) is supported in combination with 'File Browser PRO'. For more, please see: {BaseConstants.ASSET_FB}"); #endif } else { #if !UNITY_WSA || UNITY_EDITOR try { return System.IO.Directory.GetLogicalDrives(); } catch (System.Exception ex) { Debug.LogWarning($"Could not scan the path for directories: {ex}"); } #endif } return new string[0]; } /* /// Validates a given path and add missing slash. /// Path to validate /// Valid path public static string ValidPath(string path) { if (!string.IsNullOrEmpty(path)) { string pathTemp = path.Trim(); string result = null; if (isWindowsPlatform) { result = pathTemp.Replace('/', '\\'); if (!result.EndsWith(BaseConstants.PATH_DELIMITER_WINDOWS)) { result += BaseConstants.PATH_DELIMITER_WINDOWS; } } else { result = pathTemp.Replace('\\', '/'); if (!result.EndsWith(BaseConstants.PATH_DELIMITER_UNIX)) { result += BaseConstants.PATH_DELIMITER_UNIX; } } return result; } return path; } /// Validates a given file. /// File to validate /// Valid file path public static string ValidFilePath(string path) { if (!string.IsNullOrEmpty(path)) { string result = ValidPath(path); if (result.EndsWith(BaseConstants.PATH_DELIMITER_WINDOWS) || result.EndsWith(BaseConstants.PATH_DELIMITER_UNIX)) { result = result.Substring(0, result.Length - 1); } return result; } return path; } */ /// Validates a given file. /// File to validate /// Valid file path public static string ValidURLFromFilePath(string path) { if (!string.IsNullOrEmpty(path)) { if (!isValidURL(path)) return BaseConstants.PREFIX_FILE + System.Uri.EscapeUriString(ValidateFile(path).Replace('\\', '/')); return System.Uri.EscapeUriString(ValidateFile(path).Replace('\\', '/')); } return path; } /// Cleans a given URL. /// URL to clean /// Remove the protocol, e.g. http:// (default: true, optional). /// Remove www (default: true, optional). /// Remove slash at the end (default: true, optional) /// Clean URL public static string CleanUrl(string url, bool removeProtocol = true, bool removeWWW = true, bool removeSlash = true) { string result = url?.Trim(); if (!string.IsNullOrEmpty(url)) { if (removeProtocol) { result = result.Substring(result.CTIndexOf("//") + 2); } if (removeWWW) { result = result.CTReplace("www.", string.Empty); } if (removeSlash && result.CTEndsWith(BaseConstants.PATH_DELIMITER_UNIX)) { result = result.Substring(0, result.Length - 1); } /* if (urlTemp.StartsWith("http://")) { result = urlTemp.Substring(7); } else if (urlTemp.StartsWith("https://")) { result = urlTemp.Substring(8); } else { result = urlTemp; } if (result.StartsWith("www.")) { result = result.Substring(4); } */ } return result; } /// Cleans a given text from tags. /// Text to clean. /// Clean text without tags. public static string ClearTags(string text) { return text != null ? cleanTagsRegex.Replace(text, string.Empty).Trim() : null; } /// Cleans a given text from multiple spaces. /// Text to clean. /// Clean text without multiple spaces. public static string ClearSpaces(string text) { return text != null ? cleanSpacesRegex.Replace(text, " ").Trim() : null; } /// Cleans a given text from line endings. /// Text to clean. /// Clean text without line endings. public static string ClearLineEndings(string text) { return text != null ? lineEndingsRegex.Replace(text, string.Empty).Trim() : null; } /// Split the given text to lines and return it as list. /// Complete text fragment /// Ignore commente lines (default: true, optional) /// Number of skipped header lines (default: 0, optional) /// Number of skipped footer lines (default: 0, optional) /// Splitted lines as array public static System.Collections.Generic.List SplitStringToLines(string text, bool ignoreCommentedLines = true, int skipHeaderLines = 0, int skipFooterLines = 0) { System.Collections.Generic.List result = new System.Collections.Generic.List(100); if (string.IsNullOrEmpty(text)) { Debug.LogWarning("Parameter 'text' is null or empty => 'SplitStringToLines()' will return an empty string list."); } else { string[] lines = lineEndingsRegex.Split(text); for (int ii = 0; ii < lines.Length; ii++) { if (ii + 1 > skipHeaderLines && ii < lines.Length - skipFooterLines) { if (!string.IsNullOrEmpty(lines[ii])) { if (ignoreCommentedLines) { if (!lines[ii].CTStartsWith("#")) //valid and not disabled line? result.Add(lines[ii]); } else { result.Add(lines[ii]); } } } } } return result; } /// Format byte-value to Human-Readable-Form. /// Formatted byte-value in Human-Readable-Form. public static string FormatBytesToHRF(long bytes) { string[] sizes = {"B", "KB", "MB", "GB", "TB"}; double len = bytes; int order = 0; while (len >= 1024 && order < sizes.Length - 1) { order++; len /= 1024; } // Adjust the format string to your preferences. return $"{len:0.##} {sizes[order]}"; } /// Format seconds to Human-Readable-Form. /// Formatted seconds in Human-Readable-Form. public static string FormatSecondsToHourMinSec(double seconds) { int totalSeconds = (int)seconds; int calcSeconds = totalSeconds % 60; if (seconds >= 86400) { int calcDays = totalSeconds / 86400; int calcHours = (totalSeconds -= calcDays * 86400) / 3600; int calcMinutes = (totalSeconds - calcHours * 3600) / 60; return $"{calcDays}d {calcHours}:{addLeadingZero(calcMinutes)}:{addLeadingZero(calcSeconds)}"; } if (seconds >= 3600) { int calcHours = totalSeconds / 3600; int calcMinutes = (totalSeconds - calcHours * 3600) / 60; return $"{calcHours}:{addLeadingZero(calcMinutes)}:{addLeadingZero(calcSeconds)}"; } else { int calcMinutes = totalSeconds / 60; return $"{calcMinutes}:{addLeadingZero(calcSeconds)}"; } } /// /// Generate nice HSV colors. /// Based on https://gist.github.com/rje/6206099 /// /// Hue /// Saturation /// Value /// Alpha (optional) /// True if the current platform is supported. public static Color HSVToRGB(float h, float s, float v, float a = 1f) { if (Mathf.Abs(s) < BaseConstants.FLOAT_TOLERANCE) return new Color(v, v, v, a); float _h = h / 60f; int sector = Mathf.FloorToInt(_h); float fact = _h - sector; float p = v * (1f - s); float q = v * (1f - s * fact); float t = v * (1f - s * (1f - fact)); switch (sector) { case 0: return new Color(v, t, p, a); case 1: return new Color(q, v, p, a); case 2: return new Color(p, v, t, a); case 3: return new Color(p, q, v, a); case 4: return new Color(t, p, v, a); default: return new Color(v, p, q, a); } } /// Checks if the URL is valid. /// URL to check /// True if the URL is valid. public static bool isValidURL(string url) { return !string.IsNullOrEmpty(url) && (url.StartsWith(file_prefix, System.StringComparison.OrdinalIgnoreCase) || url.StartsWith(BaseConstants.PREFIX_HTTP, System.StringComparison.OrdinalIgnoreCase) || url.StartsWith(BaseConstants.PREFIX_HTTPS, System.StringComparison.OrdinalIgnoreCase)); } /// Copy or move a file. /// Input file path /// Output file path /// Move file instead of copy (default: false, optional) public static void FileCopy(string inputFile, string outputFile, bool move = false) { if ((isWSABasedPlatform || isWebPlatform) && !isEditor) { Debug.LogWarning("'FileCopy' is not supported for the current platform!"); } else { if (!string.IsNullOrEmpty(outputFile)) { try { if (!System.IO.File.Exists(inputFile)) { Debug.LogError($"Input file does not exists: {inputFile}"); } else { System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputFile)); if (System.IO.File.Exists(outputFile)) { if (BaseConstants.DEV_DEBUG) Debug.LogWarning($"Overwrite output file: {outputFile}"); System.IO.File.Delete(outputFile); } if (move) { #if UNITY_STANDALONE || UNITY_EDITOR System.IO.File.Move(inputFile, outputFile); #else System.IO.File.Copy(inputFile, outputFile); System.IO.File.Delete(inputFile); #endif } else { System.IO.File.Copy(inputFile, outputFile); } } } catch (System.Exception ex) { Debug.LogError($"Could not copy file: {ex}"); } } } } /// /// Shows the location of a path or file in OS file explorer. /// NOTE: only works for standalone platforms /// /// File path public static void ShowFileLocation(string file) { if (isStandalonePlatform || isEditor) { #if UNITY_STANDALONE || UNITY_EDITOR string path; if (string.IsNullOrEmpty(file) || file.Equals(".")) { path = "."; } else if ((isWindowsPlatform || isWindowsEditor) && file.Length < 4) { path = file; //root directory } else { path = ValidatePath(System.IO.Path.GetDirectoryName(file)); } try { if (System.IO.Directory.Exists(path)) { #if ENABLE_IL2CPP using (CTProcess process = new CTProcess()) { process.StartInfo.Arguments = $"\"{path}\""; if (isWindowsPlatform || isWindowsEditor) { process.StartInfo.FileName = "explorer.exe"; process.StartInfo.UseCmdExecute = true; process.StartInfo.CreateNoWindow = true; } else if (isMacOSPlatform || isMacOSEditor) { process.StartInfo.FileName = "open"; } else { process.StartInfo.FileName = "xdg-open"; } process.Start(); } #else System.Diagnostics.Process.Start(path); #endif } else { Debug.LogWarning($"Path to file doesn't exist: {path}"); } } catch (System.Exception ex) { Debug.LogError($"Could not show file location: {ex}"); } #endif } else { Debug.LogWarning("'ShowFileLocation' is not supported on the current platform!"); } } /// /// Opens a file with the OS default application. /// NOTE: only works for standalone platforms /// /// File path public static void OpenFile(string file) { if (isStandalonePlatform || isEditor) { try { #if UNITY_STANDALONE || UNITY_EDITOR if (System.IO.File.Exists(file)) { #if ENABLE_IL2CPP using (CTProcess process = new CTProcess()) { process.StartInfo.Arguments = $"\"{file}\""; if (isWindowsPlatform || isWindowsEditor) { process.StartInfo.FileName = "explorer.exe"; process.StartInfo.UseCmdExecute = true; process.StartInfo.CreateNoWindow = true; } else if (isMacOSPlatform || isMacOSEditor) { process.StartInfo.FileName = "open"; } else { process.StartInfo.FileName = "xdg-open"; } process.Start(); } #else using (System.Diagnostics.Process process = new System.Diagnostics.Process()) { if (isMacOSPlatform || isMacOSEditor) { process.StartInfo.FileName = "open"; process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(file) + BaseConstants.PATH_DELIMITER_UNIX; process.StartInfo.Arguments = $"-t \"{System.IO.Path.GetFileName(file)}\""; } else if (isLinuxPlatform || isLinuxEditor) { process.StartInfo.FileName = "xdg-open"; process.StartInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(file) + BaseConstants.PATH_DELIMITER_UNIX; process.StartInfo.Arguments = System.IO.Path.GetFileName(file); } else { process.StartInfo.FileName = file; } process.Start(); } #endif } else { Debug.LogWarning($"File doesn't exist: {file}"); } #endif } catch (System.Exception ex) { Debug.LogError($"Could not open file: {ex}"); } } else { Debug.LogWarning("'OpenFile' is not supported on the current platform!"); } } /// Returns the IP of a given host name. /// Host name /// IP of a given host name. public static string getIP(string host) { if (!string.IsNullOrEmpty(host)) { #if !UNITY_WSA && !UNITY_WEBGL try { return System.Net.Dns.GetHostAddresses(host)[0].ToString(); } catch (System.Exception ex) { Debug.LogWarning($"Could not resolve host '{host}': {ex}"); } #else Debug.LogWarning("'getIP' doesn't work in WebGL or WSA! Returning original string."); #endif } else { Debug.LogWarning("Host name is null or empty - can't resolve to IP!"); } return host; } private static string addLeadingZero(int value) { return value < 10 ? "0" + value : value.ToString(); } // StringHelper /* public static byte[] GetBytesFromText(string text) { return new UnicodeEncoding().GetBytes(text); } public static string GetTextFromBytes(byte[] bytes) { return new UnicodeEncoding().GetString(bytes, 0, bytes.Length); } public static byte[] GetBytesFromBase64(string text) { return Convert.FromBase64String(text); } public static string GetBase64FromBytes(byte[] bytes) { return Convert.ToBase64String(bytes); } */ // MathHelper /* public static bool IsInRange(float actValue, float refValue, float range) { return (actValue >= refValue-range) && (actValue <= refValue+range); } public static bool IsInRange(int actValue, int refValue, int range) { return (actValue >= refValue-range) && (actValue <= refValue+range); } */ // Add Math3dHelper? // Color Helper /* public static string ColorToHex(Color32 color) { // if (color == null) // throw new ArgumentNullException("color"); string hex = color.r.ToString("X2") + color.g.ToString("X2") + color.b.ToString("X2"); return hex; } public static Color HexToColor(string hex) { if (string.IsNullOrEmpty(hex)) throw new ArgumentNullException("hex"); byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber); byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber); byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber); return new Color32(r, g, b, 255); } */ #endregion } /// Helper to reset the necessary settings. public class HelperCT : MonoBehaviour { private void OnApplicationQuit() { BaseHelper.ApplicationIsPlaying = false; } } #if UNITY_EDITOR [UnityEditor.CustomEditor(typeof(HelperCT))] public class HelperCTEditor : UnityEditor.Editor { public override void OnInspectorGUI() { UnityEditor.EditorGUILayout.HelpBox("This helper ensures the flawless working of the assets from 'crosstales LLC'.\nPlease do not delete it from the hierarchy.", UnityEditor.MessageType.Info); } } #endif } // © 2015-2020 crosstales LLC (https://www.crosstales.com)