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)